Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HuasoFoundries/phpPgAdmin6.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmenadiel <amenadiel@gmail.com>2017-07-26 15:16:00 +0300
committerAmenadiel <amenadiel@gmail.com>2017-07-26 15:16:00 +0300
commit783f1af1d990f182c8b7be3e7d38f6a192062548 (patch)
treef76e796b74fc4352fba8a0dd144be1b8a6a3bab8
parent4a3fdb2bd95f04c9387a5a523db981db96bf549f (diff)
Tag v 6.0.0-beta.14 transform help scripts into classes, adds them to autoloaderv6.0.0-beta.14
-rw-r--r--composer.json5
-rw-r--r--composer.lock14
-rw-r--r--src/database/Postgres.php15763
-rw-r--r--src/database/Postgres74.php850
-rw-r--r--src/database/Postgres80.php642
-rw-r--r--src/database/Postgres81.php449
-rw-r--r--src/database/Postgres82.php541
-rw-r--r--src/database/Postgres83.php533
-rw-r--r--src/database/Postgres84.php200
-rw-r--r--src/database/Postgres90.php15
-rw-r--r--src/database/Postgres91.php105
-rw-r--r--src/database/Postgres92.php13
-rw-r--r--src/database/Postgres93.php13
-rw-r--r--src/database/Postgres94.php13
-rw-r--r--src/database/Postgres95.php13
-rw-r--r--src/database/Postgres96.php51
-rw-r--r--src/help/PostgresDoc74.php322
-rw-r--r--src/help/PostgresDoc80.php31
-rw-r--r--src/help/PostgresDoc81.php19
-rw-r--r--src/help/PostgresDoc82.php11
-rw-r--r--src/help/PostgresDoc83.php33
-rw-r--r--src/help/PostgresDoc84.php11
-rw-r--r--src/help/PostgresDoc90.php11
-rw-r--r--src/help/PostgresDoc91.php11
-rw-r--r--src/help/PostgresDoc92.php11
-rw-r--r--src/help/PostgresDoc93.php11
-rw-r--r--src/help/PostgresDoc94.php11
-rw-r--r--src/help/PostgresDoc95.php14
-rw-r--r--src/help/PostgresDoc96.php13
29 files changed, 10106 insertions, 9623 deletions
diff --git a/composer.json b/composer.json
index 00362834..055b6db5 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
"name": "huasofoundries/phppgadmin6",
- "version": "6.0.0-beta.13",
+ "version": "6.0.0-beta.14",
"description": "Like phpmyadmin but for postgres",
"type": "project",
"license": "MIT",
@@ -19,7 +19,8 @@
"PHPPgAdmin\\Middleware\\": "src/middleware",
"PHPPgAdmin\\Database\\": "src/database",
"PHPPgAdmin\\XHtml\\": "src/xhtml",
- "PHPPgAdmin\\Decorators\\": "src/decorators"
+ "PHPPgAdmin\\Decorators\\": "src/decorators",
+ "PHPPgAdmin\\Help\\": "src/help"
}
},
"require":
diff --git a/composer.lock b/composer.lock
index 2f940ee0..953c0186 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "6764dc6ac14b453b098da17a1e92d8f5",
- "content-hash": "0a0ebf9f4f434b5b3f4d38549440d300",
+ "hash": "c78297ee8abcbf4954948fbc6cc46080",
+ "content-hash": "f0d3558e928fc01c8fcfcdac4ada9b01",
"packages": [
{
"name": "adodb/adodb-php",
@@ -246,16 +246,16 @@
},
{
"name": "pimple/pimple",
- "version": "v3.2.0",
+ "version": "v3.2.2",
"source": {
"type": "git",
"url": "https://github.com/silexphp/Pimple.git",
- "reference": "729436408ef52f9845f9b60d60b2563f314bf1a9"
+ "reference": "4d45fb62d96418396ec58ba76e6f065bca16e10a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/silexphp/Pimple/zipball/729436408ef52f9845f9b60d60b2563f314bf1a9",
- "reference": "729436408ef52f9845f9b60d60b2563f314bf1a9",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/4d45fb62d96418396ec58ba76e6f065bca16e10a",
+ "reference": "4d45fb62d96418396ec58ba76e6f065bca16e10a",
"shasum": ""
},
"require": {
@@ -292,7 +292,7 @@
"container",
"dependency injection"
],
- "time": "2017-07-17 17:05:21"
+ "time": "2017-07-23 07:32:15"
},
{
"name": "psr/container",
diff --git a/src/database/Postgres.php b/src/database/Postgres.php
index 12dc0e30..e621fb3c 100644
--- a/src/database/Postgres.php
+++ b/src/database/Postgres.php
@@ -1,5 +1,6 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* A Class that implements the DB Interface for Postgres
* Note: This Class uses ADODB and returns RecordSets.
@@ -7,499 +8,528 @@ namespace PHPPgAdmin\Database;
* $Id: Postgres.php,v 1.320 2008/02/20 20:43:09 ioguix Exp $
*/
-class Postgres extends ADODB_base {
-
- use \PHPPgAdmin\HelperTrait;
-
- var $major_version = 9.5;
- // Max object name length
- var $_maxNameLen = 63;
- // Store the current schema
- var $_schema;
- // Map of database encoding names to HTTP encoding names. If a
- // database encoding does not appear in this list, then its HTTP
- // encoding name is the same as its database encoding name.
- var $codemap = [
- 'BIG5' => 'BIG5',
- 'EUC_CN' => 'GB2312',
- 'EUC_JP' => 'EUC-JP',
- 'EUC_KR' => 'EUC-KR',
- 'EUC_TW' => 'EUC-TW',
- 'GB18030' => 'GB18030',
- 'GBK' => 'GB2312',
- 'ISO_8859_5' => 'ISO-8859-5',
- 'ISO_8859_6' => 'ISO-8859-6',
- 'ISO_8859_7' => 'ISO-8859-7',
- 'ISO_8859_8' => 'ISO-8859-8',
- 'JOHAB' => 'CP1361',
- 'KOI8' => 'KOI8-R',
- 'LATIN1' => 'ISO-8859-1',
- 'LATIN2' => 'ISO-8859-2',
- 'LATIN3' => 'ISO-8859-3',
- 'LATIN4' => 'ISO-8859-4',
- 'LATIN5' => 'ISO-8859-9',
- 'LATIN6' => 'ISO-8859-10',
- 'LATIN7' => 'ISO-8859-13',
- 'LATIN8' => 'ISO-8859-14',
- 'LATIN9' => 'ISO-8859-15',
- 'LATIN10' => 'ISO-8859-16',
- 'SJIS' => 'SHIFT_JIS',
- 'SQL_ASCII' => 'US-ASCII',
- 'UHC' => 'WIN949',
- 'UTF8' => 'UTF-8',
- 'WIN866' => 'CP866',
- 'WIN874' => 'CP874',
- 'WIN1250' => 'CP1250',
- 'WIN1251' => 'CP1251',
- 'WIN1252' => 'CP1252',
- 'WIN1256' => 'CP1256',
- 'WIN1258' => 'CP1258',
- ];
- var $defaultprops = ['', '', ''];
- // Extra "magic" types. BIGSERIAL was added in PostgreSQL 7.2.
- var $extraTypes = ['SERIAL', 'BIGSERIAL'];
- // Foreign key stuff. First element MUST be the default.
- var $fkactions = ['NO ACTION', 'RESTRICT', 'CASCADE', 'SET NULL', 'SET DEFAULT'];
- var $fkdeferrable = ['NOT DEFERRABLE', 'DEFERRABLE'];
- var $fkinitial = ['INITIALLY IMMEDIATE', 'INITIALLY DEFERRED'];
- var $fkmatches = ['MATCH SIMPLE', 'MATCH FULL'];
- // Function properties
- var $funcprops = [['', 'VOLATILE', 'IMMUTABLE', 'STABLE'],
- ['', 'CALLED ON NULL INPUT', 'RETURNS NULL ON NULL INPUT'],
- ['', 'SECURITY INVOKER', 'SECURITY DEFINER']];
- // Default help URL
- var $help_base;
- // Help sub pages
- var $help_page;
- // Name of id column
- var $id = 'oid';
- // Supported join operations for use with view wizard
- var $joinOps = ['INNER JOIN' => 'INNER JOIN', 'LEFT JOIN' => 'LEFT JOIN', 'RIGHT JOIN' => 'RIGHT JOIN', 'FULL JOIN' => 'FULL JOIN'];
- // Map of internal language name to syntax highlighting name
- var $langmap = [
- 'sql' => 'SQL',
- 'plpgsql' => 'SQL',
- 'php' => 'PHP',
- 'phpu' => 'PHP',
- 'plphp' => 'PHP',
- 'plphpu' => 'PHP',
- 'perl' => 'Perl',
- 'perlu' => 'Perl',
- 'plperl' => 'Perl',
- 'plperlu' => 'Perl',
- 'java' => 'Java',
- 'javau' => 'Java',
- 'pljava' => 'Java',
- 'pljavau' => 'Java',
- 'plj' => 'Java',
- 'plju' => 'Java',
- 'python' => 'Python',
- 'pythonu' => 'Python',
- 'plpython' => 'Python',
- 'plpythonu' => 'Python',
- 'ruby' => 'Ruby',
- 'rubyu' => 'Ruby',
- 'plruby' => 'Ruby',
- 'plrubyu' => 'Ruby',
- ];
- // Predefined size types
- var $predefined_size_types = ['abstime', 'aclitem', 'bigserial', 'boolean', 'bytea', 'cid', 'cidr', 'circle', 'date', 'float4', 'float8', 'gtsvector', 'inet', 'int2', 'int4', 'int8', 'macaddr', 'money', 'oid', 'path', 'polygon', 'refcursor', 'regclass', 'regoper', 'regoperator', 'regproc', 'regprocedure', 'regtype', 'reltime', 'serial', 'smgr', 'text', 'tid', 'tinterval', 'tsquery', 'tsvector', 'varbit', 'void', 'xid'];
- // List of all legal privileges that can be applied to different types
- // of objects.
- var $privlist = [
- 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
- 'database' => ['CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'],
- 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
- 'language' => ['USAGE', 'ALL PRIVILEGES'],
- 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
- 'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
- 'column' => ['SELECT', 'INSERT', 'UPDATE', 'REFERENCES', 'ALL PRIVILEGES'],
- ];
- // List of characters in acl lists and the privileges they
- // refer to.
- var $privmap = [
- 'r' => 'SELECT',
- 'w' => 'UPDATE',
- 'a' => 'INSERT',
- 'd' => 'DELETE',
- 'D' => 'TRUNCATE',
- 'R' => 'RULE',
- 'x' => 'REFERENCES',
- 't' => 'TRIGGER',
- 'X' => 'EXECUTE',
- 'U' => 'USAGE',
- 'C' => 'CREATE',
- 'T' => 'TEMPORARY',
- 'c' => 'CONNECT',
- ];
- // Rule action types
- var $rule_events = ['SELECT', 'INSERT', 'UPDATE', 'DELETE'];
- // Select operators
- var $selectOps = ['=' => 'i', '!=' => 'i', '<' => 'i', '>' => 'i', '<=' => 'i', '>=' => 'i',
- '<<' => 'i', '>>' => 'i', '<<=' => 'i', '>>=' => 'i',
- 'LIKE' => 'i', 'NOT LIKE' => 'i', 'ILIKE' => 'i', 'NOT ILIKE' => 'i', 'SIMILAR TO' => 'i',
- 'NOT SIMILAR TO' => 'i', '~' => 'i', '!~' => 'i', '~*' => 'i', '!~*' => 'i',
- 'IS NULL' => 'p', 'IS NOT NULL' => 'p', 'IN' => 'x', 'NOT IN' => 'x',
- '@@' => 'i', '@@@' => 'i', '@>' => 'i', '<@' => 'i',
- '@@ to_tsquery' => 't', '@@@ to_tsquery' => 't', '@> to_tsquery' => 't', '<@ to_tsquery' => 't',
- '@@ plainto_tsquery' => 't', '@@@ plainto_tsquery' => 't', '@> plainto_tsquery' => 't', '<@ plainto_tsquery' => 't'];
- // Array of allowed trigger events
- var $triggerEvents = ['INSERT', 'UPDATE', 'DELETE', 'INSERT OR UPDATE', 'INSERT OR DELETE',
- 'DELETE OR UPDATE', 'INSERT OR DELETE OR UPDATE'];
- // When to execute the trigger
- var $triggerExecTimes = ['BEFORE', 'AFTER'];
- // How often to execute the trigger
- var $triggerFrequency = ['ROW', 'STATEMENT'];
- // Array of allowed type alignments
- var $typAligns = ['char', 'int2', 'int4', 'double'];
- // The default type alignment
- var $typAlignDef = 'int4';
- // Default index type
- var $typIndexDef = 'BTREE';
- // Array of allowed index types
- var $typIndexes = ['BTREE', 'RTREE', 'GIST', 'GIN', 'HASH'];
- // Array of allowed type storage attributes
- var $typStorages = ['plain', 'external', 'extended', 'main'];
- // The default type storage
- var $typStorageDef = 'plain';
-
- function __construct(&$conn, $conf) {
- $this->prtrace('major_version', $this->major_version);
- $this->conn = $conn;
- $this->conf = $conf;
- }
- // Formatting functions
-
- /**
- * Cleans (escapes) a string
- * @param $str The string to clean, by reference
- * @return The cleaned string
- */
- function clean(&$str) {
- if ($str === null) {
- return null;
- }
-
- $str = str_replace("\r\n", "\n", $str);
- $str = pg_escape_string($str);
- return $str;
- }
-
- /**
- * Cleans (escapes) an object name (eg. table, field)
- * @param $str The string to clean, by reference
- * @return The cleaned string
- */
- function fieldClean(&$str) {
- if ($str === null) {
- return null;
- }
-
- $str = str_replace('"', '""', $str);
- return $str;
- }
-
- /**
- * Cleans (escapes) an array of field names
- * @param $arr The array to clean, by reference
- * @return The cleaned array
- */
- function fieldArrayClean(&$arr) {
- foreach ($arr as $k => $v) {
- if ($v === null) {
- continue;
- }
-
- $arr[$k] = str_replace('"', '""', $v);
- }
- return $arr;
- }
-
- /**
- * Cleans (escapes) an array
- * @param $arr The array to clean, by reference
- * @return The cleaned array
- */
- function arrayClean(&$arr) {
- foreach ($arr as $k => $v) {
- if ($v === null) {
- continue;
- }
-
- $arr[$k] = pg_escape_string($v);
- }
- return $arr;
- }
-
- /**
- * Escapes bytea data for display on the screen
- * @param $data The bytea data
- * @return Data formatted for on-screen display
- */
- function escapeBytea($data) {
- return htmlentities($data, ENT_QUOTES, 'UTF-8');
- }
-
- /**
- * 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
- * @param $extras An array of attributes name as key and attributes' values as value
- */
- function printField($name, $value, $type, $extras = []) {
- $lang = $this->lang;
-
- // Determine actions string
- $extra_str = '';
- foreach ($extras as $k => $v) {
- $extra_str .= " {$k}=\"" . htmlspecialchars($v) . "\"";
- }
-
- switch (substr($type, 0, 9)) {
- case 'bool':
- case 'boolean':
- if ($value !== null && $value == '') {
- $value = null;
- } elseif ($value == 'true') {
- $value = 't';
- } elseif ($value == 'false') {
- $value = 'f';
- }
-
- // If value is null, 't' or 'f'...
- if ($value === null || $value == 't' || $value == 'f') {
- echo "<select name=\"", htmlspecialchars($name), "\"{$extra_str}>\n";
- echo "<option value=\"\"", ($value === null) ? ' selected="selected"' : '', "></option>\n";
- echo "<option value=\"t\"", ($value == 't') ? ' selected="selected"' : '', ">{$lang['strtrue']}</option>\n";
- echo "<option value=\"f\"", ($value == 'f') ? ' selected="selected"' : '', ">{$lang['strfalse']}</option>\n";
- echo "</select>\n";
- } else {
- echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=\"35\"{$extra_str} />\n";
- }
- break;
- case 'bytea':
- case 'bytea[]':
- if (!is_null($value)) {
- $value = $this->escapeBytea($value);
- }
- case 'text':
- case 'text[]':
- case 'json':
- case 'jsonb':
- case 'xml':
- case 'xml[]':
- $n = substr_count($value, "\n");
- $n = $n < 5 ? 5 : $n;
- $n = $n > 20 ? 20 : $n;
- echo "<textarea name=\"", htmlspecialchars($name), "\" rows=\"{$n}\" cols=\"75\"{$extra_str}>\n";
- echo htmlspecialchars($value);
- echo "</textarea>\n";
- break;
- case 'character':
- case 'character[]':
- $n = substr_count($value, "\n");
- $n = $n < 5 ? 5 : $n;
- $n = $n > 20 ? 20 : $n;
- echo "<textarea name=\"", htmlspecialchars($name), "\" rows=\"{$n}\" cols=\"35\"{$extra_str}>\n";
- echo htmlspecialchars($value);
- echo "</textarea>\n";
- break;
- default:
- echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=\"35\"{$extra_str} />\n";
- break;
- }
- }
-
- /**
- * Formats a value or expression for sql purposes
- * @param $type The type of the field
- * @param $format VALUE or EXPRESSION
- * @param $value The actual value entered in the field. Can be NULL
- * @return The suitably quoted and escaped value.
- */
- function formatValue($type, $format, $value) {
- switch ($type) {
- case 'bool':
- case 'boolean':
- if ($value == 't') {
- return 'TRUE';
- } elseif ($value == 'f') {
- return 'FALSE';
- } elseif ($value == '') {
- return 'NULL';
- } else {
- return $value;
- }
-
- break;
- default:
- // Checking variable fields is difficult as there might be a size
- // attribute...
- if (strpos($type, 'time') === 0) {
- // Assume it's one of the time types...
- if ($value == '') {
- return "''";
- } elseif (strcasecmp($value, 'CURRENT_TIMESTAMP') == 0
- || strcasecmp($value, 'CURRENT_TIME') == 0
- || strcasecmp($value, 'CURRENT_DATE') == 0
- || strcasecmp($value, 'LOCALTIME') == 0
- || strcasecmp($value, 'LOCALTIMESTAMP') == 0) {
- return $value;
- } elseif ($format == 'EXPRESSION') {
- return $value;
- } else {
- $this->clean($value);
- return "'{$value}'";
- }
- } else {
- if ($format == 'VALUE') {
- $this->clean($value);
- return "'{$value}'";
- }
- return $value;
- }
- }
- }
-
- /**
- * Formats a type correctly for display. Postgres 7.0 had no 'format_type'
- * built-in function, and hence we need to do it manually.
- * @param $typname The name of the type
- * @param $typmod The contents of the typmod field
- */
- function formatType($typname, $typmod) {
- // This is a specific constant in the 7.0 source
- $varhdrsz = 4;
-
- // If the first character is an underscore, it's an array type
- $is_array = false;
- if (substr($typname, 0, 1) == '_') {
- $is_array = true;
- $typname = substr($typname, 1);
- }
-
- // Show lengths on bpchar and varchar
- if ($typname == 'bpchar') {
- $len = $typmod - $varhdrsz;
- $temp = 'character';
- if ($len > 1) {
- $temp .= "({$len})";
- }
-
- } elseif ($typname == 'varchar') {
- $temp = 'character varying';
- if ($typmod != -1) {
- $temp .= "(" . ($typmod - $varhdrsz) . ")";
- }
-
- } elseif ($typname == 'numeric') {
- $temp = 'numeric';
- if ($typmod != -1) {
- $tmp_typmod = $typmod - $varhdrsz;
- $precision = ($tmp_typmod >> 16) & 0xffff;
- $scale = $tmp_typmod & 0xffff;
- $temp .= "({$precision}, {$scale})";
- }
- } else {
- $temp = $typname;
- }
-
- // Add array qualifier if it's an array
- if ($is_array) {
- $temp .= '[]';
- }
-
- return $temp;
- }
-
- // Help functions
-
- /**
- * Fetch a URL (or array of URLs) for a given help page.
- */
- function getHelp($help) {
- $this->getHelpPages();
-
- if (isset($this->help_page[$help])) {
- if (is_array($this->help_page[$help])) {
- $urls = [];
- foreach ($this->help_page[$help] as $link) {
- $urls[] = $this->help_base . $link;
- }
- return $urls;
- } else {
- return $this->help_base . $this->help_page[$help];
- }
-
- } else {
- return null;
- }
-
- }
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc95.php';
- return $this->help_page;
- }
-
- // Database functions
-
- /**
- * Return all information about a particular database
- * @param $database The name of the database to retrieve
- * @return The database info
- */
- function getDatabase($database) {
- $this->clean($database);
- $sql = "SELECT * FROM pg_database WHERE datname='{$database}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Return all database available on the server
- * @param $currentdatabase database name that should be on top of the resultset
- *
- * @return A list of databases, sorted alphabetically
- */
- function getDatabases($currentdatabase = NULL) {
- $conf = $this->conf;
- $server_info = $this->server_info;
-
- if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
- $username = $server_info['username'];
- $this->clean($username);
- $clause = " AND pr.rolname='{$username}'";
- } else {
- $clause = '';
- }
- if (isset($server_info['useonlydefaultdb']) && $server_info['useonlydefaultdb']) {
- $currentdatabase = $server_info['defaultdb'];
- $clause .= " AND pdb.datname = '{$currentdatabase}' ";
- }
-
- if (isset($server_info['hiddendbs']) && $server_info['hiddendbs']) {
- $hiddendbs = $server_info['hiddendbs'];
- $not_in = "('" . implode("','", $hiddendbs) . "')";
- $clause .= " AND pdb.datname NOT IN {$not_in} ";
- }
-
- if ($currentdatabase != NULL) {
- $this->clean($currentdatabase);
- $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
- } else {
- $orderby = "ORDER BY pdb.datname";
- }
-
- if (!$conf['show_system']) {
- $where = ' AND NOT pdb.datistemplate';
- } else {
- $where = ' AND pdb.datallowconn';
- }
-
- $sql = "
+class Postgres extends ADODB_base
+{
+
+ use \PHPPgAdmin\HelperTrait;
+
+ public $major_version = 9.6;
+ // Max object name length
+ public $_maxNameLen = 63;
+ // Store the current schema
+ public $_schema;
+ // Map of database encoding names to HTTP encoding names. If a
+ // database encoding does not appear in this list, then its HTTP
+ // encoding name is the same as its database encoding name.
+ public $codemap = [
+ 'BIG5' => 'BIG5',
+ 'EUC_CN' => 'GB2312',
+ 'EUC_JP' => 'EUC-JP',
+ 'EUC_KR' => 'EUC-KR',
+ 'EUC_TW' => 'EUC-TW',
+ 'GB18030' => 'GB18030',
+ 'GBK' => 'GB2312',
+ 'ISO_8859_5' => 'ISO-8859-5',
+ 'ISO_8859_6' => 'ISO-8859-6',
+ 'ISO_8859_7' => 'ISO-8859-7',
+ 'ISO_8859_8' => 'ISO-8859-8',
+ 'JOHAB' => 'CP1361',
+ 'KOI8' => 'KOI8-R',
+ 'LATIN1' => 'ISO-8859-1',
+ 'LATIN2' => 'ISO-8859-2',
+ 'LATIN3' => 'ISO-8859-3',
+ 'LATIN4' => 'ISO-8859-4',
+ 'LATIN5' => 'ISO-8859-9',
+ 'LATIN6' => 'ISO-8859-10',
+ 'LATIN7' => 'ISO-8859-13',
+ 'LATIN8' => 'ISO-8859-14',
+ 'LATIN9' => 'ISO-8859-15',
+ 'LATIN10' => 'ISO-8859-16',
+ 'SJIS' => 'SHIFT_JIS',
+ 'SQL_ASCII' => 'US-ASCII',
+ 'UHC' => 'WIN949',
+ 'UTF8' => 'UTF-8',
+ 'WIN866' => 'CP866',
+ 'WIN874' => 'CP874',
+ 'WIN1250' => 'CP1250',
+ 'WIN1251' => 'CP1251',
+ 'WIN1252' => 'CP1252',
+ 'WIN1256' => 'CP1256',
+ 'WIN1258' => 'CP1258',
+ ];
+ public $defaultprops = ['', '', ''];
+ // Extra "magic" types. BIGSERIAL was added in PostgreSQL 7.2.
+ public $extraTypes = ['SERIAL', 'BIGSERIAL'];
+ // Foreign key stuff. First element MUST be the default.
+ public $fkactions = ['NO ACTION', 'RESTRICT', 'CASCADE', 'SET NULL', 'SET DEFAULT'];
+ public $fkdeferrable = ['NOT DEFERRABLE', 'DEFERRABLE'];
+ public $fkinitial = ['INITIALLY IMMEDIATE', 'INITIALLY DEFERRED'];
+ public $fkmatches = ['MATCH SIMPLE', 'MATCH FULL'];
+ // Function properties
+ public $funcprops = [['', 'VOLATILE', 'IMMUTABLE', 'STABLE'],
+ ['', 'CALLED ON NULL INPUT', 'RETURNS NULL ON NULL INPUT'],
+ ['', 'SECURITY INVOKER', 'SECURITY DEFINER']];
+
+ // Default help URL
+ public $help_base = null;
+ // Help sub pages
+ public $help_page = null;
+ // Name of id column
+ public $id = 'oid';
+
+ // Supported join operations for use with view wizard
+ public $joinOps = ['INNER JOIN' => 'INNER JOIN', 'LEFT JOIN' => 'LEFT JOIN', 'RIGHT JOIN' => 'RIGHT JOIN', 'FULL JOIN' => 'FULL JOIN'];
+ // Map of internal language name to syntax highlighting name
+ public $langmap = [
+ 'sql' => 'SQL',
+ 'plpgsql' => 'SQL',
+ 'php' => 'PHP',
+ 'phpu' => 'PHP',
+ 'plphp' => 'PHP',
+ 'plphpu' => 'PHP',
+ 'perl' => 'Perl',
+ 'perlu' => 'Perl',
+ 'plperl' => 'Perl',
+ 'plperlu' => 'Perl',
+ 'java' => 'Java',
+ 'javau' => 'Java',
+ 'pljava' => 'Java',
+ 'pljavau' => 'Java',
+ 'plj' => 'Java',
+ 'plju' => 'Java',
+ 'python' => 'Python',
+ 'pythonu' => 'Python',
+ 'plpython' => 'Python',
+ 'plpythonu' => 'Python',
+ 'ruby' => 'Ruby',
+ 'rubyu' => 'Ruby',
+ 'plruby' => 'Ruby',
+ 'plrubyu' => 'Ruby',
+ ];
+ // Predefined size types
+ public $predefined_size_types = ['abstime', 'aclitem', 'bigserial', 'boolean', 'bytea', 'cid', 'cidr', 'circle', 'date', 'float4', 'float8', 'gtsvector', 'inet', 'int2', 'int4', 'int8', 'macaddr', 'money', 'oid', 'path', 'polygon', 'refcursor', 'regclass', 'regoper', 'regoperator', 'regproc', 'regprocedure', 'regtype', 'reltime', 'serial', 'smgr', 'text', 'tid', 'tinterval', 'tsquery', 'tsvector', 'varbit', 'void', 'xid'];
+ // List of all legal privileges that can be applied to different types
+ // of objects.
+ public $privlist = [
+ 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
+ 'database' => ['CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'],
+ 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
+ 'language' => ['USAGE', 'ALL PRIVILEGES'],
+ 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
+ 'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
+ 'column' => ['SELECT', 'INSERT', 'UPDATE', 'REFERENCES', 'ALL PRIVILEGES'],
+ ];
+ // List of characters in acl lists and the privileges they
+ // refer to.
+ public $privmap = [
+ 'r' => 'SELECT',
+ 'w' => 'UPDATE',
+ 'a' => 'INSERT',
+ 'd' => 'DELETE',
+ 'D' => 'TRUNCATE',
+ 'R' => 'RULE',
+ 'x' => 'REFERENCES',
+ 't' => 'TRIGGER',
+ 'X' => 'EXECUTE',
+ 'U' => 'USAGE',
+ 'C' => 'CREATE',
+ 'T' => 'TEMPORARY',
+ 'c' => 'CONNECT',
+ ];
+ // Rule action types
+ public $rule_events = ['SELECT', 'INSERT', 'UPDATE', 'DELETE'];
+ // Select operators
+ public $selectOps = ['=' => 'i', '!=' => 'i', '<' => 'i', '>' => 'i', '<=' => 'i', '>=' => 'i',
+ '<<' => 'i', '>>' => 'i', '<<=' => 'i', '>>=' => 'i',
+ 'LIKE' => 'i', 'NOT LIKE' => 'i', 'ILIKE' => 'i', 'NOT ILIKE' => 'i', 'SIMILAR TO' => 'i',
+ 'NOT SIMILAR TO' => 'i', '~' => 'i', '!~' => 'i', '~*' => 'i', '!~*' => 'i',
+ 'IS NULL' => 'p', 'IS NOT NULL' => 'p', 'IN' => 'x', 'NOT IN' => 'x',
+ '@@' => 'i', '@@@' => 'i', '@>' => 'i', '<@' => 'i',
+ '@@ to_tsquery' => 't', '@@@ to_tsquery' => 't', '@> to_tsquery' => 't', '<@ to_tsquery' => 't',
+ '@@ plainto_tsquery' => 't', '@@@ plainto_tsquery' => 't', '@> plainto_tsquery' => 't', '<@ plainto_tsquery' => 't'];
+ // Array of allowed trigger events
+ public $triggerEvents = ['INSERT', 'UPDATE', 'DELETE', 'INSERT OR UPDATE', 'INSERT OR DELETE',
+ 'DELETE OR UPDATE', 'INSERT OR DELETE OR UPDATE'];
+ // When to execute the trigger
+ public $triggerExecTimes = ['BEFORE', 'AFTER'];
+ // How often to execute the trigger
+ public $triggerFrequency = ['ROW', 'STATEMENT'];
+ // Array of allowed type alignments
+ public $typAligns = ['char', 'int2', 'int4', 'double'];
+ // The default type alignment
+ public $typAlignDef = 'int4';
+ // Default index type
+ public $typIndexDef = 'BTREE';
+ // Array of allowed index types
+ public $typIndexes = ['BTREE', 'RTREE', 'GIST', 'GIN', 'HASH'];
+ // Array of allowed type storage attributes
+ public $typStorages = ['plain', 'external', 'extended', 'main'];
+ // The default type storage
+ public $typStorageDef = 'plain';
+
+ public function __construct(&$conn, $conf)
+ {
+ $this->prtrace('major_version', $this->major_version);
+ $this->conn = $conn;
+ $this->conf = $conf;
+ }
+
+ /**
+ * Fetch a URL (or array of URLs) for a given help page.
+ */
+ public function getHelp($help)
+ {
+ $this->getHelpPages();
+
+ if (isset($this->help_page[$help])) {
+ if (is_array($this->help_page[$help])) {
+ $urls = [];
+ foreach ($this->help_page[$help] as $link) {
+ $urls[] = $this->help_base . $link;
+ }
+ return $urls;
+ } else {
+ return $this->help_base . $this->help_page[$help];
+ }
+
+ } else {
+ return null;
+ }
+
+ }
+
+ /**
+ * get help page by instancing the corresponding help class
+ * if $this->help_page and $this->help_base are set, this function is a noop
+ */
+ public function getHelpPages()
+ {
+ if ($this->help_page === null || $this->help_base === null) {
+ $help_classname = '\PHPPgAdmin\Help\PostgresDoc' . $this->major_version;
+
+ $help_class = new $help_classname($this->conf, $this->major_version);
+
+ $this->help_base = $help_class->getHelpBase();
+ $this->help_page = $help_class->getHelpPage();
+
+ }
+
+ }
+
+ // Formatting functions
+
+ /**
+ * Cleans (escapes) a string
+ * @param $str The string to clean, by reference
+ * @return The cleaned string
+ */
+ public function clean(&$str)
+ {
+ if ($str === null) {
+ return null;
+ }
+
+ $str = str_replace("\r\n", "\n", $str);
+ $str = pg_escape_string($str);
+ return $str;
+ }
+
+ /**
+ * Cleans (escapes) an object name (eg. table, field)
+ * @param $str The string to clean, by reference
+ * @return The cleaned string
+ */
+ public function fieldClean(&$str)
+ {
+ if ($str === null) {
+ return null;
+ }
+
+ $str = str_replace('"', '""', $str);
+ return $str;
+ }
+
+ /**
+ * Cleans (escapes) an array of field names
+ * @param $arr The array to clean, by reference
+ * @return The cleaned array
+ */
+ public function fieldArrayClean(&$arr)
+ {
+ foreach ($arr as $k => $v) {
+ if ($v === null) {
+ continue;
+ }
+
+ $arr[$k] = str_replace('"', '""', $v);
+ }
+ return $arr;
+ }
+
+ /**
+ * Cleans (escapes) an array
+ * @param $arr The array to clean, by reference
+ * @return The cleaned array
+ */
+ public function arrayClean(&$arr)
+ {
+ foreach ($arr as $k => $v) {
+ if ($v === null) {
+ continue;
+ }
+
+ $arr[$k] = pg_escape_string($v);
+ }
+ return $arr;
+ }
+
+ /**
+ * Escapes bytea data for display on the screen
+ * @param $data The bytea data
+ * @return Data formatted for on-screen display
+ */
+ public function escapeBytea($data)
+ {
+ return htmlentities($data, ENT_QUOTES, 'UTF-8');
+ }
+
+ /**
+ * 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
+ * @param $extras An array of attributes name as key and attributes' values as value
+ */
+ public function printField($name, $value, $type, $extras = [])
+ {
+ $lang = $this->lang;
+
+ // Determine actions string
+ $extra_str = '';
+ foreach ($extras as $k => $v) {
+ $extra_str .= " {$k}=\"" . htmlspecialchars($v) . "\"";
+ }
+
+ switch (substr($type, 0, 9)) {
+ case 'bool':
+ case 'boolean':
+ if ($value !== null && $value == '') {
+ $value = null;
+ } elseif ($value == 'true') {
+ $value = 't';
+ } elseif ($value == 'false') {
+ $value = 'f';
+ }
+
+ // If value is null, 't' or 'f'...
+ if ($value === null || $value == 't' || $value == 'f') {
+ echo "<select name=\"", htmlspecialchars($name), "\"{$extra_str}>\n";
+ echo "<option value=\"\"", ($value === null) ? ' selected="selected"' : '', "></option>\n";
+ echo "<option value=\"t\"", ($value == 't') ? ' selected="selected"' : '', ">{$lang['strtrue']}</option>\n";
+ echo "<option value=\"f\"", ($value == 'f') ? ' selected="selected"' : '', ">{$lang['strfalse']}</option>\n";
+ echo "</select>\n";
+ } else {
+ echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=\"35\"{$extra_str} />\n";
+ }
+ break;
+ case 'bytea':
+ case 'bytea[]':
+ if (!is_null($value)) {
+ $value = $this->escapeBytea($value);
+ }
+ case 'text':
+ case 'text[]':
+ case 'json':
+ case 'jsonb':
+ case 'xml':
+ case 'xml[]':
+ $n = substr_count($value, "\n");
+ $n = $n < 5 ? 5 : $n;
+ $n = $n > 20 ? 20 : $n;
+ echo "<textarea name=\"", htmlspecialchars($name), "\" rows=\"{$n}\" cols=\"75\"{$extra_str}>\n";
+ echo htmlspecialchars($value);
+ echo "</textarea>\n";
+ break;
+ case 'character':
+ case 'character[]':
+ $n = substr_count($value, "\n");
+ $n = $n < 5 ? 5 : $n;
+ $n = $n > 20 ? 20 : $n;
+ echo "<textarea name=\"", htmlspecialchars($name), "\" rows=\"{$n}\" cols=\"35\"{$extra_str}>\n";
+ echo htmlspecialchars($value);
+ echo "</textarea>\n";
+ break;
+ default:
+ echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=\"35\"{$extra_str} />\n";
+ break;
+ }
+ }
+
+ /**
+ * Formats a value or expression for sql purposes
+ * @param $type The type of the field
+ * @param $format VALUE or EXPRESSION
+ * @param $value The actual value entered in the field. Can be NULL
+ * @return The suitably quoted and escaped value.
+ */
+ public function formatValue($type, $format, $value)
+ {
+ switch ($type) {
+ case 'bool':
+ case 'boolean':
+ if ($value == 't') {
+ return 'TRUE';
+ } elseif ($value == 'f') {
+ return 'FALSE';
+ } elseif ($value == '') {
+ return 'NULL';
+ } else {
+ return $value;
+ }
+
+ break;
+ default:
+ // Checking variable fields is difficult as there might be a size
+ // attribute...
+ if (strpos($type, 'time') === 0) {
+ // Assume it's one of the time types...
+ if ($value == '') {
+ return "''";
+ } elseif (strcasecmp($value, 'CURRENT_TIMESTAMP') == 0
+ || strcasecmp($value, 'CURRENT_TIME') == 0
+ || strcasecmp($value, 'CURRENT_DATE') == 0
+ || strcasecmp($value, 'LOCALTIME') == 0
+ || strcasecmp($value, 'LOCALTIMESTAMP') == 0) {
+ return $value;
+ } elseif ($format == 'EXPRESSION') {
+ return $value;
+ } else {
+ $this->clean($value);
+ return "'{$value}'";
+ }
+ } else {
+ if ($format == 'VALUE') {
+ $this->clean($value);
+ return "'{$value}'";
+ }
+ return $value;
+ }
+ }
+ }
+
+ /**
+ * Formats a type correctly for display. Postgres 7.0 had no 'format_type'
+ * built-in function, and hence we need to do it manually.
+ * @param $typname The name of the type
+ * @param $typmod The contents of the typmod field
+ */
+ public function formatType($typname, $typmod)
+ {
+ // This is a specific constant in the 7.0 source
+ $varhdrsz = 4;
+
+ // If the first character is an underscore, it's an array type
+ $is_array = false;
+ if (substr($typname, 0, 1) == '_') {
+ $is_array = true;
+ $typname = substr($typname, 1);
+ }
+
+ // Show lengths on bpchar and varchar
+ if ($typname == 'bpchar') {
+ $len = $typmod - $varhdrsz;
+ $temp = 'character';
+ if ($len > 1) {
+ $temp .= "({$len})";
+ }
+
+ } elseif ($typname == 'varchar') {
+ $temp = 'character varying';
+ if ($typmod != -1) {
+ $temp .= "(" . ($typmod - $varhdrsz) . ")";
+ }
+
+ } elseif ($typname == 'numeric') {
+ $temp = 'numeric';
+ if ($typmod != -1) {
+ $tmp_typmod = $typmod - $varhdrsz;
+ $precision = ($tmp_typmod >> 16) & 0xffff;
+ $scale = $tmp_typmod & 0xffff;
+ $temp .= "({$precision}, {$scale})";
+ }
+ } else {
+ $temp = $typname;
+ }
+
+ // Add array qualifier if it's an array
+ if ($is_array) {
+ $temp .= '[]';
+ }
+
+ return $temp;
+ }
+
+ // Help functions
+
+ // Database functions
+
+ /**
+ * Return all information about a particular database
+ * @param $database The name of the database to retrieve
+ * @return The database info
+ */
+ public function getDatabase($database)
+ {
+ $this->clean($database);
+ $sql = "SELECT * FROM pg_database WHERE datname='{$database}'";
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Return all database available on the server
+ * @param $currentdatabase database name that should be on top of the resultset
+ *
+ * @return A list of databases, sorted alphabetically
+ */
+ public function getDatabases($currentdatabase = null)
+ {
+ $conf = $this->conf;
+ $server_info = $this->server_info;
+
+ if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
+ $username = $server_info['username'];
+ $this->clean($username);
+ $clause = " AND pr.rolname='{$username}'";
+ } else {
+ $clause = '';
+ }
+ if (isset($server_info['useonlydefaultdb']) && $server_info['useonlydefaultdb']) {
+ $currentdatabase = $server_info['defaultdb'];
+ $clause .= " AND pdb.datname = '{$currentdatabase}' ";
+ }
+
+ if (isset($server_info['hiddendbs']) && $server_info['hiddendbs']) {
+ $hiddendbs = $server_info['hiddendbs'];
+ $not_in = "('" . implode("','", $hiddendbs) . "')";
+ $clause .= " AND pdb.datname NOT IN {$not_in} ";
+ }
+
+ if ($currentdatabase != null) {
+ $this->clean($currentdatabase);
+ $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
+ } else {
+ $orderby = "ORDER BY pdb.datname";
+ }
+
+ if (!$conf['show_system']) {
+ $where = ' AND NOT pdb.datistemplate';
+ } else {
+ $where = ' AND pdb.datallowconn';
+ }
+
+ $sql = "
SELECT pdb.datname AS datname, pr.rolname AS datowner, pg_encoding_to_char(encoding) AS datencoding,
(SELECT description FROM pg_catalog.pg_shdescription pd WHERE pdb.oid=pd.objoid AND pd.classoid='pg_database'::regclass) AS datcomment,
(SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=pdb.dattablespace) AS tablespace,
@@ -514,255 +544,265 @@ class Postgres extends ADODB_base {
{$clause}
{$orderby}";
- return $this->selectSet($sql);
- }
-
- /**
- * Return the database comment of a db from the shared description table
- * @param string $database the name of the database to get the comment for
- * @return recordset of the db comment info
- */
- function getDatabaseComment($database) {
- $this->clean($database);
- $sql = "SELECT description FROM pg_catalog.pg_database JOIN pg_catalog.pg_shdescription ON (oid=objoid AND classoid='pg_database'::regclass) WHERE pg_database.datname = '{$database}' ";
- return $this->selectSet($sql);
- }
-
- /**
- * Return the database owner of a db
- * @param string $database the name of the database to get the owner for
- * @return recordset of the db owner info
- */
- function getDatabaseOwner($database) {
- $this->clean($database);
- $sql = "SELECT usename FROM pg_user, pg_database WHERE pg_user.usesysid = pg_database.datdba AND pg_database.datname = '{$database}' ";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns the current database encoding
- * @return The encoding. eg. SQL_ASCII, UTF-8, etc.
- */
- function getDatabaseEncoding() {
- return pg_parameter_status($this->conn->_connectionID, 'server_encoding');
- }
-
- /**
- * Returns the current default_with_oids setting
- * @return default_with_oids setting
- */
- function getDefaultWithOid() {
-
- $sql = "SHOW default_with_oids";
-
- return $this->selectField($sql, 'default_with_oids');
- }
-
- /**
- * Creates a database
- * @param $database The name of the database to create
- * @param $encoding Encoding of the database
- * @param $tablespace (optional) The tablespace name
- * @return 0 success
- * @return -1 tablespace error
- * @return -2 comment error
- */
- function createDatabase($database, $encoding, $tablespace = '', $comment = '', $template = 'template1',
- $lc_collate = '', $lc_ctype = '') {
- $this->fieldClean($database);
- $this->clean($encoding);
- $this->fieldClean($tablespace);
- $this->fieldClean($template);
- $this->clean($lc_collate);
- $this->clean($lc_ctype);
-
- $sql = "CREATE DATABASE \"{$database}\" WITH TEMPLATE=\"{$template}\"";
-
- if ($encoding != '') {
- $sql .= " ENCODING='{$encoding}'";
- }
-
- if ($lc_collate != '') {
- $sql .= " LC_COLLATE='{$lc_collate}'";
- }
-
- if ($lc_ctype != '') {
- $sql .= " LC_CTYPE='{$lc_ctype}'";
- }
-
- if ($tablespace != '' && $this->hasTablespaces()) {
- $sql .= " TABLESPACE \"{$tablespace}\"";
- }
-
- $status = $this->execute($sql);
- if ($status != 0) {
- return -1;
- }
-
- if ($comment != '' && $this->hasSharedComments()) {
- $status = $this->setComment('DATABASE', $database, '', $comment);
- if ($status != 0) {
- return -2;
- }
-
- }
-
- return 0;
- }
-
- /**
- * Renames a database, note that this operation cannot be
- * performed on a database that is currently being connected to
- * @param string $oldName name of database to rename
- * @param string $newName new name of database
- * @return int 0 on success
- */
- function alterDatabaseRename($oldName, $newName) {
- $this->fieldClean($oldName);
- $this->fieldClean($newName);
-
- if ($oldName != $newName) {
- $sql = "ALTER DATABASE \"{$oldName}\" RENAME TO \"{$newName}\"";
- return $this->execute($sql);
- } else //just return success, we're not going to do anything
- {
- return 0;
- }
-
- }
-
- /**
- * Drops a database
- * @param $database The name of the database to drop
- * @return 0 success
- */
- function dropDatabase($database) {
- $this->fieldClean($database);
- $sql = "DROP DATABASE \"{$database}\"";
- return $this->execute($sql);
- }
-
- /**
- * Changes ownership of a database
- * This can only be done by a superuser or the owner of the database
- * @param string $dbName database to change ownership of
- * @param string $newOwner user that will own the database
- * @return int 0 on success
- */
- function alterDatabaseOwner($dbName, $newOwner) {
- $this->fieldClean($dbName);
- $this->fieldClean($newOwner);
-
- $sql = "ALTER DATABASE \"{$dbName}\" OWNER TO \"{$newOwner}\"";
- return $this->execute($sql);
- }
-
- /**
- * Alters a database
- * the multiple return vals are for postgres 8+ which support more functionality in alter database
- * @param $dbName The name of the database
- * @param $newName new name for the database
- * @param $newOwner The new owner for the database
- * @return 0 success
- * @return -1 transaction error
- * @return -2 owner error
- * @return -3 rename error
- * @return -4 comment error
- */
- function alterDatabase($dbName, $newName, $newOwner = '', $comment = '') {
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- if ($dbName != $newName) {
- $status = $this->alterDatabaseRename($dbName, $newName);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
- $dbName = $newName;
- }
-
- if ($newOwner != '') {
- $status = $this->alterDatabaseOwner($newName, $newOwner);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -2;
- }
- }
-
- $this->fieldClean($dbName);
- $status = $this->setComment('DATABASE', $dbName, '', $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -4;
- }
- return $this->endTransaction();
- }
-
- /**
- * Returns prepared transactions information
- * @param $database (optional) Find only prepared transactions executed in a specific database
- * @return A recordset
- */
- function getPreparedXacts($database = null) {
- if ($database === null) {
- $sql = "SELECT * FROM pg_prepared_xacts";
- } else {
- $this->clean($database);
- $sql = "SELECT transaction, gid, prepared, owner FROM pg_prepared_xacts
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Return the database comment of a db from the shared description table
+ * @param string $database the name of the database to get the comment for
+ * @return recordset of the db comment info
+ */
+ public function getDatabaseComment($database)
+ {
+ $this->clean($database);
+ $sql = "SELECT description FROM pg_catalog.pg_database JOIN pg_catalog.pg_shdescription ON (oid=objoid AND classoid='pg_database'::regclass) WHERE pg_database.datname = '{$database}' ";
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Return the database owner of a db
+ * @param string $database the name of the database to get the owner for
+ * @return recordset of the db owner info
+ */
+ public function getDatabaseOwner($database)
+ {
+ $this->clean($database);
+ $sql = "SELECT usename FROM pg_user, pg_database WHERE pg_user.usesysid = pg_database.datdba AND pg_database.datname = '{$database}' ";
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns the current database encoding
+ * @return The encoding. eg. SQL_ASCII, UTF-8, etc.
+ */
+ public function getDatabaseEncoding()
+ {
+ return pg_parameter_status($this->conn->_connectionID, 'server_encoding');
+ }
+
+ /**
+ * Returns the current default_with_oids setting
+ * @return default_with_oids setting
+ */
+ public function getDefaultWithOid()
+ {
+
+ $sql = "SHOW default_with_oids";
+
+ return $this->selectField($sql, 'default_with_oids');
+ }
+
+ /**
+ * Creates a database
+ * @param $database The name of the database to create
+ * @param $encoding Encoding of the database
+ * @param $tablespace (optional) The tablespace name
+ * @return 0 success
+ * @return -1 tablespace error
+ * @return -2 comment error
+ */
+ public function createDatabase($database, $encoding, $tablespace = '', $comment = '', $template = 'template1',
+ $lc_collate = '', $lc_ctype = '') {
+ $this->fieldClean($database);
+ $this->clean($encoding);
+ $this->fieldClean($tablespace);
+ $this->fieldClean($template);
+ $this->clean($lc_collate);
+ $this->clean($lc_ctype);
+
+ $sql = "CREATE DATABASE \"{$database}\" WITH TEMPLATE=\"{$template}\"";
+
+ if ($encoding != '') {
+ $sql .= " ENCODING='{$encoding}'";
+ }
+
+ if ($lc_collate != '') {
+ $sql .= " LC_COLLATE='{$lc_collate}'";
+ }
+
+ if ($lc_ctype != '') {
+ $sql .= " LC_CTYPE='{$lc_ctype}'";
+ }
+
+ if ($tablespace != '' && $this->hasTablespaces()) {
+ $sql .= " TABLESPACE \"{$tablespace}\"";
+ }
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ return -1;
+ }
+
+ if ($comment != '' && $this->hasSharedComments()) {
+ $status = $this->setComment('DATABASE', $database, '', $comment);
+ if ($status != 0) {
+ return -2;
+ }
+
+ }
+
+ return 0;
+ }
+
+ /**
+ * Renames a database, note that this operation cannot be
+ * performed on a database that is currently being connected to
+ * @param string $oldName name of database to rename
+ * @param string $newName new name of database
+ * @return int 0 on success
+ */
+ public function alterDatabaseRename($oldName, $newName)
+ {
+ $this->fieldClean($oldName);
+ $this->fieldClean($newName);
+
+ if ($oldName != $newName) {
+ $sql = "ALTER DATABASE \"{$oldName}\" RENAME TO \"{$newName}\"";
+ return $this->execute($sql);
+ } else //just return success, we're not going to do anything
+ {
+ return 0;
+ }
+
+ }
+
+ /**
+ * Drops a database
+ * @param $database The name of the database to drop
+ * @return 0 success
+ */
+ public function dropDatabase($database)
+ {
+ $this->fieldClean($database);
+ $sql = "DROP DATABASE \"{$database}\"";
+ return $this->execute($sql);
+ }
+
+ /**
+ * Changes ownership of a database
+ * This can only be done by a superuser or the owner of the database
+ * @param string $dbName database to change ownership of
+ * @param string $newOwner user that will own the database
+ * @return int 0 on success
+ */
+ public function alterDatabaseOwner($dbName, $newOwner)
+ {
+ $this->fieldClean($dbName);
+ $this->fieldClean($newOwner);
+
+ $sql = "ALTER DATABASE \"{$dbName}\" OWNER TO \"{$newOwner}\"";
+ return $this->execute($sql);
+ }
+
+ /**
+ * Alters a database
+ * the multiple return vals are for postgres 8+ which support more functionality in alter database
+ * @param $dbName The name of the database
+ * @param $newName new name for the database
+ * @param $newOwner The new owner for the database
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 owner error
+ * @return -3 rename error
+ * @return -4 comment error
+ */
+ public function alterDatabase($dbName, $newName, $newOwner = '', $comment = '')
+ {
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ if ($dbName != $newName) {
+ $status = $this->alterDatabaseRename($dbName, $newName);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+ $dbName = $newName;
+ }
+
+ if ($newOwner != '') {
+ $status = $this->alterDatabaseOwner($newName, $newOwner);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+ }
+
+ $this->fieldClean($dbName);
+ $status = $this->setComment('DATABASE', $dbName, '', $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -4;
+ }
+ return $this->endTransaction();
+ }
+
+ /**
+ * Returns prepared transactions information
+ * @param $database (optional) Find only prepared transactions executed in a specific database
+ * @return A recordset
+ */
+ public function getPreparedXacts($database = null)
+ {
+ if ($database === null) {
+ $sql = "SELECT * FROM pg_prepared_xacts";
+ } else {
+ $this->clean($database);
+ $sql = "SELECT transaction, gid, prepared, owner FROM pg_prepared_xacts
WHERE database='{$database}' ORDER BY owner";
- }
-
- return $this->selectSet($sql);
- }
-
- /**
- * Searches all system catalogs to find objects that match a certain name.
- * @param $term The search term
- * @param $filter The object type to restrict to ('' means no restriction)
- * @return A recordset
- */
- function findObject($term, $filter) {
- $conf = $this->conf;
-
- /*about escaping:
- * SET standard_conforming_string is not available before 8.2
- * So we must use PostgreSQL specific notation :/
- * E'' notation is not available before 8.1
- * $$ is available since 8.0
- * Nothing specific from 7.4
- */
-
- // Escape search term for ILIKE match
- $this->clean($term);
- $this->clean($filter);
- $term = str_replace('_', '\_', $term);
- $term = str_replace('%', '\%', $term);
-
- // Exclude system relations if necessary
- if (!$conf['show_system']) {
- // XXX: The mention of information_schema here is in the wrong place, but
- // it's the quickest fix to exclude the info schema from 7.4
- $where = " AND pn.nspname NOT LIKE \$_PATERN_\$pg\_%\$_PATERN_\$ AND pn.nspname != 'information_schema'";
- $lan_where = "AND pl.lanispl";
- } else {
- $where = '';
- $lan_where = '';
- }
-
- // Apply outer filter
- $sql = '';
- if ($filter != '') {
- $sql = "SELECT * FROM (";
- }
-
- $term = "\$_PATERN_\$%{$term}%\$_PATERN_\$";
-
- $sql .= "
+ }
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Searches all system catalogs to find objects that match a certain name.
+ * @param $term The search term
+ * @param $filter The object type to restrict to ('' means no restriction)
+ * @return A recordset
+ */
+ public function findObject($term, $filter)
+ {
+ $conf = $this->conf;
+
+ /*about escaping:
+ * SET standard_conforming_string is not available before 8.2
+ * So we must use PostgreSQL specific notation :/
+ * E'' notation is not available before 8.1
+ * $$ is available since 8.0
+ * Nothing specific from 7.4
+ */
+
+ // Escape search term for ILIKE match
+ $this->clean($term);
+ $this->clean($filter);
+ $term = str_replace('_', '\_', $term);
+ $term = str_replace('%', '\%', $term);
+
+ // Exclude system relations if necessary
+ if (!$conf['show_system']) {
+ // XXX: The mention of information_schema here is in the wrong place, but
+ // it's the quickest fix to exclude the info schema from 7.4
+ $where = " AND pn.nspname NOT LIKE \$_PATERN_\$pg\_%\$_PATERN_\$ AND pn.nspname != 'information_schema'";
+ $lan_where = "AND pl.lanispl";
+ } else {
+ $where = '';
+ $lan_where = '';
+ }
+
+ // Apply outer filter
+ $sql = '';
+ if ($filter != '') {
+ $sql = "SELECT * FROM (";
+ }
+
+ $term = "\$_PATERN_\$%{$term}%\$_PATERN_\$";
+
+ $sql .= "
SELECT 'SCHEMA' AS type, oid, NULL AS schemaname, NULL AS relname, nspname AS name
FROM pg_catalog.pg_namespace pn WHERE nspname ILIKE {$term} {$where}
UNION ALL
@@ -819,9 +859,9 @@ class Postgres extends ADODB_base {
WHERE c.relkind='v' AND r.rulename != '_RETURN' AND r.rulename ILIKE {$term} {$where}
";
- // Add advanced objects if show_advanced is set
- if ($conf['show_advanced']) {
- $sql .= "
+ // Add advanced objects if show_advanced is set
+ if ($conf['show_advanced']) {
+ $sql .= "
UNION ALL
SELECT CASE WHEN pt.typtype='d' THEN 'DOMAIN' ELSE 'TYPE' END, pt.oid, pn.nspname, NULL,
pt.typname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn
@@ -846,10 +886,10 @@ class Postgres extends ADODB_base {
pg_catalog.pg_namespace pn WHERE po.opcnamespace=pn.oid
AND po.opcname ILIKE {$term} {$where}
";
- }
- // Otherwise just add domains
- else {
- $sql .= "
+ }
+ // Otherwise just add domains
+ else {
+ $sql .= "
UNION ALL
SELECT 'DOMAIN', pt.oid, pn.nspname, NULL,
pt.typname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn
@@ -857,45 +897,47 @@ class Postgres extends ADODB_base {
AND (pt.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = pt.typrelid))
{$where}
";
- }
+ }
- if ($filter != '') {
- // We use like to make RULE, CONSTRAINT and COLUMN searches work
- $sql .= ") AS sub WHERE type LIKE '{$filter}%' ";
- }
+ if ($filter != '') {
+ // We use like to make RULE, CONSTRAINT and COLUMN searches work
+ $sql .= ") AS sub WHERE type LIKE '{$filter}%' ";
+ }
- $sql .= "ORDER BY type, schemaname, relname, name";
+ $sql .= "ORDER BY type, schemaname, relname, name";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns all available variable information.
- * @return A recordset
- */
- function getVariables() {
- $sql = "SHOW ALL";
+ /**
+ * Returns all available variable information.
+ * @return A recordset
+ */
+ public function getVariables()
+ {
+ $sql = "SHOW ALL";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Schema functons
+ // Schema functons
- /**
- * Return all schemas in the current database.
- * @return All schemas, sorted alphabetically
- */
- function getSchemas() {
- $conf = $this->conf;
+ /**
+ * Return all schemas in the current database.
+ * @return All schemas, sorted alphabetically
+ */
+ public function getSchemas()
+ {
+ $conf = $this->conf;
- if (!$conf['show_system']) {
- $where = "WHERE nspname NOT LIKE 'pg@_%' ESCAPE '@' AND nspname != 'information_schema'";
+ if (!$conf['show_system']) {
+ $where = "WHERE nspname NOT LIKE 'pg@_%' ESCAPE '@' AND nspname != 'information_schema'";
- } else {
- $where = "WHERE nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
- }
+ } else {
+ $where = "WHERE nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
+ }
- $sql = "
+ $sql = "
SELECT pn.nspname, pu.rolname AS nspowner,
pg_catalog.obj_description(pn.oid, 'pg_namespace') AS nspcomment
FROM pg_catalog.pg_namespace pn
@@ -903,233 +945,242 @@ class Postgres extends ADODB_base {
{$where}
ORDER BY nspname";
- return $this->selectSet($sql);
- }
-
- /**
- * Return all information relating to a schema
- * @param $schema The name of the schema
- * @return Schema information
- */
- function getSchemaByName($schema) {
- $this->clean($schema);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Return all information relating to a schema
+ * @param $schema The name of the schema
+ * @return Schema information
+ */
+ public function getSchemaByName($schema)
+ {
+ $this->clean($schema);
+ $sql = "
SELECT nspname, nspowner, r.rolname AS ownername, nspacl,
pg_catalog.obj_description(pn.oid, 'pg_namespace') as nspcomment
FROM pg_catalog.pg_namespace pn
LEFT JOIN pg_roles as r ON pn.nspowner = r.oid
WHERE nspname='{$schema}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Sets the current working schema. Will also set Class variable.
- * @param $schema The the name of the schema to work in
- * @return 0 success
- */
- function setSchema($schema) {
- // Get the current schema search path, including 'pg_catalog'.
- $search_path = $this->getSearchPath();
- // Prepend $schema to search path
- array_unshift($search_path, $schema);
- $status = $this->setSearchPath($search_path);
- if ($status == 0) {
- $this->_schema = $schema;
- return 0;
- } else {
- return $status;
- }
-
- }
-
- /**
- * Sets the current schema search path
- * @param $paths An array of schemas in required search order
- * @return 0 success
- * @return -1 Array not passed
- * @return -2 Array must contain at least one item
- */
- function setSearchPath($paths) {
- if (!is_array($paths)) {
- return -1;
- } elseif (sizeof($paths) == 0) {
- return -2;
- } elseif (sizeof($paths) == 1 && $paths[0] == '') {
- // Need to handle empty paths in some cases
- $paths[0] = 'pg_catalog';
- }
-
- // Loop over all the paths to check that none are empty
- $temp = [];
- foreach ($paths as $schema) {
- if ($schema != '') {
- $temp[] = $schema;
- }
-
- }
- $this->fieldArrayClean($temp);
-
- $sql = 'SET SEARCH_PATH TO "' . implode('","', $temp) . '"';
-
- return $this->execute($sql);
- }
-
- /**
- * Creates a new schema.
- * @param $schemaname The name of the schema to create
- * @param $authorization (optional) The username to create the schema for.
- * @param $comment (optional) If omitted, defaults to nothing
- * @return 0 success
- */
- function createSchema($schemaname, $authorization = '', $comment = '') {
- $this->fieldClean($schemaname);
- $this->fieldClean($authorization);
-
- $sql = "CREATE SCHEMA \"{$schemaname}\"";
- if ($authorization != '') {
- $sql .= " AUTHORIZATION \"{$authorization}\"";
- }
-
- if ($comment != '') {
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- }
-
- // Create the new schema
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Set the comment
- if ($comment != '') {
- $status = $this->setComment('SCHEMA', $schemaname, '', $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- return $this->endTransaction();
- }
-
- return 0;
- }
-
- /**
- * Updates a schema.
- * @param $schemaname The name of the schema to drop
- * @param $comment The new comment for this schema
- * @param $owner The new owner for this schema
- * @return 0 success
- */
- function updateSchema($schemaname, $comment, $name, $owner) {
- $this->fieldClean($schemaname);
- $this->fieldClean($name);
- $this->fieldClean($owner);
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $status = $this->setComment('SCHEMA', $schemaname, '', $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $schema_rs = $this->getSchemaByName($schemaname);
- /* Only if the owner change */
- if ($schema_rs->fields['ownername'] != $owner) {
- $sql = "ALTER SCHEMA \"{$schemaname}\" OWNER TO \"{$owner}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- // Only if the name has changed
- if ($name != $schemaname) {
- $sql = "ALTER SCHEMA \"{$schemaname}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Drops a schema.
- * @param $schemaname The name of the schema to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropSchema($schemaname, $cascade) {
- $this->fieldClean($schemaname);
-
- $sql = "DROP SCHEMA \"{$schemaname}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Return the current schema search path
- * @return Array of schema names
- */
- function getSearchPath() {
- $sql = 'SELECT current_schemas(false) AS search_path';
-
- return $this->phpArray($this->selectField($sql, 'search_path'));
- }
-
- // Table functions
-
- /**
- * Checks to see whether or not a table has a unique id column
- * @param $table The table name
- * @return True if it has a unique id, false otherwise
- * @return null error
- **/
- function hasObjectID($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "SELECT relhasoids FROM pg_catalog.pg_class WHERE relname='{$table}'
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Sets the current working schema. Will also set Class variable.
+ * @param $schema The the name of the schema to work in
+ * @return 0 success
+ */
+ public function setSchema($schema)
+ {
+ // Get the current schema search path, including 'pg_catalog'.
+ $search_path = $this->getSearchPath();
+ // Prepend $schema to search path
+ array_unshift($search_path, $schema);
+ $status = $this->setSearchPath($search_path);
+ if ($status == 0) {
+ $this->_schema = $schema;
+ return 0;
+ } else {
+ return $status;
+ }
+
+ }
+
+ /**
+ * Sets the current schema search path
+ * @param $paths An array of schemas in required search order
+ * @return 0 success
+ * @return -1 Array not passed
+ * @return -2 Array must contain at least one item
+ */
+ public function setSearchPath($paths)
+ {
+ if (!is_array($paths)) {
+ return -1;
+ } elseif (sizeof($paths) == 0) {
+ return -2;
+ } elseif (sizeof($paths) == 1 && $paths[0] == '') {
+ // Need to handle empty paths in some cases
+ $paths[0] = 'pg_catalog';
+ }
+
+ // Loop over all the paths to check that none are empty
+ $temp = [];
+ foreach ($paths as $schema) {
+ if ($schema != '') {
+ $temp[] = $schema;
+ }
+
+ }
+ $this->fieldArrayClean($temp);
+
+ $sql = 'SET SEARCH_PATH TO "' . implode('","', $temp) . '"';
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Creates a new schema.
+ * @param $schemaname The name of the schema to create
+ * @param $authorization (optional) The username to create the schema for.
+ * @param $comment (optional) If omitted, defaults to nothing
+ * @return 0 success
+ */
+ public function createSchema($schemaname, $authorization = '', $comment = '')
+ {
+ $this->fieldClean($schemaname);
+ $this->fieldClean($authorization);
+
+ $sql = "CREATE SCHEMA \"{$schemaname}\"";
+ if ($authorization != '') {
+ $sql .= " AUTHORIZATION \"{$authorization}\"";
+ }
+
+ if ($comment != '') {
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+
+ // Create the new schema
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Set the comment
+ if ($comment != '') {
+ $status = $this->setComment('SCHEMA', $schemaname, '', $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ return $this->endTransaction();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Updates a schema.
+ * @param $schemaname The name of the schema to drop
+ * @param $comment The new comment for this schema
+ * @param $owner The new owner for this schema
+ * @return 0 success
+ */
+ public function updateSchema($schemaname, $comment, $name, $owner)
+ {
+ $this->fieldClean($schemaname);
+ $this->fieldClean($name);
+ $this->fieldClean($owner);
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $status = $this->setComment('SCHEMA', $schemaname, '', $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $schema_rs = $this->getSchemaByName($schemaname);
+ /* Only if the owner change */
+ if ($schema_rs->fields['ownername'] != $owner) {
+ $sql = "ALTER SCHEMA \"{$schemaname}\" OWNER TO \"{$owner}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ // Only if the name has changed
+ if ($name != $schemaname) {
+ $sql = "ALTER SCHEMA \"{$schemaname}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Drops a schema.
+ * @param $schemaname The name of the schema to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropSchema($schemaname, $cascade)
+ {
+ $this->fieldClean($schemaname);
+
+ $sql = "DROP SCHEMA \"{$schemaname}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Return the current schema search path
+ * @return Array of schema names
+ */
+ public function getSearchPath()
+ {
+ $sql = 'SELECT current_schemas(false) AS search_path';
+
+ return $this->phpArray($this->selectField($sql, 'search_path'));
+ }
+
+ // Table functions
+
+ /**
+ * Checks to see whether or not a table has a unique id column
+ * @param $table The table name
+ * @return True if it has a unique id, false otherwise
+ * @return null error
+ **/
+ public function hasObjectID($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "SELECT relhasoids FROM pg_catalog.pg_class WHERE relname='{$table}'
AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname='{$c_schema}')";
- $rs = $this->selectSet($sql);
- if ($rs->recordCount() != 1) {
- return null;
- } else {
- $rs->fields['relhasoids'] = $this->phpBool($rs->fields['relhasoids']);
- return $rs->fields['relhasoids'];
- }
- }
-
- /**
- * Returns table information
- * @param $table The name of the table
- * @return A recordset
- */
- function getTable($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "
+ $rs = $this->selectSet($sql);
+ if ($rs->recordCount() != 1) {
+ return null;
+ } else {
+ $rs->fields['relhasoids'] = $this->phpBool($rs->fields['relhasoids']);
+ return $rs->fields['relhasoids'];
+ }
+ }
+
+ /**
+ * Returns table information
+ * @param $table The name of the table
+ * @return A recordset
+ */
+ public function getTable($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "
SELECT
c.relname, n.nspname, u.usename AS relowner,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment,
@@ -1142,25 +1193,26 @@ class Postgres extends ADODB_base {
AND n.oid = c.relnamespace
AND c.relname = '{$table}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Return all tables in current database (and schema)
- * @param $all True to fetch all tables, false for just in current schema
- * @return All tables, sorted alphabetically
- */
- function getTables($all = false) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- if ($all) {
- // Exclude pg_catalog and information_schema tables
- $sql = "SELECT schemaname AS nspname, tablename AS relname, tableowner AS relowner
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Return all tables in current database (and schema)
+ * @param $all True to fetch all tables, false for just in current schema
+ * @return All tables, sorted alphabetically
+ */
+ public function getTables($all = false)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ if ($all) {
+ // Exclude pg_catalog and information_schema tables
+ $sql = "SELECT schemaname AS nspname, tablename AS relname, tableowner AS relowner
FROM pg_catalog.pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
ORDER BY schemaname, tablename";
- } else {
- $sql = "SELECT c.relname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
+ } else {
+ $sql = "SELECT c.relname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment,
reltuples::bigint,
(SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=c.reltablespace) AS tablespace
@@ -1169,28 +1221,29 @@ class Postgres extends ADODB_base {
WHERE c.relkind = 'r'
AND nspname='{$c_schema}'
ORDER BY c.relname";
- }
-
- return $this->selectSet($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 = '') {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
- $this->clean($field);
-
- if ($field == '') {
- // This query is made much more complex by the addition of the 'attisserial' field.
- // The subquery to get that field checks to see if there is an internally dependent
- // sequence on the field.
- $sql = "
+ }
+
+ return $this->selectSet($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
+ */
+ public function getTableAttributes($table, $field = '')
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+ $this->clean($field);
+
+ if ($field == '') {
+ // This query is made much more complex by the addition of the 'attisserial' field.
+ // The subquery to get that field checks to see if there is an internally dependent
+ // sequence on the field.
+ $sql = "
SELECT
a.attname, a.attnum,
pg_catalog.format_type(a.atttypid, a.atttypmod) as type,
@@ -1219,8 +1272,8 @@ class Postgres extends ADODB_base {
nspname = '{$c_schema}'))
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum";
- } else {
- $sql = "
+ } else {
+ $sql = "
SELECT
a.attname, a.attnum,
pg_catalog.format_type(a.atttypid, a.atttypmod) as type,
@@ -1239,22 +1292,23 @@ class Postgres extends ADODB_base {
AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE
nspname = '{$c_schema}'))
AND a.attname = '{$field}'";
- }
-
- return $this->selectSet($sql);
- }
-
- /**
- * Finds the names and schemas of parent tables (in order)
- * @param $table The table to find the parents for
- * @return A recordset
- */
- function getTableParents($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "
+ }
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Finds the names and schemas of parent tables (in order)
+ * @param $table The table to find the parents for
+ * @return A recordset
+ */
+ public function getTableParents($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "
SELECT
pn.nspname, relname
FROM
@@ -1268,20 +1322,21 @@ class Postgres extends ADODB_base {
pi.inhseqno
";
- return $this->selectSet($sql);
- }
-
- /**
- * Finds the names and schemas of child tables
- * @param $table The table to find the children for
- * @return A recordset
- */
- function getTableChildren($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Finds the names and schemas of child tables
+ * @param $table The table to find the children for
+ * @return A recordset
+ */
+ public function getTableChildren($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "
SELECT
pn.nspname, relname
FROM
@@ -1293,1256 +1348,1278 @@ class Postgres extends ADODB_base {
AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = '{$c_schema}'))
";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns the SQL definition for the table.
- * @pre MUST be run within a transaction
- * @param $table The table to define
- * @param $clean True to issue drop command, false otherwise
- * @return A string containing the formatted SQL code
- * @return null On error
- */
- function getTableDefPrefix($table, $clean = false) {
- // Fetch table
- $t = $this->getTable($table);
- if (!is_object($t) || $t->recordCount() != 1) {
- $this->rollbackTransaction();
- return null;
- }
- $this->fieldClean($t->fields['relname']);
- $this->fieldClean($t->fields['nspname']);
-
- // Fetch attributes
- $atts = $this->getTableAttributes($table);
- if (!is_object($atts)) {
- $this->rollbackTransaction();
- return null;
- }
-
- // Fetch constraints
- $cons = $this->getConstraints($table);
- if (!is_object($cons)) {
- $this->rollbackTransaction();
- return null;
- }
-
- // Output a reconnect command to create the table as the correct user
- $sql = $this->getChangeUserSQL($t->fields['relowner']) . "\n\n";
-
- // Set schema search path
- $sql .= "SET search_path = \"{$t->fields['nspname']}\", pg_catalog;\n\n";
-
- // Begin CREATE TABLE definition
- $sql .= "-- Definition\n\n";
- // DROP TABLE must be fully qualified in case a table with the same name exists
- // in pg_catalog.
- if (!$clean) {
- $sql .= "-- ";
- }
-
- $sql .= "DROP TABLE ";
- $sql .= "\"{$t->fields['nspname']}\".\"{$t->fields['relname']}\";\n";
- $sql .= "CREATE TABLE \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" (\n";
-
- // Output all table columns
- $col_comments_sql = ''; // Accumulate comments on columns
- $num = $atts->recordCount() + $cons->recordCount();
- $i = 1;
- while (!$atts->EOF) {
- $this->fieldClean($atts->fields['attname']);
- $sql .= " \"{$atts->fields['attname']}\"";
- // Dump SERIAL and BIGSERIAL columns correctly
- if ($this->phpBool($atts->fields['attisserial']) &&
- ($atts->fields['type'] == 'integer' || $atts->fields['type'] == 'bigint')) {
- if ($atts->fields['type'] == 'integer') {
- $sql .= " SERIAL";
- } else {
- $sql .= " BIGSERIAL";
- }
-
- } else {
- $sql .= " " . $this->formatType($atts->fields['type'], $atts->fields['atttypmod']);
-
- // Add NOT NULL if necessary
- if ($this->phpBool($atts->fields['attnotnull'])) {
- $sql .= " NOT NULL";
- }
-
- // Add default if necessary
- if ($atts->fields['adsrc'] !== null) {
- $sql .= " DEFAULT {$atts->fields['adsrc']}";
- }
-
- }
-
- // Output comma or not
- if ($i < $num) {
- $sql .= ",\n";
- } else {
- $sql .= "\n";
- }
-
- // Does this column have a comment?
- if ($atts->fields['comment'] !== null) {
- $this->clean($atts->fields['comment']);
- $col_comments_sql .= "COMMENT ON COLUMN \"{$t->fields['relname']}\".\"{$atts->fields['attname']}\" IS '{$atts->fields['comment']}';\n";
- }
-
- $atts->moveNext();
- $i++;
- }
- // Output all table constraints
- while (!$cons->EOF) {
- $this->fieldClean($cons->fields['conname']);
- $sql .= " CONSTRAINT \"{$cons->fields['conname']}\" ";
- // Nasty hack to support pre-7.4 PostgreSQL
- if ($cons->fields['consrc'] !== null) {
- $sql .= $cons->fields['consrc'];
- } else {
- switch ($cons->fields['contype']) {
- case 'p':
- $keys = $this->getAttributeNames($table, explode(' ', $cons->fields['indkey']));
- $sql .= "PRIMARY KEY (" . join(',', $keys) . ")";
- break;
- case 'u':
- $keys = $this->getAttributeNames($table, explode(' ', $cons->fields['indkey']));
- $sql .= "UNIQUE (" . join(',', $keys) . ")";
- break;
- default:
- // Unrecognised constraint
- $this->rollbackTransaction();
- return null;
- }
- }
-
- // Output comma or not
- if ($i < $num) {
- $sql .= ",\n";
- } else {
- $sql .= "\n";
- }
-
- $cons->moveNext();
- $i++;
- }
-
- $sql .= ")";
-
- // @@@@ DUMP CLUSTERING INFORMATION
-
- // Inherits
- /*
- * XXX: This is currently commented out as handling inheritance isn't this simple.
- * You also need to make sure you don't dump inherited columns and defaults, as well
- * as inherited NOT NULL and CHECK constraints. So for the time being, we just do
- * not claim to support inheritance.
- $parents = $this->getTableParents($table);
- if ($parents->recordCount() > 0) {
- $sql .= " INHERITS (";
- while (!$parents->EOF) {
- $this->fieldClean($parents->fields['relname']);
- // Qualify the parent table if it's in another schema
- if ($parents->fields['schemaname'] != $this->_schema) {
- $this->fieldClean($parents->fields['schemaname']);
- $sql .= "\"{$parents->fields['schemaname']}\".";
- }
- $sql .= "\"{$parents->fields['relname']}\"";
-
- $parents->moveNext();
- if (!$parents->EOF) $sql .= ', ';
- }
- $sql .= ")";
- }
- */
-
- // Handle WITHOUT OIDS
- if ($this->hasObjectID($table)) {
- $sql .= " WITH OIDS";
- } else {
- $sql .= " WITHOUT OIDS";
- }
-
- $sql .= ";\n";
-
- // Column storage and statistics
- $atts->moveFirst();
- $first = true;
- while (!$atts->EOF) {
- $this->fieldClean($atts->fields['attname']);
- // Statistics first
- if ($atts->fields['attstattarget'] >= 0) {
- if ($first) {
- $sql .= "\n";
- $first = false;
- }
- $sql .= "ALTER TABLE ONLY \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" ALTER COLUMN \"{$atts->fields['attname']}\" SET STATISTICS {$atts->fields['attstattarget']};\n";
- }
- // Then storage
- if ($atts->fields['attstorage'] != $atts->fields['typstorage']) {
- switch ($atts->fields['attstorage']) {
- case 'p':
- $storage = 'PLAIN';
- break;
- case 'e':
- $storage = 'EXTERNAL';
- break;
- case 'm':
- $storage = 'MAIN';
- break;
- case 'x':
- $storage = 'EXTENDED';
- break;
- default:
- // Unknown storage type
- $this->rollbackTransaction();
- return null;
- }
- $sql .= "ALTER TABLE ONLY \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" ALTER COLUMN \"{$atts->fields['attname']}\" SET STORAGE {$storage};\n";
- }
-
- $atts->moveNext();
- }
-
- // Comment
- if ($t->fields['relcomment'] !== null) {
- $this->clean($t->fields['relcomment']);
- $sql .= "\n-- Comment\n\n";
- $sql .= "COMMENT ON TABLE \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" IS '{$t->fields['relcomment']}';\n";
- }
-
- // Add comments on columns, if any
- if ($col_comments_sql != '') {
- $sql .= $col_comments_sql;
- }
-
- // Privileges
- $privs = $this->getPrivileges($table, 'table');
- if (!is_array($privs)) {
- $this->rollbackTransaction();
- return null;
- }
-
- if (sizeof($privs) > 0) {
- $sql .= "\n-- Privileges\n\n";
- /*
- * Always start with REVOKE ALL FROM PUBLIC, so that we don't have to
- * wire-in knowledge about the default public privileges for different
- * kinds of objects.
- */
- $sql .= "REVOKE ALL ON TABLE \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" FROM PUBLIC;\n";
- foreach ($privs as $v) {
- // Get non-GRANT OPTION privs
- $nongrant = array_diff($v[2], $v[4]);
-
- // Skip empty or owner ACEs
- if (sizeof($v[2]) == 0 || ($v[0] == 'user' && $v[1] == $t->fields['relowner'])) {
- continue;
- }
-
- // Change user if necessary
- if ($this->hasGrantOption() && $v[3] != $t->fields['relowner']) {
- $grantor = $v[3];
- $this->clean($grantor);
- $sql .= "SET SESSION AUTHORIZATION '{$grantor}';\n";
- }
-
- // Output privileges with no GRANT OPTION
- $sql .= "GRANT " . join(', ', $nongrant) . " ON TABLE \"{$t->fields['relname']}\" TO ";
- switch ($v[0]) {
- case 'public':
- $sql .= "PUBLIC;\n";
- break;
- case 'user':
- $this->fieldClean($v[1]);
- $sql .= "\"{$v[1]}\";\n";
- break;
- case 'group':
- $this->fieldClean($v[1]);
- $sql .= "GROUP \"{$v[1]}\";\n";
- break;
- default:
- // Unknown privilege type - fail
- $this->rollbackTransaction();
- return null;
- }
-
- // Reset user if necessary
- if ($this->hasGrantOption() && $v[3] != $t->fields['relowner']) {
- $sql .= "RESET SESSION AUTHORIZATION;\n";
- }
-
- // Output privileges with GRANT OPTION
-
- // Skip empty or owner ACEs
- if (!$this->hasGrantOption() || sizeof($v[4]) == 0) {
- continue;
- }
-
- // Change user if necessary
- if ($this->hasGrantOption() && $v[3] != $t->fields['relowner']) {
- $grantor = $v[3];
- $this->clean($grantor);
- $sql .= "SET SESSION AUTHORIZATION '{$grantor}';\n";
- }
-
- $sql .= "GRANT " . join(', ', $v[4]) . " ON \"{$t->fields['relname']}\" TO ";
- switch ($v[0]) {
- case 'public':
- $sql .= "PUBLIC";
- break;
- case 'user':
- $this->fieldClean($v[1]);
- $sql .= "\"{$v[1]}\"";
- break;
- case 'group':
- $this->fieldClean($v[1]);
- $sql .= "GROUP \"{$v[1]}\"";
- break;
- default:
- // Unknown privilege type - fail
- return null;
- }
- $sql .= " WITH GRANT OPTION;\n";
-
- // Reset user if necessary
- if ($this->hasGrantOption() && $v[3] != $t->fields['relowner']) {
- $sql .= "RESET SESSION AUTHORIZATION;\n";
- }
-
- }
- }
-
- // Add a newline to separate data that follows (if any)
- $sql .= "\n";
-
- return $sql;
- }
-
- /**
- * Returns extra table definition information that is most usefully
- * dumped after the table contents for speed and efficiency reasons
- * @param $table The table to define
- * @return A string containing the formatted SQL code
- * @return null On error
- */
- function getTableDefSuffix($table) {
- $sql = '';
-
- // Indexes
- $indexes = $this->getIndexes($table);
- if (!is_object($indexes)) {
- $this->rollbackTransaction();
- return null;
- }
-
- if ($indexes->recordCount() > 0) {
- $sql .= "\n-- Indexes\n\n";
- while (!$indexes->EOF) {
- $sql .= $indexes->fields['inddef'] . ";\n";
-
- $indexes->moveNext();
- }
- }
-
- // Triggers
- $triggers = $this->getTriggers($table);
- if (!is_object($triggers)) {
- $this->rollbackTransaction();
- return null;
- }
-
- if ($triggers->recordCount() > 0) {
- $sql .= "\n-- Triggers\n\n";
- while (!$triggers->EOF) {
-
- $sql .= $triggers->fields['tgdef'];
- $sql .= ";\n";
-
- $triggers->moveNext();
- }
- }
-
- // Rules
- $rules = $this->getRules($table);
- if (!is_object($rules)) {
- $this->rollbackTransaction();
- return null;
- }
-
- if ($rules->recordCount() > 0) {
- $sql .= "\n-- Rules\n\n";
- while (!$rules->EOF) {
- $sql .= $rules->fields['definition'] . "\n";
-
- $rules->moveNext();
- }
- }
-
- return $sql;
- }
-
- /**
- * 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 $array An array of '' or '[]' for each type if it's an array or not
- * @param $length An array of field lengths
- * @param $notnull An array of not null
- * @param $default An array of default values
- * @param $withoutoids True if WITHOUT OIDS, false otherwise
- * @param $colcomment An array of comments
- * @param $comment Table comment
- * @param $tablespace The tablespace name ('' means none/default)
- * @param $uniquekey An Array indicating the fields that are unique (those indexes that are set)
- * @param $primarykey An Array indicating the field used for the primarykey (those indexes that are set)
- * @return 0 success
- * @return -1 no fields supplied
- */
- function createTable($name, $fields, $field, $type, $array, $length, $notnull,
- $default, $withoutoids, $colcomment, $tblcomment, $tablespace,
- $uniquekey, $primarykey) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- $found = false;
- $first = true;
- $comment_sql = ''; //Accumulate comments for the columns
- $sql = "CREATE TABLE \"{$f_schema}\".\"{$name}\" (";
- for ($i = 0; $i < $fields; $i++) {
- $this->fieldClean($field[$i]);
- $this->clean($type[$i]);
- $this->clean($length[$i]);
- $this->clean($colcomment[$i]);
-
- // Skip blank columns - for user convenience
- if ($field[$i] == '' || $type[$i] == '') {
- continue;
- }
-
- // If not the first column, add a comma
- if (!$first) {
- $sql .= ", ";
- } else {
- $first = false;
- }
-
- switch ($type[$i]) {
- // Have to account for weird placing of length for with/without
- // time zone types
- case 'timestamp with time zone':
- case 'timestamp without time zone':
- $qual = substr($type[$i], 9);
- $sql .= "\"{$field[$i]}\" timestamp";
- if ($length[$i] != '') {
- $sql .= "({$length[$i]})";
- }
-
- $sql .= $qual;
- break;
- case 'time with time zone':
- case 'time without time zone':
- $qual = substr($type[$i], 4);
- $sql .= "\"{$field[$i]}\" time";
- if ($length[$i] != '') {
- $sql .= "({$length[$i]})";
- }
-
- $sql .= $qual;
- break;
- default:
- $sql .= "\"{$field[$i]}\" {$type[$i]}";
- if ($length[$i] != '') {
- $sql .= "({$length[$i]})";
- }
-
- }
- // Add array qualifier if necessary
- if ($array[$i] == '[]') {
- $sql .= '[]';
- }
-
- // Add other qualifiers
- if (!isset($primarykey[$i])) {
- if (isset($uniquekey[$i])) {
- $sql .= " UNIQUE";
- }
-
- if (isset($notnull[$i])) {
- $sql .= " NOT NULL";
- }
-
- }
- if ($default[$i] != '') {
- $sql .= " DEFAULT {$default[$i]}";
- }
-
- if ($colcomment[$i] != '') {
- $comment_sql .= "COMMENT ON COLUMN \"{$name}\".\"{$field[$i]}\" IS '{$colcomment[$i]}';\n";
- }
-
- $found = true;
- }
-
- if (!$found) {
- return -1;
- }
-
- // PRIMARY KEY
- $primarykeycolumns = [];
- for ($i = 0; $i < $fields; $i++) {
- if (isset($primarykey[$i])) {
- $primarykeycolumns[] = "\"{$field[$i]}\"";
- }
- }
- if (count($primarykeycolumns) > 0) {
- $sql .= ", PRIMARY KEY (" . implode(", ", $primarykeycolumns) . ")";
- }
-
- $sql .= ")";
-
- // WITHOUT OIDS
- if ($withoutoids) {
- $sql .= ' WITHOUT OIDS';
- } else {
- $sql .= ' WITH OIDS';
- }
-
- // Tablespace
- if ($this->hasTablespaces() && $tablespace != '') {
- $this->fieldClean($tablespace);
- $sql .= " TABLESPACE \"{$tablespace}\"";
- }
-
- $status = $this->execute($sql);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
-
- if ($tblcomment != '') {
- $status = $this->setComment('TABLE', '', $name, $tblcomment, true);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- if ($comment_sql != '') {
- $status = $this->execute($comment_sql);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
- }
- return $this->endTransaction();
- }
-
- /**
- * Creates a new table in the database copying attribs and other properties from another table
- * @param $name The name of the table
- * @param $like an array giving the schema ans the name of the table from which attribs are copying from:
- * array(
- * 'table' => table name,
- * 'schema' => the schema name,
- * )
- * @param $defaults if true, copy the defaults values as well
- * @param $constraints if true, copy the constraints as well (CHECK on table & attr)
- * @param $tablespace The tablespace name ('' means none/default)
- */
- function createTableLike($name, $like, $defaults = false, $constraints = false, $idx = false, $tablespace = '') {
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
- $this->fieldClean($like['schema']);
- $this->fieldClean($like['table']);
- $like = "\"{$like['schema']}\".\"{$like['table']}\"";
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- $sql = "CREATE TABLE \"{$f_schema}\".\"{$name}\" (LIKE {$like}";
-
- if ($defaults) {
- $sql .= " INCLUDING DEFAULTS";
- }
-
- if ($this->hasCreateTableLikeWithConstraints() && $constraints) {
- $sql .= " INCLUDING CONSTRAINTS";
- }
-
- if ($this->hasCreateTableLikeWithIndexes() && $idx) {
- $sql .= " INCLUDING INDEXES";
- }
-
- $sql .= ")";
-
- if ($this->hasTablespaces() && $tablespace != '') {
- $this->fieldClean($tablespace);
- $sql .= " TABLESPACE \"{$tablespace}\"";
- }
-
- $status = $this->execute($sql);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Alter a table's name
- * /!\ this function is called from _alterTable which take care of escaping fields
- * @param $tblrs The table RecordSet returned by getTable()
- * @param $name The new table's name
- * @return 0 success
- */
- function alterTableName($tblrs, $name = null) {
- /* vars cleaned in _alterTable */
- // Rename (only if name has changed)
- if (!empty($name) && ($name != $tblrs->fields['relname'])) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$tblrs->fields['relname']}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status == 0) {
- $tblrs->fields['relname'] = $name;
- } else {
- return $status;
- }
-
- }
- return 0;
- }
-
- /**
- * Alter a table's owner
- * /!\ this function is called from _alterTable which take care of escaping fields
- * @param $tblrs The table RecordSet returned by getTable()
- * @param $name The new table's owner
- * @return 0 success
- */
- function alterTableOwner($tblrs, $owner = null) {
- /* vars cleaned in _alterTable */
- if (!empty($owner) && ($tblrs->fields['relowner'] != $owner)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- // If owner has been changed, then do the alteration. We are
- // careful to avoid this generally as changing owner is a
- // superuser only function.
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$tblrs->fields['relname']}\" OWNER TO \"{$owner}\"";
-
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Alter a table's tablespace
- * /!\ this function is called from _alterTable which take care of escaping fields
- * @param $tblrs The table RecordSet returned by getTable()
- * @param $name The new table's tablespace
- * @return 0 success
- */
- function alterTableTablespace($tblrs, $tablespace = null) {
- /* vars cleaned in _alterTable */
- if (!empty($tablespace) && ($tblrs->fields['tablespace'] != $tablespace)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
-
- // If tablespace has been changed, then do the alteration. We
- // don't want to do this unnecessarily.
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$tblrs->fields['relname']}\" SET TABLESPACE \"{$tablespace}\"";
-
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Alter a table's schema
- * /!\ this function is called from _alterTable which take care of escaping fields
- * @param $tblrs The table RecordSet returned by getTable()
- * @param $name The new table's schema
- * @return 0 success
- */
- function alterTableSchema($tblrs, $schema = null) {
- /* vars cleaned in _alterTable */
- if (!empty($schema) && ($tblrs->fields['nspname'] != $schema)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- // If tablespace has been changed, then do the alteration. We
- // don't want to do this unnecessarily.
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$tblrs->fields['relname']}\" SET SCHEMA \"{$schema}\"";
-
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Protected method which alter a table
- * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
- * @param $tblrs The table recordSet returned by getTable()
- * @param $name The new name for the table
- * @param $owner The new owner for the table
- * @param $schema The new schema for the table
- * @param $comment The comment on the table
- * @param $tablespace The new tablespace for the table ('' means leave as is)
- * @return 0 success
- * @return -3 rename error
- * @return -4 comment error
- * @return -5 owner error
- * @return -6 tablespace error
- * @return -7 schema error
- */
- protected
- function _alterTable($tblrs, $name, $owner, $schema, $comment, $tablespace) {
-
- $this->fieldArrayClean($tblrs->fields);
-
- // Comment
- $status = $this->setComment('TABLE', '', $tblrs->fields['relname'], $comment);
- if ($status != 0) {
- return -4;
- }
-
- // Owner
- $this->fieldClean($owner);
- $status = $this->alterTableOwner($tblrs, $owner);
- if ($status != 0) {
- return -5;
- }
-
- // Tablespace
- $this->fieldClean($tablespace);
- $status = $this->alterTableTablespace($tblrs, $tablespace);
- if ($status != 0) {
- return -6;
- }
-
- // Rename
- $this->fieldClean($name);
- $status = $this->alterTableName($tblrs, $name);
- if ($status != 0) {
- return -3;
- }
-
- // Schema
- $this->fieldClean($schema);
- $status = $this->alterTableSchema($tblrs, $schema);
- if ($status != 0) {
- return -7;
- }
-
- return 0;
- }
-
- /**
- * Alter table properties
- * @param $table The name of the table
- * @param $name The new name for the table
- * @param $owner The new owner for the table
- * @param $schema The new schema for the table
- * @param $comment The comment on the table
- * @param $tablespace The new tablespace for the table ('' means leave as is)
- * @return 0 success
- * @return -1 transaction error
- * @return -2 get existing table error
- * @return $this->_alterTable error code
- */
- function alterTable($table, $name, $owner, $schema, $comment, $tablespace) {
-
- $data = $this->getTable($table);
-
- if ($data->recordCount() != 1) {
- return -2;
- }
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $status = $this->_alterTable($data, $name, $owner, $schema, $comment, $tablespace);
-
- if ($status != 0) {
- $this->rollbackTransaction();
- return $status;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Returns the SQL for changing the current user
- * @param $user The user to change to
- * @return The SQL
- */
- function getChangeUserSQL($user) {
- $this->clean($user);
- return "SET SESSION AUTHORIZATION '{$user}';";
- }
-
- /**
- * Given an array of attnums and a relation, returns an array mapping
- * attribute number to attribute name.
- * @param $table The table to get attributes for
- * @param $atts An array of attribute numbers
- * @return An array mapping attnum to attname
- * @return -1 $atts must be an array
- * @return -2 wrong number of attributes found
- */
- function getAttributeNames($table, $atts) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
- $this->arrayClean($atts);
-
- if (!is_array($atts)) {
- return -1;
- }
-
- if (sizeof($atts) == 0) {
- return [];
- }
-
- $sql = "SELECT attnum, attname FROM pg_catalog.pg_attribute WHERE
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns the SQL definition for the table.
+ * @pre MUST be run within a transaction
+ * @param $table The table to define
+ * @param $clean True to issue drop command, false otherwise
+ * @return A string containing the formatted SQL code
+ * @return null On error
+ */
+ public function getTableDefPrefix($table, $clean = false)
+ {
+ // Fetch table
+ $t = $this->getTable($table);
+ if (!is_object($t) || $t->recordCount() != 1) {
+ $this->rollbackTransaction();
+ return null;
+ }
+ $this->fieldClean($t->fields['relname']);
+ $this->fieldClean($t->fields['nspname']);
+
+ // Fetch attributes
+ $atts = $this->getTableAttributes($table);
+ if (!is_object($atts)) {
+ $this->rollbackTransaction();
+ return null;
+ }
+
+ // Fetch constraints
+ $cons = $this->getConstraints($table);
+ if (!is_object($cons)) {
+ $this->rollbackTransaction();
+ return null;
+ }
+
+ // Output a reconnect command to create the table as the correct user
+ $sql = $this->getChangeUserSQL($t->fields['relowner']) . "\n\n";
+
+ // Set schema search path
+ $sql .= "SET search_path = \"{$t->fields['nspname']}\", pg_catalog;\n\n";
+
+ // Begin CREATE TABLE definition
+ $sql .= "-- Definition\n\n";
+ // DROP TABLE must be fully qualified in case a table with the same name exists
+ // in pg_catalog.
+ if (!$clean) {
+ $sql .= "-- ";
+ }
+
+ $sql .= "DROP TABLE ";
+ $sql .= "\"{$t->fields['nspname']}\".\"{$t->fields['relname']}\";\n";
+ $sql .= "CREATE TABLE \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" (\n";
+
+ // Output all table columns
+ $col_comments_sql = ''; // Accumulate comments on columns
+ $num = $atts->recordCount() + $cons->recordCount();
+ $i = 1;
+ while (!$atts->EOF) {
+ $this->fieldClean($atts->fields['attname']);
+ $sql .= " \"{$atts->fields['attname']}\"";
+ // Dump SERIAL and BIGSERIAL columns correctly
+ if ($this->phpBool($atts->fields['attisserial']) &&
+ ($atts->fields['type'] == 'integer' || $atts->fields['type'] == 'bigint')) {
+ if ($atts->fields['type'] == 'integer') {
+ $sql .= " SERIAL";
+ } else {
+ $sql .= " BIGSERIAL";
+ }
+
+ } else {
+ $sql .= " " . $this->formatType($atts->fields['type'], $atts->fields['atttypmod']);
+
+ // Add NOT NULL if necessary
+ if ($this->phpBool($atts->fields['attnotnull'])) {
+ $sql .= " NOT NULL";
+ }
+
+ // Add default if necessary
+ if ($atts->fields['adsrc'] !== null) {
+ $sql .= " DEFAULT {$atts->fields['adsrc']}";
+ }
+
+ }
+
+ // Output comma or not
+ if ($i < $num) {
+ $sql .= ",\n";
+ } else {
+ $sql .= "\n";
+ }
+
+ // Does this column have a comment?
+ if ($atts->fields['comment'] !== null) {
+ $this->clean($atts->fields['comment']);
+ $col_comments_sql .= "COMMENT ON COLUMN \"{$t->fields['relname']}\".\"{$atts->fields['attname']}\" IS '{$atts->fields['comment']}';\n";
+ }
+
+ $atts->moveNext();
+ $i++;
+ }
+ // Output all table constraints
+ while (!$cons->EOF) {
+ $this->fieldClean($cons->fields['conname']);
+ $sql .= " CONSTRAINT \"{$cons->fields['conname']}\" ";
+ // Nasty hack to support pre-7.4 PostgreSQL
+ if ($cons->fields['consrc'] !== null) {
+ $sql .= $cons->fields['consrc'];
+ } else {
+ switch ($cons->fields['contype']) {
+ case 'p':
+ $keys = $this->getAttributeNames($table, explode(' ', $cons->fields['indkey']));
+ $sql .= "PRIMARY KEY (" . join(',', $keys) . ")";
+ break;
+ case 'u':
+ $keys = $this->getAttributeNames($table, explode(' ', $cons->fields['indkey']));
+ $sql .= "UNIQUE (" . join(',', $keys) . ")";
+ break;
+ default:
+ // Unrecognised constraint
+ $this->rollbackTransaction();
+ return null;
+ }
+ }
+
+ // Output comma or not
+ if ($i < $num) {
+ $sql .= ",\n";
+ } else {
+ $sql .= "\n";
+ }
+
+ $cons->moveNext();
+ $i++;
+ }
+
+ $sql .= ")";
+
+ // @@@@ DUMP CLUSTERING INFORMATION
+
+ // Inherits
+ /*
+ * XXX: This is currently commented out as handling inheritance isn't this simple.
+ * You also need to make sure you don't dump inherited columns and defaults, as well
+ * as inherited NOT NULL and CHECK constraints. So for the time being, we just do
+ * not claim to support inheritance.
+ $parents = $this->getTableParents($table);
+ if ($parents->recordCount() > 0) {
+ $sql .= " INHERITS (";
+ while (!$parents->EOF) {
+ $this->fieldClean($parents->fields['relname']);
+ // Qualify the parent table if it's in another schema
+ if ($parents->fields['schemaname'] != $this->_schema) {
+ $this->fieldClean($parents->fields['schemaname']);
+ $sql .= "\"{$parents->fields['schemaname']}\".";
+ }
+ $sql .= "\"{$parents->fields['relname']}\"";
+
+ $parents->moveNext();
+ if (!$parents->EOF) $sql .= ', ';
+ }
+ $sql .= ")";
+ }
+ */
+
+ // Handle WITHOUT OIDS
+ if ($this->hasObjectID($table)) {
+ $sql .= " WITH OIDS";
+ } else {
+ $sql .= " WITHOUT OIDS";
+ }
+
+ $sql .= ";\n";
+
+ // Column storage and statistics
+ $atts->moveFirst();
+ $first = true;
+ while (!$atts->EOF) {
+ $this->fieldClean($atts->fields['attname']);
+ // Statistics first
+ if ($atts->fields['attstattarget'] >= 0) {
+ if ($first) {
+ $sql .= "\n";
+ $first = false;
+ }
+ $sql .= "ALTER TABLE ONLY \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" ALTER COLUMN \"{$atts->fields['attname']}\" SET STATISTICS {$atts->fields['attstattarget']};\n";
+ }
+ // Then storage
+ if ($atts->fields['attstorage'] != $atts->fields['typstorage']) {
+ switch ($atts->fields['attstorage']) {
+ case 'p':
+ $storage = 'PLAIN';
+ break;
+ case 'e':
+ $storage = 'EXTERNAL';
+ break;
+ case 'm':
+ $storage = 'MAIN';
+ break;
+ case 'x':
+ $storage = 'EXTENDED';
+ break;
+ default:
+ // Unknown storage type
+ $this->rollbackTransaction();
+ return null;
+ }
+ $sql .= "ALTER TABLE ONLY \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" ALTER COLUMN \"{$atts->fields['attname']}\" SET STORAGE {$storage};\n";
+ }
+
+ $atts->moveNext();
+ }
+
+ // Comment
+ if ($t->fields['relcomment'] !== null) {
+ $this->clean($t->fields['relcomment']);
+ $sql .= "\n-- Comment\n\n";
+ $sql .= "COMMENT ON TABLE \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" IS '{$t->fields['relcomment']}';\n";
+ }
+
+ // Add comments on columns, if any
+ if ($col_comments_sql != '') {
+ $sql .= $col_comments_sql;
+ }
+
+ // Privileges
+ $privs = $this->getPrivileges($table, 'table');
+ if (!is_array($privs)) {
+ $this->rollbackTransaction();
+ return null;
+ }
+
+ if (sizeof($privs) > 0) {
+ $sql .= "\n-- Privileges\n\n";
+ /*
+ * Always start with REVOKE ALL FROM PUBLIC, so that we don't have to
+ * wire-in knowledge about the default public privileges for different
+ * kinds of objects.
+ */
+ $sql .= "REVOKE ALL ON TABLE \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" FROM PUBLIC;\n";
+ foreach ($privs as $v) {
+ // Get non-GRANT OPTION privs
+ $nongrant = array_diff($v[2], $v[4]);
+
+ // Skip empty or owner ACEs
+ if (sizeof($v[2]) == 0 || ($v[0] == 'user' && $v[1] == $t->fields['relowner'])) {
+ continue;
+ }
+
+ // Change user if necessary
+ if ($this->hasGrantOption() && $v[3] != $t->fields['relowner']) {
+ $grantor = $v[3];
+ $this->clean($grantor);
+ $sql .= "SET SESSION AUTHORIZATION '{$grantor}';\n";
+ }
+
+ // Output privileges with no GRANT OPTION
+ $sql .= "GRANT " . join(', ', $nongrant) . " ON TABLE \"{$t->fields['relname']}\" TO ";
+ switch ($v[0]) {
+ case 'public':
+ $sql .= "PUBLIC;\n";
+ break;
+ case 'user':
+ $this->fieldClean($v[1]);
+ $sql .= "\"{$v[1]}\";\n";
+ break;
+ case 'group':
+ $this->fieldClean($v[1]);
+ $sql .= "GROUP \"{$v[1]}\";\n";
+ break;
+ default:
+ // Unknown privilege type - fail
+ $this->rollbackTransaction();
+ return null;
+ }
+
+ // Reset user if necessary
+ if ($this->hasGrantOption() && $v[3] != $t->fields['relowner']) {
+ $sql .= "RESET SESSION AUTHORIZATION;\n";
+ }
+
+ // Output privileges with GRANT OPTION
+
+ // Skip empty or owner ACEs
+ if (!$this->hasGrantOption() || sizeof($v[4]) == 0) {
+ continue;
+ }
+
+ // Change user if necessary
+ if ($this->hasGrantOption() && $v[3] != $t->fields['relowner']) {
+ $grantor = $v[3];
+ $this->clean($grantor);
+ $sql .= "SET SESSION AUTHORIZATION '{$grantor}';\n";
+ }
+
+ $sql .= "GRANT " . join(', ', $v[4]) . " ON \"{$t->fields['relname']}\" TO ";
+ switch ($v[0]) {
+ case 'public':
+ $sql .= "PUBLIC";
+ break;
+ case 'user':
+ $this->fieldClean($v[1]);
+ $sql .= "\"{$v[1]}\"";
+ break;
+ case 'group':
+ $this->fieldClean($v[1]);
+ $sql .= "GROUP \"{$v[1]}\"";
+ break;
+ default:
+ // Unknown privilege type - fail
+ return null;
+ }
+ $sql .= " WITH GRANT OPTION;\n";
+
+ // Reset user if necessary
+ if ($this->hasGrantOption() && $v[3] != $t->fields['relowner']) {
+ $sql .= "RESET SESSION AUTHORIZATION;\n";
+ }
+
+ }
+ }
+
+ // Add a newline to separate data that follows (if any)
+ $sql .= "\n";
+
+ return $sql;
+ }
+
+ /**
+ * Returns extra table definition information that is most usefully
+ * dumped after the table contents for speed and efficiency reasons
+ * @param $table The table to define
+ * @return A string containing the formatted SQL code
+ * @return null On error
+ */
+ public function getTableDefSuffix($table)
+ {
+ $sql = '';
+
+ // Indexes
+ $indexes = $this->getIndexes($table);
+ if (!is_object($indexes)) {
+ $this->rollbackTransaction();
+ return null;
+ }
+
+ if ($indexes->recordCount() > 0) {
+ $sql .= "\n-- Indexes\n\n";
+ while (!$indexes->EOF) {
+ $sql .= $indexes->fields['inddef'] . ";\n";
+
+ $indexes->moveNext();
+ }
+ }
+
+ // Triggers
+ $triggers = $this->getTriggers($table);
+ if (!is_object($triggers)) {
+ $this->rollbackTransaction();
+ return null;
+ }
+
+ if ($triggers->recordCount() > 0) {
+ $sql .= "\n-- Triggers\n\n";
+ while (!$triggers->EOF) {
+
+ $sql .= $triggers->fields['tgdef'];
+ $sql .= ";\n";
+
+ $triggers->moveNext();
+ }
+ }
+
+ // Rules
+ $rules = $this->getRules($table);
+ if (!is_object($rules)) {
+ $this->rollbackTransaction();
+ return null;
+ }
+
+ if ($rules->recordCount() > 0) {
+ $sql .= "\n-- Rules\n\n";
+ while (!$rules->EOF) {
+ $sql .= $rules->fields['definition'] . "\n";
+
+ $rules->moveNext();
+ }
+ }
+
+ return $sql;
+ }
+
+ /**
+ * 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 $array An array of '' or '[]' for each type if it's an array or not
+ * @param $length An array of field lengths
+ * @param $notnull An array of not null
+ * @param $default An array of default values
+ * @param $withoutoids True if WITHOUT OIDS, false otherwise
+ * @param $colcomment An array of comments
+ * @param $comment Table comment
+ * @param $tablespace The tablespace name ('' means none/default)
+ * @param $uniquekey An Array indicating the fields that are unique (those indexes that are set)
+ * @param $primarykey An Array indicating the field used for the primarykey (those indexes that are set)
+ * @return 0 success
+ * @return -1 no fields supplied
+ */
+ public function createTable($name, $fields, $field, $type, $array, $length, $notnull,
+ $default, $withoutoids, $colcomment, $tblcomment, $tablespace,
+ $uniquekey, $primarykey) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ $found = false;
+ $first = true;
+ $comment_sql = ''; //Accumulate comments for the columns
+ $sql = "CREATE TABLE \"{$f_schema}\".\"{$name}\" (";
+ for ($i = 0; $i < $fields; $i++) {
+ $this->fieldClean($field[$i]);
+ $this->clean($type[$i]);
+ $this->clean($length[$i]);
+ $this->clean($colcomment[$i]);
+
+ // Skip blank columns - for user convenience
+ if ($field[$i] == '' || $type[$i] == '') {
+ continue;
+ }
+
+ // If not the first column, add a comma
+ if (!$first) {
+ $sql .= ", ";
+ } else {
+ $first = false;
+ }
+
+ switch ($type[$i]) {
+ // Have to account for weird placing of length for with/without
+ // time zone types
+ case 'timestamp with time zone':
+ case 'timestamp without time zone':
+ $qual = substr($type[$i], 9);
+ $sql .= "\"{$field[$i]}\" timestamp";
+ if ($length[$i] != '') {
+ $sql .= "({$length[$i]})";
+ }
+
+ $sql .= $qual;
+ break;
+ case 'time with time zone':
+ case 'time without time zone':
+ $qual = substr($type[$i], 4);
+ $sql .= "\"{$field[$i]}\" time";
+ if ($length[$i] != '') {
+ $sql .= "({$length[$i]})";
+ }
+
+ $sql .= $qual;
+ break;
+ default:
+ $sql .= "\"{$field[$i]}\" {$type[$i]}";
+ if ($length[$i] != '') {
+ $sql .= "({$length[$i]})";
+ }
+
+ }
+ // Add array qualifier if necessary
+ if ($array[$i] == '[]') {
+ $sql .= '[]';
+ }
+
+ // Add other qualifiers
+ if (!isset($primarykey[$i])) {
+ if (isset($uniquekey[$i])) {
+ $sql .= " UNIQUE";
+ }
+
+ if (isset($notnull[$i])) {
+ $sql .= " NOT NULL";
+ }
+
+ }
+ if ($default[$i] != '') {
+ $sql .= " DEFAULT {$default[$i]}";
+ }
+
+ if ($colcomment[$i] != '') {
+ $comment_sql .= "COMMENT ON COLUMN \"{$name}\".\"{$field[$i]}\" IS '{$colcomment[$i]}';\n";
+ }
+
+ $found = true;
+ }
+
+ if (!$found) {
+ return -1;
+ }
+
+ // PRIMARY KEY
+ $primarykeycolumns = [];
+ for ($i = 0; $i < $fields; $i++) {
+ if (isset($primarykey[$i])) {
+ $primarykeycolumns[] = "\"{$field[$i]}\"";
+ }
+ }
+ if (count($primarykeycolumns) > 0) {
+ $sql .= ", PRIMARY KEY (" . implode(", ", $primarykeycolumns) . ")";
+ }
+
+ $sql .= ")";
+
+ // WITHOUT OIDS
+ if ($withoutoids) {
+ $sql .= ' WITHOUT OIDS';
+ } else {
+ $sql .= ' WITH OIDS';
+ }
+
+ // Tablespace
+ if ($this->hasTablespaces() && $tablespace != '') {
+ $this->fieldClean($tablespace);
+ $sql .= " TABLESPACE \"{$tablespace}\"";
+ }
+
+ $status = $this->execute($sql);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ if ($tblcomment != '') {
+ $status = $this->setComment('TABLE', '', $name, $tblcomment, true);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ if ($comment_sql != '') {
+ $status = $this->execute($comment_sql);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+ return $this->endTransaction();
+ }
+
+ /**
+ * Creates a new table in the database copying attribs and other properties from another table
+ * @param $name The name of the table
+ * @param $like an array giving the schema ans the name of the table from which attribs are copying from:
+ * array(
+ * 'table' => table name,
+ * 'schema' => the schema name,
+ * )
+ * @param $defaults if true, copy the defaults values as well
+ * @param $constraints if true, copy the constraints as well (CHECK on table & attr)
+ * @param $tablespace The tablespace name ('' means none/default)
+ */
+ public function createTableLike($name, $like, $defaults = false, $constraints = false, $idx = false, $tablespace = '')
+ {
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+ $this->fieldClean($like['schema']);
+ $this->fieldClean($like['table']);
+ $like = "\"{$like['schema']}\".\"{$like['table']}\"";
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ $sql = "CREATE TABLE \"{$f_schema}\".\"{$name}\" (LIKE {$like}";
+
+ if ($defaults) {
+ $sql .= " INCLUDING DEFAULTS";
+ }
+
+ if ($this->hasCreateTableLikeWithConstraints() && $constraints) {
+ $sql .= " INCLUDING CONSTRAINTS";
+ }
+
+ if ($this->hasCreateTableLikeWithIndexes() && $idx) {
+ $sql .= " INCLUDING INDEXES";
+ }
+
+ $sql .= ")";
+
+ if ($this->hasTablespaces() && $tablespace != '') {
+ $this->fieldClean($tablespace);
+ $sql .= " TABLESPACE \"{$tablespace}\"";
+ }
+
+ $status = $this->execute($sql);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Alter a table's name
+ * /!\ this function is called from _alterTable which take care of escaping fields
+ * @param $tblrs The table RecordSet returned by getTable()
+ * @param $name The new table's name
+ * @return 0 success
+ */
+ public function alterTableName($tblrs, $name = null)
+ {
+ /* vars cleaned in _alterTable */
+ // Rename (only if name has changed)
+ if (!empty($name) && ($name != $tblrs->fields['relname'])) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$tblrs->fields['relname']}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status == 0) {
+ $tblrs->fields['relname'] = $name;
+ } else {
+ return $status;
+ }
+
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a table's owner
+ * /!\ this function is called from _alterTable which take care of escaping fields
+ * @param $tblrs The table RecordSet returned by getTable()
+ * @param $name The new table's owner
+ * @return 0 success
+ */
+ public function alterTableOwner($tblrs, $owner = null)
+ {
+ /* vars cleaned in _alterTable */
+ if (!empty($owner) && ($tblrs->fields['relowner'] != $owner)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ // If owner has been changed, then do the alteration. We are
+ // careful to avoid this generally as changing owner is a
+ // superuser only function.
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$tblrs->fields['relname']}\" OWNER TO \"{$owner}\"";
+
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a table's tablespace
+ * /!\ this function is called from _alterTable which take care of escaping fields
+ * @param $tblrs The table RecordSet returned by getTable()
+ * @param $name The new table's tablespace
+ * @return 0 success
+ */
+ public function alterTableTablespace($tblrs, $tablespace = null)
+ {
+ /* vars cleaned in _alterTable */
+ if (!empty($tablespace) && ($tblrs->fields['tablespace'] != $tablespace)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+
+ // If tablespace has been changed, then do the alteration. We
+ // don't want to do this unnecessarily.
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$tblrs->fields['relname']}\" SET TABLESPACE \"{$tablespace}\"";
+
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a table's schema
+ * /!\ this function is called from _alterTable which take care of escaping fields
+ * @param $tblrs The table RecordSet returned by getTable()
+ * @param $name The new table's schema
+ * @return 0 success
+ */
+ public function alterTableSchema($tblrs, $schema = null)
+ {
+ /* vars cleaned in _alterTable */
+ if (!empty($schema) && ($tblrs->fields['nspname'] != $schema)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ // If tablespace has been changed, then do the alteration. We
+ // don't want to do this unnecessarily.
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$tblrs->fields['relname']}\" SET SCHEMA \"{$schema}\"";
+
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Protected method which alter a table
+ * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
+ * @param $tblrs The table recordSet returned by getTable()
+ * @param $name The new name for the table
+ * @param $owner The new owner for the table
+ * @param $schema The new schema for the table
+ * @param $comment The comment on the table
+ * @param $tablespace The new tablespace for the table ('' means leave as is)
+ * @return 0 success
+ * @return -3 rename error
+ * @return -4 comment error
+ * @return -5 owner error
+ * @return -6 tablespace error
+ * @return -7 schema error
+ */
+ protected function _alterTable($tblrs, $name, $owner, $schema, $comment, $tablespace)
+ {
+
+ $this->fieldArrayClean($tblrs->fields);
+
+ // Comment
+ $status = $this->setComment('TABLE', '', $tblrs->fields['relname'], $comment);
+ if ($status != 0) {
+ return -4;
+ }
+
+ // Owner
+ $this->fieldClean($owner);
+ $status = $this->alterTableOwner($tblrs, $owner);
+ if ($status != 0) {
+ return -5;
+ }
+
+ // Tablespace
+ $this->fieldClean($tablespace);
+ $status = $this->alterTableTablespace($tblrs, $tablespace);
+ if ($status != 0) {
+ return -6;
+ }
+
+ // Rename
+ $this->fieldClean($name);
+ $status = $this->alterTableName($tblrs, $name);
+ if ($status != 0) {
+ return -3;
+ }
+
+ // Schema
+ $this->fieldClean($schema);
+ $status = $this->alterTableSchema($tblrs, $schema);
+ if ($status != 0) {
+ return -7;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Alter table properties
+ * @param $table The name of the table
+ * @param $name The new name for the table
+ * @param $owner The new owner for the table
+ * @param $schema The new schema for the table
+ * @param $comment The comment on the table
+ * @param $tablespace The new tablespace for the table ('' means leave as is)
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 get existing table error
+ * @return $this->_alterTable error code
+ */
+ public function alterTable($table, $name, $owner, $schema, $comment, $tablespace)
+ {
+
+ $data = $this->getTable($table);
+
+ if ($data->recordCount() != 1) {
+ return -2;
+ }
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $status = $this->_alterTable($data, $name, $owner, $schema, $comment, $tablespace);
+
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return $status;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Returns the SQL for changing the current user
+ * @param $user The user to change to
+ * @return The SQL
+ */
+ public function getChangeUserSQL($user)
+ {
+ $this->clean($user);
+ return "SET SESSION AUTHORIZATION '{$user}';";
+ }
+
+ /**
+ * Given an array of attnums and a relation, returns an array mapping
+ * attribute number to attribute name.
+ * @param $table The table to get attributes for
+ * @param $atts An array of attribute numbers
+ * @return An array mapping attnum to attname
+ * @return -1 $atts must be an array
+ * @return -2 wrong number of attributes found
+ */
+ public function getAttributeNames($table, $atts)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+ $this->arrayClean($atts);
+
+ if (!is_array($atts)) {
+ return -1;
+ }
+
+ if (sizeof($atts) == 0) {
+ return [];
+ }
+
+ $sql = "SELECT attnum, attname FROM pg_catalog.pg_attribute WHERE
attrelid=(SELECT oid FROM pg_catalog.pg_class WHERE relname='{$table}' AND
relnamespace=(SELECT oid FROM pg_catalog.pg_namespace WHERE nspname='{$c_schema}'))
AND attnum IN ('" . join("','", $atts) . "')";
- $rs = $this->selectSet($sql);
- if ($rs->recordCount() != sizeof($atts)) {
- return -2;
- } else {
- $temp = [];
- while (!$rs->EOF) {
- $temp[$rs->fields['attnum']] = $rs->fields['attname'];
- $rs->moveNext();
- }
- return $temp;
- }
- }
-
- /**
- * Empties a table in the database
- * @param $table The table to be emptied
- * @return 0 success
- */
- function emptyTable($table) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
-
- $sql = "DELETE FROM \"{$f_schema}\".\"{$table}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * Removes a table from the database
- * @param $table The table to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropTable($table, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
-
- $sql = "DROP TABLE \"{$f_schema}\".\"{$table}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * 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 $array True if array type, false otherwise
- * @param $notnull True if NOT NULL, false otherwise
- * @param $default The default for the column. '' for none.
- * @param $length The optional size of the column (ie. 30 for varchar(30))
- * @return 0 success
- */
- function addColumn($table, $column, $type, $array, $length, $notnull, $default, $comment) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($column);
- $this->clean($type);
- $this->clean($length);
-
- if ($length == '') {
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" {$type}";
- } else {
- switch ($type) {
- // Have to account for weird placing of length for with/without
- // time zone types
- case 'timestamp with time zone':
- case 'timestamp without time zone':
- $qual = substr($type, 9);
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" timestamp({$length}){$qual}";
- break;
- case 'time with time zone':
- case 'time without time zone':
- $qual = substr($type, 4);
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" time({$length}){$qual}";
- break;
- default:
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" {$type}({$length})";
- }
- }
-
- // Add array qualifier, if requested
- if ($array) {
- $sql .= '[]';
- }
-
- // If we have advanced column adding, add the extra qualifiers
- if ($this->hasCreateFieldWithConstraints()) {
- // NOT NULL clause
- if ($notnull) {
- $sql .= ' NOT NULL';
- }
-
- // DEFAULT clause
- if ($default != '') {
- $sql .= ' DEFAULT ' . $default;
- }
-
- }
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $status = $this->setComment('COLUMN', $column, $table, $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * 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 $oldnotnull (boolean) True if column is already not null, false otherwise
- * @param $default The new default for the column
- * @param $olddefault The old default for the column
- * @param $type The new type for the column
- * @param $array True if array type, false otherwise
- * @param $length The optional size of the column (ie. 30 for varchar(30))
- * @param $oldtype The old type for the column
- * @param $comment Comment for the column
- * @return 0 success
- * @return -1 batch alteration failed
- * @return -4 rename column error
- * @return -5 comment error
- * @return -6 transaction error
- */
- function alterColumn($table, $column, $name, $notnull, $oldnotnull, $default, $olddefault,
- $type, $length, $array, $oldtype, $comment) {
- // Begin transaction
- $status = $this->beginTransaction();
- $sql = '';
- if ($status != 0) {
- $this->rollbackTransaction();
- return [-6, $sql];
- }
-
- // Rename the column, if it has been changed
- if ($column != $name) {
- $status = $this->renameColumn($table, $column, $name);
- if ($status != 0) {
- $this->rollbackTransaction();
- return [-4, $sql];
- }
- }
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
- $this->fieldClean($table);
- $this->fieldClean($column);
-
- $toAlter = [];
- // Create the command for changing nullability
- if ($notnull != $oldnotnull) {
- $toAlter[] = "ALTER COLUMN \"{$name}\" " . (($notnull) ? 'SET' : 'DROP') . " NOT NULL";
- }
-
- // Add default, if it has changed
- if ($default != $olddefault) {
- if ($default == '') {
- $toAlter[] = "ALTER COLUMN \"{$name}\" DROP DEFAULT";
- } else {
- $toAlter[] = "ALTER COLUMN \"{$name}\" SET DEFAULT {$default}";
- }
- }
-
- // Add type, if it has changed
- if ($length == '') {
- $ftype = $type;
- } else {
- switch ($type) {
- // Have to account for weird placing of length for with/without
- // time zone types
- case 'timestamp with time zone':
- case 'timestamp without time zone':
- $qual = substr($type, 9);
- $ftype = "timestamp({$length}){$qual}";
- break;
- case 'time with time zone':
- case 'time without time zone':
- $qual = substr($type, 4);
- $ftype = "time({$length}){$qual}";
- break;
- default:
- $ftype = "{$type}({$length})";
- }
- }
-
- // Add array qualifier, if requested
- if ($array) {
- $ftype .= '[]';
- }
-
- if ($ftype != $oldtype) {
- $toAlter[] = "ALTER COLUMN \"{$name}\" TYPE {$ftype}";
- }
-
- // Attempt to process the batch alteration, if anything has been changed
- if (!empty($toAlter)) {
- // Initialise an empty SQL string
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" "
- . implode(',', $toAlter);
-
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return [-1, $sql];
- }
- }
-
- // Update the comment on the column
- $status = $this->setComment('COLUMN', $name, $table, $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return [-5, $sql];
- }
-
- return [$this->endTransaction(), $sql];
- }
-
- /**
- * 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) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($column);
- $this->fieldClean($newName);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" RENAME COLUMN \"{$column}\" TO \"{$newName}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * 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) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($column);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" SET DEFAULT {$default}";
-
- 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
- */
- function setColumnNull($table, $column, $state) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($column);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" " . (($state) ? 'DROP' : 'SET') . " NOT NULL";
-
- return $this->execute($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 $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropColumn($table, $column, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($column);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" DROP COLUMN \"{$column}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- 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) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($column);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" DROP DEFAULT";
-
- return $this->execute($sql);
- }
-
- /**
- * Sets up the data object for a dump. eg. Starts the appropriate
- * transaction, sets variables, etc.
- * @return 0 success
- */
- function beginDump() {
- // Begin serializable transaction (to dump consistent data)
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- // Set serializable
- $sql = "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Set datestyle to ISO
- $sql = "SET DATESTYLE = ISO";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Set extra_float_digits to 2
- $sql = "SET extra_float_digits TO 2";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- return 0;
- }
-
- /**
- * Ends the data object for a dump.
- * @return 0 success
- */
- function endDump() {
- return $this->endTransaction();
- }
-
- /**
- * Returns a recordset of all columns in a relation. Used for data export.
- * @@ Note: Really needs to use a cursor
- * @param $relation The name of a relation
- * @return A recordset on success
- * @return -1 Failed to set datestyle
- */
- function dumpRelation($relation, $oids) {
- $this->fieldClean($relation);
-
- // Actually retrieve the rows
- if ($oids) {
- $oid_str = $this->id . ', ';
- } else {
- $oid_str = '';
- }
-
- return $this->selectSet("SELECT {$oid_str}* FROM \"{$relation}\"");
- }
-
- /**
- * Returns all available autovacuum per table information.
- * @param $table if given, return autovacuum info for the given table or return all informations for all table
- *
- * @return A recordset
- */
- function getTableAutovacuum($table = '') {
-
- $sql = '';
-
- if ($table !== '') {
- $this->clean($table);
- $c_schema = $this->_schema;
- $this->clean($c_schema);
-
- $sql = "SELECT c.oid, nspname, relname, pg_catalog.array_to_string(reloptions, E',') AS reloptions
+ $rs = $this->selectSet($sql);
+ if ($rs->recordCount() != sizeof($atts)) {
+ return -2;
+ } else {
+ $temp = [];
+ while (!$rs->EOF) {
+ $temp[$rs->fields['attnum']] = $rs->fields['attname'];
+ $rs->moveNext();
+ }
+ return $temp;
+ }
+ }
+
+ /**
+ * Empties a table in the database
+ * @param $table The table to be emptied
+ * @return 0 success
+ */
+ public function emptyTable($table)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ $sql = "DELETE FROM \"{$f_schema}\".\"{$table}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes a table from the database
+ * @param $table The table to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropTable($table, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ $sql = "DROP TABLE \"{$f_schema}\".\"{$table}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * 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 $array True if array type, false otherwise
+ * @param $notnull True if NOT NULL, false otherwise
+ * @param $default The default for the column. '' for none.
+ * @param $length The optional size of the column (ie. 30 for varchar(30))
+ * @return 0 success
+ */
+ public function addColumn($table, $column, $type, $array, $length, $notnull, $default, $comment)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($column);
+ $this->clean($type);
+ $this->clean($length);
+
+ if ($length == '') {
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" {$type}";
+ } else {
+ switch ($type) {
+ // Have to account for weird placing of length for with/without
+ // time zone types
+ case 'timestamp with time zone':
+ case 'timestamp without time zone':
+ $qual = substr($type, 9);
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" timestamp({$length}){$qual}";
+ break;
+ case 'time with time zone':
+ case 'time without time zone':
+ $qual = substr($type, 4);
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" time({$length}){$qual}";
+ break;
+ default:
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" {$type}({$length})";
+ }
+ }
+
+ // Add array qualifier, if requested
+ if ($array) {
+ $sql .= '[]';
+ }
+
+ // If we have advanced column adding, add the extra qualifiers
+ if ($this->hasCreateFieldWithConstraints()) {
+ // NOT NULL clause
+ if ($notnull) {
+ $sql .= ' NOT NULL';
+ }
+
+ // DEFAULT clause
+ if ($default != '') {
+ $sql .= ' DEFAULT ' . $default;
+ }
+
+ }
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $status = $this->setComment('COLUMN', $column, $table, $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * 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 $oldnotnull (boolean) True if column is already not null, false otherwise
+ * @param $default The new default for the column
+ * @param $olddefault The old default for the column
+ * @param $type The new type for the column
+ * @param $array True if array type, false otherwise
+ * @param $length The optional size of the column (ie. 30 for varchar(30))
+ * @param $oldtype The old type for the column
+ * @param $comment Comment for the column
+ * @return 0 success
+ * @return -1 batch alteration failed
+ * @return -4 rename column error
+ * @return -5 comment error
+ * @return -6 transaction error
+ */
+ public function alterColumn($table, $column, $name, $notnull, $oldnotnull, $default, $olddefault,
+ $type, $length, $array, $oldtype, $comment) {
+ // Begin transaction
+ $status = $this->beginTransaction();
+ $sql = '';
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return [-6, $sql];
+ }
+
+ // Rename the column, if it has been changed
+ if ($column != $name) {
+ $status = $this->renameColumn($table, $column, $name);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return [-4, $sql];
+ }
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+ $this->fieldClean($table);
+ $this->fieldClean($column);
+
+ $toAlter = [];
+ // Create the command for changing nullability
+ if ($notnull != $oldnotnull) {
+ $toAlter[] = "ALTER COLUMN \"{$name}\" " . (($notnull) ? 'SET' : 'DROP') . " NOT NULL";
+ }
+
+ // Add default, if it has changed
+ if ($default != $olddefault) {
+ if ($default == '') {
+ $toAlter[] = "ALTER COLUMN \"{$name}\" DROP DEFAULT";
+ } else {
+ $toAlter[] = "ALTER COLUMN \"{$name}\" SET DEFAULT {$default}";
+ }
+ }
+
+ // Add type, if it has changed
+ if ($length == '') {
+ $ftype = $type;
+ } else {
+ switch ($type) {
+ // Have to account for weird placing of length for with/without
+ // time zone types
+ case 'timestamp with time zone':
+ case 'timestamp without time zone':
+ $qual = substr($type, 9);
+ $ftype = "timestamp({$length}){$qual}";
+ break;
+ case 'time with time zone':
+ case 'time without time zone':
+ $qual = substr($type, 4);
+ $ftype = "time({$length}){$qual}";
+ break;
+ default:
+ $ftype = "{$type}({$length})";
+ }
+ }
+
+ // Add array qualifier, if requested
+ if ($array) {
+ $ftype .= '[]';
+ }
+
+ if ($ftype != $oldtype) {
+ $toAlter[] = "ALTER COLUMN \"{$name}\" TYPE {$ftype}";
+ }
+
+ // Attempt to process the batch alteration, if anything has been changed
+ if (!empty($toAlter)) {
+ // Initialise an empty SQL string
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" "
+ . implode(',', $toAlter);
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return [-1, $sql];
+ }
+ }
+
+ // Update the comment on the column
+ $status = $this->setComment('COLUMN', $name, $table, $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return [-5, $sql];
+ }
+
+ return [$this->endTransaction(), $sql];
+ }
+
+ /**
+ * 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
+ */
+ public function renameColumn($table, $column, $newName)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($column);
+ $this->fieldClean($newName);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" RENAME COLUMN \"{$column}\" TO \"{$newName}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * 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
+ */
+ public function setColumnDefault($table, $column, $default)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($column);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" SET DEFAULT {$default}";
+
+ 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
+ */
+ public function setColumnNull($table, $column, $state)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($column);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" " . (($state) ? 'DROP' : 'SET') . " NOT NULL";
+
+ return $this->execute($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 $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropColumn($table, $column, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($column);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" DROP COLUMN \"{$column}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ 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
+ */
+ public function dropColumnDefault($table, $column)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($column);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" DROP DEFAULT";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Sets up the data object for a dump. eg. Starts the appropriate
+ * transaction, sets variables, etc.
+ * @return 0 success
+ */
+ public function beginDump()
+ {
+ // Begin serializable transaction (to dump consistent data)
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ // Set serializable
+ $sql = "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Set datestyle to ISO
+ $sql = "SET DATESTYLE = ISO";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Set extra_float_digits to 2
+ $sql = "SET extra_float_digits TO 2";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Ends the data object for a dump.
+ * @return 0 success
+ */
+ public function endDump()
+ {
+ return $this->endTransaction();
+ }
+
+ /**
+ * Returns a recordset of all columns in a relation. Used for data export.
+ * @@ Note: Really needs to use a cursor
+ * @param $relation The name of a relation
+ * @return A recordset on success
+ * @return -1 Failed to set datestyle
+ */
+ public function dumpRelation($relation, $oids)
+ {
+ $this->fieldClean($relation);
+
+ // Actually retrieve the rows
+ if ($oids) {
+ $oid_str = $this->id . ', ';
+ } else {
+ $oid_str = '';
+ }
+
+ return $this->selectSet("SELECT {$oid_str}* FROM \"{$relation}\"");
+ }
+
+ /**
+ * Returns all available autovacuum per table information.
+ * @param $table if given, return autovacuum info for the given table or return all informations for all table
+ *
+ * @return A recordset
+ */
+ public function getTableAutovacuum($table = '')
+ {
+
+ $sql = '';
+
+ if ($table !== '') {
+ $this->clean($table);
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+
+ $sql = "SELECT c.oid, nspname, relname, pg_catalog.array_to_string(reloptions, E',') AS reloptions
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'::\"char\"
@@ -2550,8 +2627,8 @@ class Postgres extends ADODB_base {
AND c.reloptions IS NOT NULL
AND c.relname = '{$table}' AND n.nspname = '{$c_schema}'
ORDER BY nspname, relname";
- } else {
- $sql = "SELECT c.oid, nspname, relname, pg_catalog.array_to_string(reloptions, E',') AS reloptions
+ } else {
+ $sql = "SELECT c.oid, nspname, relname, pg_catalog.array_to_string(reloptions, E',') AS reloptions
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'::\"char\"
@@ -2559,54 +2636,55 @@ class Postgres extends ADODB_base {
AND c.reloptions IS NOT NULL
ORDER BY nspname, relname";
- }
-
- /* tmp var to parse the results */
- $_autovacs = $this->selectSet($sql);
-
- /* result aray to return as RS */
- $autovacs = [];
- while (!$_autovacs->EOF) {
- $_ = [
- 'nspname' => $_autovacs->fields['nspname'],
- 'relname' => $_autovacs->fields['relname'],
- ];
-
- foreach (explode(',', $_autovacs->fields['reloptions']) as $var) {
- list($o, $v) = explode('=', $var);
- $_[$o] = $v;
- }
-
- $autovacs[] = $_;
-
- $_autovacs->moveNext();
- }
-
- return new \PHPPgAdmin\ArrayRecordSet($autovacs);
- }
-
- // Row 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) {
- $oldtable = $table;
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- // Get the first primary or unique index (sorting primary keys first) that
- // is NOT a partial index.
- $sql = "
+ }
+
+ /* tmp var to parse the results */
+ $_autovacs = $this->selectSet($sql);
+
+ /* result aray to return as RS */
+ $autovacs = [];
+ while (!$_autovacs->EOF) {
+ $_ = [
+ 'nspname' => $_autovacs->fields['nspname'],
+ 'relname' => $_autovacs->fields['relname'],
+ ];
+
+ foreach (explode(',', $_autovacs->fields['reloptions']) as $var) {
+ list($o, $v) = explode('=', $var);
+ $_[$o] = $v;
+ }
+
+ $autovacs[] = $_;
+
+ $_autovacs->moveNext();
+ }
+
+ return new \PHPPgAdmin\ArrayRecordSet($autovacs);
+ }
+
+ // Row 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
+ */
+ public function getRowIdentifier($table)
+ {
+ $oldtable = $table;
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ // Get the first primary or unique index (sorting primary keys first) that
+ // is NOT a partial index.
+ $sql = "
SELECT indrelid, indkey
FROM pg_catalog.pg_index
WHERE indisunique AND indrelid=(
@@ -2617,206 +2695,210 @@ class Postgres extends ADODB_base {
)
) AND indpred IS NULL AND indexprs IS NULL
ORDER BY indisprimary DESC LIMIT 1";
- $rs = $this->selectSet($sql);
-
- // If none, check for an OID column. Even though OIDs can be duplicated, the edit and delete row
- // functions check that they're only modiying a single row. Otherwise, return empty array.
- if ($rs->recordCount() == 0) {
- // Check for OID column
- $temp = [];
- if ($this->hasObjectID($table)) {
- $temp = ['oid'];
- }
- $this->endTransaction();
- return $temp;
- }
- // Otherwise find the names of the keys
- else {
- $attnames = $this->getAttributeNames($oldtable, explode(' ', $rs->fields['indkey']));
- if (!is_array($attnames)) {
- $this->rollbackTransaction();
- return -1;
- } else {
- $this->endTransaction();
- return $attnames;
- }
- }
- }
-
- /**
- * Adds a new row to a table
- * @param $table The table in which to insert
- * @param $fields Array of given field in values
- * @param $values Array of new values for the row
- * @param $nulls An array mapping column => something if it is to be null
- * @param $format An array of the data type (VALUE or EXPRESSION)
- * @param $types An array of field types
- * @return 0 success
- * @return -1 invalid parameters
- */
- function insertRow($table, $fields, $values, $nulls, $format, $types) {
-
- if (!is_array($fields) || !is_array($values) || !is_array($nulls)
- || !is_array($format) || !is_array($types)
- || (count($fields) != count($values))
- ) {
- return -1;
- } else {
- // Build clause
- if (count($values) > 0) {
- // Escape all field names
- $fields = array_map(['\PHPPgAdmin\Database\Postgres', 'fieldClean'], $fields);
- $f_schema = $this->_schema;
- $this->fieldClean($table);
- $this->fieldClean($f_schema);
-
- $sql = '';
- foreach ($values as $i => $value) {
-
- // Handle NULL values
- if (isset($nulls[$i])) {
- $sql .= ',NULL';
- } else {
- $sql .= ',' . $this->formatValue($types[$i], $format[$i], $value);
- }
-
- }
-
- $sql = "INSERT INTO \"{$f_schema}\".\"{$table}\" (\"" . implode('","', $fields) . "\")
+ $rs = $this->selectSet($sql);
+
+ // If none, check for an OID column. Even though OIDs can be duplicated, the edit and delete row
+ // functions check that they're only modiying a single row. Otherwise, return empty array.
+ if ($rs->recordCount() == 0) {
+ // Check for OID column
+ $temp = [];
+ if ($this->hasObjectID($table)) {
+ $temp = ['oid'];
+ }
+ $this->endTransaction();
+ return $temp;
+ }
+ // Otherwise find the names of the keys
+ else {
+ $attnames = $this->getAttributeNames($oldtable, explode(' ', $rs->fields['indkey']));
+ if (!is_array($attnames)) {
+ $this->rollbackTransaction();
+ return -1;
+ } else {
+ $this->endTransaction();
+ return $attnames;
+ }
+ }
+ }
+
+ /**
+ * Adds a new row to a table
+ * @param $table The table in which to insert
+ * @param $fields Array of given field in values
+ * @param $values Array of new values for the row
+ * @param $nulls An array mapping column => something if it is to be null
+ * @param $format An array of the data type (VALUE or EXPRESSION)
+ * @param $types An array of field types
+ * @return 0 success
+ * @return -1 invalid parameters
+ */
+ public function insertRow($table, $fields, $values, $nulls, $format, $types)
+ {
+
+ if (!is_array($fields) || !is_array($values) || !is_array($nulls)
+ || !is_array($format) || !is_array($types)
+ || (count($fields) != count($values))
+ ) {
+ return -1;
+ } else {
+ // Build clause
+ if (count($values) > 0) {
+ // Escape all field names
+ $fields = array_map(['\PHPPgAdmin\Database\Postgres', 'fieldClean'], $fields);
+ $f_schema = $this->_schema;
+ $this->fieldClean($table);
+ $this->fieldClean($f_schema);
+
+ $sql = '';
+ foreach ($values as $i => $value) {
+
+ // Handle NULL values
+ if (isset($nulls[$i])) {
+ $sql .= ',NULL';
+ } else {
+ $sql .= ',' . $this->formatValue($types[$i], $format[$i], $value);
+ }
+
+ }
+
+ $sql = "INSERT INTO \"{$f_schema}\".\"{$table}\" (\"" . implode('","', $fields) . "\")
VALUES (" . substr($sql, 1) . ")";
- return $this->execute($sql);
- }
- }
-
- return -1;
- }
-
- /**
- * Updates a row in a table
- * @param $table The table in which to update
- * @param $vars An array mapping new values for the row
- * @param $nulls An array mapping column => something if it is to be null
- * @param $format An array of the data type (VALUE or EXPRESSION)
- * @param $types An array of field types
- * @param $keyarr An array mapping column => value to update
- * @return 0 success
- * @return -1 invalid parameters
- */
- function editRow($table, $vars, $nulls, $format, $types, $keyarr) {
- if (!is_array($vars) || !is_array($nulls) || !is_array($format) || !is_array($types)) {
- return -1;
- } else {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
-
- // Build clause
- if (sizeof($vars) > 0) {
-
- foreach ($vars as $key => $value) {
- $this->fieldClean($key);
-
- // Handle NULL values
- if (isset($nulls[$key])) {
- $tmp = 'NULL';
- } else {
- $tmp = $this->formatValue($types[$key], $format[$key], $value);
- }
-
- if (isset($sql)) {
- $sql .= ", \"{$key}\"={$tmp}";
- } else {
- $sql = "UPDATE \"{$f_schema}\".\"{$table}\" SET \"{$key}\"={$tmp}";
- }
-
- }
- $first = true;
- foreach ($keyarr as $k => $v) {
- $this->fieldClean($k);
- $this->clean($v);
- if ($first) {
- $sql .= " WHERE \"{$k}\"='{$v}'";
- $first = false;
- } else {
- $sql .= " AND \"{$k}\"='{$v}'";
- }
-
- }
- }
-
- // Begin transaction. We do this so that we can ensure only one row is
- // edited
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $status = $this->execute($sql);
- if ($status != 0) {
- // update failed
- $this->rollbackTransaction();
- return -1;
- } elseif ($this->conn->Affected_Rows() != 1) {
- // more than one row could be updated
- $this->rollbackTransaction();
- return -2;
- }
-
- // End transaction
- return $this->endTransaction();
- }
- }
-
- /**
- * Delete a row from a table
- * @param $table The table from which to delete
- * @param $key An array mapping column => value to delete
- * @return 0 success
- */
- function deleteRow($table, $key, $schema = false) {
- if (!is_array($key)) {
- return -1;
- } else {
- // Begin transaction. We do this so that we can ensure only one row is
- // deleted
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- if ($schema === false) {
- $schema = $this->_schema;
- }
-
- $status = $this->delete($table, $key, $schema);
- if ($status != 0 || $this->conn->Affected_Rows() != 1) {
- $this->rollbackTransaction();
- return -2;
- }
-
- // End transaction
- return $this->endTransaction();
- }
- }
-
- // Sequence functions
-
- /**
- * Returns properties of a single sequence
- * @param $sequence Sequence name
- * @return A recordset
- */
- function getSequence($sequence) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $c_sequence = $sequence;
- $this->fieldClean($sequence);
- $this->clean($c_sequence);
-
- $sql = "
+ return $this->execute($sql);
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Updates a row in a table
+ * @param $table The table in which to update
+ * @param $vars An array mapping new values for the row
+ * @param $nulls An array mapping column => something if it is to be null
+ * @param $format An array of the data type (VALUE or EXPRESSION)
+ * @param $types An array of field types
+ * @param $keyarr An array mapping column => value to update
+ * @return 0 success
+ * @return -1 invalid parameters
+ */
+ public function editRow($table, $vars, $nulls, $format, $types, $keyarr)
+ {
+ if (!is_array($vars) || !is_array($nulls) || !is_array($format) || !is_array($types)) {
+ return -1;
+ } else {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ // Build clause
+ if (sizeof($vars) > 0) {
+
+ foreach ($vars as $key => $value) {
+ $this->fieldClean($key);
+
+ // Handle NULL values
+ if (isset($nulls[$key])) {
+ $tmp = 'NULL';
+ } else {
+ $tmp = $this->formatValue($types[$key], $format[$key], $value);
+ }
+
+ if (isset($sql)) {
+ $sql .= ", \"{$key}\"={$tmp}";
+ } else {
+ $sql = "UPDATE \"{$f_schema}\".\"{$table}\" SET \"{$key}\"={$tmp}";
+ }
+
+ }
+ $first = true;
+ foreach ($keyarr as $k => $v) {
+ $this->fieldClean($k);
+ $this->clean($v);
+ if ($first) {
+ $sql .= " WHERE \"{$k}\"='{$v}'";
+ $first = false;
+ } else {
+ $sql .= " AND \"{$k}\"='{$v}'";
+ }
+
+ }
+ }
+
+ // Begin transaction. We do this so that we can ensure only one row is
+ // edited
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ // update failed
+ $this->rollbackTransaction();
+ return -1;
+ } elseif ($this->conn->Affected_Rows() != 1) {
+ // more than one row could be updated
+ $this->rollbackTransaction();
+ return -2;
+ }
+
+ // End transaction
+ return $this->endTransaction();
+ }
+ }
+
+ /**
+ * Delete a row from a table
+ * @param $table The table from which to delete
+ * @param $key An array mapping column => value to delete
+ * @return 0 success
+ */
+ public function deleteRow($table, $key, $schema = false)
+ {
+ if (!is_array($key)) {
+ return -1;
+ } else {
+ // Begin transaction. We do this so that we can ensure only one row is
+ // deleted
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ if ($schema === false) {
+ $schema = $this->_schema;
+ }
+
+ $status = $this->delete($table, $key, $schema);
+ if ($status != 0 || $this->conn->Affected_Rows() != 1) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+
+ // End transaction
+ return $this->endTransaction();
+ }
+ }
+
+ // Sequence functions
+
+ /**
+ * Returns properties of a single sequence
+ * @param $sequence Sequence name
+ * @return A recordset
+ */
+ public function getSequence($sequence)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $c_sequence = $sequence;
+ $this->fieldClean($sequence);
+ $this->clean($c_sequence);
+
+ $sql = "
SELECT c.relname AS seqname, s.*,
pg_catalog.obj_description(s.tableoid, 'pg_class') AS seqcomment,
u.usename AS seqowner, n.nspname
@@ -2825,434 +2907,443 @@ class Postgres extends ADODB_base {
AND c.relname = '{$c_sequence}' AND c.relkind = 'S' AND n.nspname='{$c_schema}'
AND n.oid = c.relnamespace";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns all sequences in the current database
- * @return A recordset
- */
- function getSequences($all = false) {
- if ($all) {
- // Exclude pg_catalog and information_schema tables
- $sql = "SELECT n.nspname, c.relname AS seqname, u.usename AS seqowner
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns all sequences in the current database
+ * @return A recordset
+ */
+ public function getSequences($all = false)
+ {
+ if ($all) {
+ // Exclude pg_catalog and information_schema tables
+ $sql = "SELECT n.nspname, c.relname AS seqname, u.usename AS seqowner
FROM pg_catalog.pg_class c, pg_catalog.pg_user u, pg_catalog.pg_namespace n
WHERE c.relowner=u.usesysid AND c.relnamespace=n.oid
AND c.relkind = 'S'
AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
ORDER BY nspname, seqname";
- } else {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "SELECT c.relname AS seqname, u.usename AS seqowner, pg_catalog.obj_description(c.oid, 'pg_class') AS seqcomment,
+ } else {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "SELECT c.relname AS seqname, u.usename AS seqowner, pg_catalog.obj_description(c.oid, 'pg_class') AS seqcomment,
(SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=c.reltablespace) AS tablespace
FROM pg_catalog.pg_class c, pg_catalog.pg_user u, pg_catalog.pg_namespace n
WHERE c.relowner=u.usesysid AND c.relnamespace=n.oid
AND c.relkind = 'S' AND n.nspname='{$c_schema}' ORDER BY seqname";
- }
-
- return $this->selectSet($sql);
- }
-
- /**
- * Execute nextval on a given sequence
- * @param $sequence Sequence name
- * @return 0 success
- * @return -1 sequence not found
- */
- function nextvalSequence($sequence) {
- /* This double-cleaning is deliberate */
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->clean($f_schema);
- $this->fieldClean($sequence);
- $this->clean($sequence);
-
- $sql = "SELECT pg_catalog.NEXTVAL('\"{$f_schema}\".\"{$sequence}\"')";
-
- return $this->execute($sql);
- }
-
- /**
- * Execute setval on a given sequence
- * @param $sequence Sequence name
- * @param $nextvalue The next value
- * @return 0 success
- * @return -1 sequence not found
- */
- function setvalSequence($sequence, $nextvalue) {
- /* This double-cleaning is deliberate */
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->clean($f_schema);
- $this->fieldClean($sequence);
- $this->clean($sequence);
- $this->clean($nextvalue);
-
- $sql = "SELECT pg_catalog.SETVAL('\"{$f_schema}\".\"{$sequence}\"', '{$nextvalue}')";
-
- return $this->execute($sql);
- }
-
- /**
- * Restart a given sequence to its start value
- * @param $sequence Sequence name
- * @return 0 success
- * @return -1 sequence not found
- */
- function restartSequence($sequence) {
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($sequence);
-
- $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$sequence}\" RESTART;";
-
- return $this->execute($sql);
- }
-
- /**
- * Resets a given sequence to min value of sequence
- * @param $sequence Sequence name
- * @return 0 success
- * @return -1 sequence not found
- */
- function resetSequence($sequence) {
- // Get the minimum value of the sequence
- $seq = $this->getSequence($sequence);
- if ($seq->recordCount() != 1) {
- return -1;
- }
-
- $minvalue = $seq->fields['min_value'];
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- /* This double-cleaning is deliberate */
- $this->fieldClean($sequence);
- $this->clean($sequence);
-
- $sql = "SELECT pg_catalog.SETVAL('\"{$f_schema}\".\"{$sequence}\"', {$minvalue})";
-
- return $this->execute($sql);
- }
-
- /**
- * Creates a new sequence
- * @param $sequence Sequence name
- * @param $increment The increment
- * @param $minvalue The min value
- * @param $maxvalue The max value
- * @param $startvalue The starting value
- * @param $cachevalue The cache value
- * @param $cycledvalue True if cycled, false otherwise
- * @return 0 success
- */
- function createSequence($sequence, $increment, $minvalue, $maxvalue,
- $startvalue, $cachevalue, $cycledvalue) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($sequence);
- $this->clean($increment);
- $this->clean($minvalue);
- $this->clean($maxvalue);
- $this->clean($startvalue);
- $this->clean($cachevalue);
-
- $sql = "CREATE SEQUENCE \"{$f_schema}\".\"{$sequence}\"";
- if ($increment != '') {
- $sql .= " INCREMENT {$increment}";
- }
-
- if ($minvalue != '') {
- $sql .= " MINVALUE {$minvalue}";
- }
-
- if ($maxvalue != '') {
- $sql .= " MAXVALUE {$maxvalue}";
- }
-
- if ($startvalue != '') {
- $sql .= " START {$startvalue}";
- }
-
- if ($cachevalue != '') {
- $sql .= " CACHE {$cachevalue}";
- }
-
- if ($cycledvalue) {
- $sql .= " CYCLE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Rename a sequence
- * @param $seqrs The sequence RecordSet returned by getSequence()
- * @param $name The new name for the sequence
- * @return 0 success
- */
- function alterSequenceName($seqrs, $name) {
- /* vars are cleaned in _alterSequence */
- if (!empty($name) && ($seqrs->fields['seqname'] != $name)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status == 0) {
- $seqrs->fields['seqname'] = $name;
- } else {
- return $status;
- }
-
- }
- return 0;
- }
-
- /**
- * Alter a sequence's owner
- * @param $seqrs The sequence RecordSet returned by getSequence()
- * @param $name The new owner for the sequence
- * @return 0 success
- */
- function alterSequenceOwner($seqrs, $owner) {
- // If owner has been changed, then do the alteration. We are
- // careful to avoid this generally as changing owner is a
- // superuser only function.
- /* vars are cleaned in _alterSequence */
- if (!empty($owner) && ($seqrs->fields['seqowner'] != $owner)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" OWNER TO \"{$owner}\"";
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Alter a sequence's schema
- * @param $seqrs The sequence RecordSet returned by getSequence()
- * @param $name The new schema for the sequence
- * @return 0 success
- */
- function alterSequenceSchema($seqrs, $schema) {
- /* vars are cleaned in _alterSequence */
- if (!empty($schema) && ($seqrs->fields['nspname'] != $schema)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" SET SCHEMA {$schema}";
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Alter a sequence's properties
- * @param $seqrs The sequence RecordSet returned by getSequence()
- * @param $increment The sequence incremental value
- * @param $minvalue The sequence minimum value
- * @param $maxvalue The sequence maximum value
- * @param $restartvalue The sequence current value
- * @param $cachevalue The sequence cache value
- * @param $cycledvalue Sequence can cycle ?
- * @param $startvalue The sequence start value when issueing a restart
- * @return 0 success
- */
- function alterSequenceProps($seqrs, $increment, $minvalue, $maxvalue,
- $restartvalue, $cachevalue, $cycledvalue, $startvalue) {
-
- $sql = '';
- /* vars are cleaned in _alterSequence */
- if (!empty($increment) && ($increment != $seqrs->fields['increment_by'])) {
- $sql .= " INCREMENT {$increment}";
- }
-
- if (!empty($minvalue) && ($minvalue != $seqrs->fields['min_value'])) {
- $sql .= " MINVALUE {$minvalue}";
- }
-
- if (!empty($maxvalue) && ($maxvalue != $seqrs->fields['max_value'])) {
- $sql .= " MAXVALUE {$maxvalue}";
- }
-
- if (!empty($restartvalue) && ($restartvalue != $seqrs->fields['last_value'])) {
- $sql .= " RESTART {$restartvalue}";
- }
-
- if (!empty($cachevalue) && ($cachevalue != $seqrs->fields['cache_value'])) {
- $sql .= " CACHE {$cachevalue}";
- }
-
- if (!empty($startvalue) && ($startvalue != $seqrs->fields['start_value'])) {
- $sql .= " START {$startvalue}";
- }
-
- // toggle cycle yes/no
- if (!is_null($cycledvalue)) {
- $sql .= (!$cycledvalue ? ' NO ' : '') . " CYCLE";
- }
-
- if ($sql != '') {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" {$sql}";
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Protected method which alter a sequence
- * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
- * @param $seqrs The sequence recordSet returned by getSequence()
- * @param $name The new name for the sequence
- * @param $comment The comment on the sequence
- * @param $owner The new owner for the sequence
- * @param $schema The new schema for the sequence
- * @param $increment The increment
- * @param $minvalue The min value
- * @param $maxvalue The max value
- * @param $restartvalue The starting value
- * @param $cachevalue The cache value
- * @param $cycledvalue True if cycled, false otherwise
- * @param $startvalue The sequence start value when issueing a restart
- * @return 0 success
- * @return -3 rename error
- * @return -4 comment error
- * @return -5 owner error
- * @return -6 get sequence props error
- * @return -7 schema error
- */
- protected
- function _alterSequence($seqrs, $name, $comment, $owner, $schema, $increment,
- $minvalue, $maxvalue, $restartvalue, $cachevalue, $cycledvalue, $startvalue) {
-
- $this->fieldArrayClean($seqrs->fields);
-
- // Comment
- $status = $this->setComment('SEQUENCE', $seqrs->fields['seqname'], '', $comment);
- if ($status != 0) {
- return -4;
- }
-
- // Owner
- $this->fieldClean($owner);
- $status = $this->alterSequenceOwner($seqrs, $owner);
- if ($status != 0) {
- return -5;
- }
-
- // Props
- $this->clean($increment);
- $this->clean($minvalue);
- $this->clean($maxvalue);
- $this->clean($restartvalue);
- $this->clean($cachevalue);
- $this->clean($cycledvalue);
- $this->clean($startvalue);
- $status = $this->alterSequenceProps($seqrs, $increment, $minvalue,
- $maxvalue, $restartvalue, $cachevalue, $cycledvalue, $startvalue);
- if ($status != 0) {
- return -6;
- }
-
- // Rename
- $this->fieldClean($name);
- $status = $this->alterSequenceName($seqrs, $name);
- if ($status != 0) {
- return -3;
- }
-
- // Schema
- $this->clean($schema);
- $status = $this->alterSequenceSchema($seqrs, $schema);
- if ($status != 0) {
- return -7;
- }
-
- return 0;
- }
-
- /**
- * Alters a sequence
- * @param $sequence The name of the sequence
- * @param $name The new name for the sequence
- * @param $comment The comment on the sequence
- * @param $owner The new owner for the sequence
- * @param $schema The new schema for the sequence
- * @param $increment The increment
- * @param $minvalue The min value
- * @param $maxvalue The max value
- * @param $restartvalue The starting value
- * @param $cachevalue The cache value
- * @param $cycledvalue True if cycled, false otherwise
- * @param $startvalue The sequence start value when issueing a restart
- * @return 0 success
- * @return -1 transaction error
- * @return -2 get existing sequence error
- * @return $this->_alterSequence error code
- */
- function alterSequence($sequence, $name, $comment, $owner = null, $schema = null, $increment = null,
- $minvalue = null, $maxvalue = null, $restartvalue = null, $cachevalue = null, $cycledvalue = null, $startvalue = null) {
-
- $this->fieldClean($sequence);
-
- $data = $this->getSequence($sequence);
-
- if ($data->recordCount() != 1) {
- return -2;
- }
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $status = $this->_alterSequence($data, $name, $comment, $owner, $schema, $increment,
- $minvalue, $maxvalue, $restartvalue, $cachevalue, $cycledvalue, $startvalue);
-
- if ($status != 0) {
- $this->rollbackTransaction();
- return $status;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Drops a given sequence
- * @param $sequence Sequence name
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropSequence($sequence, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($sequence);
-
- $sql = "DROP SEQUENCE \"{$f_schema}\".\"{$sequence}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- // View functions
-
- /**
- * Returns all details for a particular view
- * @param $view The name of the view to retrieve
- * @return View info
- */
- function getView($view) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($view);
-
- $sql = "
+ }
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Execute nextval on a given sequence
+ * @param $sequence Sequence name
+ * @return 0 success
+ * @return -1 sequence not found
+ */
+ public function nextvalSequence($sequence)
+ {
+ /* This double-cleaning is deliberate */
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->clean($f_schema);
+ $this->fieldClean($sequence);
+ $this->clean($sequence);
+
+ $sql = "SELECT pg_catalog.NEXTVAL('\"{$f_schema}\".\"{$sequence}\"')";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Execute setval on a given sequence
+ * @param $sequence Sequence name
+ * @param $nextvalue The next value
+ * @return 0 success
+ * @return -1 sequence not found
+ */
+ public function setvalSequence($sequence, $nextvalue)
+ {
+ /* This double-cleaning is deliberate */
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->clean($f_schema);
+ $this->fieldClean($sequence);
+ $this->clean($sequence);
+ $this->clean($nextvalue);
+
+ $sql = "SELECT pg_catalog.SETVAL('\"{$f_schema}\".\"{$sequence}\"', '{$nextvalue}')";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Restart a given sequence to its start value
+ * @param $sequence Sequence name
+ * @return 0 success
+ * @return -1 sequence not found
+ */
+ public function restartSequence($sequence)
+ {
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($sequence);
+
+ $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$sequence}\" RESTART;";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Resets a given sequence to min value of sequence
+ * @param $sequence Sequence name
+ * @return 0 success
+ * @return -1 sequence not found
+ */
+ public function resetSequence($sequence)
+ {
+ // Get the minimum value of the sequence
+ $seq = $this->getSequence($sequence);
+ if ($seq->recordCount() != 1) {
+ return -1;
+ }
+
+ $minvalue = $seq->fields['min_value'];
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ /* This double-cleaning is deliberate */
+ $this->fieldClean($sequence);
+ $this->clean($sequence);
+
+ $sql = "SELECT pg_catalog.SETVAL('\"{$f_schema}\".\"{$sequence}\"', {$minvalue})";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Creates a new sequence
+ * @param $sequence Sequence name
+ * @param $increment The increment
+ * @param $minvalue The min value
+ * @param $maxvalue The max value
+ * @param $startvalue The starting value
+ * @param $cachevalue The cache value
+ * @param $cycledvalue True if cycled, false otherwise
+ * @return 0 success
+ */
+ public function createSequence($sequence, $increment, $minvalue, $maxvalue,
+ $startvalue, $cachevalue, $cycledvalue) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($sequence);
+ $this->clean($increment);
+ $this->clean($minvalue);
+ $this->clean($maxvalue);
+ $this->clean($startvalue);
+ $this->clean($cachevalue);
+
+ $sql = "CREATE SEQUENCE \"{$f_schema}\".\"{$sequence}\"";
+ if ($increment != '') {
+ $sql .= " INCREMENT {$increment}";
+ }
+
+ if ($minvalue != '') {
+ $sql .= " MINVALUE {$minvalue}";
+ }
+
+ if ($maxvalue != '') {
+ $sql .= " MAXVALUE {$maxvalue}";
+ }
+
+ if ($startvalue != '') {
+ $sql .= " START {$startvalue}";
+ }
+
+ if ($cachevalue != '') {
+ $sql .= " CACHE {$cachevalue}";
+ }
+
+ if ($cycledvalue) {
+ $sql .= " CYCLE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Rename a sequence
+ * @param $seqrs The sequence RecordSet returned by getSequence()
+ * @param $name The new name for the sequence
+ * @return 0 success
+ */
+ public function alterSequenceName($seqrs, $name)
+ {
+ /* vars are cleaned in _alterSequence */
+ if (!empty($name) && ($seqrs->fields['seqname'] != $name)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status == 0) {
+ $seqrs->fields['seqname'] = $name;
+ } else {
+ return $status;
+ }
+
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a sequence's owner
+ * @param $seqrs The sequence RecordSet returned by getSequence()
+ * @param $name The new owner for the sequence
+ * @return 0 success
+ */
+ public function alterSequenceOwner($seqrs, $owner)
+ {
+ // If owner has been changed, then do the alteration. We are
+ // careful to avoid this generally as changing owner is a
+ // superuser only function.
+ /* vars are cleaned in _alterSequence */
+ if (!empty($owner) && ($seqrs->fields['seqowner'] != $owner)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" OWNER TO \"{$owner}\"";
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a sequence's schema
+ * @param $seqrs The sequence RecordSet returned by getSequence()
+ * @param $name The new schema for the sequence
+ * @return 0 success
+ */
+ public function alterSequenceSchema($seqrs, $schema)
+ {
+ /* vars are cleaned in _alterSequence */
+ if (!empty($schema) && ($seqrs->fields['nspname'] != $schema)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" SET SCHEMA {$schema}";
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a sequence's properties
+ * @param $seqrs The sequence RecordSet returned by getSequence()
+ * @param $increment The sequence incremental value
+ * @param $minvalue The sequence minimum value
+ * @param $maxvalue The sequence maximum value
+ * @param $restartvalue The sequence current value
+ * @param $cachevalue The sequence cache value
+ * @param $cycledvalue Sequence can cycle ?
+ * @param $startvalue The sequence start value when issueing a restart
+ * @return 0 success
+ */
+ public function alterSequenceProps($seqrs, $increment, $minvalue, $maxvalue,
+ $restartvalue, $cachevalue, $cycledvalue, $startvalue) {
+
+ $sql = '';
+ /* vars are cleaned in _alterSequence */
+ if (!empty($increment) && ($increment != $seqrs->fields['increment_by'])) {
+ $sql .= " INCREMENT {$increment}";
+ }
+
+ if (!empty($minvalue) && ($minvalue != $seqrs->fields['min_value'])) {
+ $sql .= " MINVALUE {$minvalue}";
+ }
+
+ if (!empty($maxvalue) && ($maxvalue != $seqrs->fields['max_value'])) {
+ $sql .= " MAXVALUE {$maxvalue}";
+ }
+
+ if (!empty($restartvalue) && ($restartvalue != $seqrs->fields['last_value'])) {
+ $sql .= " RESTART {$restartvalue}";
+ }
+
+ if (!empty($cachevalue) && ($cachevalue != $seqrs->fields['cache_value'])) {
+ $sql .= " CACHE {$cachevalue}";
+ }
+
+ if (!empty($startvalue) && ($startvalue != $seqrs->fields['start_value'])) {
+ $sql .= " START {$startvalue}";
+ }
+
+ // toggle cycle yes/no
+ if (!is_null($cycledvalue)) {
+ $sql .= (!$cycledvalue ? ' NO ' : '') . " CYCLE";
+ }
+
+ if ($sql != '') {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" {$sql}";
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Protected method which alter a sequence
+ * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
+ * @param $seqrs The sequence recordSet returned by getSequence()
+ * @param $name The new name for the sequence
+ * @param $comment The comment on the sequence
+ * @param $owner The new owner for the sequence
+ * @param $schema The new schema for the sequence
+ * @param $increment The increment
+ * @param $minvalue The min value
+ * @param $maxvalue The max value
+ * @param $restartvalue The starting value
+ * @param $cachevalue The cache value
+ * @param $cycledvalue True if cycled, false otherwise
+ * @param $startvalue The sequence start value when issueing a restart
+ * @return 0 success
+ * @return -3 rename error
+ * @return -4 comment error
+ * @return -5 owner error
+ * @return -6 get sequence props error
+ * @return -7 schema error
+ */
+ protected function _alterSequence($seqrs, $name, $comment, $owner, $schema, $increment,
+ $minvalue, $maxvalue, $restartvalue, $cachevalue, $cycledvalue, $startvalue) {
+
+ $this->fieldArrayClean($seqrs->fields);
+
+ // Comment
+ $status = $this->setComment('SEQUENCE', $seqrs->fields['seqname'], '', $comment);
+ if ($status != 0) {
+ return -4;
+ }
+
+ // Owner
+ $this->fieldClean($owner);
+ $status = $this->alterSequenceOwner($seqrs, $owner);
+ if ($status != 0) {
+ return -5;
+ }
+
+ // Props
+ $this->clean($increment);
+ $this->clean($minvalue);
+ $this->clean($maxvalue);
+ $this->clean($restartvalue);
+ $this->clean($cachevalue);
+ $this->clean($cycledvalue);
+ $this->clean($startvalue);
+ $status = $this->alterSequenceProps($seqrs, $increment, $minvalue,
+ $maxvalue, $restartvalue, $cachevalue, $cycledvalue, $startvalue);
+ if ($status != 0) {
+ return -6;
+ }
+
+ // Rename
+ $this->fieldClean($name);
+ $status = $this->alterSequenceName($seqrs, $name);
+ if ($status != 0) {
+ return -3;
+ }
+
+ // Schema
+ $this->clean($schema);
+ $status = $this->alterSequenceSchema($seqrs, $schema);
+ if ($status != 0) {
+ return -7;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Alters a sequence
+ * @param $sequence The name of the sequence
+ * @param $name The new name for the sequence
+ * @param $comment The comment on the sequence
+ * @param $owner The new owner for the sequence
+ * @param $schema The new schema for the sequence
+ * @param $increment The increment
+ * @param $minvalue The min value
+ * @param $maxvalue The max value
+ * @param $restartvalue The starting value
+ * @param $cachevalue The cache value
+ * @param $cycledvalue True if cycled, false otherwise
+ * @param $startvalue The sequence start value when issueing a restart
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 get existing sequence error
+ * @return $this->_alterSequence error code
+ */
+ public function alterSequence($sequence, $name, $comment, $owner = null, $schema = null, $increment = null,
+ $minvalue = null, $maxvalue = null, $restartvalue = null, $cachevalue = null, $cycledvalue = null, $startvalue = null) {
+
+ $this->fieldClean($sequence);
+
+ $data = $this->getSequence($sequence);
+
+ if ($data->recordCount() != 1) {
+ return -2;
+ }
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $status = $this->_alterSequence($data, $name, $comment, $owner, $schema, $increment,
+ $minvalue, $maxvalue, $restartvalue, $cachevalue, $cycledvalue, $startvalue);
+
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return $status;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Drops a given sequence
+ * @param $sequence Sequence name
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropSequence($sequence, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($sequence);
+
+ $sql = "DROP SEQUENCE \"{$f_schema}\".\"{$sequence}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ // View functions
+
+ /**
+ * Returns all details for a particular view
+ * @param $view The name of the view to retrieve
+ * @return View info
+ */
+ public function getView($view)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($view);
+
+ $sql = "
SELECT c.relname, n.nspname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
pg_catalog.pg_get_viewdef(c.oid, true) AS vwdefinition,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment
@@ -3260,17 +3351,18 @@ class Postgres extends ADODB_base {
LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = c.relnamespace)
WHERE (c.relname = '{$view}') AND n.nspname='{$c_schema}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns a list of all views in the database
- * @return All views
- */
- function getViews() {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns a list of all views in the database
+ * @return All views
+ */
+ public function getViews()
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "
SELECT c.relname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment
FROM pg_catalog.pg_class c
@@ -3278,17 +3370,18 @@ class Postgres extends ADODB_base {
WHERE (n.nspname='{$c_schema}') AND (c.relkind = 'v'::\"char\")
ORDER BY relname";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns a list of all views in the database
- * @return All views
- */
- function getMaterializedViews() {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns a list of all views in the database
+ * @return All views
+ */
+ public function getMaterializedViews()
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "
SELECT c.relname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment
FROM pg_catalog.pg_class c
@@ -3296,268 +3389,278 @@ class Postgres extends ADODB_base {
WHERE (n.nspname='{$c_schema}') AND (c.relkind = 'm'::\"char\")
ORDER BY relname";
- return $this->selectSet($sql);
- }
- /**
- * Updates a view.
- * @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, $comment) {
- return $this->createView($viewname, $definition, true, $comment);
- }
-
- /**
- * Creates a new view.
- * @param $viewname The name of the view to create
- * @param $definition The definition for the new view
- * @param $replace True to replace the view, false otherwise
- * @return 0 success
- */
- function createView($viewname, $definition, $replace, $comment) {
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($viewname);
-
- // Note: $definition not cleaned
-
- $sql = "CREATE ";
- if ($replace) {
- $sql .= "OR REPLACE ";
- }
-
- $sql .= "VIEW \"{$f_schema}\".\"{$viewname}\" AS {$definition}";
-
- $status = $this->execute($sql);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
-
- if ($comment != '') {
- $status = $this->setComment('VIEW', $viewname, '', $comment);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Rename a view
- * @param $vwrs The view recordSet returned by getView()
- * @param $name The new view's name
- * @return 0 success
- */
- function alterViewName($vwrs, $name) {
- // Rename (only if name has changed)
- /* $vwrs and $name are cleaned in _alterView */
- if (!empty($name) && ($name != $vwrs->fields['relname'])) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER VIEW \"{$f_schema}\".\"{$vwrs->fields['relname']}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status == 0) {
- $vwrs->fields['relname'] = $name;
- } else {
- return $status;
- }
-
- }
- return 0;
- }
-
- /**
- * Alter a view's owner
- * @param $vwrs The view recordSet returned by getView()
- * @param $name The new view's owner
- * @return 0 success
- */
- function alterViewOwner($vwrs, $owner = null) {
- /* $vwrs and $owner are cleaned in _alterView */
- if ((!empty($owner)) && ($vwrs->fields['relowner'] != $owner)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- // If owner has been changed, then do the alteration. We are
- // careful to avoid this generally as changing owner is a
- // superuser only function.
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$vwrs->fields['relname']}\" OWNER TO \"{$owner}\"";
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Alter a view's schema
- * @param $vwrs The view recordSet returned by getView()
- * @param $name The new view's schema
- * @return 0 success
- */
- function alterViewSchema($vwrs, $schema) {
- /* $vwrs and $schema are cleaned in _alterView */
- if (!empty($schema) && ($vwrs->fields['nspname'] != $schema)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- // If tablespace has been changed, then do the alteration. We
- // don't want to do this unnecessarily.
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$vwrs->fields['relname']}\" SET SCHEMA \"{$schema}\"";
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Protected method which alter a view
- * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
- * @param $vwrs The view recordSet returned by getView()
- * @param $name The new name for the view
- * @param $owner The new owner for the view
- * @param $comment The comment on the view
- * @return 0 success
- * @return -3 rename error
- * @return -4 comment error
- * @return -5 owner error
- * @return -6 schema error
- */
- protected
- function _alterView($vwrs, $name, $owner, $schema, $comment) {
-
- $this->fieldArrayClean($vwrs->fields);
-
- // Comment
- if ($this->setComment('VIEW', $vwrs->fields['relname'], '', $comment) != 0) {
- return -4;
- }
-
- // Owner
- $this->fieldClean($owner);
- $status = $this->alterViewOwner($vwrs, $owner);
- if ($status != 0) {
- return -5;
- }
-
- // Rename
- $this->fieldClean($name);
- $status = $this->alterViewName($vwrs, $name);
- if ($status != 0) {
- return -3;
- }
-
- // Schema
- $this->fieldClean($schema);
- $status = $this->alterViewSchema($vwrs, $schema);
- if ($status != 0) {
- return -6;
- }
-
- return 0;
- }
-
- /**
- * Alter view properties
- * @param $view The name of the view
- * @param $name The new name for the view
- * @param $owner The new owner for the view
- * @param $schema The new schema for the view
- * @param $comment The comment on the view
- * @return 0 success
- * @return -1 transaction error
- * @return -2 get existing view error
- * @return $this->_alterView error code
- */
- function alterView($view, $name, $owner, $schema, $comment) {
-
- $data = $this->getView($view);
- if ($data->recordCount() != 1) {
- return -2;
- }
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $status = $this->_alterView($data, $name, $owner, $schema, $comment);
-
- if ($status != 0) {
- $this->rollbackTransaction();
- return $status;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Drops a view.
- * @param $viewname The name of the view to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropView($viewname, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($viewname);
-
- $sql = "DROP VIEW \"{$f_schema}\".\"{$viewname}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- // Index functions
-
- /**
- * Grabs a list of indexes for a table
- * @param $table The name of a table whose indexes to retrieve
- * @param $unique Only get unique/pk indexes
- * @return A recordset
- */
- function getIndexes($table = '', $unique = false) {
- $this->clean($table);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Updates a view.
+ * @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
+ */
+ public function setView($viewname, $definition, $comment)
+ {
+ return $this->createView($viewname, $definition, true, $comment);
+ }
+
+ /**
+ * Creates a new view.
+ * @param $viewname The name of the view to create
+ * @param $definition The definition for the new view
+ * @param $replace True to replace the view, false otherwise
+ * @return 0 success
+ */
+ public function createView($viewname, $definition, $replace, $comment)
+ {
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($viewname);
+
+ // Note: $definition not cleaned
+
+ $sql = "CREATE ";
+ if ($replace) {
+ $sql .= "OR REPLACE ";
+ }
+
+ $sql .= "VIEW \"{$f_schema}\".\"{$viewname}\" AS {$definition}";
+
+ $status = $this->execute($sql);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ if ($comment != '') {
+ $status = $this->setComment('VIEW', $viewname, '', $comment);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Rename a view
+ * @param $vwrs The view recordSet returned by getView()
+ * @param $name The new view's name
+ * @return 0 success
+ */
+ public function alterViewName($vwrs, $name)
+ {
+ // Rename (only if name has changed)
+ /* $vwrs and $name are cleaned in _alterView */
+ if (!empty($name) && ($name != $vwrs->fields['relname'])) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER VIEW \"{$f_schema}\".\"{$vwrs->fields['relname']}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status == 0) {
+ $vwrs->fields['relname'] = $name;
+ } else {
+ return $status;
+ }
+
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a view's owner
+ * @param $vwrs The view recordSet returned by getView()
+ * @param $name The new view's owner
+ * @return 0 success
+ */
+ public function alterViewOwner($vwrs, $owner = null)
+ {
+ /* $vwrs and $owner are cleaned in _alterView */
+ if ((!empty($owner)) && ($vwrs->fields['relowner'] != $owner)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ // If owner has been changed, then do the alteration. We are
+ // careful to avoid this generally as changing owner is a
+ // superuser only function.
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$vwrs->fields['relname']}\" OWNER TO \"{$owner}\"";
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a view's schema
+ * @param $vwrs The view recordSet returned by getView()
+ * @param $name The new view's schema
+ * @return 0 success
+ */
+ public function alterViewSchema($vwrs, $schema)
+ {
+ /* $vwrs and $schema are cleaned in _alterView */
+ if (!empty($schema) && ($vwrs->fields['nspname'] != $schema)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ // If tablespace has been changed, then do the alteration. We
+ // don't want to do this unnecessarily.
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$vwrs->fields['relname']}\" SET SCHEMA \"{$schema}\"";
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Protected method which alter a view
+ * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
+ * @param $vwrs The view recordSet returned by getView()
+ * @param $name The new name for the view
+ * @param $owner The new owner for the view
+ * @param $comment The comment on the view
+ * @return 0 success
+ * @return -3 rename error
+ * @return -4 comment error
+ * @return -5 owner error
+ * @return -6 schema error
+ */
+ protected function _alterView($vwrs, $name, $owner, $schema, $comment)
+ {
+
+ $this->fieldArrayClean($vwrs->fields);
+
+ // Comment
+ if ($this->setComment('VIEW', $vwrs->fields['relname'], '', $comment) != 0) {
+ return -4;
+ }
+
+ // Owner
+ $this->fieldClean($owner);
+ $status = $this->alterViewOwner($vwrs, $owner);
+ if ($status != 0) {
+ return -5;
+ }
+
+ // Rename
+ $this->fieldClean($name);
+ $status = $this->alterViewName($vwrs, $name);
+ if ($status != 0) {
+ return -3;
+ }
+
+ // Schema
+ $this->fieldClean($schema);
+ $status = $this->alterViewSchema($vwrs, $schema);
+ if ($status != 0) {
+ return -6;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Alter view properties
+ * @param $view The name of the view
+ * @param $name The new name for the view
+ * @param $owner The new owner for the view
+ * @param $schema The new schema for the view
+ * @param $comment The comment on the view
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 get existing view error
+ * @return $this->_alterView error code
+ */
+ public function alterView($view, $name, $owner, $schema, $comment)
+ {
+
+ $data = $this->getView($view);
+ if ($data->recordCount() != 1) {
+ return -2;
+ }
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $status = $this->_alterView($data, $name, $owner, $schema, $comment);
+
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return $status;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Drops a view.
+ * @param $viewname The name of the view to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropView($viewname, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($viewname);
+
+ $sql = "DROP VIEW \"{$f_schema}\".\"{$viewname}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ // Index functions
+
+ /**
+ * Grabs a list of indexes for a table
+ * @param $table The name of a table whose indexes to retrieve
+ * @param $unique Only get unique/pk indexes
+ * @return A recordset
+ */
+ public function getIndexes($table = '', $unique = false)
+ {
+ $this->clean($table);
+
+ $sql = "
SELECT c2.relname AS indname, i.indisprimary, i.indisunique, i.indisclustered,
pg_catalog.pg_get_indexdef(i.indexrelid, 0, true) AS inddef
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
WHERE c.relname = '{$table}' AND pg_catalog.pg_table_is_visible(c.oid)
AND c.oid = i.indrelid AND i.indexrelid = c2.oid
";
- if ($unique) {
- $sql .= " AND i.indisunique ";
- }
+ if ($unique) {
+ $sql .= " AND i.indisunique ";
+ }
- $sql .= " ORDER BY c2.relname";
+ $sql .= " ORDER BY c2.relname";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * test if a table has been clustered on an index
- * @param $table The table to test
- *
- * @return true if the table has been already clustered
- */
- function alreadyClustered($table) {
+ /**
+ * test if a table has been clustered on an index
+ * @param $table The table to test
+ *
+ * @return true if the table has been already clustered
+ */
+ public function alreadyClustered($table)
+ {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
- $sql = "SELECT i.indisclustered
+ $sql = "SELECT i.indisclustered
FROM pg_catalog.pg_class c, pg_catalog.pg_index i
WHERE c.relname = '{$table}'
AND c.oid = i.indrelid AND i.indisclustered
@@ -3565,161 +3668,166 @@ class Postgres extends ADODB_base {
WHERE nspname='{$c_schema}')
";
- $v = $this->selectSet($sql);
-
- if ($v->recordCount() == 0) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Creates an index
- * @param $name The index name
- * @param $table The table on which to add the index
- * @param $columns An array of columns that form the index
- * or a string expression for a functional index
- * @param $type The index type
- * @param $unique True if unique, false otherwise
- * @param $where Index predicate ('' for none)
- * @param $tablespace The tablespaces ('' means none/default)
- * @return 0 success
- */
- function createIndex($name, $table, $columns, $type, $unique, $where, $tablespace, $concurrently) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
- $this->fieldClean($table);
-
- $sql = "CREATE";
- if ($unique) {
- $sql .= " UNIQUE";
- }
-
- $sql .= " INDEX";
- if ($concurrently) {
- $sql .= " CONCURRENTLY";
- }
-
- $sql .= " \"{$name}\" ON \"{$f_schema}\".\"{$table}\" USING {$type} ";
-
- if (is_array($columns)) {
- $this->arrayClean($columns);
- $sql .= "(\"" . implode('","', $columns) . "\")";
- } else {
- $sql .= "(" . $columns . ")";
- }
-
- // Tablespace
- if ($this->hasTablespaces() && $tablespace != '') {
- $this->fieldClean($tablespace);
- $sql .= " TABLESPACE \"{$tablespace}\"";
- }
-
- // Predicate
- if (trim($where) != '') {
- $sql .= " WHERE ({$where})";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Removes an index from the database
- * @param $index The index to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropIndex($index, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($index);
-
- $sql = "DROP INDEX \"{$f_schema}\".\"{$index}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Rebuild indexes
- * @param $type 'DATABASE' or 'TABLE' or 'INDEX'
- * @param $name The name of the specific database, table, or index to be reindexed
- * @param $force If true, recreates indexes forcedly in PostgreSQL 7.0-7.1, forces rebuild of system indexes in 7.2-7.3, ignored in >=7.4
- */
- function reindex($type, $name, $force = false) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
- switch ($type) {
- case 'DATABASE':
- $sql = "REINDEX {$type} \"{$name}\"";
- if ($force) {
- $sql .= ' FORCE';
- }
-
- break;
- case 'TABLE':
- case 'INDEX':
- $sql = "REINDEX {$type} \"{$f_schema}\".\"{$name}\"";
- if ($force) {
- $sql .= ' FORCE';
- }
-
- break;
- default:
- return -1;
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Clusters an index
- * @param $index The name of the index
- * @param $table The table the index is on
- * @return 0 success
- */
- function clusterIndex($table = '', $index = '') {
-
- $sql = 'CLUSTER';
-
- // We don't bother with a transaction here, as there's no point rolling
- // back an expensive cluster if a cheap analyze fails for whatever reason
-
- if (!empty($table)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $sql .= " \"{$f_schema}\".\"{$table}\"";
-
- if (!empty($index)) {
- $this->fieldClean($index);
- $sql .= " USING \"{$index}\"";
- }
- }
-
- return $this->execute($sql);
- }
-
- // Constraint functions
-
- /**
- * Returns a list of all constraints on a table
- * @param $table The table to find rules for
- * @return A recordset
- */
- function getConstraints($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- // This SQL is greatly complicated by the need to retrieve
- // index clustering information for primary and unique constraints
- $sql = "SELECT
+ $v = $this->selectSet($sql);
+
+ if ($v->recordCount() == 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates an index
+ * @param $name The index name
+ * @param $table The table on which to add the index
+ * @param $columns An array of columns that form the index
+ * or a string expression for a functional index
+ * @param $type The index type
+ * @param $unique True if unique, false otherwise
+ * @param $where Index predicate ('' for none)
+ * @param $tablespace The tablespaces ('' means none/default)
+ * @return 0 success
+ */
+ public function createIndex($name, $table, $columns, $type, $unique, $where, $tablespace, $concurrently)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+ $this->fieldClean($table);
+
+ $sql = "CREATE";
+ if ($unique) {
+ $sql .= " UNIQUE";
+ }
+
+ $sql .= " INDEX";
+ if ($concurrently) {
+ $sql .= " CONCURRENTLY";
+ }
+
+ $sql .= " \"{$name}\" ON \"{$f_schema}\".\"{$table}\" USING {$type} ";
+
+ if (is_array($columns)) {
+ $this->arrayClean($columns);
+ $sql .= "(\"" . implode('","', $columns) . "\")";
+ } else {
+ $sql .= "(" . $columns . ")";
+ }
+
+ // Tablespace
+ if ($this->hasTablespaces() && $tablespace != '') {
+ $this->fieldClean($tablespace);
+ $sql .= " TABLESPACE \"{$tablespace}\"";
+ }
+
+ // Predicate
+ if (trim($where) != '') {
+ $sql .= " WHERE ({$where})";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes an index from the database
+ * @param $index The index to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropIndex($index, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($index);
+
+ $sql = "DROP INDEX \"{$f_schema}\".\"{$index}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Rebuild indexes
+ * @param $type 'DATABASE' or 'TABLE' or 'INDEX'
+ * @param $name The name of the specific database, table, or index to be reindexed
+ * @param $force If true, recreates indexes forcedly in PostgreSQL 7.0-7.1, forces rebuild of system indexes in 7.2-7.3, ignored in >=7.4
+ */
+ public function reindex($type, $name, $force = false)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+ switch ($type) {
+ case 'DATABASE':
+ $sql = "REINDEX {$type} \"{$name}\"";
+ if ($force) {
+ $sql .= ' FORCE';
+ }
+
+ break;
+ case 'TABLE':
+ case 'INDEX':
+ $sql = "REINDEX {$type} \"{$f_schema}\".\"{$name}\"";
+ if ($force) {
+ $sql .= ' FORCE';
+ }
+
+ break;
+ default:
+ return -1;
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Clusters an index
+ * @param $index The name of the index
+ * @param $table The table the index is on
+ * @return 0 success
+ */
+ public function clusterIndex($table = '', $index = '')
+ {
+
+ $sql = 'CLUSTER';
+
+ // We don't bother with a transaction here, as there's no point rolling
+ // back an expensive cluster if a cheap analyze fails for whatever reason
+
+ if (!empty($table)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $sql .= " \"{$f_schema}\".\"{$table}\"";
+
+ if (!empty($index)) {
+ $this->fieldClean($index);
+ $sql .= " USING \"{$index}\"";
+ }
+ }
+
+ return $this->execute($sql);
+ }
+
+ // Constraint functions
+
+ /**
+ * Returns a list of all constraints on a table
+ * @param $table The table to find rules for
+ * @return A recordset
+ */
+ public function getConstraints($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ // This SQL is greatly complicated by the need to retrieve
+ // index clustering information for primary and unique constraints
+ $sql = "SELECT
pc.conname,
pg_catalog.pg_get_constraintdef(pc.oid, true) AS consrc,
pc.contype,
@@ -3748,24 +3856,25 @@ class Postgres extends ADODB_base {
1
";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns a list of all constraints on a table,
- * including constraint name, definition, related col and referenced namespace,
- * table and col if needed
- * @param $table the table where we are looking for fk
- * @return a recordset
- */
- function getConstraintsWithFields($table) {
-
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- // get the max number of col used in a constraint for the table
- $sql = "SELECT DISTINCT
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns a list of all constraints on a table,
+ * including constraint name, definition, related col and referenced namespace,
+ * table and col if needed
+ * @param $table the table where we are looking for fk
+ * @return a recordset
+ */
+ public function getConstraintsWithFields($table)
+ {
+
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ // get the max number of col used in a constraint for the table
+ $sql = "SELECT DISTINCT
max(SUBSTRING(array_dims(c.conkey) FROM \$patern\$^\\[.*:(.*)\\]$\$patern\$)) as nb
FROM pg_catalog.pg_constraint AS c
JOIN pg_catalog.pg_class AS r ON (c.conrelid=r.oid)
@@ -3773,15 +3882,15 @@ class Postgres extends ADODB_base {
WHERE
r.relname = '{$table}' AND ns.nspname='{$c_schema}'";
- $rs = $this->selectSet($sql);
+ $rs = $this->selectSet($sql);
- if ($rs->EOF) {
- $max_col = 0;
- } else {
- $max_col = $rs->fields['nb'];
- }
+ if ($rs->EOF) {
+ $max_col = 0;
+ } else {
+ $max_col = $rs->fields['nb'];
+ }
- $sql = '
+ $sql = '
SELECT
c.oid AS conid, c.contype, c.conname, pg_catalog.pg_get_constraintdef(c.oid, true) AS consrc,
ns1.nspname as p_schema, r1.relname as p_table, ns2.nspname as f_schema,
@@ -3792,294 +3901,300 @@ class Postgres extends ADODB_base {
pg_catalog.pg_constraint AS c
JOIN pg_catalog.pg_class AS r1 ON (c.conrelid=r1.oid)
JOIN pg_catalog.pg_attribute AS f1 ON (f1.attrelid=r1.oid AND (f1.attnum=c.conkey[1]';
- for ($i = 2; $i <= $rs->fields['nb']; $i++) {
- $sql .= " OR f1.attnum=c.conkey[$i]";
- }
- $sql .= '))
+ for ($i = 2; $i <= $rs->fields['nb']; $i++) {
+ $sql .= " OR f1.attnum=c.conkey[$i]";
+ }
+ $sql .= '))
JOIN pg_catalog.pg_namespace AS ns1 ON r1.relnamespace=ns1.oid
LEFT JOIN (
pg_catalog.pg_class AS r2 JOIN pg_catalog.pg_namespace AS ns2 ON (r2.relnamespace=ns2.oid)
) ON (c.confrelid=r2.oid)
LEFT JOIN pg_catalog.pg_attribute AS f2 ON
(f2.attrelid=r2.oid AND ((c.confkey[1]=f2.attnum AND c.conkey[1]=f1.attnum)';
- for ($i = 2; $i <= $rs->fields['nb']; $i++) {
- $sql .= " OR (c.confkey[$i]=f2.attnum AND c.conkey[$i]=f1.attnum)";
- }
+ for ($i = 2; $i <= $rs->fields['nb']; $i++) {
+ $sql .= " OR (c.confkey[$i]=f2.attnum AND c.conkey[$i]=f1.attnum)";
+ }
- $sql .= sprintf("))
+ $sql .= sprintf("))
WHERE
r1.relname = '%s' AND ns1.nspname='%s'
ORDER BY 1", $table, $c_schema);
- return $this->selectSet($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
- * @param $tablespace (optional) The tablespace for the schema, '' indicates default.
- * @return 0 success
- * @return -1 no fields given
- */
- function addPrimaryKey($table, $fields, $name = '', $tablespace = '') {
- if (!is_array($fields) || sizeof($fields) == 0) {
- return -1;
- }
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldArrayClean($fields);
- $this->fieldClean($name);
- $this->fieldClean($tablespace);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
- if ($name != '') {
- $sql .= "CONSTRAINT \"{$name}\" ";
- }
-
- $sql .= "PRIMARY KEY (\"" . join('","', $fields) . "\")";
-
- if ($tablespace != '' && $this->hasTablespaces()) {
- $sql .= " USING INDEX TABLESPACE \"{$tablespace}\"";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Adds a unique constraint to a table
- * @param $table The table to which to add the unique key
- * @param $fields (array) An array of fields over which to add the unique key
- * @param $name (optional) The name to give the key, otherwise default name is assigned
- * @param $tablespace (optional) The tablespace for the schema, '' indicates default.
- * @return 0 success
- * @return -1 no fields given
- */
- function addUniqueKey($table, $fields, $name = '', $tablespace = '') {
- if (!is_array($fields) || sizeof($fields) == 0) {
- return -1;
- }
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldArrayClean($fields);
- $this->fieldClean($name);
- $this->fieldClean($tablespace);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
- if ($name != '') {
- $sql .= "CONSTRAINT \"{$name}\" ";
- }
-
- $sql .= "UNIQUE (\"" . join('","', $fields) . "\")";
-
- if ($tablespace != '' && $this->hasTablespaces()) {
- $sql .= " USING INDEX TABLESPACE \"{$tablespace}\"";
- }
-
- 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 = '') {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($name);
- // @@ How the heck do you clean a definition???
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
- if ($name != '') {
- $sql .= "CONSTRAINT \"{$name}\" ";
- }
-
- $sql .= "CHECK ({$definition})";
-
- 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) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $c_table = $table;
- $this->fieldClean($table);
- $this->clean($c_table);
- $this->clean($name);
-
- // Begin transaction
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -2;
- }
-
- // Properly lock the table
- $sql = "LOCK TABLE \"{$f_schema}\".\"{$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_catalog.pg_class WHERE relname='{$c_table}'
+ return $this->selectSet($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
+ * @param $tablespace (optional) The tablespace for the schema, '' indicates default.
+ * @return 0 success
+ * @return -1 no fields given
+ */
+ public function addPrimaryKey($table, $fields, $name = '', $tablespace = '')
+ {
+ if (!is_array($fields) || sizeof($fields) == 0) {
+ return -1;
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldArrayClean($fields);
+ $this->fieldClean($name);
+ $this->fieldClean($tablespace);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
+ if ($name != '') {
+ $sql .= "CONSTRAINT \"{$name}\" ";
+ }
+
+ $sql .= "PRIMARY KEY (\"" . join('","', $fields) . "\")";
+
+ if ($tablespace != '' && $this->hasTablespaces()) {
+ $sql .= " USING INDEX TABLESPACE \"{$tablespace}\"";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adds a unique constraint to a table
+ * @param $table The table to which to add the unique key
+ * @param $fields (array) An array of fields over which to add the unique key
+ * @param $name (optional) The name to give the key, otherwise default name is assigned
+ * @param $tablespace (optional) The tablespace for the schema, '' indicates default.
+ * @return 0 success
+ * @return -1 no fields given
+ */
+ public function addUniqueKey($table, $fields, $name = '', $tablespace = '')
+ {
+ if (!is_array($fields) || sizeof($fields) == 0) {
+ return -1;
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldArrayClean($fields);
+ $this->fieldClean($name);
+ $this->fieldClean($tablespace);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
+ if ($name != '') {
+ $sql .= "CONSTRAINT \"{$name}\" ";
+ }
+
+ $sql .= "UNIQUE (\"" . join('","', $fields) . "\")";
+
+ if ($tablespace != '' && $this->hasTablespaces()) {
+ $sql .= " USING INDEX TABLESPACE \"{$tablespace}\"";
+ }
+
+ 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
+ */
+ public function addCheckConstraint($table, $definition, $name = '')
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($name);
+ // @@ How the heck do you clean a definition???
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
+ if ($name != '') {
+ $sql .= "CONSTRAINT \"{$name}\" ";
+ }
+
+ $sql .= "CHECK ({$definition})";
+
+ 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
+ */
+ public function dropCheckConstraint($table, $name)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $c_table = $table;
+ $this->fieldClean($table);
+ $this->clean($c_table);
+ $this->clean($name);
+
+ // Begin transaction
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -2;
+ }
+
+ // Properly lock the table
+ $sql = "LOCK TABLE \"{$f_schema}\".\"{$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_catalog.pg_class WHERE relname='{$c_table}'
AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE
nspname = '{$c_schema}')) 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
+ $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_catalog.pg_class WHERE relname='{$c_table}'
AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE
nspname = '{$c_schema}')))
WHERE relname='{$c_table}'";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -4;
- }
-
- // Otherwise, close the transaction
- return $this->endTransaction();
- }
-
- /**
- * Adds a foreign key constraint to a table
- * @param $targschema The schema that houses the target table to which to add the foreign key
- * @param $targtable The table to which to add the foreign key
- * @param $target The table that contains the target columns
- * @param $sfields (array) An array of source fields over which to add the foreign key
- * @param $tfields (array) An array of target fields over which to add the foreign key
- * @param $upd_action The action for updates (eg. RESTRICT)
- * @param $del_action The action for deletes (eg. RESTRICT)
- * @param $match The match type (eg. MATCH FULL)
- * @param $deferrable The deferrability (eg. NOT DEFERRABLE)
- * @param $intially The initial deferrability (eg. INITIALLY IMMEDIATE)
- * @param $name (optional) The name to give the key, otherwise default name is assigned
- * @return 0 success
- * @return -1 no fields given
- */
- function addForeignKey($table, $targschema, $targtable, $sfields, $tfields, $upd_action, $del_action,
- $match, $deferrable, $initially, $name = '') {
- if (!is_array($sfields) || sizeof($sfields) == 0 ||
- !is_array($tfields) || sizeof($tfields) == 0) {
- return -1;
- }
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($targschema);
- $this->fieldClean($targtable);
- $this->fieldArrayClean($sfields);
- $this->fieldArrayClean($tfields);
- $this->fieldClean($name);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
- if ($name != '') {
- $sql .= "CONSTRAINT \"{$name}\" ";
- }
-
- $sql .= "FOREIGN KEY (\"" . join('","', $sfields) . "\") ";
- // Target table needs to be fully qualified
- $sql .= "REFERENCES \"{$targschema}\".\"{$targtable}\"(\"" . join('","', $tfields) . "\") ";
- if ($match != $this->fkmatches[0]) {
- $sql .= " {$match}";
- }
-
- if ($upd_action != $this->fkactions[0]) {
- $sql .= " ON UPDATE {$upd_action}";
- }
-
- if ($del_action != $this->fkactions[0]) {
- $sql .= " ON DELETE {$del_action}";
- }
-
- if ($deferrable != $this->fkdeferrable[0]) {
- $sql .= " {$deferrable}";
- }
-
- if ($initially != $this->fkinitial[0]) {
- $sql .= " {$initially}";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Removes a constraint from a relation
- * @param $constraint The constraint to drop
- * @param $relation The relation from which to drop
- * @param $type The type of constraint (c, f, u or p)
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropConstraint($constraint, $relation, $type, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($constraint);
- $this->fieldClean($relation);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$relation}\" DROP CONSTRAINT \"{$constraint}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * A function for getting all columns linked by foreign keys given a group of tables
- * @param $tables multi dimensional assoc array that holds schema and table name
- * @return A recordset of linked tables and columns
- * @return -1 $tables isn't an array
- */
- function getLinkingKeys($tables) {
- if (!is_array($tables)) {
- return -1;
- }
-
- $this->clean($tables[0]['tablename']);
- $this->clean($tables[0]['schemaname']);
- $tables_list = "'{$tables[0]['tablename']}'";
- $schema_list = "'{$tables[0]['schemaname']}'";
- $schema_tables_list = "'{$tables[0]['schemaname']}.{$tables[0]['tablename']}'";
-
- for ($i = 1; $i < sizeof($tables); $i++) {
- $this->clean($tables[$i]['tablename']);
- $this->clean($tables[$i]['schemaname']);
- $tables_list .= ", '{$tables[$i]['tablename']}'";
- $schema_list .= ", '{$tables[$i]['schemaname']}'";
- $schema_tables_list .= ", '{$tables[$i]['schemaname']}.{$tables[$i]['tablename']}'";
- }
-
- $maxDimension = 1;
-
- $sql = "
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -4;
+ }
+
+ // Otherwise, close the transaction
+ return $this->endTransaction();
+ }
+
+ /**
+ * Adds a foreign key constraint to a table
+ * @param $targschema The schema that houses the target table to which to add the foreign key
+ * @param $targtable The table to which to add the foreign key
+ * @param $target The table that contains the target columns
+ * @param $sfields (array) An array of source fields over which to add the foreign key
+ * @param $tfields (array) An array of target fields over which to add the foreign key
+ * @param $upd_action The action for updates (eg. RESTRICT)
+ * @param $del_action The action for deletes (eg. RESTRICT)
+ * @param $match The match type (eg. MATCH FULL)
+ * @param $deferrable The deferrability (eg. NOT DEFERRABLE)
+ * @param $intially The initial deferrability (eg. INITIALLY IMMEDIATE)
+ * @param $name (optional) The name to give the key, otherwise default name is assigned
+ * @return 0 success
+ * @return -1 no fields given
+ */
+ public function addForeignKey($table, $targschema, $targtable, $sfields, $tfields, $upd_action, $del_action,
+ $match, $deferrable, $initially, $name = '') {
+ if (!is_array($sfields) || sizeof($sfields) == 0 ||
+ !is_array($tfields) || sizeof($tfields) == 0) {
+ return -1;
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($targschema);
+ $this->fieldClean($targtable);
+ $this->fieldArrayClean($sfields);
+ $this->fieldArrayClean($tfields);
+ $this->fieldClean($name);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD ";
+ if ($name != '') {
+ $sql .= "CONSTRAINT \"{$name}\" ";
+ }
+
+ $sql .= "FOREIGN KEY (\"" . join('","', $sfields) . "\") ";
+ // Target table needs to be fully qualified
+ $sql .= "REFERENCES \"{$targschema}\".\"{$targtable}\"(\"" . join('","', $tfields) . "\") ";
+ if ($match != $this->fkmatches[0]) {
+ $sql .= " {$match}";
+ }
+
+ if ($upd_action != $this->fkactions[0]) {
+ $sql .= " ON UPDATE {$upd_action}";
+ }
+
+ if ($del_action != $this->fkactions[0]) {
+ $sql .= " ON DELETE {$del_action}";
+ }
+
+ if ($deferrable != $this->fkdeferrable[0]) {
+ $sql .= " {$deferrable}";
+ }
+
+ if ($initially != $this->fkinitial[0]) {
+ $sql .= " {$initially}";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes a constraint from a relation
+ * @param $constraint The constraint to drop
+ * @param $relation The relation from which to drop
+ * @param $type The type of constraint (c, f, u or p)
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropConstraint($constraint, $relation, $type, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($constraint);
+ $this->fieldClean($relation);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$relation}\" DROP CONSTRAINT \"{$constraint}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * A function for getting all columns linked by foreign keys given a group of tables
+ * @param $tables multi dimensional assoc array that holds schema and table name
+ * @return A recordset of linked tables and columns
+ * @return -1 $tables isn't an array
+ */
+ public function getLinkingKeys($tables)
+ {
+ if (!is_array($tables)) {
+ return -1;
+ }
+
+ $this->clean($tables[0]['tablename']);
+ $this->clean($tables[0]['schemaname']);
+ $tables_list = "'{$tables[0]['tablename']}'";
+ $schema_list = "'{$tables[0]['schemaname']}'";
+ $schema_tables_list = "'{$tables[0]['schemaname']}.{$tables[0]['tablename']}'";
+
+ for ($i = 1; $i < sizeof($tables); $i++) {
+ $this->clean($tables[$i]['tablename']);
+ $this->clean($tables[$i]['schemaname']);
+ $tables_list .= ", '{$tables[$i]['tablename']}'";
+ $schema_list .= ", '{$tables[$i]['schemaname']}'";
+ $schema_tables_list .= ", '{$tables[$i]['schemaname']}.{$tables[$i]['tablename']}'";
+ }
+
+ $maxDimension = 1;
+
+ $sql = "
SELECT DISTINCT
array_dims(pc.conkey) AS arr_dim,
pgc1.relname AS p_table
@@ -4092,23 +4207,23 @@ class Postgres extends ADODB_base {
AND pgc1.relname IN ($tables_list)
";
- //parse our output to find the highest dimension of foreign keys since pc.conkey is stored in an array
- $rs = $this->selectSet($sql);
- while (!$rs->EOF) {
- $arrData = explode(':', $rs->fields['arr_dim']);
- $tmpDimension = intval(substr($arrData[1], 0, strlen($arrData[1] - 1)));
- $maxDimension = $tmpDimension > $maxDimension ? $tmpDimension : $maxDimension;
- $rs->MoveNext();
- }
-
- //we know the highest index for foreign keys that conkey goes up to, expand for us in an IN query
- $cons_str = '( (pfield.attnum = conkey[1] AND cfield.attnum = confkey[1]) ';
- for ($i = 2; $i <= $maxDimension; $i++) {
- $cons_str .= "OR (pfield.attnum = conkey[{$i}] AND cfield.attnum = confkey[{$i}]) ";
- }
- $cons_str .= ') ';
-
- $sql = "
+ //parse our output to find the highest dimension of foreign keys since pc.conkey is stored in an array
+ $rs = $this->selectSet($sql);
+ while (!$rs->EOF) {
+ $arrData = explode(':', $rs->fields['arr_dim']);
+ $tmpDimension = intval(substr($arrData[1], 0, strlen($arrData[1] - 1)));
+ $maxDimension = $tmpDimension > $maxDimension ? $tmpDimension : $maxDimension;
+ $rs->MoveNext();
+ }
+
+ //we know the highest index for foreign keys that conkey goes up to, expand for us in an IN query
+ $cons_str = '( (pfield.attnum = conkey[1] AND cfield.attnum = confkey[1]) ';
+ for ($i = 2; $i <= $maxDimension; $i++) {
+ $cons_str .= "OR (pfield.attnum = conkey[{$i}] AND cfield.attnum = confkey[{$i}]) ";
+ }
+ $cons_str .= ') ';
+
+ $sql = "
SELECT
pgc1.relname AS p_table,
pgc2.relname AS f_table,
@@ -4136,26 +4251,27 @@ class Postgres extends ADODB_base {
AND pgns1.nspname || '.' || pgc1.relname IN ($schema_tables_list)
AND pgns2.nspname || '.' || pgc2.relname IN ($schema_tables_list)
";
- return $this->selectSet($sql);
- }
-
- /**
- * Finds the foreign keys that refer to the specified table
- * @param $table The table to find referrers for
- * @return A recordset
- */
- function getReferrers($table) {
- $this->clean($table);
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- $c_schema = $this->_schema;
- $this->clean($c_schema);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Finds the foreign keys that refer to the specified table
+ * @param $table The table to find referrers for
+ * @return A recordset
+ */
+ public function getReferrers($table)
+ {
+ $this->clean($table);
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+
+ $sql = "
SELECT
pn.nspname,
pl.relname,
@@ -4175,22 +4291,23 @@ class Postgres extends ADODB_base {
ORDER BY 1,2,3
";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Domain functions
+ // Domain functions
- /**
- * Gets all information for a single domain
- * @param $domain The name of the domain to fetch
- * @return A recordset
- */
- function getDomain($domain) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($domain);
+ /**
+ * Gets all information for a single domain
+ * @param $domain The name of the domain to fetch
+ * @return A recordset
+ */
+ public function getDomain($domain)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($domain);
- $sql = "
+ $sql = "
SELECT
t.typname AS domname,
pg_catalog.format_type(t.typbasetype, t.typtypmod) AS domtype,
@@ -4206,18 +4323,19 @@ class Postgres extends ADODB_base {
AND t.typnamespace = (SELECT oid FROM pg_catalog.pg_namespace
WHERE nspname = '{$c_schema}')";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Return all domains in current schema. Excludes domain constraints.
- * @return All tables, sorted alphabetically
- */
- function getDomains() {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
+ /**
+ * Return all domains in current schema. Excludes domain constraints.
+ * @return All tables, sorted alphabetically
+ */
+ public function getDomains()
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
- $sql = "
+ $sql = "
SELECT
t.typname AS domname,
pg_catalog.format_type(t.typbasetype, t.typtypmod) AS domtype,
@@ -4233,20 +4351,21 @@ class Postgres extends ADODB_base {
WHERE nspname='{$c_schema}')
ORDER BY t.typname";
- return $this->selectSet($sql);
- }
-
- /**
- * Get domain constraints
- * @param $domain The name of the domain whose constraints to fetch
- * @return A recordset
- */
- function getDomainConstraints($domain) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($domain);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Get domain constraints
+ * @param $domain The name of the domain whose constraints to fetch
+ * @return A recordset
+ */
+ public function getDomainConstraints($domain)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($domain);
+
+ $sql = "
SELECT
conname,
contype,
@@ -4263,204 +4382,210 @@ class Postgres extends ADODB_base {
)
ORDER BY conname";
- return $this->selectSet($sql);
- }
-
- /**
- * Creates a domain
- * @param $domain The name of the domain to create
- * @param $type The base type for the domain
- * @param $length Optional type length
- * @param $array True for array type, false otherwise
- * @param $notnull True for NOT NULL, false otherwise
- * @param $default Default value for domain
- * @param $check A CHECK constraint if there is one
- * @return 0 success
- */
- function createDomain($domain, $type, $length, $array, $notnull, $default, $check) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($domain);
-
- $sql = "CREATE DOMAIN \"{$f_schema}\".\"{$domain}\" AS ";
-
- if ($length == '') {
- $sql .= $type;
- } else {
- switch ($type) {
- // Have to account for weird placing of length for with/without
- // time zone types
- case 'timestamp with time zone':
- case 'timestamp without time zone':
- $qual = substr($type, 9);
- $sql .= "timestamp({$length}){$qual}";
- break;
- case 'time with time zone':
- case 'time without time zone':
- $qual = substr($type, 4);
- $sql .= "time({$length}){$qual}";
- break;
- default:
- $sql .= "{$type}({$length})";
- }
- }
-
- // Add array qualifier, if requested
- if ($array) {
- $sql .= '[]';
- }
-
- if ($notnull) {
- $sql .= ' NOT NULL';
- }
-
- if ($default != '') {
- $sql .= " DEFAULT {$default}";
- }
-
- if ($this->hasDomainConstraints() && $check != '') {
- $sql .= " CHECK ({$check})";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Alters a domain
- * @param $domain The domain to alter
- * @param $domdefault The domain default
- * @param $domnotnull True for NOT NULL, false otherwise
- * @param $domowner The domain owner
- * @return 0 success
- * @return -1 transaction error
- * @return -2 default error
- * @return -3 not null error
- * @return -4 owner error
- */
- function alterDomain($domain, $domdefault, $domnotnull, $domowner) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($domain);
- $this->fieldClean($domowner);
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Default
- if ($domdefault == '') {
- $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" DROP DEFAULT";
- } else {
- $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" SET DEFAULT {$domdefault}";
- }
-
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -2;
- }
-
- // NOT NULL
- if ($domnotnull) {
- $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" SET NOT NULL";
- } else {
- $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" DROP NOT NULL";
- }
-
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
-
- // Owner
- $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" OWNER TO \"{$domowner}\"";
-
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -4;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Drops a domain.
- * @param $domain The name of the domain to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropDomain($domain, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($domain);
-
- $sql = "DROP DOMAIN \"{$f_schema}\".\"{$domain}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Adds a check constraint to a domain
- * @param $domain The domain 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 addDomainCheckConstraint($domain, $definition, $name = '') {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($domain);
- $this->fieldClean($name);
-
- $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" ADD ";
- if ($name != '') {
- $sql .= "CONSTRAINT \"{$name}\" ";
- }
-
- $sql .= "CHECK ({$definition})";
-
- return $this->execute($sql);
- }
-
- /**
- * Drops a domain constraint
- * @param $domain The domain from which to remove the constraint
- * @param $constraint The constraint to remove
- * @param $cascade True to cascade, false otherwise
- * @return 0 success
- */
- function dropDomainConstraint($domain, $constraint, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($domain);
- $this->fieldClean($constraint);
-
- $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" DROP CONSTRAINT \"{$constraint}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- // Function functions
-
- /**
- * Returns all details for a particular function
- * @param $func The name of the function to retrieve
- * @return Function info
- */
- function getFunction($function_oid) {
- $this->clean($function_oid);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a domain
+ * @param $domain The name of the domain to create
+ * @param $type The base type for the domain
+ * @param $length Optional type length
+ * @param $array True for array type, false otherwise
+ * @param $notnull True for NOT NULL, false otherwise
+ * @param $default Default value for domain
+ * @param $check A CHECK constraint if there is one
+ * @return 0 success
+ */
+ public function createDomain($domain, $type, $length, $array, $notnull, $default, $check)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($domain);
+
+ $sql = "CREATE DOMAIN \"{$f_schema}\".\"{$domain}\" AS ";
+
+ if ($length == '') {
+ $sql .= $type;
+ } else {
+ switch ($type) {
+ // Have to account for weird placing of length for with/without
+ // time zone types
+ case 'timestamp with time zone':
+ case 'timestamp without time zone':
+ $qual = substr($type, 9);
+ $sql .= "timestamp({$length}){$qual}";
+ break;
+ case 'time with time zone':
+ case 'time without time zone':
+ $qual = substr($type, 4);
+ $sql .= "time({$length}){$qual}";
+ break;
+ default:
+ $sql .= "{$type}({$length})";
+ }
+ }
+
+ // Add array qualifier, if requested
+ if ($array) {
+ $sql .= '[]';
+ }
+
+ if ($notnull) {
+ $sql .= ' NOT NULL';
+ }
+
+ if ($default != '') {
+ $sql .= " DEFAULT {$default}";
+ }
+
+ if ($this->hasDomainConstraints() && $check != '') {
+ $sql .= " CHECK ({$check})";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Alters a domain
+ * @param $domain The domain to alter
+ * @param $domdefault The domain default
+ * @param $domnotnull True for NOT NULL, false otherwise
+ * @param $domowner The domain owner
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 default error
+ * @return -3 not null error
+ * @return -4 owner error
+ */
+ public function alterDomain($domain, $domdefault, $domnotnull, $domowner)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($domain);
+ $this->fieldClean($domowner);
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Default
+ if ($domdefault == '') {
+ $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" DROP DEFAULT";
+ } else {
+ $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" SET DEFAULT {$domdefault}";
+ }
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+
+ // NOT NULL
+ if ($domnotnull) {
+ $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" SET NOT NULL";
+ } else {
+ $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" DROP NOT NULL";
+ }
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+
+ // Owner
+ $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" OWNER TO \"{$domowner}\"";
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -4;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Drops a domain.
+ * @param $domain The name of the domain to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropDomain($domain, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($domain);
+
+ $sql = "DROP DOMAIN \"{$f_schema}\".\"{$domain}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adds a check constraint to a domain
+ * @param $domain The domain 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
+ */
+ public function addDomainCheckConstraint($domain, $definition, $name = '')
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($domain);
+ $this->fieldClean($name);
+
+ $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" ADD ";
+ if ($name != '') {
+ $sql .= "CONSTRAINT \"{$name}\" ";
+ }
+
+ $sql .= "CHECK ({$definition})";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Drops a domain constraint
+ * @param $domain The domain from which to remove the constraint
+ * @param $constraint The constraint to remove
+ * @param $cascade True to cascade, false otherwise
+ * @return 0 success
+ */
+ public function dropDomainConstraint($domain, $constraint, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($domain);
+ $this->fieldClean($constraint);
+
+ $sql = "ALTER DOMAIN \"{$f_schema}\".\"{$domain}\" DROP CONSTRAINT \"{$constraint}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ // Function functions
+
+ /**
+ * Returns all details for a particular function
+ * @param $func The name of the function to retrieve
+ * @return Function info
+ */
+ public function getFunction($function_oid)
+ {
+ $this->clean($function_oid);
+
+ $sql = "
SELECT
pc.oid AS prooid, proname,
pg_catalog.pg_get_userbyid(proowner) AS proowner,
@@ -4483,32 +4608,33 @@ class Postgres extends ADODB_base {
AND pc.pronamespace = pn.oid
";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns a list of all functions in the database
- * @param $all If true, will find all available functions, if false just those in search path
- * @param $type If not null, will find all functions with return value = type
- *
- * @return All functions
- */
- function getFunctions($all = false, $type = null) {
- if ($all) {
- $where = 'pg_catalog.pg_function_is_visible(p.oid)';
- $distinct = 'DISTINCT ON (p.proname)';
-
- if ($type) {
- $where .= " AND p.prorettype = (select oid from pg_catalog.pg_type p where p.typname = 'trigger') ";
- }
- } else {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $where = "n.nspname = '{$c_schema}'";
- $distinct = '';
- }
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns a list of all functions in the database
+ * @param $all If true, will find all available functions, if false just those in search path
+ * @param $type If not null, will find all functions with return value = type
+ *
+ * @return All functions
+ */
+ public function getFunctions($all = false, $type = null)
+ {
+ if ($all) {
+ $where = 'pg_catalog.pg_function_is_visible(p.oid)';
+ $distinct = 'DISTINCT ON (p.proname)';
+
+ if ($type) {
+ $where .= " AND p.prorettype = (select oid from pg_catalog.pg_type p where p.typname = 'trigger') ";
+ }
+ } else {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $where = "n.nspname = '{$c_schema}'";
+ $distinct = '';
+ }
+
+ $sql = "
SELECT
{$distinct}
p.oid AS prooid,
@@ -4530,300 +4656,306 @@ class Postgres extends ADODB_base {
ORDER BY p.proname, proresult
";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns an array containing a function's properties
- * @param $f The array of data for the function
- * @return An array containing the properties
- */
- function getFunctionProperties($f) {
- $temp = [];
-
- // Volatility
- if ($f['provolatile'] == 'v') {
- $temp[] = 'VOLATILE';
- } elseif ($f['provolatile'] == 'i') {
- $temp[] = 'IMMUTABLE';
- } elseif ($f['provolatile'] == 's') {
- $temp[] = 'STABLE';
- } else {
- return -1;
- }
-
- // Null handling
- $f['proisstrict'] = $this->phpBool($f['proisstrict']);
- if ($f['proisstrict']) {
- $temp[] = 'RETURNS NULL ON NULL INPUT';
- } else {
- $temp[] = 'CALLED ON NULL INPUT';
- }
-
- // Security
- $f['prosecdef'] = $this->phpBool($f['prosecdef']);
- if ($f['prosecdef']) {
- $temp[] = 'SECURITY DEFINER';
- } else {
- $temp[] = 'SECURITY INVOKER';
- }
-
- return $temp;
- }
-
- /**
- * Updates (replaces) a function.
- * @param $function_oid The OID of the function
- * @param $funcname The name of the function to create
- * @param $newname The new name for the function
- * @param $args The array of argument types
- * @param $returns The return type
- * @param $definition The definition for the new function
- * @param $language The language the function is written for
- * @param $flags An array of optional flags
- * @param $setof True if returns a set, false otherwise
- * @param $comment The comment on the function
- * @return 0 success
- * @return -1 transaction error
- * @return -3 create function error
- * @return -4 comment error
- * @return -5 rename function error
- * @return -6 alter owner error
- * @return -7 alter schema error
- */
- function setFunction($function_oid, $funcname, $newname, $args, $returns, $definition, $language, $flags, $setof, $funcown, $newown, $funcschema, $newschema, $cost, $rows, $comment) {
- // Begin a transaction
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Replace the existing function
- $status = $this->createFunction($funcname, $args, $returns, $definition, $language, $flags, $setof, $cost, $rows, $comment, true);
- if ($status != 0) {
- $this->rollbackTransaction();
- return $status;
- }
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
-
- // Rename the function, if necessary
- $this->fieldClean($newname);
- /* $funcname is escaped in createFunction */
- if ($funcname != $newname) {
- $sql = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) RENAME TO \"{$newname}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -5;
- }
-
- $funcname = $newname;
- }
-
- // Alter the owner, if necessary
- if ($this->hasFunctionAlterOwner()) {
- $this->fieldClean($newown);
- if ($funcown != $newown) {
- $sql = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) OWNER TO \"{$newown}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -6;
- }
- }
-
- }
-
- // Alter the schema, if necessary
- if ($this->hasFunctionAlterSchema()) {
- $this->fieldClean($newschema);
- /* $funcschema is escaped in createFunction */
- if ($funcschema != $newschema) {
- $sql = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) SET SCHEMA \"{$newschema}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -7;
- }
- }
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Creates a new function.
- * @param $funcname The name of the function to create
- * @param $args A comma separated string of types
- * @param $returns The return type
- * @param $definition The definition for the new function
- * @param $language The language the function is written for
- * @param $flags An array of optional flags
- * @param $setof True if it returns a set, false otherwise
- * @param $rows number of rows planner should estimate will be returned
- * @param $cost cost the planner should use in the function execution step
- * @param $comment Comment for the function
- * @param $replace (optional) True if OR REPLACE, false for normal
- * @return 0 success
- * @return -3 create function failed
- * @return -4 set comment failed
- */
- function createFunction($funcname, $args, $returns, $definition, $language, $flags, $setof, $cost, $rows, $comment, $replace = false) {
-
- // Begin a transaction
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $this->fieldClean($funcname);
- $this->clean($args);
- $this->fieldClean($language);
- $this->arrayClean($flags);
- $this->clean($cost);
- $this->clean($rows);
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
-
- $sql = "CREATE";
- if ($replace) {
- $sql .= " OR REPLACE";
- }
-
- $sql .= " FUNCTION \"{$f_schema}\".\"{$funcname}\" (";
-
- if ($args != '') {
- $sql .= $args;
- }
-
- // For some reason, the returns field cannot have quotes...
- $sql .= ") RETURNS ";
- if ($setof) {
- $sql .= "SETOF ";
- }
-
- $sql .= "{$returns} AS ";
-
- if (is_array($definition)) {
- $this->arrayClean($definition);
- $sql .= "'" . $definition[0] . "'";
- if ($definition[1]) {
- $sql .= ",'" . $definition[1] . "'";
- }
- } else {
- $this->clean($definition);
- $sql .= "'" . $definition . "'";
- }
-
- $sql .= " LANGUAGE \"{$language}\"";
-
- // Add costs
- if (!empty($cost)) {
- $sql .= " COST {$cost}";
- }
-
- if ($rows != 0) {
- $sql .= " ROWS {$rows}";
- }
-
- // Add flags
- foreach ($flags as $v) {
- // Skip default flags
- if ($v == '') {
- continue;
- } else {
- $sql .= "\n{$v}";
- }
-
- }
-
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
-
- /* set the comment */
- $status = $this->setComment('FUNCTION', "\"{$funcname}\"({$args})", null, $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -4;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Drops a function.
- * @param $function_oid The OID of the function to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropFunction($function_oid, $cascade) {
- // Function comes in with $object as function OID
- $fn = $this->getFunction($function_oid);
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($fn->fields['proname']);
-
- $sql = "DROP FUNCTION \"{$f_schema}\".\"{$fn->fields['proname']}\"({$fn->fields['proarguments']})";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- // Type functions
-
- /**
- * Returns all details for a particular type
- * @param $typname The name of the view to retrieve
- * @return Type info
- */
- function getType($typname) {
- $this->clean($typname);
-
- $sql = "SELECT typtype, typbyval, typname, typinput AS typin, typoutput AS typout, typlen, typalign
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns an array containing a function's properties
+ * @param $f The array of data for the function
+ * @return An array containing the properties
+ */
+ public function getFunctionProperties($f)
+ {
+ $temp = [];
+
+ // Volatility
+ if ($f['provolatile'] == 'v') {
+ $temp[] = 'VOLATILE';
+ } elseif ($f['provolatile'] == 'i') {
+ $temp[] = 'IMMUTABLE';
+ } elseif ($f['provolatile'] == 's') {
+ $temp[] = 'STABLE';
+ } else {
+ return -1;
+ }
+
+ // Null handling
+ $f['proisstrict'] = $this->phpBool($f['proisstrict']);
+ if ($f['proisstrict']) {
+ $temp[] = 'RETURNS NULL ON NULL INPUT';
+ } else {
+ $temp[] = 'CALLED ON NULL INPUT';
+ }
+
+ // Security
+ $f['prosecdef'] = $this->phpBool($f['prosecdef']);
+ if ($f['prosecdef']) {
+ $temp[] = 'SECURITY DEFINER';
+ } else {
+ $temp[] = 'SECURITY INVOKER';
+ }
+
+ return $temp;
+ }
+
+ /**
+ * Updates (replaces) a function.
+ * @param $function_oid The OID of the function
+ * @param $funcname The name of the function to create
+ * @param $newname The new name for the function
+ * @param $args The array of argument types
+ * @param $returns The return type
+ * @param $definition The definition for the new function
+ * @param $language The language the function is written for
+ * @param $flags An array of optional flags
+ * @param $setof True if returns a set, false otherwise
+ * @param $comment The comment on the function
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -3 create function error
+ * @return -4 comment error
+ * @return -5 rename function error
+ * @return -6 alter owner error
+ * @return -7 alter schema error
+ */
+ public function setFunction($function_oid, $funcname, $newname, $args, $returns, $definition, $language, $flags, $setof, $funcown, $newown, $funcschema, $newschema, $cost, $rows, $comment)
+ {
+ // Begin a transaction
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Replace the existing function
+ $status = $this->createFunction($funcname, $args, $returns, $definition, $language, $flags, $setof, $cost, $rows, $comment, true);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return $status;
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+
+ // Rename the function, if necessary
+ $this->fieldClean($newname);
+ /* $funcname is escaped in createFunction */
+ if ($funcname != $newname) {
+ $sql = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) RENAME TO \"{$newname}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -5;
+ }
+
+ $funcname = $newname;
+ }
+
+ // Alter the owner, if necessary
+ if ($this->hasFunctionAlterOwner()) {
+ $this->fieldClean($newown);
+ if ($funcown != $newown) {
+ $sql = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) OWNER TO \"{$newown}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -6;
+ }
+ }
+
+ }
+
+ // Alter the schema, if necessary
+ if ($this->hasFunctionAlterSchema()) {
+ $this->fieldClean($newschema);
+ /* $funcschema is escaped in createFunction */
+ if ($funcschema != $newschema) {
+ $sql = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) SET SCHEMA \"{$newschema}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -7;
+ }
+ }
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Creates a new function.
+ * @param $funcname The name of the function to create
+ * @param $args A comma separated string of types
+ * @param $returns The return type
+ * @param $definition The definition for the new function
+ * @param $language The language the function is written for
+ * @param $flags An array of optional flags
+ * @param $setof True if it returns a set, false otherwise
+ * @param $rows number of rows planner should estimate will be returned
+ * @param $cost cost the planner should use in the function execution step
+ * @param $comment Comment for the function
+ * @param $replace (optional) True if OR REPLACE, false for normal
+ * @return 0 success
+ * @return -3 create function failed
+ * @return -4 set comment failed
+ */
+ public function createFunction($funcname, $args, $returns, $definition, $language, $flags, $setof, $cost, $rows, $comment, $replace = false)
+ {
+
+ // Begin a transaction
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $this->fieldClean($funcname);
+ $this->clean($args);
+ $this->fieldClean($language);
+ $this->arrayClean($flags);
+ $this->clean($cost);
+ $this->clean($rows);
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+
+ $sql = "CREATE";
+ if ($replace) {
+ $sql .= " OR REPLACE";
+ }
+
+ $sql .= " FUNCTION \"{$f_schema}\".\"{$funcname}\" (";
+
+ if ($args != '') {
+ $sql .= $args;
+ }
+
+ // For some reason, the returns field cannot have quotes...
+ $sql .= ") RETURNS ";
+ if ($setof) {
+ $sql .= "SETOF ";
+ }
+
+ $sql .= "{$returns} AS ";
+
+ if (is_array($definition)) {
+ $this->arrayClean($definition);
+ $sql .= "'" . $definition[0] . "'";
+ if ($definition[1]) {
+ $sql .= ",'" . $definition[1] . "'";
+ }
+ } else {
+ $this->clean($definition);
+ $sql .= "'" . $definition . "'";
+ }
+
+ $sql .= " LANGUAGE \"{$language}\"";
+
+ // Add costs
+ if (!empty($cost)) {
+ $sql .= " COST {$cost}";
+ }
+
+ if ($rows != 0) {
+ $sql .= " ROWS {$rows}";
+ }
+
+ // Add flags
+ foreach ($flags as $v) {
+ // Skip default flags
+ if ($v == '') {
+ continue;
+ } else {
+ $sql .= "\n{$v}";
+ }
+
+ }
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+
+ /* set the comment */
+ $status = $this->setComment('FUNCTION', "\"{$funcname}\"({$args})", null, $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -4;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Drops a function.
+ * @param $function_oid The OID of the function to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropFunction($function_oid, $cascade)
+ {
+ // Function comes in with $object as function OID
+ $fn = $this->getFunction($function_oid);
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($fn->fields['proname']);
+
+ $sql = "DROP FUNCTION \"{$f_schema}\".\"{$fn->fields['proname']}\"({$fn->fields['proarguments']})";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ // Type functions
+
+ /**
+ * Returns all details for a particular type
+ * @param $typname The name of the view to retrieve
+ * @return Type info
+ */
+ public function getType($typname)
+ {
+ $this->clean($typname);
+
+ $sql = "SELECT typtype, typbyval, typname, typinput AS typin, typoutput AS typout, typlen, typalign
FROM pg_type WHERE typname='{$typname}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns a list of all types in the database
- * @param $all If true, will find all available types, if false just those in search path
- * @param $tabletypes If true, will include table types
- * @param $domains If true, will include domains
- * @return A recordet
- */
- function getTypes($all = false, $tabletypes = false, $domains = false) {
- if ($all) {
- $where = '1 = 1';
- } else {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $where = "n.nspname = '{$c_schema}'";
- }
- // Never show system table types
- $where2 = "AND c.relnamespace NOT IN (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname LIKE 'pg@_%' ESCAPE '@')";
-
- // Create type filter
- $tqry = "'c'";
- if ($tabletypes) {
- $tqry .= ", 'r', 'v'";
- }
-
- // Create domain filter
- if (!$domains) {
- $where .= " AND t.typtype != 'd'";
- }
-
- $sql = "SELECT
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns a list of all types in the database
+ * @param $all If true, will find all available types, if false just those in search path
+ * @param $tabletypes If true, will include table types
+ * @param $domains If true, will include domains
+ * @return A recordet
+ */
+ public function getTypes($all = false, $tabletypes = false, $domains = false)
+ {
+ if ($all) {
+ $where = '1 = 1';
+ } else {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $where = "n.nspname = '{$c_schema}'";
+ }
+ // Never show system table types
+ $where2 = "AND c.relnamespace NOT IN (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname LIKE 'pg@_%' ESCAPE '@')";
+
+ // Create type filter
+ $tqry = "'c'";
+ if ($tabletypes) {
+ $tqry .= ", 'r', 'v'";
+ }
+
+ // Create domain filter
+ if (!$domains) {
+ $where .= " AND t.typtype != 'd'";
+ }
+
+ $sql = "SELECT
t.typname AS basename,
pg_catalog.format_type(t.oid, NULL) AS typname,
pu.usename AS typowner,
@@ -4838,276 +4970,281 @@ class Postgres extends ADODB_base {
ORDER BY typname
";
- return $this->selectSet($sql);
- }
-
- /**
- * Creates a new type
- * @param ...
- * @return 0 success
- */
- function createType($typname, $typin, $typout, $typlen, $typdef,
- $typelem, $typdelim, $typbyval, $typalign, $typstorage) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($typname);
- $this->fieldClean($typin);
- $this->fieldClean($typout);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a new type
+ * @param ...
+ * @return 0 success
+ */
+ public function createType($typname, $typin, $typout, $typlen, $typdef,
+ $typelem, $typdelim, $typbyval, $typalign, $typstorage) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($typname);
+ $this->fieldClean($typin);
+ $this->fieldClean($typout);
+
+ $sql = "
CREATE TYPE \"{$f_schema}\".\"{$typname}\" (
INPUT = \"{$typin}\",
OUTPUT = \"{$typout}\",
INTERNALLENGTH = {$typlen}";
- if ($typdef != '') {
- $sql .= ", DEFAULT = {$typdef}";
- }
-
- if ($typelem != '') {
- $sql .= ", ELEMENT = {$typelem}";
- }
-
- if ($typdelim != '') {
- $sql .= ", DELIMITER = {$typdelim}";
- }
-
- if ($typbyval) {
- $sql .= ", PASSEDBYVALUE, ";
- }
-
- if ($typalign != '') {
- $sql .= ", ALIGNMENT = {$typalign}";
- }
-
- if ($typstorage != '') {
- $sql .= ", STORAGE = {$typstorage}";
- }
-
- $sql .= ")";
-
- return $this->execute($sql);
- }
-
- /**
- * Drops a type.
- * @param $typname The name of the type to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropType($typname, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($typname);
-
- $sql = "DROP TYPE \"{$f_schema}\".\"{$typname}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Creates a new enum type in the database
- * @param $name The name of the type
- * @param $values An array of values
- * @param $typcomment Type comment
- * @return 0 success
- * @return -1 transaction error
- * @return -2 no values supplied
- */
- function createEnumType($name, $values, $typcomment) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
-
- if (empty($values)) {
- return -2;
- }
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- $values = array_unique($values);
-
- $nbval = count($values);
-
- for ($i = 0; $i < $nbval; $i++) {
- $this->clean($values[$i]);
- }
-
- $sql = "CREATE TYPE \"{$f_schema}\".\"{$name}\" AS ENUM ('";
- $sql .= implode("','", $values);
- $sql .= "')";
-
- $status = $this->execute($sql);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
-
- if ($typcomment != '') {
- $status = $this->setComment('TYPE', $name, '', $typcomment, true);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- return $this->endTransaction();
-
- }
-
- /**
- * Get defined values for a given enum
- * @return A recordset
- */
- function getEnumValues($name) {
- $this->clean($name);
-
- $sql = "SELECT enumlabel AS enumval
+ if ($typdef != '') {
+ $sql .= ", DEFAULT = {$typdef}";
+ }
+
+ if ($typelem != '') {
+ $sql .= ", ELEMENT = {$typelem}";
+ }
+
+ if ($typdelim != '') {
+ $sql .= ", DELIMITER = {$typdelim}";
+ }
+
+ if ($typbyval) {
+ $sql .= ", PASSEDBYVALUE, ";
+ }
+
+ if ($typalign != '') {
+ $sql .= ", ALIGNMENT = {$typalign}";
+ }
+
+ if ($typstorage != '') {
+ $sql .= ", STORAGE = {$typstorage}";
+ }
+
+ $sql .= ")";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Drops a type.
+ * @param $typname The name of the type to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropType($typname, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($typname);
+
+ $sql = "DROP TYPE \"{$f_schema}\".\"{$typname}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Creates a new enum type in the database
+ * @param $name The name of the type
+ * @param $values An array of values
+ * @param $typcomment Type comment
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 no values supplied
+ */
+ public function createEnumType($name, $values, $typcomment)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+
+ if (empty($values)) {
+ return -2;
+ }
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ $values = array_unique($values);
+
+ $nbval = count($values);
+
+ for ($i = 0; $i < $nbval; $i++) {
+ $this->clean($values[$i]);
+ }
+
+ $sql = "CREATE TYPE \"{$f_schema}\".\"{$name}\" AS ENUM ('";
+ $sql .= implode("','", $values);
+ $sql .= "')";
+
+ $status = $this->execute($sql);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ if ($typcomment != '') {
+ $status = $this->setComment('TYPE', $name, '', $typcomment, true);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ return $this->endTransaction();
+
+ }
+
+ /**
+ * Get defined values for a given enum
+ * @return A recordset
+ */
+ public function getEnumValues($name)
+ {
+ $this->clean($name);
+
+ $sql = "SELECT enumlabel AS enumval
FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON (t.oid=e.enumtypid)
WHERE t.typname = '{$name}' ORDER BY e.oid";
- return $this->selectSet($sql);
- }
-
- /**
- * Creates a new composite type in the database
- * @param $name The name of the type
- * @param $fields The number of fields
- * @param $field An array of field names
- * @param $type An array of field types
- * @param $array An array of '' or '[]' for each type if it's an array or not
- * @param $length An array of field lengths
- * @param $colcomment An array of comments
- * @param $typcomment Type comment
- * @return 0 success
- * @return -1 no fields supplied
- */
- function createCompositeType($name, $fields, $field, $type, $array, $length, $colcomment, $typcomment) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- $found = false;
- $first = true;
- $comment_sql = ''; // Accumulate comments for the columns
- $sql = "CREATE TYPE \"{$f_schema}\".\"{$name}\" AS (";
- for ($i = 0; $i < $fields; $i++) {
- $this->fieldClean($field[$i]);
- $this->clean($type[$i]);
- $this->clean($length[$i]);
- $this->clean($colcomment[$i]);
-
- // Skip blank columns - for user convenience
- if ($field[$i] == '' || $type[$i] == '') {
- continue;
- }
-
- // If not the first column, add a comma
- if (!$first) {
- $sql .= ", ";
- } else {
- $first = false;
- }
-
- switch ($type[$i]) {
- // Have to account for weird placing of length for with/without
- // time zone types
- case 'timestamp with time zone':
- case 'timestamp without time zone':
- $qual = substr($type[$i], 9);
- $sql .= "\"{$field[$i]}\" timestamp";
- if ($length[$i] != '') {
- $sql .= "({$length[$i]})";
- }
-
- $sql .= $qual;
- break;
- case 'time with time zone':
- case 'time without time zone':
- $qual = substr($type[$i], 4);
- $sql .= "\"{$field[$i]}\" time";
- if ($length[$i] != '') {
- $sql .= "({$length[$i]})";
- }
-
- $sql .= $qual;
- break;
- default:
- $sql .= "\"{$field[$i]}\" {$type[$i]}";
- if ($length[$i] != '') {
- $sql .= "({$length[$i]})";
- }
-
- }
- // Add array qualifier if necessary
- if ($array[$i] == '[]') {
- $sql .= '[]';
- }
-
- if ($colcomment[$i] != '') {
- $comment_sql .= "COMMENT ON COLUMN \"{$f_schema}\".\"{$name}\".\"{$field[$i]}\" IS '{$colcomment[$i]}';\n";
- }
-
- $found = true;
- }
-
- if (!$found) {
- return -1;
- }
-
- $sql .= ")";
-
- $status = $this->execute($sql);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
-
- if ($typcomment != '') {
- $status = $this->setComment('TYPE', $name, '', $typcomment, true);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- if ($comment_sql != '') {
- $status = $this->execute($comment_sql);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
- }
- return $this->endTransaction();
- }
-
- /**
- * Returns a list of all casts in the database
- * @return All casts
- */
- function getCasts() {
- $conf = $this->conf;
-
- if ($conf['show_system']) {
- $where = '';
- } else {
- $where = '
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a new composite type in the database
+ * @param $name The name of the type
+ * @param $fields The number of fields
+ * @param $field An array of field names
+ * @param $type An array of field types
+ * @param $array An array of '' or '[]' for each type if it's an array or not
+ * @param $length An array of field lengths
+ * @param $colcomment An array of comments
+ * @param $typcomment Type comment
+ * @return 0 success
+ * @return -1 no fields supplied
+ */
+ public function createCompositeType($name, $fields, $field, $type, $array, $length, $colcomment, $typcomment)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ $found = false;
+ $first = true;
+ $comment_sql = ''; // Accumulate comments for the columns
+ $sql = "CREATE TYPE \"{$f_schema}\".\"{$name}\" AS (";
+ for ($i = 0; $i < $fields; $i++) {
+ $this->fieldClean($field[$i]);
+ $this->clean($type[$i]);
+ $this->clean($length[$i]);
+ $this->clean($colcomment[$i]);
+
+ // Skip blank columns - for user convenience
+ if ($field[$i] == '' || $type[$i] == '') {
+ continue;
+ }
+
+ // If not the first column, add a comma
+ if (!$first) {
+ $sql .= ", ";
+ } else {
+ $first = false;
+ }
+
+ switch ($type[$i]) {
+ // Have to account for weird placing of length for with/without
+ // time zone types
+ case 'timestamp with time zone':
+ case 'timestamp without time zone':
+ $qual = substr($type[$i], 9);
+ $sql .= "\"{$field[$i]}\" timestamp";
+ if ($length[$i] != '') {
+ $sql .= "({$length[$i]})";
+ }
+
+ $sql .= $qual;
+ break;
+ case 'time with time zone':
+ case 'time without time zone':
+ $qual = substr($type[$i], 4);
+ $sql .= "\"{$field[$i]}\" time";
+ if ($length[$i] != '') {
+ $sql .= "({$length[$i]})";
+ }
+
+ $sql .= $qual;
+ break;
+ default:
+ $sql .= "\"{$field[$i]}\" {$type[$i]}";
+ if ($length[$i] != '') {
+ $sql .= "({$length[$i]})";
+ }
+
+ }
+ // Add array qualifier if necessary
+ if ($array[$i] == '[]') {
+ $sql .= '[]';
+ }
+
+ if ($colcomment[$i] != '') {
+ $comment_sql .= "COMMENT ON COLUMN \"{$f_schema}\".\"{$name}\".\"{$field[$i]}\" IS '{$colcomment[$i]}';\n";
+ }
+
+ $found = true;
+ }
+
+ if (!$found) {
+ return -1;
+ }
+
+ $sql .= ")";
+
+ $status = $this->execute($sql);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ if ($typcomment != '') {
+ $status = $this->setComment('TYPE', $name, '', $typcomment, true);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ if ($comment_sql != '') {
+ $status = $this->execute($comment_sql);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+ return $this->endTransaction();
+ }
+
+ /**
+ * Returns a list of all casts in the database
+ * @return All casts
+ */
+ public function getCasts()
+ {
+ $conf = $this->conf;
+
+ if ($conf['show_system']) {
+ $where = '';
+ } else {
+ $where = '
AND n1.nspname NOT LIKE $$pg\_%$$
AND n2.nspname NOT LIKE $$pg\_%$$
AND n3.nspname NOT LIKE $$pg\_%$$
';
- }
+ }
- $sql = "
+ $sql = "
SELECT
c.castsource::pg_catalog.regtype AS castsource,
c.casttarget::pg_catalog.regtype AS casttarget,
@@ -5130,17 +5267,18 @@ class Postgres extends ADODB_base {
ORDER BY 1, 2
";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns a list of all conversions in the database
- * @return All conversions
- */
- function getConversions() {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns a list of all conversions in the database
+ * @return All conversions
+ */
+ public function getConversions()
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "
SELECT
c.conname,
pg_catalog.pg_encoding_to_char(c.conforencoding) AS conforencoding,
@@ -5153,22 +5291,23 @@ class Postgres extends ADODB_base {
ORDER BY 1;
";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Rule functions
+ // Rule functions
- /**
- * Returns a list of all rules on a table OR view
- * @param $table The table to find rules for
- * @return A recordset
- */
- function getRules($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
+ /**
+ * Returns a list of all rules on a table OR view
+ * @param $table The table to find rules for
+ * @return A recordset
+ */
+ public function getRules($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
- $sql = "
+ $sql = "
SELECT *
FROM pg_catalog.pg_rules
WHERE
@@ -5176,128 +5315,133 @@ class Postgres extends ADODB_base {
ORDER BY rulename
";
- return $this->selectSet($sql);
- }
-
- /**
- * Edits a rule on a table OR view
- * @param $name The name of the new rule
- * @param $event SELECT, INSERT, UPDATE or DELETE
- * @param $table Table on which to create the rule
- * @param $where When to execute the rule, '' indicates always
- * @param $instead True if an INSTEAD rule, false otherwise
- * @param $type NOTHING for a do nothing rule, SOMETHING to use given action
- * @param $action The action to take
- * @return 0 success
- * @return -1 invalid event
- */
- function setRule($name, $event, $table, $where, $instead, $type, $action) {
- return $this->createRule($name, $event, $table, $where, $instead, $type, $action, true);
- }
-
- /**
- * Creates a rule
- * @param $name The name of the new rule
- * @param $event SELECT, INSERT, UPDATE or DELETE
- * @param $table Table on which to create the rule
- * @param $where When to execute the rule, '' indicates always
- * @param $instead True if an INSTEAD rule, false otherwise
- * @param $type NOTHING for a do nothing rule, SOMETHING to use given action
- * @param $action The action to take
- * @param $replace (optional) True to replace existing rule, false otherwise
- * @return 0 success
- * @return -1 invalid event
- */
- function createRule($name, $event, $table, $where, $instead, $type, $action, $replace = false) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
- $this->fieldClean($table);
- if (!in_array($event, $this->rule_events)) {
- return -1;
- }
-
- $sql = "CREATE";
- if ($replace) {
- $sql .= " OR REPLACE";
- }
-
- $sql .= " RULE \"{$name}\" AS ON {$event} TO \"{$f_schema}\".\"{$table}\"";
- // Can't escape WHERE clause
- if ($where != '') {
- $sql .= " WHERE {$where}";
- }
-
- $sql .= " DO";
- if ($instead) {
- $sql .= " INSTEAD";
- }
-
- if ($type == 'NOTHING') {
- $sql .= " NOTHING";
- } else {
- $sql .= " ({$action})";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Removes a rule from a table OR view
- * @param $rule The rule to drop
- * @param $relation The relation from which to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropRule($rule, $relation, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($rule);
- $this->fieldClean($relation);
-
- $sql = "DROP RULE \"{$rule}\" ON \"{$f_schema}\".\"{$relation}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- // Trigger functions
-
- /**
- * Grabs a single trigger
- * @param $table The name of a table whose triggers to retrieve
- * @param $trigger The name of the trigger to retrieve
- * @return A recordset
- */
- function getTrigger($table, $trigger) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
- $this->clean($trigger);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Edits a rule on a table OR view
+ * @param $name The name of the new rule
+ * @param $event SELECT, INSERT, UPDATE or DELETE
+ * @param $table Table on which to create the rule
+ * @param $where When to execute the rule, '' indicates always
+ * @param $instead True if an INSTEAD rule, false otherwise
+ * @param $type NOTHING for a do nothing rule, SOMETHING to use given action
+ * @param $action The action to take
+ * @return 0 success
+ * @return -1 invalid event
+ */
+ public function setRule($name, $event, $table, $where, $instead, $type, $action)
+ {
+ return $this->createRule($name, $event, $table, $where, $instead, $type, $action, true);
+ }
+
+ /**
+ * Creates a rule
+ * @param $name The name of the new rule
+ * @param $event SELECT, INSERT, UPDATE or DELETE
+ * @param $table Table on which to create the rule
+ * @param $where When to execute the rule, '' indicates always
+ * @param $instead True if an INSTEAD rule, false otherwise
+ * @param $type NOTHING for a do nothing rule, SOMETHING to use given action
+ * @param $action The action to take
+ * @param $replace (optional) True to replace existing rule, false otherwise
+ * @return 0 success
+ * @return -1 invalid event
+ */
+ public function createRule($name, $event, $table, $where, $instead, $type, $action, $replace = false)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+ $this->fieldClean($table);
+ if (!in_array($event, $this->rule_events)) {
+ return -1;
+ }
+
+ $sql = "CREATE";
+ if ($replace) {
+ $sql .= " OR REPLACE";
+ }
+
+ $sql .= " RULE \"{$name}\" AS ON {$event} TO \"{$f_schema}\".\"{$table}\"";
+ // Can't escape WHERE clause
+ if ($where != '') {
+ $sql .= " WHERE {$where}";
+ }
+
+ $sql .= " DO";
+ if ($instead) {
+ $sql .= " INSTEAD";
+ }
+
+ if ($type == 'NOTHING') {
+ $sql .= " NOTHING";
+ } else {
+ $sql .= " ({$action})";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes a rule from a table OR view
+ * @param $rule The rule to drop
+ * @param $relation The relation from which to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropRule($rule, $relation, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($rule);
+ $this->fieldClean($relation);
+
+ $sql = "DROP RULE \"{$rule}\" ON \"{$f_schema}\".\"{$relation}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ // Trigger functions
+
+ /**
+ * Grabs a single trigger
+ * @param $table The name of a table whose triggers to retrieve
+ * @param $trigger The name of the trigger to retrieve
+ * @return A recordset
+ */
+ public function getTrigger($table, $trigger)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+ $this->clean($trigger);
+
+ $sql = "
SELECT * FROM pg_catalog.pg_trigger t, pg_catalog.pg_class c
WHERE t.tgrelid=c.oid AND c.relname='{$table}' AND t.tgname='{$trigger}'
AND c.relnamespace=(
SELECT oid FROM pg_catalog.pg_namespace
WHERE nspname='{$c_schema}')";
- return $this->selectSet($sql);
- }
-
- /**
- * Grabs a list of triggers on a table
- * @param $table The name of a table whose triggers to retrieve
- * @return A recordset
- */
- function getTriggers($table = '') {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "SELECT
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Grabs a list of triggers on a table
+ * @param $table The name of a table whose triggers to retrieve
+ * @return A recordset
+ */
+ public function getTriggers($table = '')
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "SELECT
t.tgname, pg_catalog.pg_get_triggerdef(t.oid) AS tgdef,
CASE WHEN t.tgenabled = 'D' THEN FALSE ELSE TRUE END AS tgenabled, p.oid AS prooid,
p.proname || ' (' || pg_catalog.oidvectortypes(p.proargtypes) || ')' AS proproto,
@@ -5312,253 +5456,261 @@ class Postgres extends ADODB_base {
AND p.oid=t.tgfoid
AND p.pronamespace = ns.oid";
- return $this->selectSet($sql);
- }
-
- /**
- * A helper function for getTriggers that translates
- * an array of attribute numbers to an array of field names.
- * Note: Only needed for pre-7.4 servers, this function is deprecated
- * @param $trigger An array containing fields from the trigger table
- * @return The trigger definition string
- */
- function getTriggerDef($trigger) {
-
- $this->fieldArrayClean($trigger);
- // Constants to figure out tgtype
- if (!defined('TRIGGER_TYPE_ROW')) {
- define('TRIGGER_TYPE_ROW', (1 << 0));
- }
-
- if (!defined('TRIGGER_TYPE_BEFORE')) {
- define('TRIGGER_TYPE_BEFORE', (1 << 1));
- }
-
- if (!defined('TRIGGER_TYPE_INSERT')) {
- define('TRIGGER_TYPE_INSERT', (1 << 2));
- }
-
- if (!defined('TRIGGER_TYPE_DELETE')) {
- define('TRIGGER_TYPE_DELETE', (1 << 3));
- }
-
- if (!defined('TRIGGER_TYPE_UPDATE')) {
- define('TRIGGER_TYPE_UPDATE', (1 << 4));
- }
-
- $trigger['tgisconstraint'] = $this->phpBool($trigger['tgisconstraint']);
- $trigger['tgdeferrable'] = $this->phpBool($trigger['tgdeferrable']);
- $trigger['tginitdeferred'] = $this->phpBool($trigger['tginitdeferred']);
-
- // Constraint trigger or normal trigger
- if ($trigger['tgisconstraint']) {
- $tgdef = 'CREATE CONSTRAINT TRIGGER ';
- } else {
- $tgdef = 'CREATE TRIGGER ';
- }
-
- $tgdef .= "\"{$trigger['tgname']}\" ";
-
- // Trigger type
- $findx = 0;
- if (($trigger['tgtype'] & TRIGGER_TYPE_BEFORE) == TRIGGER_TYPE_BEFORE) {
- $tgdef .= 'BEFORE';
- } else {
- $tgdef .= 'AFTER';
- }
-
- if (($trigger['tgtype'] & TRIGGER_TYPE_INSERT) == TRIGGER_TYPE_INSERT) {
- $tgdef .= ' INSERT';
- $findx++;
- }
- if (($trigger['tgtype'] & TRIGGER_TYPE_DELETE) == TRIGGER_TYPE_DELETE) {
- if ($findx > 0) {
- $tgdef .= ' OR DELETE';
- } else {
- $tgdef .= ' DELETE';
- $findx++;
- }
- }
- if (($trigger['tgtype'] & TRIGGER_TYPE_UPDATE) == TRIGGER_TYPE_UPDATE) {
- if ($findx > 0) {
- $tgdef .= ' OR UPDATE';
- } else {
- $tgdef .= ' UPDATE';
- }
-
- }
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- // Table name
- $tgdef .= " ON \"{$f_schema}\".\"{$trigger['relname']}\" ";
-
- // Deferrability
- if ($trigger['tgisconstraint']) {
- if ($trigger['tgconstrrelid'] != 0) {
- // Assume constrelname is not null
- $tgdef .= " FROM \"{$trigger['tgconstrrelname']}\" ";
- }
- if (!$trigger['tgdeferrable']) {
- $tgdef .= 'NOT ';
- }
-
- $tgdef .= 'DEFERRABLE INITIALLY ';
- if ($trigger['tginitdeferred']) {
- $tgdef .= 'DEFERRED ';
- } else {
- $tgdef .= 'IMMEDIATE ';
- }
-
- }
-
- // Row or statement
- if ($trigger['tgtype'] & TRIGGER_TYPE_ROW == TRIGGER_TYPE_ROW) {
- $tgdef .= 'FOR EACH ROW ';
- } else {
- $tgdef .= 'FOR EACH STATEMENT ';
- }
-
- // Execute procedure
- $tgdef .= "EXECUTE PROCEDURE \"{$trigger['tgfname']}\"(";
-
- // Parameters
- // Escape null characters
- $v = addCSlashes($trigger['tgargs'], "\0");
- // Split on escaped null characters
- $params = explode('\\000', $v);
- for ($findx = 0; $findx < $trigger['tgnargs']; $findx++) {
- $param = "'" . str_replace('\'', '\\\'', $params[$findx]) . "'";
- $tgdef .= $param;
- if ($findx < ($trigger['tgnargs'] - 1)) {
- $tgdef .= ', ';
- }
-
- }
-
- // Finish it off
- $tgdef .= ')';
-
- return $tgdef;
- }
-
- /**
- * Returns a list of all functions that can be used in triggers
- */
- function getTriggerFunctions() {
- return $this->getFunctions(true, 'trigger');
- }
-
- /**
- * Creates a trigger
- * @param $tgname The name of the trigger to create
- * @param $table The name of the table
- * @param $tgproc The function to execute
- * @param $tgtime BEFORE or AFTER
- * @param $tgevent Event
- * @param $tgargs The function arguments
- * @return 0 success
- */
- function createTrigger($tgname, $table, $tgproc, $tgtime, $tgevent, $tgfrequency, $tgargs) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($tgname);
- $this->fieldClean($table);
- $this->fieldClean($tgproc);
-
- /* No Statement Level Triggers in PostgreSQL (by now) */
- $sql = "CREATE TRIGGER \"{$tgname}\" {$tgtime}
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * A helper function for getTriggers that translates
+ * an array of attribute numbers to an array of field names.
+ * Note: Only needed for pre-7.4 servers, this function is deprecated
+ * @param $trigger An array containing fields from the trigger table
+ * @return The trigger definition string
+ */
+ public function getTriggerDef($trigger)
+ {
+
+ $this->fieldArrayClean($trigger);
+ // Constants to figure out tgtype
+ if (!defined('TRIGGER_TYPE_ROW')) {
+ define('TRIGGER_TYPE_ROW', (1 << 0));
+ }
+
+ if (!defined('TRIGGER_TYPE_BEFORE')) {
+ define('TRIGGER_TYPE_BEFORE', (1 << 1));
+ }
+
+ if (!defined('TRIGGER_TYPE_INSERT')) {
+ define('TRIGGER_TYPE_INSERT', (1 << 2));
+ }
+
+ if (!defined('TRIGGER_TYPE_DELETE')) {
+ define('TRIGGER_TYPE_DELETE', (1 << 3));
+ }
+
+ if (!defined('TRIGGER_TYPE_UPDATE')) {
+ define('TRIGGER_TYPE_UPDATE', (1 << 4));
+ }
+
+ $trigger['tgisconstraint'] = $this->phpBool($trigger['tgisconstraint']);
+ $trigger['tgdeferrable'] = $this->phpBool($trigger['tgdeferrable']);
+ $trigger['tginitdeferred'] = $this->phpBool($trigger['tginitdeferred']);
+
+ // Constraint trigger or normal trigger
+ if ($trigger['tgisconstraint']) {
+ $tgdef = 'CREATE CONSTRAINT TRIGGER ';
+ } else {
+ $tgdef = 'CREATE TRIGGER ';
+ }
+
+ $tgdef .= "\"{$trigger['tgname']}\" ";
+
+ // Trigger type
+ $findx = 0;
+ if (($trigger['tgtype'] & TRIGGER_TYPE_BEFORE) == TRIGGER_TYPE_BEFORE) {
+ $tgdef .= 'BEFORE';
+ } else {
+ $tgdef .= 'AFTER';
+ }
+
+ if (($trigger['tgtype'] & TRIGGER_TYPE_INSERT) == TRIGGER_TYPE_INSERT) {
+ $tgdef .= ' INSERT';
+ $findx++;
+ }
+ if (($trigger['tgtype'] & TRIGGER_TYPE_DELETE) == TRIGGER_TYPE_DELETE) {
+ if ($findx > 0) {
+ $tgdef .= ' OR DELETE';
+ } else {
+ $tgdef .= ' DELETE';
+ $findx++;
+ }
+ }
+ if (($trigger['tgtype'] & TRIGGER_TYPE_UPDATE) == TRIGGER_TYPE_UPDATE) {
+ if ($findx > 0) {
+ $tgdef .= ' OR UPDATE';
+ } else {
+ $tgdef .= ' UPDATE';
+ }
+
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ // Table name
+ $tgdef .= " ON \"{$f_schema}\".\"{$trigger['relname']}\" ";
+
+ // Deferrability
+ if ($trigger['tgisconstraint']) {
+ if ($trigger['tgconstrrelid'] != 0) {
+ // Assume constrelname is not null
+ $tgdef .= " FROM \"{$trigger['tgconstrrelname']}\" ";
+ }
+ if (!$trigger['tgdeferrable']) {
+ $tgdef .= 'NOT ';
+ }
+
+ $tgdef .= 'DEFERRABLE INITIALLY ';
+ if ($trigger['tginitdeferred']) {
+ $tgdef .= 'DEFERRED ';
+ } else {
+ $tgdef .= 'IMMEDIATE ';
+ }
+
+ }
+
+ // Row or statement
+ if ($trigger['tgtype'] & TRIGGER_TYPE_ROW == TRIGGER_TYPE_ROW) {
+ $tgdef .= 'FOR EACH ROW ';
+ } else {
+ $tgdef .= 'FOR EACH STATEMENT ';
+ }
+
+ // Execute procedure
+ $tgdef .= "EXECUTE PROCEDURE \"{$trigger['tgfname']}\"(";
+
+ // Parameters
+ // Escape null characters
+ $v = addCSlashes($trigger['tgargs'], "\0");
+ // Split on escaped null characters
+ $params = explode('\\000', $v);
+ for ($findx = 0; $findx < $trigger['tgnargs']; $findx++) {
+ $param = "'" . str_replace('\'', '\\\'', $params[$findx]) . "'";
+ $tgdef .= $param;
+ if ($findx < ($trigger['tgnargs'] - 1)) {
+ $tgdef .= ', ';
+ }
+
+ }
+
+ // Finish it off
+ $tgdef .= ')';
+
+ return $tgdef;
+ }
+
+ /**
+ * Returns a list of all functions that can be used in triggers
+ */
+ public function getTriggerFunctions()
+ {
+ return $this->getFunctions(true, 'trigger');
+ }
+
+ /**
+ * Creates a trigger
+ * @param $tgname The name of the trigger to create
+ * @param $table The name of the table
+ * @param $tgproc The function to execute
+ * @param $tgtime BEFORE or AFTER
+ * @param $tgevent Event
+ * @param $tgargs The function arguments
+ * @return 0 success
+ */
+ public function createTrigger($tgname, $table, $tgproc, $tgtime, $tgevent, $tgfrequency, $tgargs)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($tgname);
+ $this->fieldClean($table);
+ $this->fieldClean($tgproc);
+
+ /* No Statement Level Triggers in PostgreSQL (by now) */
+ $sql = "CREATE TRIGGER \"{$tgname}\" {$tgtime}
{$tgevent} ON \"{$f_schema}\".\"{$table}\"
FOR EACH {$tgfrequency} EXECUTE PROCEDURE \"{$tgproc}\"({$tgargs})";
- return $this->execute($sql);
- }
-
- /**
- * Alters a trigger
- * @param $table The name of the table containing the trigger
- * @param $trigger The name of the trigger to alter
- * @param $name The new name for the trigger
- * @return 0 success
- */
- function alterTrigger($table, $trigger, $name) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $this->fieldClean($trigger);
- $this->fieldClean($name);
-
- $sql = "ALTER TRIGGER \"{$trigger}\" ON \"{$f_schema}\".\"{$table}\" RENAME TO \"{$name}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * Drops a trigger
- * @param $tgname The name of the trigger to drop
- * @param $table The table from which to drop the trigger
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropTrigger($tgname, $table, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($tgname);
- $this->fieldClean($table);
-
- $sql = "DROP TRIGGER \"{$tgname}\" ON \"{$f_schema}\".\"{$table}\"";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Enables a trigger
- * @param $tgname The name of the trigger to enable
- * @param $table The table in which to enable the trigger
- * @return 0 success
- */
- function enableTrigger($tgname, $table) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($tgname);
- $this->fieldClean($table);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ENABLE TRIGGER \"{$tgname}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * Disables a trigger
- * @param $tgname The name of the trigger to disable
- * @param $table The table in which to disable the trigger
- * @return 0 success
- */
- function disableTrigger($tgname, $table) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($tgname);
- $this->fieldClean($table);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" DISABLE TRIGGER \"{$tgname}\"";
-
- return $this->execute($sql);
- }
-
- // Operator functions
-
- /**
- * Returns a list of all operators in the database
- * @return All operators
- */
- function getOperators() {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- // We stick with the subselects here, as you cannot ORDER BY a regtype
- $sql = "
+ return $this->execute($sql);
+ }
+
+ /**
+ * Alters a trigger
+ * @param $table The name of the table containing the trigger
+ * @param $trigger The name of the trigger to alter
+ * @param $name The new name for the trigger
+ * @return 0 success
+ */
+ public function alterTrigger($table, $trigger, $name)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $this->fieldClean($trigger);
+ $this->fieldClean($name);
+
+ $sql = "ALTER TRIGGER \"{$trigger}\" ON \"{$f_schema}\".\"{$table}\" RENAME TO \"{$name}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Drops a trigger
+ * @param $tgname The name of the trigger to drop
+ * @param $table The table from which to drop the trigger
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropTrigger($tgname, $table, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($tgname);
+ $this->fieldClean($table);
+
+ $sql = "DROP TRIGGER \"{$tgname}\" ON \"{$f_schema}\".\"{$table}\"";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Enables a trigger
+ * @param $tgname The name of the trigger to enable
+ * @param $table The table in which to enable the trigger
+ * @return 0 success
+ */
+ public function enableTrigger($tgname, $table)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($tgname);
+ $this->fieldClean($table);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ENABLE TRIGGER \"{$tgname}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Disables a trigger
+ * @param $tgname The name of the trigger to disable
+ * @param $table The table in which to disable the trigger
+ * @return 0 success
+ */
+ public function disableTrigger($tgname, $table)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($tgname);
+ $this->fieldClean($table);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" DISABLE TRIGGER \"{$tgname}\"";
+
+ return $this->execute($sql);
+ }
+
+ // Operator functions
+
+ /**
+ * Returns a list of all operators in the database
+ * @return All operators
+ */
+ public function getOperators()
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ // We stick with the subselects here, as you cannot ORDER BY a regtype
+ $sql = "
SELECT
po.oid, po.oprname,
(SELECT pg_catalog.format_type(oid, NULL) FROM pg_catalog.pg_type pt WHERE pt.oid=po.oprleft) AS oprleftname,
@@ -5573,18 +5725,19 @@ class Postgres extends ADODB_base {
po.oprname, oprleftname, oprrightname
";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns all details for a particular operator
- * @param $operator_oid The oid of the operator
- * @return Function info
- */
- function getOperator($operator_oid) {
- $this->clean($operator_oid);
+ /**
+ * Returns all details for a particular operator
+ * @param $operator_oid The oid of the operator
+ * @return Function info
+ */
+ public function getOperator($operator_oid)
+ {
+ $this->clean($operator_oid);
- $sql = "
+ $sql = "
SELECT
po.oid, po.oprname,
oprleft::pg_catalog.regtype AS oprleftname,
@@ -5603,55 +5756,57 @@ class Postgres extends ADODB_base {
po.oid='{$operator_oid}'
";
- return $this->selectSet($sql);
- }
-
- /**
- * Drops an operator
- * @param $operator_oid The OID of the operator to drop
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropOperator($operator_oid, $cascade) {
- // Function comes in with $object as operator OID
- $opr = $this->getOperator($operator_oid);
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($opr->fields['oprname']);
-
- $sql = "DROP OPERATOR \"{$f_schema}\".{$opr->fields['oprname']} (";
- // Quoting or formatting here???
- if ($opr->fields['oprleftname'] !== null) {
- $sql .= $opr->fields['oprleftname'] . ', ';
- } else {
- $sql .= "NONE, ";
- }
-
- if ($opr->fields['oprrightname'] !== null) {
- $sql .= $opr->fields['oprrightname'] . ')';
- } else {
- $sql .= "NONE)";
- }
-
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- // Operator Class functions
-
- /**
- * Gets all opclasses
- *
- * @return A recordset
- */
-
- function getOpClasses() {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Drops an operator
+ * @param $operator_oid The OID of the operator to drop
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropOperator($operator_oid, $cascade)
+ {
+ // Function comes in with $object as operator OID
+ $opr = $this->getOperator($operator_oid);
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($opr->fields['oprname']);
+
+ $sql = "DROP OPERATOR \"{$f_schema}\".{$opr->fields['oprname']} (";
+ // Quoting or formatting here???
+ if ($opr->fields['oprleftname'] !== null) {
+ $sql .= $opr->fields['oprleftname'] . ', ';
+ } else {
+ $sql .= "NONE, ";
+ }
+
+ if ($opr->fields['oprrightname'] !== null) {
+ $sql .= $opr->fields['oprrightname'] . ')';
+ } else {
+ $sql .= "NONE)";
+ }
+
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ // Operator Class functions
+
+ /**
+ * Gets all opclasses
+ *
+ * @return A recordset
+ */
+
+ public function getOpClasses()
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "
SELECT
pa.amname, po.opcname,
po.opcintype::pg_catalog.regtype AS opcintype,
@@ -5666,81 +5821,83 @@ class Postgres extends ADODB_base {
ORDER BY 1,2
";
- return $this->selectSet($sql);
- }
-
- // FTS functions
-
- /**
- * Creates a new FTS configuration.
- * @param string $cfgname The name of the FTS configuration to create
- * @param string $parser The parser to be used in new FTS configuration
- * @param string $locale Locale of the FTS configuration
- * @param string $template The existing FTS configuration to be used as template for the new one
- * @param string $withmap Should we copy whole map of existing FTS configuration to the new one
- * @param string $makeDefault Should this configuration be the default for locale given
- * @param string $comment If omitted, defaults to nothing
- *
- * @return 0 success
- */
- function createFtsConfiguration($cfgname, $parser = '', $template = '', $comment = '') {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($cfgname);
-
- $sql = "CREATE TEXT SEARCH CONFIGURATION \"{$f_schema}\".\"{$cfgname}\" (";
- if ($parser != '') {
- $this->fieldClean($parser['schema']);
- $this->fieldClean($parser['parser']);
- $parser = "\"{$parser['schema']}\".\"{$parser['parser']}\"";
- $sql .= " PARSER = {$parser}";
- }
- if ($template != '') {
- $this->fieldClean($template['schema']);
- $this->fieldClean($template['name']);
- $sql .= " COPY = \"{$template['schema']}\".\"{$template['name']}\"";
- }
- $sql .= ")";
-
- if ($comment != '') {
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- }
-
- // Create the FTS configuration
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Set the comment
- if ($comment != '') {
- $status = $this->setComment('TEXT SEARCH CONFIGURATION', $cfgname, '', $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- return $this->endTransaction();
- }
-
- return 0;
- }
-
- /**
- * Returns available FTS configurations
- * @param $all if false, returns schema qualified FTS confs
- *
- * @return A recordset
- */
- function getFtsConfigurations($all = true) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ // FTS functions
+
+ /**
+ * Creates a new FTS configuration.
+ * @param string $cfgname The name of the FTS configuration to create
+ * @param string $parser The parser to be used in new FTS configuration
+ * @param string $locale Locale of the FTS configuration
+ * @param string $template The existing FTS configuration to be used as template for the new one
+ * @param string $withmap Should we copy whole map of existing FTS configuration to the new one
+ * @param string $makeDefault Should this configuration be the default for locale given
+ * @param string $comment If omitted, defaults to nothing
+ *
+ * @return 0 success
+ */
+ public function createFtsConfiguration($cfgname, $parser = '', $template = '', $comment = '')
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($cfgname);
+
+ $sql = "CREATE TEXT SEARCH CONFIGURATION \"{$f_schema}\".\"{$cfgname}\" (";
+ if ($parser != '') {
+ $this->fieldClean($parser['schema']);
+ $this->fieldClean($parser['parser']);
+ $parser = "\"{$parser['schema']}\".\"{$parser['parser']}\"";
+ $sql .= " PARSER = {$parser}";
+ }
+ if ($template != '') {
+ $this->fieldClean($template['schema']);
+ $this->fieldClean($template['name']);
+ $sql .= " COPY = \"{$template['schema']}\".\"{$template['name']}\"";
+ }
+ $sql .= ")";
+
+ if ($comment != '') {
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+
+ // Create the FTS configuration
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Set the comment
+ if ($comment != '') {
+ $status = $this->setComment('TEXT SEARCH CONFIGURATION', $cfgname, '', $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ return $this->endTransaction();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns available FTS configurations
+ * @param $all if false, returns schema qualified FTS confs
+ *
+ * @return A recordset
+ */
+ public function getFtsConfigurations($all = true)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "
SELECT
n.nspname as schema,
c.cfgname as name,
@@ -5751,26 +5908,27 @@ class Postgres extends ADODB_base {
WHERE
pg_catalog.pg_ts_config_is_visible(c.oid)";
- if (!$all) {
- $sql .= " AND n.nspname='{$c_schema}'\n";
- }
-
- $sql .= "ORDER BY name";
-
- return $this->selectSet($sql);
- }
-
- /**
- * Return all information related to a FTS configuration
- * @param $ftscfg The name of the FTS configuration
- *
- * @return FTS configuration information
- */
- function getFtsConfigurationByName($ftscfg) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($ftscfg);
- $sql = "
+ if (!$all) {
+ $sql .= " AND n.nspname='{$c_schema}'\n";
+ }
+
+ $sql .= "ORDER BY name";
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Return all information related to a FTS configuration
+ * @param $ftscfg The name of the FTS configuration
+ *
+ * @return FTS configuration information
+ */
+ public function getFtsConfigurationByName($ftscfg)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($ftscfg);
+ $sql = "
SELECT
n.nspname as schema,
c.cfgname as name,
@@ -5784,31 +5942,32 @@ class Postgres extends ADODB_base {
AND c.cfgname = '{$ftscfg}'
AND n.nspname='{$c_schema}'";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns the map of FTS configuration given
- * (list of mappings (tokens) and their processing dictionaries)
- * @param string $ftscfg Name of the FTS configuration
- *
- * @return RecordSet
- */
- function getFtsConfigurationMap($ftscfg) {
+ /**
+ * Returns the map of FTS configuration given
+ * (list of mappings (tokens) and their processing dictionaries)
+ * @param string $ftscfg Name of the FTS configuration
+ *
+ * @return RecordSet
+ */
+ public function getFtsConfigurationMap($ftscfg)
+ {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->fieldClean($ftscfg);
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->fieldClean($ftscfg);
- $oidSet = $this->selectSet("SELECT c.oid
+ $oidSet = $this->selectSet("SELECT c.oid
FROM pg_catalog.pg_ts_config AS c
LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = c.cfgnamespace)
WHERE c.cfgname = '{$ftscfg}'
AND n.nspname='{$c_schema}'");
- $oid = $oidSet->fields['oid'];
+ $oid = $oidSet->fields['oid'];
- $sql = "
+ $sql = "
SELECT
(SELECT t.alias FROM pg_catalog.ts_token_type(c.cfgparser) AS t WHERE t.tokid = m.maptokentype) AS name,
(SELECT t.description FROM pg_catalog.ts_token_type(c.cfgparser) AS t WHERE t.tokid = m.maptokentype) AS description,
@@ -5823,19 +5982,20 @@ class Postgres extends ADODB_base {
AND d.dictnamespace = n.oid
ORDER BY name
";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns FTS parsers available
- * @param $all if false, return only Parsers from the current schema
- *
- * @return RecordSet
- */
- function getFtsParsers($all = true) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns FTS parsers available
+ * @param $all if false, return only Parsers from the current schema
+ *
+ * @return RecordSet
+ */
+ public function getFtsParsers($all = true)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "
SELECT
n.nspname as schema,
p.prsname as name,
@@ -5844,25 +6004,26 @@ class Postgres extends ADODB_base {
LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = p.prsnamespace)
WHERE pg_catalog.pg_ts_parser_is_visible(p.oid)";
- if (!$all) {
- $sql .= " AND n.nspname='{$c_schema}'\n";
- }
-
- $sql .= "ORDER BY name";
-
- return $this->selectSet($sql);
- }
-
- /**
- * Returns FTS dictionaries available
- * @param $all if false, return only Dics from the current schema
- *
- * @returns RecordSet
- */
- function getFtsDictionaries($all = true) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "
+ if (!$all) {
+ $sql .= " AND n.nspname='{$c_schema}'\n";
+ }
+
+ $sql .= "ORDER BY name";
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns FTS dictionaries available
+ * @param $all if false, return only Dics from the current schema
+ *
+ * @returns RecordSet
+ */
+ public function getFtsDictionaries($all = true)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "
SELECT
n.nspname as schema, d.dictname as name,
pg_catalog.obj_description(d.oid, 'pg_ts_dict') as comment
@@ -5870,21 +6031,22 @@ class Postgres extends ADODB_base {
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace
WHERE pg_catalog.pg_ts_dict_is_visible(d.oid)";
- if (!$all) {
- $sql .= " AND n.nspname='{$c_schema}'\n";
- }
+ if (!$all) {
+ $sql .= " AND n.nspname='{$c_schema}'\n";
+ }
- $sql .= "ORDER BY name;";
+ $sql .= "ORDER BY name;";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns all FTS dictionary templates available
- */
- function getFtsDictionaryTemplates() {
+ /**
+ * Returns all FTS dictionary templates available
+ */
+ public function getFtsDictionaryTemplates()
+ {
- $sql = "
+ $sql = "
SELECT
n.nspname as schema,
t.tmplname as name,
@@ -5902,227 +6064,232 @@ class Postgres extends ADODB_base {
WHERE pg_catalog.pg_ts_template_is_visible(t.oid)
ORDER BY name;";
- return $this->selectSet($sql);
- }
-
- /**
- * Drops FTS coniguration
- * @param $ftscfg The configuration's name
- * @param $cascade Cascade to dependenced objects
- *
- * @return 0 on success
- */
- function dropFtsConfiguration($ftscfg, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($ftscfg);
-
- $sql = "DROP TEXT SEARCH CONFIGURATION \"{$f_schema}\".\"{$ftscfg}\"";
- if ($cascade) {
- $sql .= ' CASCADE';
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Drops FTS dictionary
- * @param $ftsdict The dico's name
- * @param $cascade Cascade to dependenced objects
- *
- * @todo Support of dictionary templates dropping
- * @return 0 on success
- */
- function dropFtsDictionary($ftsdict, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($ftsdict);
-
- $sql = "DROP TEXT SEARCH DICTIONARY";
- $sql .= " \"{$f_schema}\".\"{$ftsdict}\"";
- if ($cascade) {
- $sql .= ' CASCADE';
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Alters FTS configuration
- * @param $cfgname The conf's name
- * @param $comment A comment on for the conf
- * @param $name The new conf name
- *
- * @return 0 on success
- */
- function updateFtsConfiguration($cfgname, $comment, $name) {
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $this->fieldClean($cfgname);
-
- $status = $this->setComment('TEXT SEARCH CONFIGURATION', $cfgname, '', $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Only if the name has changed
- if ($name != $cfgname) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
-
- $sql = "ALTER TEXT SEARCH CONFIGURATION \"{$f_schema}\".\"{$cfgname}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Creates a new FTS dictionary or FTS dictionary template.
- * @param string $dictname The name of the FTS dictionary to create
- * @param boolean $isTemplate Flag whether we create usual dictionary or dictionary template
- * @param string $template The existing FTS dictionary to be used as template for the new one
- * @param string $lexize The name of the function, which does transformation of input word
- * @param string $init The name of the function, which initializes dictionary
- * @param string $option Usually, it stores various options required for the dictionary
- * @param string $comment If omitted, defaults to nothing
- *
- * @return 0 success
- */
- function createFtsDictionary($dictname, $isTemplate = false, $template = '', $lexize = '',
- $init = '', $option = '', $comment = '') {
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($dictname);
- $this->fieldClean($template);
- $this->fieldClean($lexize);
- $this->fieldClean($init);
- $this->fieldClean($option);
-
- $sql = "CREATE TEXT SEARCH";
- if ($isTemplate) {
- $sql .= " TEMPLATE \"{$f_schema}\".\"{$dictname}\" (";
- if ($lexize != '') {
- $sql .= " LEXIZE = {$lexize}";
- }
-
- if ($init != '') {
- $sql .= ", INIT = {$init}";
- }
-
- $sql .= ")";
- $whatToComment = 'TEXT SEARCH TEMPLATE';
- } else {
- $sql .= " DICTIONARY \"{$f_schema}\".\"{$dictname}\" (";
- if ($template != '') {
- $this->fieldClean($template['schema']);
- $this->fieldClean($template['name']);
- $template = "\"{$template['schema']}\".\"{$template['name']}\"";
-
- $sql .= " TEMPLATE = {$template}";
- }
- if ($option != '') {
- $sql .= ", {$option}";
- }
-
- $sql .= ")";
- $whatToComment = 'TEXT SEARCH DICTIONARY';
- }
-
- /* if comment, begin a transaction to
- * run both commands */
- if ($comment != '') {
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- }
-
- // Create the FTS dictionary
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Set the comment
- if ($comment != '') {
- $status = $this->setComment($whatToComment, $dictname, '', $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Alters FTS dictionary or dictionary template
- * @param $dictname The dico's name
- * @param $comment The comment
- * @param $name The new dico's name
- *
- * @return 0 on success
- */
- function updateFtsDictionary($dictname, $comment, $name) {
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $this->fieldClean($dictname);
- $status = $this->setComment('TEXT SEARCH DICTIONARY', $dictname, '', $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- // Only if the name has changed
- if ($name != $dictname) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
-
- $sql = "ALTER TEXT SEARCH DICTIONARY \"{$f_schema}\".\"{$dictname}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Return all information relating to a FTS dictionary
- * @param $ftsdict The name of the FTS dictionary
- *
- * @return RecordSet of FTS dictionary information
- */
- function getFtsDictionaryByName($ftsdict) {
-
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($ftsdict);
-
- $sql = "SELECT
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Drops FTS coniguration
+ * @param $ftscfg The configuration's name
+ * @param $cascade Cascade to dependenced objects
+ *
+ * @return 0 on success
+ */
+ public function dropFtsConfiguration($ftscfg, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($ftscfg);
+
+ $sql = "DROP TEXT SEARCH CONFIGURATION \"{$f_schema}\".\"{$ftscfg}\"";
+ if ($cascade) {
+ $sql .= ' CASCADE';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Drops FTS dictionary
+ * @param $ftsdict The dico's name
+ * @param $cascade Cascade to dependenced objects
+ *
+ * @todo Support of dictionary templates dropping
+ * @return 0 on success
+ */
+ public function dropFtsDictionary($ftsdict, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($ftsdict);
+
+ $sql = "DROP TEXT SEARCH DICTIONARY";
+ $sql .= " \"{$f_schema}\".\"{$ftsdict}\"";
+ if ($cascade) {
+ $sql .= ' CASCADE';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Alters FTS configuration
+ * @param $cfgname The conf's name
+ * @param $comment A comment on for the conf
+ * @param $name The new conf name
+ *
+ * @return 0 on success
+ */
+ public function updateFtsConfiguration($cfgname, $comment, $name)
+ {
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $this->fieldClean($cfgname);
+
+ $status = $this->setComment('TEXT SEARCH CONFIGURATION', $cfgname, '', $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Only if the name has changed
+ if ($name != $cfgname) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+
+ $sql = "ALTER TEXT SEARCH CONFIGURATION \"{$f_schema}\".\"{$cfgname}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Creates a new FTS dictionary or FTS dictionary template.
+ * @param string $dictname The name of the FTS dictionary to create
+ * @param boolean $isTemplate Flag whether we create usual dictionary or dictionary template
+ * @param string $template The existing FTS dictionary to be used as template for the new one
+ * @param string $lexize The name of the function, which does transformation of input word
+ * @param string $init The name of the function, which initializes dictionary
+ * @param string $option Usually, it stores various options required for the dictionary
+ * @param string $comment If omitted, defaults to nothing
+ *
+ * @return 0 success
+ */
+ public function createFtsDictionary($dictname, $isTemplate = false, $template = '', $lexize = '',
+ $init = '', $option = '', $comment = '') {
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($dictname);
+ $this->fieldClean($template);
+ $this->fieldClean($lexize);
+ $this->fieldClean($init);
+ $this->fieldClean($option);
+
+ $sql = "CREATE TEXT SEARCH";
+ if ($isTemplate) {
+ $sql .= " TEMPLATE \"{$f_schema}\".\"{$dictname}\" (";
+ if ($lexize != '') {
+ $sql .= " LEXIZE = {$lexize}";
+ }
+
+ if ($init != '') {
+ $sql .= ", INIT = {$init}";
+ }
+
+ $sql .= ")";
+ $whatToComment = 'TEXT SEARCH TEMPLATE';
+ } else {
+ $sql .= " DICTIONARY \"{$f_schema}\".\"{$dictname}\" (";
+ if ($template != '') {
+ $this->fieldClean($template['schema']);
+ $this->fieldClean($template['name']);
+ $template = "\"{$template['schema']}\".\"{$template['name']}\"";
+
+ $sql .= " TEMPLATE = {$template}";
+ }
+ if ($option != '') {
+ $sql .= ", {$option}";
+ }
+
+ $sql .= ")";
+ $whatToComment = 'TEXT SEARCH DICTIONARY';
+ }
+
+ /* if comment, begin a transaction to
+ * run both commands */
+ if ($comment != '') {
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+
+ // Create the FTS dictionary
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Set the comment
+ if ($comment != '') {
+ $status = $this->setComment($whatToComment, $dictname, '', $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Alters FTS dictionary or dictionary template
+ * @param $dictname The dico's name
+ * @param $comment The comment
+ * @param $name The new dico's name
+ *
+ * @return 0 on success
+ */
+ public function updateFtsDictionary($dictname, $comment, $name)
+ {
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $this->fieldClean($dictname);
+ $status = $this->setComment('TEXT SEARCH DICTIONARY', $dictname, '', $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ // Only if the name has changed
+ if ($name != $dictname) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+
+ $sql = "ALTER TEXT SEARCH DICTIONARY \"{$f_schema}\".\"{$dictname}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Return all information relating to a FTS dictionary
+ * @param $ftsdict The name of the FTS dictionary
+ *
+ * @return RecordSet of FTS dictionary information
+ */
+ public function getFtsDictionaryByName($ftsdict)
+ {
+
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($ftsdict);
+
+ $sql = "SELECT
n.nspname as schema,
d.dictname as name,
( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM
@@ -6138,124 +6305,128 @@ class Postgres extends ADODB_base {
AND n.nspname='{$c_schema}'
ORDER BY name";
- return $this->selectSet($sql);
- }
-
- /**
- * Creates/updates/deletes FTS mapping.
- * @param string $cfgname The name of the FTS configuration to alter
- * @param array $mapping Array of tokens' names
- * @param string $action What to do with the mapping: add, alter or drop
- * @param string $dictname Dictionary that will process tokens given or null in case of drop action
- *
- * @return 0 success
- */
- function changeFtsMapping($ftscfg, $mapping, $action, $dictname = null) {
-
- if (count($mapping) > 0) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($ftscfg);
- $this->fieldClean($dictname);
- $this->arrayClean($mapping);
-
- switch ($action) {
- case 'alter':
- $whatToDo = "ALTER";
- break;
- case 'drop':
- $whatToDo = "DROP";
- break;
- default:
- $whatToDo = "ADD";
- break;
- }
-
- $sql = "ALTER TEXT SEARCH CONFIGURATION \"{$f_schema}\".\"{$ftscfg}\" {$whatToDo} MAPPING FOR ";
- $sql .= implode(",", $mapping);
- if ($action != 'drop' && !empty($dictname)) {
- $sql .= " WITH {$dictname}";
- }
-
- return $this->execute($sql);
- } else {
- return -1;
- }
- }
-
- /**
- * Return all information related to a given FTS configuration's mapping
- * @param $ftscfg The name of the FTS configuration
- * @param $mapping The name of the mapping
- *
- * @return FTS configuration information
- */
- function getFtsMappingByName($ftscfg, $mapping) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($ftscfg);
- $this->clean($mapping);
-
- $oidSet = $this->selectSet("SELECT c.oid, cfgparser
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates/updates/deletes FTS mapping.
+ * @param string $cfgname The name of the FTS configuration to alter
+ * @param array $mapping Array of tokens' names
+ * @param string $action What to do with the mapping: add, alter or drop
+ * @param string $dictname Dictionary that will process tokens given or null in case of drop action
+ *
+ * @return 0 success
+ */
+ public function changeFtsMapping($ftscfg, $mapping, $action, $dictname = null)
+ {
+
+ if (count($mapping) > 0) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($ftscfg);
+ $this->fieldClean($dictname);
+ $this->arrayClean($mapping);
+
+ switch ($action) {
+ case 'alter':
+ $whatToDo = "ALTER";
+ break;
+ case 'drop':
+ $whatToDo = "DROP";
+ break;
+ default:
+ $whatToDo = "ADD";
+ break;
+ }
+
+ $sql = "ALTER TEXT SEARCH CONFIGURATION \"{$f_schema}\".\"{$ftscfg}\" {$whatToDo} MAPPING FOR ";
+ $sql .= implode(",", $mapping);
+ if ($action != 'drop' && !empty($dictname)) {
+ $sql .= " WITH {$dictname}";
+ }
+
+ return $this->execute($sql);
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * Return all information related to a given FTS configuration's mapping
+ * @param $ftscfg The name of the FTS configuration
+ * @param $mapping The name of the mapping
+ *
+ * @return FTS configuration information
+ */
+ public function getFtsMappingByName($ftscfg, $mapping)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($ftscfg);
+ $this->clean($mapping);
+
+ $oidSet = $this->selectSet("SELECT c.oid, cfgparser
FROM pg_catalog.pg_ts_config AS c
LEFT JOIN pg_catalog.pg_namespace AS n ON n.oid = c.cfgnamespace
WHERE c.cfgname = '{$ftscfg}'
AND n.nspname='{$c_schema}'");
- $oid = $oidSet->fields['oid'];
- $cfgparser = $oidSet->fields['cfgparser'];
+ $oid = $oidSet->fields['oid'];
+ $cfgparser = $oidSet->fields['cfgparser'];
- $tokenIdSet = $this->selectSet("SELECT tokid
+ $tokenIdSet = $this->selectSet("SELECT tokid
FROM pg_catalog.ts_token_type({$cfgparser})
WHERE alias = '{$mapping}'");
- $tokid = $tokenIdSet->fields['tokid'];
+ $tokid = $tokenIdSet->fields['tokid'];
- $sql = "SELECT
+ $sql = "SELECT
(SELECT t.alias FROM pg_catalog.ts_token_type(c.cfgparser) AS t WHERE t.tokid = m.maptokentype) AS name,
d.dictname as dictionaries
FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m, pg_catalog.pg_ts_dict d
WHERE c.oid = {$oid} AND m.mapcfg = c.oid AND m.maptokentype = {$tokid} AND m.mapdict = d.oid
LIMIT 1;";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Return list of FTS mappings possible for given parser
- * (specified by given configuration since configuration can only have 1 parser)
- * @param $ftscfg The config's name that use the parser
- *
- * @return 0 on success
- */
- function getFtsMappings($ftscfg) {
+ /**
+ * Return list of FTS mappings possible for given parser
+ * (specified by given configuration since configuration can only have 1 parser)
+ * @param $ftscfg The config's name that use the parser
+ *
+ * @return 0 on success
+ */
+ public function getFtsMappings($ftscfg)
+ {
- $cfg = $this->getFtsConfigurationByName($ftscfg);
+ $cfg = $this->getFtsConfigurationByName($ftscfg);
- $sql = "SELECT alias AS name, description
+ $sql = "SELECT alias AS name, description
FROM pg_catalog.ts_token_type({$cfg->fields['parser_id']})
ORDER BY name";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Language functions
+ // Language functions
- /**
- * Gets all languages
- * @param $all True to get all languages, regardless of show_system
- * @return A recordset
- */
- function getLanguages($all = false) {
- $conf = $this->conf;
+ /**
+ * Gets all languages
+ * @param $all True to get all languages, regardless of show_system
+ * @return A recordset
+ */
+ public function getLanguages($all = false)
+ {
+ $conf = $this->conf;
- if ($conf['show_system'] || $all) {
- $where = '';
- } else {
- $where = 'WHERE lanispl';
- }
+ if ($conf['show_system'] || $all) {
+ $where = '';
+ } else {
+ $where = 'WHERE lanispl';
+ }
- $sql = "
+ $sql = "
SELECT
lanname, lanpltrusted,
lanplcallfoid::pg_catalog.regproc AS lanplcallf
@@ -6265,116 +6436,120 @@ class Postgres extends ADODB_base {
ORDER BY lanname
";
- return $this->selectSet($sql);
- }
-
- // Aggregate functions
-
- /**
- * Creates a new aggregate in the database
- * @param $name The name of the aggregate
- * @param $basetype The input data type of the aggregate
- * @param $sfunc The name of the state transition function for the aggregate
- * @param $stype The data type for the aggregate's state value
- * @param $ffunc The name of the final function for the aggregate
- * @param $initcond The initial setting for the state value
- * @param $sortop The sort operator for the aggregate
- * @param $comment Aggregate comment
- * @return 0 success
- * @return -1 error
- */
- function createAggregate($name, $basetype, $sfunc, $stype, $ffunc, $initcond, $sortop, $comment) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($name);
- $this->fieldClean($basetype);
- $this->fieldClean($sfunc);
- $this->fieldClean($stype);
- $this->fieldClean($ffunc);
- $this->fieldClean($initcond);
- $this->fieldClean($sortop);
-
- $this->beginTransaction();
-
- $sql = "CREATE AGGREGATE \"{$f_schema}\".\"{$name}\" (BASETYPE = \"{$basetype}\", SFUNC = \"{$sfunc}\", STYPE = \"{$stype}\"";
- if (trim($ffunc) != '') {
- $sql .= ", FINALFUNC = \"{$ffunc}\"";
- }
-
- if (trim($initcond) != '') {
- $sql .= ", INITCOND = \"{$initcond}\"";
- }
-
- if (trim($sortop) != '') {
- $sql .= ", SORTOP = \"{$sortop}\"";
- }
-
- $sql .= ")";
-
- $status = $this->execute($sql);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
-
- if (trim($comment) != '') {
- $status = $this->setComment('AGGREGATE', $name, '', $comment, $basetype);
- if ($status) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Renames an aggregate function
- * @param $aggrname The actual name of the aggregate
- * @param $aggrtype The actual input data type of the aggregate
- * @param $newaggrname The new name of the aggregate
- * @return 0 success
- */
- function renameAggregate($aggrschema, $aggrname, $aggrtype, $newaggrname) {
- /* this function is called from alterAggregate where params are cleaned */
- $sql = "ALTER AGGREGATE \"{$aggrschema}\"" . '.' . "\"{$aggrname}\" (\"{$aggrtype}\") RENAME TO \"{$newaggrname}\"";
- return $this->execute($sql);
- }
-
- /**
- * Removes an aggregate function from the database
- * @param $aggrname The name of the aggregate
- * @param $aggrtype The input data type of the aggregate
- * @param $cascade True to cascade drop, false to restrict
- * @return 0 success
- */
- function dropAggregate($aggrname, $aggrtype, $cascade) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($aggrname);
- $this->fieldClean($aggrtype);
-
- $sql = "DROP AGGREGATE \"{$f_schema}\".\"{$aggrname}\" (\"{$aggrtype}\")";
- if ($cascade) {
- $sql .= " CASCADE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Gets all information for an aggregate
- * @param $name The name of the aggregate
- * @param $basetype The input data type of the aggregate
- * @return A recordset
- */
- function getAggregate($name, $basetype) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->fieldclean($name);
- $this->fieldclean($basetype);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ // Aggregate functions
+
+ /**
+ * Creates a new aggregate in the database
+ * @param $name The name of the aggregate
+ * @param $basetype The input data type of the aggregate
+ * @param $sfunc The name of the state transition function for the aggregate
+ * @param $stype The data type for the aggregate's state value
+ * @param $ffunc The name of the final function for the aggregate
+ * @param $initcond The initial setting for the state value
+ * @param $sortop The sort operator for the aggregate
+ * @param $comment Aggregate comment
+ * @return 0 success
+ * @return -1 error
+ */
+ public function createAggregate($name, $basetype, $sfunc, $stype, $ffunc, $initcond, $sortop, $comment)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($name);
+ $this->fieldClean($basetype);
+ $this->fieldClean($sfunc);
+ $this->fieldClean($stype);
+ $this->fieldClean($ffunc);
+ $this->fieldClean($initcond);
+ $this->fieldClean($sortop);
+
+ $this->beginTransaction();
+
+ $sql = "CREATE AGGREGATE \"{$f_schema}\".\"{$name}\" (BASETYPE = \"{$basetype}\", SFUNC = \"{$sfunc}\", STYPE = \"{$stype}\"";
+ if (trim($ffunc) != '') {
+ $sql .= ", FINALFUNC = \"{$ffunc}\"";
+ }
+
+ if (trim($initcond) != '') {
+ $sql .= ", INITCOND = \"{$initcond}\"";
+ }
+
+ if (trim($sortop) != '') {
+ $sql .= ", SORTOP = \"{$sortop}\"";
+ }
+
+ $sql .= ")";
+
+ $status = $this->execute($sql);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ if (trim($comment) != '') {
+ $status = $this->setComment('AGGREGATE', $name, '', $comment, $basetype);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Renames an aggregate function
+ * @param $aggrname The actual name of the aggregate
+ * @param $aggrtype The actual input data type of the aggregate
+ * @param $newaggrname The new name of the aggregate
+ * @return 0 success
+ */
+ public function renameAggregate($aggrschema, $aggrname, $aggrtype, $newaggrname)
+ {
+ /* this function is called from alterAggregate where params are cleaned */
+ $sql = "ALTER AGGREGATE \"{$aggrschema}\"" . '.' . "\"{$aggrname}\" (\"{$aggrtype}\") RENAME TO \"{$newaggrname}\"";
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes an aggregate function from the database
+ * @param $aggrname The name of the aggregate
+ * @param $aggrtype The input data type of the aggregate
+ * @param $cascade True to cascade drop, false to restrict
+ * @return 0 success
+ */
+ public function dropAggregate($aggrname, $aggrtype, $cascade)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($aggrname);
+ $this->fieldClean($aggrtype);
+
+ $sql = "DROP AGGREGATE \"{$f_schema}\".\"{$aggrname}\" (\"{$aggrtype}\")";
+ if ($cascade) {
+ $sql .= " CASCADE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Gets all information for an aggregate
+ * @param $name The name of the aggregate
+ * @param $basetype The input data type of the aggregate
+ * @return A recordset
+ */
+ public function getAggregate($name, $basetype)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->fieldclean($name);
+ $this->fieldclean($basetype);
+
+ $sql = "
SELECT p.proname, CASE p.proargtypes[0]
WHEN 'pg_catalog.\"any\"'::pg_catalog.regtype THEN NULL
ELSE pg_catalog.format_type(p.proargtypes[0], NULL) END AS proargtypes,
@@ -6389,701 +6564,724 @@ class Postgres extends ADODB_base {
ELSE pg_catalog.format_type(p.proargtypes[0], NULL)
END ='" . $basetype . "'";
- return $this->selectSet($sql);
- }
-
- /**
- * Gets all aggregates
- * @return A recordset
- */
- function getAggregates() {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "SELECT p.proname, CASE p.proargtypes[0] WHEN 'pg_catalog.\"any\"'::pg_catalog.regtype THEN NULL ELSE
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Gets all aggregates
+ * @return A recordset
+ */
+ public function getAggregates()
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "SELECT p.proname, CASE p.proargtypes[0] WHEN 'pg_catalog.\"any\"'::pg_catalog.regtype THEN NULL ELSE
pg_catalog.format_type(p.proargtypes[0], NULL) END AS proargtypes, a.aggtransfn, u.usename,
pg_catalog.obj_description(p.oid, 'pg_proc') AS aggrcomment
FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n, pg_catalog.pg_user u, pg_catalog.pg_aggregate a
WHERE n.oid = p.pronamespace AND p.proowner=u.usesysid AND p.oid=a.aggfnoid
AND p.proisagg AND n.nspname='{$c_schema}' ORDER BY 1, 2";
- return $this->selectSet($sql);
- }
-
- /**
- * Changes the owner of an aggregate function
- * @param $aggrname The name of the aggregate
- * @param $aggrtype The input data type of the aggregate
- * @param $newaggrowner The new owner of the aggregate
- * @return 0 success
- */
- function changeAggregateOwner($aggrname, $aggrtype, $newaggrowner) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($aggrname);
- $this->fieldClean($newaggrowner);
- $sql = "ALTER AGGREGATE \"{$f_schema}\".\"{$aggrname}\" (\"{$aggrtype}\") OWNER TO \"{$newaggrowner}\"";
- return $this->execute($sql);
- }
-
- /**
- * Changes the schema of an aggregate function
- * @param $aggrname The name of the aggregate
- * @param $aggrtype The input data type of the aggregate
- * @param $newaggrschema The new schema for the aggregate
- * @return 0 success
- */
- function changeAggregateSchema($aggrname, $aggrtype, $newaggrschema) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($aggrname);
- $this->fieldClean($newaggrschema);
- $sql = "ALTER AGGREGATE \"{$f_schema}\".\"{$aggrname}\" (\"{$aggrtype}\") SET SCHEMA \"{$newaggrschema}\"";
- return $this->execute($sql);
- }
-
- /**
- * Alters an aggregate
- * @param $aggrname The actual name of the aggregate
- * @param $aggrtype The actual input data type of the aggregate
- * @param $aggrowner The actual owner of the aggregate
- * @param $aggrschema The actual schema the aggregate belongs to
- * @param $aggrcomment The actual comment for the aggregate
- * @param $newaggrname The new name of the aggregate
- * @param $newaggrowner The new owner of the aggregate
- * @param $newaggrschema The new schema where the aggregate will belong to
- * @param $newaggrcomment The new comment for the aggregate
- * @return 0 success
- * @return -1 change owner error
- * @return -2 change comment error
- * @return -3 change schema error
- * @return -4 change name error
- */
- function alterAggregate($aggrname, $aggrtype, $aggrowner, $aggrschema, $aggrcomment, $newaggrname, $newaggrowner, $newaggrschema, $newaggrcomment) {
- // Clean fields
- $this->fieldClean($aggrname);
- $this->fieldClean($aggrtype);
- $this->fieldClean($aggrowner);
- $this->fieldClean($aggrschema);
- $this->fieldClean($newaggrname);
- $this->fieldClean($newaggrowner);
- $this->fieldClean($newaggrschema);
-
- $this->beginTransaction();
-
- // Change the owner, if it has changed
- if ($aggrowner != $newaggrowner) {
- $status = $this->changeAggregateOwner($aggrname, $aggrtype, $newaggrowner);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
- }
-
- // Set the comment, if it has changed
- if ($aggrcomment != $newaggrcomment) {
- $status = $this->setComment('AGGREGATE', $aggrname, '', $newaggrcomment, $aggrtype);
- if ($status) {
- $this->rollbackTransaction();
- return -2;
- }
- }
-
- // Change the schema, if it has changed
- if ($aggrschema != $newaggrschema) {
- $status = $this->changeAggregateSchema($aggrname, $aggrtype, $newaggrschema);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
- }
-
- // Rename the aggregate, if it has changed
- if ($aggrname != $newaggrname) {
- $status = $this->renameAggregate($newaggrschema, $aggrname, $aggrtype, $newaggrname);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -4;
- }
- }
-
- return $this->endTransaction();
- }
-
- // Role, User/Group functions
-
- /**
- * Returns all roles in the database cluster
- * @param $rolename (optional) The role name to exclude from the select
- * @return All roles
- */
- function getRoles($rolename = '') {
- $sql = '
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Changes the owner of an aggregate function
+ * @param $aggrname The name of the aggregate
+ * @param $aggrtype The input data type of the aggregate
+ * @param $newaggrowner The new owner of the aggregate
+ * @return 0 success
+ */
+ public function changeAggregateOwner($aggrname, $aggrtype, $newaggrowner)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($aggrname);
+ $this->fieldClean($newaggrowner);
+ $sql = "ALTER AGGREGATE \"{$f_schema}\".\"{$aggrname}\" (\"{$aggrtype}\") OWNER TO \"{$newaggrowner}\"";
+ return $this->execute($sql);
+ }
+
+ /**
+ * Changes the schema of an aggregate function
+ * @param $aggrname The name of the aggregate
+ * @param $aggrtype The input data type of the aggregate
+ * @param $newaggrschema The new schema for the aggregate
+ * @return 0 success
+ */
+ public function changeAggregateSchema($aggrname, $aggrtype, $newaggrschema)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($aggrname);
+ $this->fieldClean($newaggrschema);
+ $sql = "ALTER AGGREGATE \"{$f_schema}\".\"{$aggrname}\" (\"{$aggrtype}\") SET SCHEMA \"{$newaggrschema}\"";
+ return $this->execute($sql);
+ }
+
+ /**
+ * Alters an aggregate
+ * @param $aggrname The actual name of the aggregate
+ * @param $aggrtype The actual input data type of the aggregate
+ * @param $aggrowner The actual owner of the aggregate
+ * @param $aggrschema The actual schema the aggregate belongs to
+ * @param $aggrcomment The actual comment for the aggregate
+ * @param $newaggrname The new name of the aggregate
+ * @param $newaggrowner The new owner of the aggregate
+ * @param $newaggrschema The new schema where the aggregate will belong to
+ * @param $newaggrcomment The new comment for the aggregate
+ * @return 0 success
+ * @return -1 change owner error
+ * @return -2 change comment error
+ * @return -3 change schema error
+ * @return -4 change name error
+ */
+ public function alterAggregate($aggrname, $aggrtype, $aggrowner, $aggrschema, $aggrcomment, $newaggrname, $newaggrowner, $newaggrschema, $newaggrcomment)
+ {
+ // Clean fields
+ $this->fieldClean($aggrname);
+ $this->fieldClean($aggrtype);
+ $this->fieldClean($aggrowner);
+ $this->fieldClean($aggrschema);
+ $this->fieldClean($newaggrname);
+ $this->fieldClean($newaggrowner);
+ $this->fieldClean($newaggrschema);
+
+ $this->beginTransaction();
+
+ // Change the owner, if it has changed
+ if ($aggrowner != $newaggrowner) {
+ $status = $this->changeAggregateOwner($aggrname, $aggrtype, $newaggrowner);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+ }
+
+ // Set the comment, if it has changed
+ if ($aggrcomment != $newaggrcomment) {
+ $status = $this->setComment('AGGREGATE', $aggrname, '', $newaggrcomment, $aggrtype);
+ if ($status) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+ }
+
+ // Change the schema, if it has changed
+ if ($aggrschema != $newaggrschema) {
+ $status = $this->changeAggregateSchema($aggrname, $aggrtype, $newaggrschema);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+ }
+
+ // Rename the aggregate, if it has changed
+ if ($aggrname != $newaggrname) {
+ $status = $this->renameAggregate($newaggrschema, $aggrname, $aggrtype, $newaggrname);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -4;
+ }
+ }
+
+ return $this->endTransaction();
+ }
+
+ // Role, User/Group functions
+
+ /**
+ * Returns all roles in the database cluster
+ * @param $rolename (optional) The role name to exclude from the select
+ * @return All roles
+ */
+ public function getRoles($rolename = '')
+ {
+ $sql = '
SELECT rolname, rolsuper, rolcreatedb, rolcreaterole, rolinherit,
rolcanlogin, rolconnlimit, rolvaliduntil, rolconfig
FROM pg_catalog.pg_roles';
- if ($rolename) {
- $sql .= " WHERE rolname!='{$rolename}'";
- }
+ if ($rolename) {
+ $sql .= " WHERE rolname!='{$rolename}'";
+ }
- $sql .= ' ORDER BY rolname';
+ $sql .= ' ORDER BY rolname';
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns information about a single role
- * @param $rolename The name of the role to retrieve
- * @return The role's data
- */
- function getRole($rolename) {
- $this->clean($rolename);
+ /**
+ * Returns information about a single role
+ * @param $rolename The name of the role to retrieve
+ * @return The role's data
+ */
+ public function getRole($rolename)
+ {
+ $this->clean($rolename);
- $sql = "
+ $sql = "
SELECT rolname, rolsuper, rolcreatedb, rolcreaterole, rolinherit,
rolcanlogin, rolconnlimit, rolvaliduntil, rolconfig
FROM pg_catalog.pg_roles WHERE rolname='{$rolename}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Grants membership in a role
- * @param $role The name of the target role
- * @param $rolename The name of the role that will belong to the target role
- * @param $admin (optional) Flag to grant the admin option
- * @return 0 success
- */
- function grantRole($role, $rolename, $admin = 0) {
- $this->fieldClean($role);
- $this->fieldClean($rolename);
-
- $sql = "GRANT \"{$role}\" TO \"{$rolename}\"";
- if ($admin == 1) {
- $sql .= ' WITH ADMIN OPTION';
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Revokes membership in a role
- * @param $role The name of the target role
- * @param $rolename The name of the role that will not belong to the target role
- * @param $admin (optional) Flag to revoke only the admin option
- * @param $type (optional) Type of revoke: RESTRICT | CASCADE
- * @return 0 success
- */
- function revokeRole($role, $rolename, $admin = 0, $type = 'RESTRICT') {
- $this->fieldClean($role);
- $this->fieldClean($rolename);
-
- $sql = "REVOKE ";
- if ($admin == 1) {
- $sql .= 'ADMIN OPTION FOR ';
- }
-
- $sql .= "\"{$role}\" FROM \"{$rolename}\" {$type}";
-
- return $this->execute($sql);
- }
-
- /**
- * Returns all users in the database cluster
- * @return All users
- */
- function getUsers() {
- $sql = "SELECT usename, usesuper, usecreatedb, valuntil AS useexpires, useconfig
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Grants membership in a role
+ * @param $role The name of the target role
+ * @param $rolename The name of the role that will belong to the target role
+ * @param $admin (optional) Flag to grant the admin option
+ * @return 0 success
+ */
+ public function grantRole($role, $rolename, $admin = 0)
+ {
+ $this->fieldClean($role);
+ $this->fieldClean($rolename);
+
+ $sql = "GRANT \"{$role}\" TO \"{$rolename}\"";
+ if ($admin == 1) {
+ $sql .= ' WITH ADMIN OPTION';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Revokes membership in a role
+ * @param $role The name of the target role
+ * @param $rolename The name of the role that will not belong to the target role
+ * @param $admin (optional) Flag to revoke only the admin option
+ * @param $type (optional) Type of revoke: RESTRICT | CASCADE
+ * @return 0 success
+ */
+ public function revokeRole($role, $rolename, $admin = 0, $type = 'RESTRICT')
+ {
+ $this->fieldClean($role);
+ $this->fieldClean($rolename);
+
+ $sql = "REVOKE ";
+ if ($admin == 1) {
+ $sql .= 'ADMIN OPTION FOR ';
+ }
+
+ $sql .= "\"{$role}\" FROM \"{$rolename}\" {$type}";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Returns all users in the database cluster
+ * @return All users
+ */
+ public function getUsers()
+ {
+ $sql = "SELECT usename, usesuper, usecreatedb, valuntil AS useexpires, useconfig
FROM pg_user
ORDER BY usename";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns 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);
+ /**
+ * Returns information about a single user
+ * @param $username The username of the user to retrieve
+ * @return The user's data
+ */
+ public function getUser($username)
+ {
+ $this->clean($username);
- $sql = "SELECT usename, usesuper, usecreatedb, valuntil AS useexpires, useconfig
+ $sql = "SELECT usename, usesuper, usecreatedb, valuntil AS useexpires, useconfig
FROM pg_user
WHERE usename='{$username}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Creates a new role
- * @param $rolename The name of the role to create
- * @param $password A password for the role
- * @param $superuser Boolean whether or not the role is a superuser
- * @param $createdb Boolean whether or not the role can create databases
- * @param $createrole Boolean whether or not the role can create other roles
- * @param $inherits Boolean whether or not the role inherits the privileges from parent roles
- * @param $login Boolean whether or not the role will be allowed to login
- * @param $connlimit Number of concurrent connections the role can make
- * @param $expiry String Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
- * @param $memberof (array) Roles to which the new role will be immediately added as a new member
- * @param $members (array) Roles which are automatically added as members of the new role
- * @param $adminmembers (array) Roles which are automatically added as admin members of the new role
- * @return 0 success
- */
- function createRole($rolename, $password, $superuser, $createdb, $createrole, $inherits, $login, $connlimit, $expiry, $memberof, $members, $adminmembers) {
- $enc = $this->_encryptPassword($rolename, $password);
- $this->fieldClean($rolename);
- $this->clean($enc);
- $this->clean($connlimit);
- $this->clean($expiry);
- $this->fieldArrayClean($memberof);
- $this->fieldArrayClean($members);
- $this->fieldArrayClean($adminmembers);
-
- $sql = "CREATE ROLE \"{$rolename}\"";
- if ($password != '') {
- $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
- }
-
- $sql .= ($superuser) ? ' SUPERUSER' : ' NOSUPERUSER';
- $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';
- $sql .= ($createrole) ? ' CREATEROLE' : ' NOCREATEROLE';
- $sql .= ($inherits) ? ' INHERIT' : ' NOINHERIT';
- $sql .= ($login) ? ' LOGIN' : ' NOLOGIN';
- if ($connlimit != '') {
- $sql .= " CONNECTION LIMIT {$connlimit}";
- } else {
- $sql .= ' CONNECTION LIMIT -1';
- }
-
- if ($expiry != '') {
- $sql .= " VALID UNTIL '{$expiry}'";
- } else {
- $sql .= " VALID UNTIL 'infinity'";
- }
-
- if (is_array($memberof) && sizeof($memberof) > 0) {
- $sql .= ' IN ROLE "' . join('", "', $memberof) . '"';
- }
-
- if (is_array($members) && sizeof($members) > 0) {
- $sql .= ' ROLE "' . join('", "', $members) . '"';
- }
-
- if (is_array($adminmembers) && sizeof($adminmembers) > 0) {
- $sql .= ' ADMIN "' . join('", "', $adminmembers) . '"';
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Adjusts a role's info
- * @param $rolename The name of the role to adjust
- * @param $password A password for the role
- * @param $superuser Boolean whether or not the role is a superuser
- * @param $createdb Boolean whether or not the role can create databases
- * @param $createrole Boolean whether or not the role can create other roles
- * @param $inherits Boolean whether or not the role inherits the privileges from parent roles
- * @param $login Boolean whether or not the role will be allowed to login
- * @param $connlimit Number of concurrent connections the role can make
- * @param $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
- * @param $memberof (array) Roles to which the role will be immediately added as a new member
- * @param $members (array) Roles which are automatically added as members of the role
- * @param $adminmembers (array) Roles which are automatically added as admin members of the role
- * @param $memberofold (array) Original roles whose the role belongs to
- * @param $membersold (array) Original roles that are members of the role
- * @param $adminmembersold (array) Original roles that are admin members of the role
- * @return 0 success
- */
- function setRole($rolename, $password, $superuser, $createdb, $createrole, $inherits, $login, $connlimit, $expiry, $memberof, $members, $adminmembers, $memberofold, $membersold, $adminmembersold) {
- $enc = $this->_encryptPassword($rolename, $password);
- $this->fieldClean($rolename);
- $this->clean($enc);
- $this->clean($connlimit);
- $this->clean($expiry);
- $this->fieldArrayClean($memberof);
- $this->fieldArrayClean($members);
- $this->fieldArrayClean($adminmembers);
-
- $sql = "ALTER ROLE \"{$rolename}\"";
- if ($password != '') {
- $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
- }
-
- $sql .= ($superuser) ? ' SUPERUSER' : ' NOSUPERUSER';
- $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';
- $sql .= ($createrole) ? ' CREATEROLE' : ' NOCREATEROLE';
- $sql .= ($inherits) ? ' INHERIT' : ' NOINHERIT';
- $sql .= ($login) ? ' LOGIN' : ' NOLOGIN';
- if ($connlimit != '') {
- $sql .= " CONNECTION LIMIT {$connlimit}";
- } else {
- $sql .= ' CONNECTION LIMIT -1';
- }
-
- if ($expiry != '') {
- $sql .= " VALID UNTIL '{$expiry}'";
- } else {
- $sql .= " VALID UNTIL 'infinity'";
- }
-
- $status = $this->execute($sql);
-
- if ($status != 0) {
- return -1;
- }
-
- //memberof
- $old = explode(',', $memberofold);
- foreach ($memberof as $m) {
- if (!in_array($m, $old)) {
- $status = $this->grantRole($m, $rolename);
- if ($status != 0) {
- return -1;
- }
-
- }
- }
- if ($memberofold) {
- foreach ($old as $o) {
- if (!in_array($o, $memberof)) {
- $status = $this->revokeRole($o, $rolename, 0, 'CASCADE');
- if ($status != 0) {
- return -1;
- }
-
- }
- }
- }
-
- //members
- $old = explode(',', $membersold);
- foreach ($members as $m) {
- if (!in_array($m, $old)) {
- $status = $this->grantRole($rolename, $m);
- if ($status != 0) {
- return -1;
- }
-
- }
- }
- if ($membersold) {
- foreach ($old as $o) {
- if (!in_array($o, $members)) {
- $status = $this->revokeRole($rolename, $o, 0, 'CASCADE');
- if ($status != 0) {
- return -1;
- }
-
- }
- }
- }
-
- //adminmembers
- $old = explode(',', $adminmembersold);
- foreach ($adminmembers as $m) {
- if (!in_array($m, $old)) {
- $status = $this->grantRole($rolename, $m, 1);
- if ($status != 0) {
- return -1;
- }
-
- }
- }
- if ($adminmembersold) {
- foreach ($old as $o) {
- if (!in_array($o, $adminmembers)) {
- $status = $this->revokeRole($rolename, $o, 1, 'CASCADE');
- if ($status != 0) {
- return -1;
- }
-
- }
- }
- }
-
- return $status;
- }
-
- /**
- * Renames a role
- * @param $rolename The name of the role to rename
- * @param $newrolename The new name of the role
- * @return 0 success
- */
- function renameRole($rolename, $newrolename) {
- $this->fieldClean($rolename);
- $this->fieldClean($newrolename);
-
- $sql = "ALTER ROLE \"{$rolename}\" RENAME TO \"{$newrolename}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * Adjusts a role's info and renames it
- * @param $rolename The name of the role to adjust
- * @param $password A password for the role
- * @param $superuser Boolean whether or not the role is a superuser
- * @param $createdb Boolean whether or not the role can create databases
- * @param $createrole Boolean whether or not the role can create other roles
- * @param $inherits Boolean whether or not the role inherits the privileges from parent roles
- * @param $login Boolean whether or not the role will be allowed to login
- * @param $connlimit Number of concurrent connections the role can make
- * @param $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
- * @param $memberof (array) Roles to which the role will be immediately added as a new member
- * @param $members (array) Roles which are automatically added as members of the role
- * @param $adminmembers (array) Roles which are automatically added as admin members of the role
- * @param $memberofold (array) Original roles whose the role belongs to
- * @param $membersold (array) Original roles that are members of the role
- * @param $adminmembersold (array) Original roles that are admin members of the role
- * @param $newrolename The new name of the role
- * @return 0 success
- * @return -1 transaction error
- * @return -2 set role attributes error
- * @return -3 rename error
- */
- function setRenameRole($rolename, $password, $superuser, $createdb, $createrole,
- $inherits, $login, $connlimit, $expiry, $memberof, $members, $adminmembers,
- $memberofold, $membersold, $adminmembersold, $newrolename) {
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- if ($rolename != $newrolename) {
- $status = $this->renameRole($rolename, $newrolename);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
- $rolename = $newrolename;
- }
-
- $status = $this->setRole($rolename, $password, $superuser, $createdb, $createrole, $inherits, $login, $connlimit, $expiry, $memberof, $members, $adminmembers, $memberofold, $membersold, $adminmembersold);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -2;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Removes a role
- * @param $rolename The name of the role to drop
- * @return 0 success
- */
- function dropRole($rolename) {
- $this->fieldClean($rolename);
-
- $sql = "DROP ROLE \"{$rolename}\"";
-
- return $this->execute($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'. '' means never expire
- * @param $group (array) The groups to create the user in
- * @return 0 success
- */
- function createUser($username, $password, $createdb, $createuser, $expiry, $groups) {
- $enc = $this->_encryptPassword($username, $password);
- $this->fieldClean($username);
- $this->clean($enc);
- $this->clean($expiry);
- $this->fieldArrayClean($groups);
-
- $sql = "CREATE USER \"{$username}\"";
- if ($password != '') {
- $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
- }
-
- $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}'";
- } else {
- $sql .= " VALID UNTIL 'infinity'";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Renames a user
- * @param $username The username of the user to rename
- * @param $newname The new name of the user
- * @return 0 success
- */
- function renameUser($username, $newname) {
- $this->fieldClean($username);
- $this->fieldClean($newname);
-
- $sql = "ALTER USER \"{$username}\" RENAME TO \"{$newname}\"";
-
- 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'. '' means never expire.
- * @return 0 success
- */
- function setUser($username, $password, $createdb, $createuser, $expiry) {
- $enc = $this->_encryptPassword($username, $password);
- $this->fieldClean($username);
- $this->clean($enc);
- $this->clean($expiry);
-
- $sql = "ALTER USER \"{$username}\"";
- if ($password != '') {
- $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
- }
-
- $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';
- $sql .= ($createuser) ? ' CREATEUSER' : ' NOCREATEUSER';
- if ($expiry != '') {
- $sql .= " VALID UNTIL '{$expiry}'";
- } else {
- $sql .= " VALID UNTIL 'infinity'";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Adjusts a user's info and renames the user
- * @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'. '' means never expire.
- * @param $newname The new name of the user
- * @return 0 success
- * @return -1 transaction error
- * @return -2 set user attributes error
- * @return -3 rename error
- */
- function setRenameUser($username, $password, $createdb, $createuser, $expiry, $newname) {
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- if ($username != $newname) {
- $status = $this->renameUser($username, $newname);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
- $username = $newname;
- }
-
- $status = $this->setUser($username, $password, $createdb, $createuser, $expiry);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -2;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Removes a user
- * @param $username The username of the user to drop
- * @return 0 success
- */
- function dropUser($username) {
- $this->fieldClean($username);
-
- $sql = "DROP USER \"{$username}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * Determines whether or not a user is a super user
- * @param $username The username of the user
- * @return True if is a super user, false otherwise
- */
- function isSuperUser($username = '') {
- $this->clean($username);
-
- if (empty($usename)) {
- $val = pg_parameter_status($this->conn->_connectionID, 'is_superuser');
- if ($val !== false) {
- return $val == 'on';
- }
-
- }
-
- $sql = "SELECT usesuper FROM pg_user WHERE usename='{$username}'";
-
- $usesuper = $this->selectField($sql, 'usesuper');
- if ($usesuper == -1) {
- return false;
- } else {
- return $usesuper == 't';
- }
-
- }
-
- /**
- * Changes a role's password
- * @param $rolename The role name
- * @param $password The new password
- * @return 0 success
- */
- function changePassword($rolename, $password) {
- $enc = $this->_encryptPassword($rolename, $password);
- $this->fieldClean($rolename);
- $this->clean($enc);
-
- $sql = "ALTER ROLE \"{$rolename}\" WITH ENCRYPTED PASSWORD '{$enc}'";
-
- return $this->execute($sql);
- }
-
- /**
- * Adds a group member
- * @param $groname The name of the group
- * @param $user The name of the user to add to the group
- * @return 0 success
- */
- function addGroupMember($groname, $user) {
- $this->fieldClean($groname);
- $this->fieldClean($user);
-
- $sql = "ALTER GROUP \"{$groname}\" ADD USER \"{$user}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * Returns all role names which the role belongs to
- * @param $rolename The role name
- * @return All role names
- */
- function getMemberOf($rolename) {
- $this->clean($rolename);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a new role
+ * @param $rolename The name of the role to create
+ * @param $password A password for the role
+ * @param $superuser Boolean whether or not the role is a superuser
+ * @param $createdb Boolean whether or not the role can create databases
+ * @param $createrole Boolean whether or not the role can create other roles
+ * @param $inherits Boolean whether or not the role inherits the privileges from parent roles
+ * @param $login Boolean whether or not the role will be allowed to login
+ * @param $connlimit Number of concurrent connections the role can make
+ * @param $expiry String Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
+ * @param $memberof (array) Roles to which the new role will be immediately added as a new member
+ * @param $members (array) Roles which are automatically added as members of the new role
+ * @param $adminmembers (array) Roles which are automatically added as admin members of the new role
+ * @return 0 success
+ */
+ public function createRole($rolename, $password, $superuser, $createdb, $createrole, $inherits, $login, $connlimit, $expiry, $memberof, $members, $adminmembers)
+ {
+ $enc = $this->_encryptPassword($rolename, $password);
+ $this->fieldClean($rolename);
+ $this->clean($enc);
+ $this->clean($connlimit);
+ $this->clean($expiry);
+ $this->fieldArrayClean($memberof);
+ $this->fieldArrayClean($members);
+ $this->fieldArrayClean($adminmembers);
+
+ $sql = "CREATE ROLE \"{$rolename}\"";
+ if ($password != '') {
+ $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
+ }
+
+ $sql .= ($superuser) ? ' SUPERUSER' : ' NOSUPERUSER';
+ $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';
+ $sql .= ($createrole) ? ' CREATEROLE' : ' NOCREATEROLE';
+ $sql .= ($inherits) ? ' INHERIT' : ' NOINHERIT';
+ $sql .= ($login) ? ' LOGIN' : ' NOLOGIN';
+ if ($connlimit != '') {
+ $sql .= " CONNECTION LIMIT {$connlimit}";
+ } else {
+ $sql .= ' CONNECTION LIMIT -1';
+ }
+
+ if ($expiry != '') {
+ $sql .= " VALID UNTIL '{$expiry}'";
+ } else {
+ $sql .= " VALID UNTIL 'infinity'";
+ }
+
+ if (is_array($memberof) && sizeof($memberof) > 0) {
+ $sql .= ' IN ROLE "' . join('", "', $memberof) . '"';
+ }
+
+ if (is_array($members) && sizeof($members) > 0) {
+ $sql .= ' ROLE "' . join('", "', $members) . '"';
+ }
+
+ if (is_array($adminmembers) && sizeof($adminmembers) > 0) {
+ $sql .= ' ADMIN "' . join('", "', $adminmembers) . '"';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adjusts a role's info
+ * @param $rolename The name of the role to adjust
+ * @param $password A password for the role
+ * @param $superuser Boolean whether or not the role is a superuser
+ * @param $createdb Boolean whether or not the role can create databases
+ * @param $createrole Boolean whether or not the role can create other roles
+ * @param $inherits Boolean whether or not the role inherits the privileges from parent roles
+ * @param $login Boolean whether or not the role will be allowed to login
+ * @param $connlimit Number of concurrent connections the role can make
+ * @param $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
+ * @param $memberof (array) Roles to which the role will be immediately added as a new member
+ * @param $members (array) Roles which are automatically added as members of the role
+ * @param $adminmembers (array) Roles which are automatically added as admin members of the role
+ * @param $memberofold (array) Original roles whose the role belongs to
+ * @param $membersold (array) Original roles that are members of the role
+ * @param $adminmembersold (array) Original roles that are admin members of the role
+ * @return 0 success
+ */
+ public function setRole($rolename, $password, $superuser, $createdb, $createrole, $inherits, $login, $connlimit, $expiry, $memberof, $members, $adminmembers, $memberofold, $membersold, $adminmembersold)
+ {
+ $enc = $this->_encryptPassword($rolename, $password);
+ $this->fieldClean($rolename);
+ $this->clean($enc);
+ $this->clean($connlimit);
+ $this->clean($expiry);
+ $this->fieldArrayClean($memberof);
+ $this->fieldArrayClean($members);
+ $this->fieldArrayClean($adminmembers);
+
+ $sql = "ALTER ROLE \"{$rolename}\"";
+ if ($password != '') {
+ $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
+ }
+
+ $sql .= ($superuser) ? ' SUPERUSER' : ' NOSUPERUSER';
+ $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';
+ $sql .= ($createrole) ? ' CREATEROLE' : ' NOCREATEROLE';
+ $sql .= ($inherits) ? ' INHERIT' : ' NOINHERIT';
+ $sql .= ($login) ? ' LOGIN' : ' NOLOGIN';
+ if ($connlimit != '') {
+ $sql .= " CONNECTION LIMIT {$connlimit}";
+ } else {
+ $sql .= ' CONNECTION LIMIT -1';
+ }
+
+ if ($expiry != '') {
+ $sql .= " VALID UNTIL '{$expiry}'";
+ } else {
+ $sql .= " VALID UNTIL 'infinity'";
+ }
+
+ $status = $this->execute($sql);
+
+ if ($status != 0) {
+ return -1;
+ }
+
+ //memberof
+ $old = explode(',', $memberofold);
+ foreach ($memberof as $m) {
+ if (!in_array($m, $old)) {
+ $status = $this->grantRole($m, $rolename);
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+ }
+ if ($memberofold) {
+ foreach ($old as $o) {
+ if (!in_array($o, $memberof)) {
+ $status = $this->revokeRole($o, $rolename, 0, 'CASCADE');
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+ }
+ }
+
+ //members
+ $old = explode(',', $membersold);
+ foreach ($members as $m) {
+ if (!in_array($m, $old)) {
+ $status = $this->grantRole($rolename, $m);
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+ }
+ if ($membersold) {
+ foreach ($old as $o) {
+ if (!in_array($o, $members)) {
+ $status = $this->revokeRole($rolename, $o, 0, 'CASCADE');
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+ }
+ }
+
+ //adminmembers
+ $old = explode(',', $adminmembersold);
+ foreach ($adminmembers as $m) {
+ if (!in_array($m, $old)) {
+ $status = $this->grantRole($rolename, $m, 1);
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+ }
+ if ($adminmembersold) {
+ foreach ($old as $o) {
+ if (!in_array($o, $adminmembers)) {
+ $status = $this->revokeRole($rolename, $o, 1, 'CASCADE');
+ if ($status != 0) {
+ return -1;
+ }
+
+ }
+ }
+ }
+
+ return $status;
+ }
+
+ /**
+ * Renames a role
+ * @param $rolename The name of the role to rename
+ * @param $newrolename The new name of the role
+ * @return 0 success
+ */
+ public function renameRole($rolename, $newrolename)
+ {
+ $this->fieldClean($rolename);
+ $this->fieldClean($newrolename);
+
+ $sql = "ALTER ROLE \"{$rolename}\" RENAME TO \"{$newrolename}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adjusts a role's info and renames it
+ * @param $rolename The name of the role to adjust
+ * @param $password A password for the role
+ * @param $superuser Boolean whether or not the role is a superuser
+ * @param $createdb Boolean whether or not the role can create databases
+ * @param $createrole Boolean whether or not the role can create other roles
+ * @param $inherits Boolean whether or not the role inherits the privileges from parent roles
+ * @param $login Boolean whether or not the role will be allowed to login
+ * @param $connlimit Number of concurrent connections the role can make
+ * @param $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
+ * @param $memberof (array) Roles to which the role will be immediately added as a new member
+ * @param $members (array) Roles which are automatically added as members of the role
+ * @param $adminmembers (array) Roles which are automatically added as admin members of the role
+ * @param $memberofold (array) Original roles whose the role belongs to
+ * @param $membersold (array) Original roles that are members of the role
+ * @param $adminmembersold (array) Original roles that are admin members of the role
+ * @param $newrolename The new name of the role
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 set role attributes error
+ * @return -3 rename error
+ */
+ public function setRenameRole($rolename, $password, $superuser, $createdb, $createrole,
+ $inherits, $login, $connlimit, $expiry, $memberof, $members, $adminmembers,
+ $memberofold, $membersold, $adminmembersold, $newrolename) {
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ if ($rolename != $newrolename) {
+ $status = $this->renameRole($rolename, $newrolename);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+ $rolename = $newrolename;
+ }
+
+ $status = $this->setRole($rolename, $password, $superuser, $createdb, $createrole, $inherits, $login, $connlimit, $expiry, $memberof, $members, $adminmembers, $memberofold, $membersold, $adminmembersold);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Removes a role
+ * @param $rolename The name of the role to drop
+ * @return 0 success
+ */
+ public function dropRole($rolename)
+ {
+ $this->fieldClean($rolename);
+
+ $sql = "DROP ROLE \"{$rolename}\"";
+
+ return $this->execute($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'. '' means never expire
+ * @param $group (array) The groups to create the user in
+ * @return 0 success
+ */
+ public function createUser($username, $password, $createdb, $createuser, $expiry, $groups)
+ {
+ $enc = $this->_encryptPassword($username, $password);
+ $this->fieldClean($username);
+ $this->clean($enc);
+ $this->clean($expiry);
+ $this->fieldArrayClean($groups);
+
+ $sql = "CREATE USER \"{$username}\"";
+ if ($password != '') {
+ $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
+ }
+
+ $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}'";
+ } else {
+ $sql .= " VALID UNTIL 'infinity'";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Renames a user
+ * @param $username The username of the user to rename
+ * @param $newname The new name of the user
+ * @return 0 success
+ */
+ public function renameUser($username, $newname)
+ {
+ $this->fieldClean($username);
+ $this->fieldClean($newname);
+
+ $sql = "ALTER USER \"{$username}\" RENAME TO \"{$newname}\"";
+
+ 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'. '' means never expire.
+ * @return 0 success
+ */
+ public function setUser($username, $password, $createdb, $createuser, $expiry)
+ {
+ $enc = $this->_encryptPassword($username, $password);
+ $this->fieldClean($username);
+ $this->clean($enc);
+ $this->clean($expiry);
+
+ $sql = "ALTER USER \"{$username}\"";
+ if ($password != '') {
+ $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
+ }
+
+ $sql .= ($createdb) ? ' CREATEDB' : ' NOCREATEDB';
+ $sql .= ($createuser) ? ' CREATEUSER' : ' NOCREATEUSER';
+ if ($expiry != '') {
+ $sql .= " VALID UNTIL '{$expiry}'";
+ } else {
+ $sql .= " VALID UNTIL 'infinity'";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adjusts a user's info and renames the user
+ * @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'. '' means never expire.
+ * @param $newname The new name of the user
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 set user attributes error
+ * @return -3 rename error
+ */
+ public function setRenameUser($username, $password, $createdb, $createuser, $expiry, $newname)
+ {
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ if ($username != $newname) {
+ $status = $this->renameUser($username, $newname);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+ $username = $newname;
+ }
+
+ $status = $this->setUser($username, $password, $createdb, $createuser, $expiry);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Removes a user
+ * @param $username The username of the user to drop
+ * @return 0 success
+ */
+ public function dropUser($username)
+ {
+ $this->fieldClean($username);
+
+ $sql = "DROP USER \"{$username}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Determines whether or not a user is a super user
+ * @param $username The username of the user
+ * @return True if is a super user, false otherwise
+ */
+ public function isSuperUser($username = '')
+ {
+ $this->clean($username);
+
+ if (empty($usename)) {
+ $val = pg_parameter_status($this->conn->_connectionID, 'is_superuser');
+ if ($val !== false) {
+ return $val == 'on';
+ }
+
+ }
+
+ $sql = "SELECT usesuper FROM pg_user WHERE usename='{$username}'";
+
+ $usesuper = $this->selectField($sql, 'usesuper');
+ if ($usesuper == -1) {
+ return false;
+ } else {
+ return $usesuper == 't';
+ }
+
+ }
+
+ /**
+ * Changes a role's password
+ * @param $rolename The role name
+ * @param $password The new password
+ * @return 0 success
+ */
+ public function changePassword($rolename, $password)
+ {
+ $enc = $this->_encryptPassword($rolename, $password);
+ $this->fieldClean($rolename);
+ $this->clean($enc);
+
+ $sql = "ALTER ROLE \"{$rolename}\" WITH ENCRYPTED PASSWORD '{$enc}'";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adds a group member
+ * @param $groname The name of the group
+ * @param $user The name of the user to add to the group
+ * @return 0 success
+ */
+ public function addGroupMember($groname, $user)
+ {
+ $this->fieldClean($groname);
+ $this->fieldClean($user);
+
+ $sql = "ALTER GROUP \"{$groname}\" ADD USER \"{$user}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Returns all role names which the role belongs to
+ * @param $rolename The role name
+ * @return All role names
+ */
+ public function getMemberOf($rolename)
+ {
+ $this->clean($rolename);
+
+ $sql = "
SELECT rolname FROM pg_catalog.pg_roles R, pg_auth_members M
WHERE R.oid=M.roleid
AND member IN (
@@ -7091,247 +7289,255 @@ class Postgres extends ADODB_base {
WHERE rolname='{$rolename}')
ORDER BY rolname";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns all role names that are members of a role
- * @param $rolename The role name
- * @param $admin (optional) Find only admin members
- * @return All role names
- */
- function getMembers($rolename, $admin = 'f') {
- $this->clean($rolename);
+ /**
+ * Returns all role names that are members of a role
+ * @param $rolename The role name
+ * @param $admin (optional) Find only admin members
+ * @return All role names
+ */
+ public function getMembers($rolename, $admin = 'f')
+ {
+ $this->clean($rolename);
- $sql = "
+ $sql = "
SELECT rolname FROM pg_catalog.pg_roles R, pg_auth_members M
WHERE R.oid=M.member AND admin_option='{$admin}'
AND roleid IN (SELECT oid FROM pg_catalog.pg_roles
WHERE rolname='{$rolename}')
ORDER BY rolname";
- return $this->selectSet($sql);
- }
-
- /**
- * Removes a group member
- * @param $groname The name of the group
- * @param $user The name of the user to remove from the group
- * @return 0 success
- */
- function dropGroupMember($groname, $user) {
- $this->fieldClean($groname);
- $this->fieldClean($user);
-
- $sql = "ALTER GROUP \"{$groname}\" DROP USER \"{$user}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * Return users in a specific group
- * @param $groname The name of the group
- * @return All users in the group
- */
- function getGroup($groname) {
- $this->clean($groname);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Removes a group member
+ * @param $groname The name of the group
+ * @param $user The name of the user to remove from the group
+ * @return 0 success
+ */
+ public function dropGroupMember($groname, $user)
+ {
+ $this->fieldClean($groname);
+ $this->fieldClean($user);
+
+ $sql = "ALTER GROUP \"{$groname}\" DROP USER \"{$user}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Return users in a specific group
+ * @param $groname The name of the group
+ * @return All users in the group
+ */
+ public function getGroup($groname)
+ {
+ $this->clean($groname);
+
+ $sql = "
SELECT s.usename FROM pg_catalog.pg_user s, pg_catalog.pg_group g
WHERE g.groname='{$groname}' AND s.usesysid = ANY (g.grolist)
ORDER BY s.usename";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns all groups in the database cluser
- * @return All groups
- */
- function getGroups() {
- $sql = "SELECT groname FROM pg_group ORDER BY groname";
-
- return $this->selectSet($sql);
- }
-
- /**
- * Creates a new group
- * @param $groname The name of the group
- * @param $users An array of users to add to the group
- * @return 0 success
- */
- function createGroup($groname, $users) {
- $this->fieldClean($groname);
-
- $sql = "CREATE GROUP \"{$groname}\"";
-
- if (is_array($users) && sizeof($users) > 0) {
- $this->fieldArrayClean($users);
- $sql .= ' WITH USER "' . join('", "', $users) . '"';
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Removes a group
- * @param $groname The name of the group to drop
- * @return 0 success
- */
- function dropGroup($groname) {
- $this->fieldClean($groname);
-
- $sql = "DROP GROUP \"{$groname}\"";
-
- return $this->execute($sql);
- }
-
- /**
- * Internal function used for parsing ACLs
- * @param $acl The ACL to parse (of type aclitem[])
- * @return Privileges array
- */
- function _parseACL($acl) {
- // Take off the first and last characters (the braces)
- $acl = substr($acl, 1, strlen($acl) - 2);
-
- // Pick out individual ACE's by carefully parsing. This is necessary in order
- // to cope with usernames and stuff that contain commas
- $aces = [];
- $i = $j = 0;
- $in_quotes = false;
- while ($i < strlen($acl)) {
- // If current char is a double quote and it's not escaped, then
- // enter quoted bit
- $char = substr($acl, $i, 1);
- if ($char == '"' && ($i == 0 || substr($acl, $i - 1, 1) != '\\')) {
- $in_quotes = !$in_quotes;
- } elseif ($char == ',' && !$in_quotes) {
- // Add text so far to the array
- $aces[] = substr($acl, $j, $i - $j);
- $j = $i + 1;
- }
- $i++;
- }
- // Add final text to the array
- $aces[] = substr($acl, $j);
-
- // Create the array to be returned
- $temp = [];
-
- // For each ACE, generate an entry in $temp
- foreach ($aces as $v) {
-
- // If the ACE begins with a double quote, strip them off both ends
- // and unescape backslashes and double quotes
- $unquote = false;
- if (strpos($v, '"') === 0) {
- $v = substr($v, 1, strlen($v) - 2);
- $v = str_replace('\\"', '"', $v);
- $v = str_replace('\\\\', '\\', $v);
- }
-
- // Figure out type of ACE (public, user or group)
- if (strpos($v, '=') === 0) {
- $atype = 'public';
- } else if ($this->hasRoles()) {
- $atype = 'role';
- } else if (strpos($v, 'group ') === 0) {
- $atype = 'group';
- // Tear off 'group' prefix
- $v = substr($v, 6);
- } else {
- $atype = 'user';
- }
-
- // Break on unquoted equals sign...
- $i = 0;
- $in_quotes = false;
- $entity = null;
- $chars = null;
- while ($i < strlen($v)) {
- // If current char is a double quote and it's not escaped, then
- // enter quoted bit
- $char = substr($v, $i, 1);
- $next_char = substr($v, $i + 1, 1);
- if ($char == '"' && ($i == 0 || $next_char != '"')) {
- $in_quotes = !$in_quotes;
- }
- // Skip over escaped double quotes
- elseif ($char == '"' && $next_char == '"') {
- $i++;
- } elseif ($char == '=' && !$in_quotes) {
- // Split on current equals sign
- $entity = substr($v, 0, $i);
- $chars = substr($v, $i + 1);
- break;
- }
- $i++;
- }
-
- // Check for quoting on entity name, and unescape if necessary
- if (strpos($entity, '"') === 0) {
- $entity = substr($entity, 1, strlen($entity) - 2);
- $entity = str_replace('""', '"', $entity);
- }
-
- // New row to be added to $temp
- // (type, grantee, privileges, grantor, grant option?
- $row = [$atype, $entity, [], '', []];
-
- // Loop over chars and add privs to $row
- for ($i = 0; $i < strlen($chars); $i++) {
- // Append to row's privs list the string representing
- // the privilege
- $char = substr($chars, $i, 1);
- if ($char == '*') {
- $row[4][] = $this->privmap[substr($chars, $i - 1, 1)];
- } elseif ($char == '/') {
- $grantor = substr($chars, $i + 1);
- // Check for quoting
- if (strpos($grantor, '"') === 0) {
- $grantor = substr($grantor, 1, strlen($grantor) - 2);
- $grantor = str_replace('""', '"', $grantor);
- }
- $row[3] = $grantor;
- break;
- } else {
- if (!isset($this->privmap[$char])) {
- return -3;
- } else {
- $row[2][] = $this->privmap[$char];
- }
-
- }
- }
-
- // Append row to temp
- $temp[] = $row;
- }
-
- return $temp;
- }
-
- /**
- * Grabs an array of users and their privileges for an object,
- * given its type.
- * @param $object The name of the object whose privileges are to be retrieved
- * @param $type The type of the object (eg. database, schema, relation, function or language)
- * @param $table Optional, column's table if type = column
- * @return Privileges array
- * @return -1 invalid type
- * @return -2 object not found
- * @return -3 unknown privilege type
- */
- function getPrivileges($object, $type, $table = null) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($object);
-
- switch ($type) {
- case 'column':
- $this->clean($table);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns all groups in the database cluser
+ * @return All groups
+ */
+ public function getGroups()
+ {
+ $sql = "SELECT groname FROM pg_group ORDER BY groname";
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a new group
+ * @param $groname The name of the group
+ * @param $users An array of users to add to the group
+ * @return 0 success
+ */
+ public function createGroup($groname, $users)
+ {
+ $this->fieldClean($groname);
+
+ $sql = "CREATE GROUP \"{$groname}\"";
+
+ if (is_array($users) && sizeof($users) > 0) {
+ $this->fieldArrayClean($users);
+ $sql .= ' WITH USER "' . join('", "', $users) . '"';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes a group
+ * @param $groname The name of the group to drop
+ * @return 0 success
+ */
+ public function dropGroup($groname)
+ {
+ $this->fieldClean($groname);
+
+ $sql = "DROP GROUP \"{$groname}\"";
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Internal function used for parsing ACLs
+ * @param $acl The ACL to parse (of type aclitem[])
+ * @return Privileges array
+ */
+ public function _parseACL($acl)
+ {
+ // Take off the first and last characters (the braces)
+ $acl = substr($acl, 1, strlen($acl) - 2);
+
+ // Pick out individual ACE's by carefully parsing. This is necessary in order
+ // to cope with usernames and stuff that contain commas
+ $aces = [];
+ $i = $j = 0;
+ $in_quotes = false;
+ while ($i < strlen($acl)) {
+ // If current char is a double quote and it's not escaped, then
+ // enter quoted bit
+ $char = substr($acl, $i, 1);
+ if ($char == '"' && ($i == 0 || substr($acl, $i - 1, 1) != '\\')) {
+ $in_quotes = !$in_quotes;
+ } elseif ($char == ',' && !$in_quotes) {
+ // Add text so far to the array
+ $aces[] = substr($acl, $j, $i - $j);
+ $j = $i + 1;
+ }
+ $i++;
+ }
+ // Add final text to the array
+ $aces[] = substr($acl, $j);
+
+ // Create the array to be returned
+ $temp = [];
+
+ // For each ACE, generate an entry in $temp
+ foreach ($aces as $v) {
+
+ // If the ACE begins with a double quote, strip them off both ends
+ // and unescape backslashes and double quotes
+ $unquote = false;
+ if (strpos($v, '"') === 0) {
+ $v = substr($v, 1, strlen($v) - 2);
+ $v = str_replace('\\"', '"', $v);
+ $v = str_replace('\\\\', '\\', $v);
+ }
+
+ // Figure out type of ACE (public, user or group)
+ if (strpos($v, '=') === 0) {
+ $atype = 'public';
+ } else if ($this->hasRoles()) {
+ $atype = 'role';
+ } else if (strpos($v, 'group ') === 0) {
+ $atype = 'group';
+ // Tear off 'group' prefix
+ $v = substr($v, 6);
+ } else {
+ $atype = 'user';
+ }
+
+ // Break on unquoted equals sign...
+ $i = 0;
+ $in_quotes = false;
+ $entity = null;
+ $chars = null;
+ while ($i < strlen($v)) {
+ // If current char is a double quote and it's not escaped, then
+ // enter quoted bit
+ $char = substr($v, $i, 1);
+ $next_char = substr($v, $i + 1, 1);
+ if ($char == '"' && ($i == 0 || $next_char != '"')) {
+ $in_quotes = !$in_quotes;
+ }
+ // Skip over escaped double quotes
+ elseif ($char == '"' && $next_char == '"') {
+ $i++;
+ } elseif ($char == '=' && !$in_quotes) {
+ // Split on current equals sign
+ $entity = substr($v, 0, $i);
+ $chars = substr($v, $i + 1);
+ break;
+ }
+ $i++;
+ }
+
+ // Check for quoting on entity name, and unescape if necessary
+ if (strpos($entity, '"') === 0) {
+ $entity = substr($entity, 1, strlen($entity) - 2);
+ $entity = str_replace('""', '"', $entity);
+ }
+
+ // New row to be added to $temp
+ // (type, grantee, privileges, grantor, grant option?
+ $row = [$atype, $entity, [], '', []];
+
+ // Loop over chars and add privs to $row
+ for ($i = 0; $i < strlen($chars); $i++) {
+ // Append to row's privs list the string representing
+ // the privilege
+ $char = substr($chars, $i, 1);
+ if ($char == '*') {
+ $row[4][] = $this->privmap[substr($chars, $i - 1, 1)];
+ } elseif ($char == '/') {
+ $grantor = substr($chars, $i + 1);
+ // Check for quoting
+ if (strpos($grantor, '"') === 0) {
+ $grantor = substr($grantor, 1, strlen($grantor) - 2);
+ $grantor = str_replace('""', '"', $grantor);
+ }
+ $row[3] = $grantor;
+ break;
+ } else {
+ if (!isset($this->privmap[$char])) {
+ return -3;
+ } else {
+ $row[2][] = $this->privmap[$char];
+ }
+
+ }
+ }
+
+ // Append row to temp
+ $temp[] = $row;
+ }
+
+ return $temp;
+ }
+
+ /**
+ * Grabs an array of users and their privileges for an object,
+ * given its type.
+ * @param $object The name of the object whose privileges are to be retrieved
+ * @param $type The type of the object (eg. database, schema, relation, function or language)
+ * @param $table Optional, column's table if type = column
+ * @return Privileges array
+ * @return -1 invalid type
+ * @return -2 object not found
+ * @return -3 unknown privilege type
+ */
+ public function getPrivileges($object, $type, $table = null)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($object);
+
+ switch ($type) {
+ case 'column':
+ $this->clean($table);
+ $sql = "
SELECT E'{' || pg_catalog.array_to_string(attacl, E',') || E'}' as acl
FROM pg_catalog.pg_attribute a
LEFT JOIN pg_catalog.pg_class c ON (a.attrelid = c.oid)
@@ -7339,391 +7545,400 @@ class Postgres extends ADODB_base {
WHERE n.nspname='{$c_schema}'
AND c.relname='{$table}'
AND a.attname='{$object}'";
- break;
- case 'table':
- case 'view':
- case 'sequence':
- $sql = "
+ break;
+ case 'table':
+ case 'view':
+ case 'sequence':
+ $sql = "
SELECT relacl AS acl FROM pg_catalog.pg_class
WHERE relname='{$object}'
AND relnamespace=(SELECT oid FROM pg_catalog.pg_namespace
WHERE nspname='{$c_schema}')";
- break;
- case 'database':
- $sql = "SELECT datacl AS acl FROM pg_catalog.pg_database WHERE datname='{$object}'";
- break;
- case 'function':
- // Since we fetch functions by oid, they are already constrained to
- // the current schema.
- $sql = "SELECT proacl AS acl FROM pg_catalog.pg_proc WHERE oid='{$object}'";
- break;
- case 'language':
- $sql = "SELECT lanacl AS acl FROM pg_catalog.pg_language WHERE lanname='{$object}'";
- break;
- case 'schema':
- $sql = "SELECT nspacl AS acl FROM pg_catalog.pg_namespace WHERE nspname='{$object}'";
- break;
- case 'tablespace':
- $sql = "SELECT spcacl AS acl FROM pg_catalog.pg_tablespace WHERE spcname='{$object}'";
- break;
- default:
- return -1;
- }
-
- // Fetch the ACL for object
- $acl = $this->selectField($sql, 'acl');
- if ($acl == -1) {
- return -2;
- } elseif ($acl == '' || $acl == null) {
- return [];
- } else {
- return $this->_parseACL($acl);
- }
-
- }
-
- /**
- * Grants a privilege to a user, group or public
- * @param $mode 'GRANT' or 'REVOKE';
- * @param $type The type of object
- * @param $object The name of the object
- * @param $public True to grant to public, false otherwise
- * @param $usernames The array of usernames to grant privs to.
- * @param $groupnames The array of group names to grant privs to.
- * @param $privileges The array of privileges to grant (eg. ('SELECT', 'ALL PRIVILEGES', etc.) )
- * @param $grantoption True if has grant option, false otherwise
- * @param $cascade True for cascade revoke, false otherwise
- * @param $table the column's table if type=column
- * @return 0 success
- * @return -1 invalid type
- * @return -2 invalid entity
- * @return -3 invalid privileges
- * @return -4 not granting to anything
- * @return -4 invalid mode
- */
- function setPrivileges($mode, $type, $object, $public, $usernames, $groupnames,
- $privileges, $grantoption, $cascade, $table
- ) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldArrayClean($usernames);
- $this->fieldArrayClean($groupnames);
-
- // Input checking
- if (!is_array($privileges) || sizeof($privileges) == 0) {
- return -3;
- }
-
- if (!is_array($usernames) || !is_array($groupnames) ||
- (!$public && sizeof($usernames) == 0 && sizeof($groupnames) == 0)) {
- return -4;
- }
-
- if ($mode != 'GRANT' && $mode != 'REVOKE') {
- return -5;
- }
-
- $sql = $mode;
-
- // Grant option
- if ($this->hasGrantOption() && $mode == 'REVOKE' && $grantoption) {
- $sql .= ' GRANT OPTION FOR';
- }
-
- if (in_array('ALL PRIVILEGES', $privileges)) {
- $sql .= ' ALL PRIVILEGES';
- } else {
- if ($type == 'column') {
- $this->fieldClean($object);
- $sql .= ' ' . join(" (\"{$object}\"), ", $privileges);
- } else {
- $sql .= ' ' . join(', ', $privileges);
- }
- }
-
- switch ($type) {
- case 'column':
- $sql .= " (\"{$object}\")";
- $object = $table;
- case 'table':
- case 'view':
- case 'sequence':
- $this->fieldClean($object);
- $sql .= " ON \"{$f_schema}\".\"{$object}\"";
- break;
- case 'database':
- $this->fieldClean($object);
- $sql .= " ON DATABASE \"{$object}\"";
- break;
- case 'function':
- // Function comes in with $object as function OID
- $fn = $this->getFunction($object);
- $this->fieldClean($fn->fields['proname']);
- $sql .= " ON FUNCTION \"{$f_schema}\".\"{$fn->fields['proname']}\"({$fn->fields['proarguments']})";
- break;
- case 'language':
- $this->fieldClean($object);
- $sql .= " ON LANGUAGE \"{$object}\"";
- break;
- case 'schema':
- $this->fieldClean($object);
- $sql .= " ON SCHEMA \"{$object}\"";
- break;
- case 'tablespace':
- $this->fieldClean($object);
- $sql .= " ON TABLESPACE \"{$object}\"";
- break;
- default:
- return -1;
- }
-
- // Dump PUBLIC
- $first = true;
- $sql .= ($mode == 'GRANT') ? ' TO ' : ' FROM ';
- if ($public) {
- $sql .= 'PUBLIC';
- $first = false;
- }
- // Dump users
- foreach ($usernames as $v) {
- if ($first) {
- $sql .= "\"{$v}\"";
- $first = false;
- } else {
- $sql .= ", \"{$v}\"";
- }
- }
- // Dump groups
- foreach ($groupnames as $v) {
- if ($first) {
- $sql .= "GROUP \"{$v}\"";
- $first = false;
- } else {
- $sql .= ", GROUP \"{$v}\"";
- }
- }
-
- // Grant option
- if ($this->hasGrantOption() && $mode == 'GRANT' && $grantoption) {
- $sql .= ' WITH GRANT OPTION';
- }
-
- // Cascade revoke
- if ($this->hasGrantOption() && $mode == 'REVOKE' && $cascade) {
- $sql .= ' CASCADE';
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Helper function that computes encypted PostgreSQL passwords
- * @param $username The username
- * @param $password The password
- */
- function _encryptPassword($username, $password) {
- return 'md5' . md5($password . $username);
- }
-
- // Tablespace functions
-
- /**
- * Retrieves information for all tablespaces
- * @param $all Include all tablespaces (necessary when moving objects back to the default space)
- * @return A recordset
- */
- function getTablespaces($all = false) {
- $conf = $this->conf;
-
- $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, pg_catalog.pg_tablespace_location(oid) as spclocation,
+ break;
+ case 'database':
+ $sql = "SELECT datacl AS acl FROM pg_catalog.pg_database WHERE datname='{$object}'";
+ break;
+ case 'function':
+ // Since we fetch functions by oid, they are already constrained to
+ // the current schema.
+ $sql = "SELECT proacl AS acl FROM pg_catalog.pg_proc WHERE oid='{$object}'";
+ break;
+ case 'language':
+ $sql = "SELECT lanacl AS acl FROM pg_catalog.pg_language WHERE lanname='{$object}'";
+ break;
+ case 'schema':
+ $sql = "SELECT nspacl AS acl FROM pg_catalog.pg_namespace WHERE nspname='{$object}'";
+ break;
+ case 'tablespace':
+ $sql = "SELECT spcacl AS acl FROM pg_catalog.pg_tablespace WHERE spcname='{$object}'";
+ break;
+ default:
+ return -1;
+ }
+
+ // Fetch the ACL for object
+ $acl = $this->selectField($sql, 'acl');
+ if ($acl == -1) {
+ return -2;
+ } elseif ($acl == '' || $acl == null) {
+ return [];
+ } else {
+ return $this->_parseACL($acl);
+ }
+
+ }
+
+ /**
+ * Grants a privilege to a user, group or public
+ * @param $mode 'GRANT' or 'REVOKE';
+ * @param $type The type of object
+ * @param $object The name of the object
+ * @param $public True to grant to public, false otherwise
+ * @param $usernames The array of usernames to grant privs to.
+ * @param $groupnames The array of group names to grant privs to.
+ * @param $privileges The array of privileges to grant (eg. ('SELECT', 'ALL PRIVILEGES', etc.) )
+ * @param $grantoption True if has grant option, false otherwise
+ * @param $cascade True for cascade revoke, false otherwise
+ * @param $table the column's table if type=column
+ * @return 0 success
+ * @return -1 invalid type
+ * @return -2 invalid entity
+ * @return -3 invalid privileges
+ * @return -4 not granting to anything
+ * @return -4 invalid mode
+ */
+ public function setPrivileges($mode, $type, $object, $public, $usernames, $groupnames,
+ $privileges, $grantoption, $cascade, $table
+ ) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldArrayClean($usernames);
+ $this->fieldArrayClean($groupnames);
+
+ // Input checking
+ if (!is_array($privileges) || sizeof($privileges) == 0) {
+ return -3;
+ }
+
+ if (!is_array($usernames) || !is_array($groupnames) ||
+ (!$public && sizeof($usernames) == 0 && sizeof($groupnames) == 0)) {
+ return -4;
+ }
+
+ if ($mode != 'GRANT' && $mode != 'REVOKE') {
+ return -5;
+ }
+
+ $sql = $mode;
+
+ // Grant option
+ if ($this->hasGrantOption() && $mode == 'REVOKE' && $grantoption) {
+ $sql .= ' GRANT OPTION FOR';
+ }
+
+ if (in_array('ALL PRIVILEGES', $privileges)) {
+ $sql .= ' ALL PRIVILEGES';
+ } else {
+ if ($type == 'column') {
+ $this->fieldClean($object);
+ $sql .= ' ' . join(" (\"{$object}\"), ", $privileges);
+ } else {
+ $sql .= ' ' . join(', ', $privileges);
+ }
+ }
+
+ switch ($type) {
+ case 'column':
+ $sql .= " (\"{$object}\")";
+ $object = $table;
+ case 'table':
+ case 'view':
+ case 'sequence':
+ $this->fieldClean($object);
+ $sql .= " ON \"{$f_schema}\".\"{$object}\"";
+ break;
+ case 'database':
+ $this->fieldClean($object);
+ $sql .= " ON DATABASE \"{$object}\"";
+ break;
+ case 'function':
+ // Function comes in with $object as function OID
+ $fn = $this->getFunction($object);
+ $this->fieldClean($fn->fields['proname']);
+ $sql .= " ON FUNCTION \"{$f_schema}\".\"{$fn->fields['proname']}\"({$fn->fields['proarguments']})";
+ break;
+ case 'language':
+ $this->fieldClean($object);
+ $sql .= " ON LANGUAGE \"{$object}\"";
+ break;
+ case 'schema':
+ $this->fieldClean($object);
+ $sql .= " ON SCHEMA \"{$object}\"";
+ break;
+ case 'tablespace':
+ $this->fieldClean($object);
+ $sql .= " ON TABLESPACE \"{$object}\"";
+ break;
+ default:
+ return -1;
+ }
+
+ // Dump PUBLIC
+ $first = true;
+ $sql .= ($mode == 'GRANT') ? ' TO ' : ' FROM ';
+ if ($public) {
+ $sql .= 'PUBLIC';
+ $first = false;
+ }
+ // Dump users
+ foreach ($usernames as $v) {
+ if ($first) {
+ $sql .= "\"{$v}\"";
+ $first = false;
+ } else {
+ $sql .= ", \"{$v}\"";
+ }
+ }
+ // Dump groups
+ foreach ($groupnames as $v) {
+ if ($first) {
+ $sql .= "GROUP \"{$v}\"";
+ $first = false;
+ } else {
+ $sql .= ", GROUP \"{$v}\"";
+ }
+ }
+
+ // Grant option
+ if ($this->hasGrantOption() && $mode == 'GRANT' && $grantoption) {
+ $sql .= ' WITH GRANT OPTION';
+ }
+
+ // Cascade revoke
+ if ($this->hasGrantOption() && $mode == 'REVOKE' && $cascade) {
+ $sql .= ' CASCADE';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Helper function that computes encypted PostgreSQL passwords
+ * @param $username The username
+ * @param $password The password
+ */
+ public function _encryptPassword($username, $password)
+ {
+ return 'md5' . md5($password . $username);
+ }
+
+ // Tablespace functions
+
+ /**
+ * Retrieves information for all tablespaces
+ * @param $all Include all tablespaces (necessary when moving objects back to the default space)
+ * @return A recordset
+ */
+ public function getTablespaces($all = false)
+ {
+ $conf = $this->conf;
+
+ $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, pg_catalog.pg_tablespace_location(oid) as spclocation,
(SELECT description FROM pg_catalog.pg_shdescription pd WHERE pg_tablespace.oid=pd.objoid AND pd.classoid='pg_tablespace'::regclass) AS spccomment
FROM pg_catalog.pg_tablespace";
- if (!$conf['show_system'] && !$all) {
- $sql .= ' WHERE spcname NOT LIKE $$pg\_%$$';
- }
+ if (!$conf['show_system'] && !$all) {
+ $sql .= ' WHERE spcname NOT LIKE $$pg\_%$$';
+ }
- $sql .= " ORDER BY spcname";
+ $sql .= " ORDER BY spcname";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Retrieves a tablespace's information
- * @return A recordset
- */
- function getTablespace($spcname) {
- $this->clean($spcname);
+ /**
+ * Retrieves a tablespace's information
+ * @return A recordset
+ */
+ public function getTablespace($spcname)
+ {
+ $this->clean($spcname);
- $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, pg_catalog.pg_tablespace_location(oid) as spclocation,
+ $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, pg_catalog.pg_tablespace_location(oid) as spclocation,
(SELECT description FROM pg_catalog.pg_shdescription pd WHERE pg_tablespace.oid=pd.objoid AND pd.classoid='pg_tablespace'::regclass) AS spccomment
FROM pg_catalog.pg_tablespace WHERE spcname='{$spcname}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Creates a tablespace
- * @param $spcname The name of the tablespace to create
- * @param $spcowner The owner of the tablespace. '' for current
- * @param $spcloc The directory in which to create the tablespace
- * @return 0 success
- */
- function createTablespace($spcname, $spcowner, $spcloc, $comment = '') {
- $this->fieldClean($spcname);
- $this->clean($spcloc);
-
- $sql = "CREATE TABLESPACE \"{$spcname}\"";
-
- if ($spcowner != '') {
- $this->fieldClean($spcowner);
- $sql .= " OWNER \"{$spcowner}\"";
- }
-
- $sql .= " LOCATION '{$spcloc}'";
-
- $status = $this->execute($sql);
- if ($status != 0) {
- return -1;
- }
-
- if ($comment != '' && $this->hasSharedComments()) {
- $status = $this->setComment('TABLESPACE', $spcname, '', $comment);
- if ($status != 0) {
- return -2;
- }
-
- }
-
- return 0;
- }
-
- /**
- * Alters a tablespace
- * @param $spcname The name of the tablespace
- * @param $name The new name for the tablespace
- * @param $owner The new owner for the tablespace
- * @return 0 success
- * @return -1 transaction error
- * @return -2 owner error
- * @return -3 rename error
- * @return -4 comment error
- */
- function alterTablespace($spcname, $name, $owner, $comment = '') {
- $this->fieldClean($spcname);
- $this->fieldClean($name);
- $this->fieldClean($owner);
-
- // Begin transaction
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- // Owner
- $sql = "ALTER TABLESPACE \"{$spcname}\" OWNER TO \"{$owner}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -2;
- }
-
- // Rename (only if name has changed)
- if ($name != $spcname) {
- $sql = "ALTER TABLESPACE \"{$spcname}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
-
- $spcname = $name;
- }
-
- // Set comment if it has changed
- if (trim($comment) != '' && $this->hasSharedComments()) {
- $status = $this->setComment('TABLESPACE', $spcname, '', $comment);
- if ($status != 0) {
- return -4;
- }
-
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Drops a tablespace
- * @param $spcname The name of the domain to drop
- * @return 0 success
- */
- function dropTablespace($spcname) {
- $this->fieldClean($spcname);
-
- $sql = "DROP TABLESPACE \"{$spcname}\"";
-
- return $this->execute($sql);
- }
-
- // Administration functions
-
- /**
- * Analyze a database
- * @param $table (optional) The table to analyze
- */
- function analyzeDB($table = '') {
- if ($table != '') {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
-
- $sql = "ANALYZE \"{$f_schema}\".\"{$table}\"";
- } else {
- $sql = "ANALYZE";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Vacuums a database
- * @param $table The table to vacuum
- * @param $analyze If true, also does analyze
- * @param $full If true, selects "full" vacuum
- * @param $freeze If true, selects aggressive "freezing" of tuples
- */
- function vacuumDB($table = '', $analyze = false, $full = false, $freeze = false) {
-
- $sql = "VACUUM";
- if ($full) {
- $sql .= " FULL";
- }
-
- if ($freeze) {
- $sql .= " FREEZE";
- }
-
- if ($analyze) {
- $sql .= " ANALYZE";
- }
-
- if ($table != '') {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
- $sql .= " \"{$f_schema}\".\"{$table}\"";
- }
-
- return $this->execute($sql);
- }
-
- /**
- * Returns all autovacuum global configuration
- * @return associative array array( param => value, ...)
- */
- function getAutovacuum() {
-
- $_defaults = $this->selectSet("SELECT name, setting
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a tablespace
+ * @param $spcname The name of the tablespace to create
+ * @param $spcowner The owner of the tablespace. '' for current
+ * @param $spcloc The directory in which to create the tablespace
+ * @return 0 success
+ */
+ public function createTablespace($spcname, $spcowner, $spcloc, $comment = '')
+ {
+ $this->fieldClean($spcname);
+ $this->clean($spcloc);
+
+ $sql = "CREATE TABLESPACE \"{$spcname}\"";
+
+ if ($spcowner != '') {
+ $this->fieldClean($spcowner);
+ $sql .= " OWNER \"{$spcowner}\"";
+ }
+
+ $sql .= " LOCATION '{$spcloc}'";
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ return -1;
+ }
+
+ if ($comment != '' && $this->hasSharedComments()) {
+ $status = $this->setComment('TABLESPACE', $spcname, '', $comment);
+ if ($status != 0) {
+ return -2;
+ }
+
+ }
+
+ return 0;
+ }
+
+ /**
+ * Alters a tablespace
+ * @param $spcname The name of the tablespace
+ * @param $name The new name for the tablespace
+ * @param $owner The new owner for the tablespace
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 owner error
+ * @return -3 rename error
+ * @return -4 comment error
+ */
+ public function alterTablespace($spcname, $name, $owner, $comment = '')
+ {
+ $this->fieldClean($spcname);
+ $this->fieldClean($name);
+ $this->fieldClean($owner);
+
+ // Begin transaction
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ // Owner
+ $sql = "ALTER TABLESPACE \"{$spcname}\" OWNER TO \"{$owner}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+
+ // Rename (only if name has changed)
+ if ($name != $spcname) {
+ $sql = "ALTER TABLESPACE \"{$spcname}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+
+ $spcname = $name;
+ }
+
+ // Set comment if it has changed
+ if (trim($comment) != '' && $this->hasSharedComments()) {
+ $status = $this->setComment('TABLESPACE', $spcname, '', $comment);
+ if ($status != 0) {
+ return -4;
+ }
+
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Drops a tablespace
+ * @param $spcname The name of the domain to drop
+ * @return 0 success
+ */
+ public function dropTablespace($spcname)
+ {
+ $this->fieldClean($spcname);
+
+ $sql = "DROP TABLESPACE \"{$spcname}\"";
+
+ return $this->execute($sql);
+ }
+
+ // Administration functions
+
+ /**
+ * Analyze a database
+ * @param $table (optional) The table to analyze
+ */
+ public function analyzeDB($table = '')
+ {
+ if ($table != '') {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ $sql = "ANALYZE \"{$f_schema}\".\"{$table}\"";
+ } else {
+ $sql = "ANALYZE";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Vacuums a database
+ * @param $table The table to vacuum
+ * @param $analyze If true, also does analyze
+ * @param $full If true, selects "full" vacuum
+ * @param $freeze If true, selects aggressive "freezing" of tuples
+ */
+ public function vacuumDB($table = '', $analyze = false, $full = false, $freeze = false)
+ {
+
+ $sql = "VACUUM";
+ if ($full) {
+ $sql .= " FULL";
+ }
+
+ if ($freeze) {
+ $sql .= " FREEZE";
+ }
+
+ if ($analyze) {
+ $sql .= " ANALYZE";
+ }
+
+ if ($table != '') {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+ $sql .= " \"{$f_schema}\".\"{$table}\"";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Returns all autovacuum global configuration
+ * @return associative array array( param => value, ...)
+ */
+ public function getAutovacuum()
+ {
+
+ $_defaults = $this->selectSet("SELECT name, setting
FROM pg_catalog.pg_settings
WHERE
name = 'autovacuum'
@@ -7736,114 +7951,117 @@ class Postgres extends ADODB_base {
OR name = 'vacuum_freeze_min_age'
OR name = 'autovacuum_freeze_max_age'
"
- );
-
- $ret = [];
- while (!$_defaults->EOF) {
- $ret[$_defaults->fields['name']] = $_defaults->fields['setting'];
- $_defaults->moveNext();
- }
-
- return $ret;
- }
-
- /**
- * Returns all available autovacuum per table information.
- * @return A recordset
- */
- function saveAutovacuum($table, $vacenabled, $vacthreshold, $vacscalefactor, $anathresold,
- $anascalefactor, $vaccostdelay, $vaccostlimit) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
-
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" SET (";
-
- if (!empty($vacenabled)) {
- $this->clean($vacenabled);
- $params[] = "autovacuum_enabled='{$vacenabled}'";
- }
- if (!empty($vacthreshold)) {
- $this->clean($vacthreshold);
- $params[] = "autovacuum_vacuum_threshold='{$vacthreshold}'";
- }
- if (!empty($vacscalefactor)) {
- $this->clean($vacscalefactor);
- $params[] = "autovacuum_vacuum_scale_factor='{$vacscalefactor}'";
- }
- if (!empty($anathresold)) {
- $this->clean($anathresold);
- $params[] = "autovacuum_analyze_threshold='{$anathresold}'";
- }
- if (!empty($anascalefactor)) {
- $this->clean($anascalefactor);
- $params[] = "autovacuum_analyze_scale_factor='{$anascalefactor}'";
- }
- if (!empty($vaccostdelay)) {
- $this->clean($vaccostdelay);
- $params[] = "autovacuum_vacuum_cost_delay='{$vaccostdelay}'";
- }
- if (!empty($vaccostlimit)) {
- $this->clean($vaccostlimit);
- $params[] = "autovacuum_vacuum_cost_limit='{$vaccostlimit}'";
- }
-
- $sql = $sql . implode(',', $params) . ');';
-
- return $this->execute($sql);
- }
-
- function dropAutovacuum($table) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
-
- return $this->execute("
+ );
+
+ $ret = [];
+ while (!$_defaults->EOF) {
+ $ret[$_defaults->fields['name']] = $_defaults->fields['setting'];
+ $_defaults->moveNext();
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Returns all available autovacuum per table information.
+ * @return A recordset
+ */
+ public function saveAutovacuum($table, $vacenabled, $vacthreshold, $vacscalefactor, $anathresold,
+ $anascalefactor, $vaccostdelay, $vaccostlimit) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" SET (";
+
+ if (!empty($vacenabled)) {
+ $this->clean($vacenabled);
+ $params[] = "autovacuum_enabled='{$vacenabled}'";
+ }
+ if (!empty($vacthreshold)) {
+ $this->clean($vacthreshold);
+ $params[] = "autovacuum_vacuum_threshold='{$vacthreshold}'";
+ }
+ if (!empty($vacscalefactor)) {
+ $this->clean($vacscalefactor);
+ $params[] = "autovacuum_vacuum_scale_factor='{$vacscalefactor}'";
+ }
+ if (!empty($anathresold)) {
+ $this->clean($anathresold);
+ $params[] = "autovacuum_analyze_threshold='{$anathresold}'";
+ }
+ if (!empty($anascalefactor)) {
+ $this->clean($anascalefactor);
+ $params[] = "autovacuum_analyze_scale_factor='{$anascalefactor}'";
+ }
+ if (!empty($vaccostdelay)) {
+ $this->clean($vaccostdelay);
+ $params[] = "autovacuum_vacuum_cost_delay='{$vaccostdelay}'";
+ }
+ if (!empty($vaccostlimit)) {
+ $this->clean($vaccostlimit);
+ $params[] = "autovacuum_vacuum_cost_limit='{$vaccostlimit}'";
+ }
+
+ $sql = $sql . implode(',', $params) . ');';
+
+ return $this->execute($sql);
+ }
+
+ public function dropAutovacuum($table)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ return $this->execute("
ALTER TABLE \"{$f_schema}\".\"{$table}\" RESET (autovacuum_enabled, autovacuum_vacuum_threshold,
autovacuum_vacuum_scale_factor, autovacuum_analyze_threshold, autovacuum_analyze_scale_factor,
autovacuum_vacuum_cost_delay, autovacuum_vacuum_cost_limit
);"
- );
- }
-
- /**
- * Returns all available process information.
- * @param $database (optional) Find only connections to specified database
- * @return A recordset
- */
- function getProcesses($database = null) {
- if ($database === null) {
- $sql = "SELECT datname, usename, pid, waiting, state_change as query_start,
+ );
+ }
+
+ /**
+ * Returns all available process information.
+ * @param $database (optional) Find only connections to specified database
+ * @return A recordset
+ */
+ public function getProcesses($database = null)
+ {
+ if ($database === null) {
+ $sql = "SELECT datname, usename, pid, waiting, state_change as query_start,
case when state='idle in transaction' then '<IDLE> in transaction' when state = 'idle' then '<IDLE>' else query end as query
FROM pg_catalog.pg_stat_activity
ORDER BY datname, usename, pid";
- } else {
- $this->clean($database);
- $sql = "SELECT datname, usename, pid, waiting, state_change as query_start,
+ } else {
+ $this->clean($database);
+ $sql = "SELECT datname, usename, pid, waiting, state_change as query_start,
case when state='idle in transaction' then '<IDLE> in transaction' when state = 'idle' then '<IDLE>' else query end as query
FROM pg_catalog.pg_stat_activity
WHERE datname='{$database}'
ORDER BY usename, pid";
- }
+ }
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns table locks information in the current database
- * @return A recordset
- */
+ /**
+ * Returns table locks information in the current database
+ * @return A recordset
+ */
- function getLocks() {
- $conf = $this->conf;
+ public function getLocks()
+ {
+ $conf = $this->conf;
- if (!$conf['show_system']) {
- $where = 'AND pn.nspname NOT LIKE $$pg\_%$$';
- } else {
- $where = "AND nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
- }
+ if (!$conf['show_system']) {
+ $where = 'AND pn.nspname NOT LIKE $$pg\_%$$';
+ } else {
+ $where = "AND nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
+ }
- $sql = "
+ $sql = "
SELECT
pn.nspname, pc.relname AS tablename, pl.pid, pl.mode, pl.granted, pl.virtualtransaction,
(select transactionid from pg_catalog.pg_locks l2 where l2.locktype='transactionid'
@@ -7857,802 +8075,905 @@ class Postgres extends ADODB_base {
{$where}
ORDER BY pid,nspname,tablename";
- return $this->selectSet($sql);
- }
-
- /**
- * Sends a cancel or kill command to a process
- * @param $pid The ID of the backend process
- * @param $signal 'CANCEL'
- * @return 0 success
- * @return -1 invalid signal type
- */
- function sendSignal($pid, $signal) {
- // Clean
- $pid = (int) $pid;
-
- if ($signal == 'CANCEL') {
- $sql = "SELECT pg_catalog.pg_cancel_backend({$pid}) AS val";
- } elseif ($signal == 'KILL') {
- $sql = "SELECT pg_catalog.pg_terminate_backend({$pid}) AS val";
- } else {
- return -1;
- }
-
- // Execute the query
- $val = $this->selectField($sql, 'val');
-
- if ($val === 'f') {
- return -1;
- } elseif ($val === 't') {
- return 0;
- } else {
- return -1;
- }
-
- }
-
- // Misc functions
-
- /**
- * Sets the comment for an object in the database
- * @pre All parameters must already be cleaned
- * @param $obj_type One of 'TABLE' | 'COLUMN' | 'VIEW' | 'SCHEMA' | 'SEQUENCE' | 'TYPE' | 'FUNCTION' | 'AGGREGATE'
- * @param $obj_name The name of the object for which to attach a comment.
- * @param $table Name of table that $obj_name belongs to. Ignored unless $obj_type is 'TABLE' or 'COLUMN'.
- * @param $comment The comment to add.
- * @return 0 success
- */
- function setComment($obj_type, $obj_name, $table, $comment, $basetype = NULL) {
- $sql = "COMMENT ON {$obj_type} ";
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->clean($comment); // Passing in an already cleaned comment will lead to double escaped data
- // So, while counter-intuitive, it is important to not clean comments before
- // calling setComment. We will clean it here instead.
- /*
- $this->fieldClean($table);
- $this->fieldClean($obj_name);
-*/
-
- switch ($obj_type) {
- case 'TABLE':
- $sql .= "\"{$f_schema}\".\"{$table}\" IS ";
- break;
- case 'COLUMN':
- $sql .= "\"{$f_schema}\".\"{$table}\".\"{$obj_name}\" IS ";
- break;
- case 'SEQUENCE':
- case 'VIEW':
- case 'TEXT SEARCH CONFIGURATION':
- case 'TEXT SEARCH DICTIONARY':
- case 'TEXT SEARCH TEMPLATE':
- case 'TEXT SEARCH PARSER':
- case 'TYPE':
- $sql .= "\"{$f_schema}\".";
- case 'DATABASE':
- case 'ROLE':
- case 'SCHEMA':
- case 'TABLESPACE':
- $sql .= "\"{$obj_name}\" IS ";
- break;
- case 'FUNCTION':
- $sql .= "\"{$f_schema}\".{$obj_name} IS ";
- break;
- case 'AGGREGATE':
- $sql .= "\"{$f_schema}\".\"{$obj_name}\" (\"{$basetype}\") IS ";
- break;
- default:
- // Unknown object type
- return -1;
- }
-
- if ($comment != '') {
- $sql .= "'{$comment}';";
- } else {
- $sql .= 'NULL;';
- }
-
- return $this->execute($sql);
-
- }
-
- /**
- * A private helper method for executeScript that advances the
- * character by 1. In psql this is careful to take into account
- * multibyte languages, but we don't at the moment, so this function
- * is someone redundant, since it will always advance by 1
- * @param &$i The current character position in the line
- * @param &$prevlen Length of previous character (ie. 1)
- * @param &$thislen Length of current character (ie. 1)
- */
- private
- function advance_1(&$i, &$prevlen, &$thislen) {
- $prevlen = $thislen;
- $i += $thislen;
- $thislen = 1;
- }
-
- /**
- * Private helper method to detect a valid $foo$ quote delimiter at
- * the start of the parameter dquote
- * @return True if valid, false otherwise
- */
- private
- function valid_dolquote($dquote) {
- // XXX: support multibyte
- return (preg_match('/^[$][$]/', $dquote) || preg_match('/^[$][_[:alpha:]][_[:alnum:]]*[$]/', $dquote));
- }
-
- /**
- * Executes an SQL script as a series of SQL statements. Returns
- * the result of the final step. This is a very complicated lexer
- * based on the REL7_4_STABLE src/bin/psql/mainloop.c lexer in
- * the PostgreSQL source code.
- * XXX: It does not handle multibyte languages properly.
- * @param $name Entry in $_FILES to use
- * @param $callback (optional) Callback function to call with each query,
- its result and line number.
- * @return True for general success, false on any failure.
- */
- function executeScript($name, $callback = null) {
-
- // This whole function isn't very encapsulated, but hey...
- $conn = $this->conn->_connectionID;
- if (!is_uploaded_file($_FILES[$name]['tmp_name'])) {
- return false;
- }
-
- $fd = fopen($_FILES[$name]['tmp_name'], 'r');
- if (!$fd) {
- return false;
- }
-
- // Build up each SQL statement, they can be multiline
- $query_buf = null;
- $query_start = 0;
- $in_quote = 0;
- $in_xcomment = 0;
- $bslash_count = 0;
- $dol_quote = null;
- $paren_level = 0;
- $len = 0;
- $i = 0;
- $prevlen = 0;
- $thislen = 0;
- $lineno = 0;
-
- // Loop over each line in the file
- while (!feof($fd)) {
- $line = fgets($fd);
- $lineno++;
-
- // Nothing left on line? Then ignore...
- if (trim($line) == '') {
- continue;
- }
-
- $len = strlen($line);
- $query_start = 0;
-
- /*
- * Parse line, looking for command separators.
- *
- * The current character is at line[i], the prior character at line[i
- * - prevlen], the next character at line[i + thislen].
- */
- $prevlen = 0;
- $thislen = ($len > 0) ? 1 : 0;
-
- for ($i = 0; $i < $len; $this->advance_1($i, $prevlen, $thislen)) {
-
- /* was the previous character a backslash? */
- if ($i > 0 && substr($line, $i - $prevlen, 1) == '\\') {
- $bslash_count++;
- } else {
- $bslash_count = 0;
- }
-
- /*
- * It is important to place the in_* test routines before the
- * in_* detection routines. i.e. we have to test if we are in
- * a quote before testing for comments.
- */
-
- /* in quote? */
- if ($in_quote !== 0) {
- /*
- * end of quote if matching non-backslashed character.
- * backslashes don't count for double quotes, though.
- */
- if (substr($line, $i, 1) == $in_quote &&
- ($bslash_count % 2 == 0 || $in_quote == '"')) {
- $in_quote = 0;
- }
-
- }
-
- /* in or end of $foo$ type quote? */
- else if ($dol_quote) {
- if (strncmp(substr($line, $i), $dol_quote, strlen($dol_quote)) == 0) {
- $this->advance_1($i, $prevlen, $thislen);
- while (substr($line, $i, 1) != '$') {
- $this->advance_1($i, $prevlen, $thislen);
- }
-
- $dol_quote = null;
- }
- }
-
- /* start of extended comment? */
- else if (substr($line, $i, 2) == '/*') {
- $in_xcomment++;
- if ($in_xcomment == 1) {
- $this->advance_1($i, $prevlen, $thislen);
- }
-
- }
-
- /* in or end of extended comment? */
- else if ($in_xcomment) {
- if (substr($line, $i, 2) == '*/' && !--$in_xcomment) {
- $this->advance_1($i, $prevlen, $thislen);
- }
-
- }
-
- /* start of quote? */
- else if (substr($line, $i, 1) == '\'' || substr($line, $i, 1) == '"') {
- $in_quote = substr($line, $i, 1);
- }
-
- /*
- * start of $foo$ type quote?
- */
- else if (!$dol_quote && $this->valid_dolquote(substr($line, $i))) {
- $dol_end = strpos(substr($line, $i + 1), '$');
- $dol_quote = substr($line, $i, $dol_end + 1);
- $this->advance_1($i, $prevlen, $thislen);
- while (substr($line, $i, 1) != '$') {
- $this->advance_1($i, $prevlen, $thislen);
- }
-
- }
-
- /* single-line comment? truncate line */
- else if (substr($line, $i, 2) == '--') {
- $line = substr($line, 0, $i); /* remove comment */
- break;
- }
-
- /* count nested parentheses */
- else if (substr($line, $i, 1) == '(') {
- $paren_level++;
- } else if (substr($line, $i, 1) == ')' && $paren_level > 0) {
- $paren_level--;
- }
-
- /* semicolon? then send query */
- else if (substr($line, $i, 1) == ';' && !$bslash_count && !$paren_level) {
- $subline = substr(substr($line, 0, $i), $query_start);
- /* is there anything else on the line? */
- if (strspn($subline, " \t\n\r") != strlen($subline)) {
- /*
- * insert a cosmetic newline, if this is not the first
- * line in the buffer
- */
- if (strlen($query_buf) > 0) {
- $query_buf .= "\n";
- }
-
- /* append the line to the query buffer */
- $query_buf .= $subline;
- $query_buf .= ';';
-
- // Execute the query. PHP cannot execute
- // empty queries, unlike libpq
- $res = @pg_query($conn, $query_buf);
-
- // Call the callback function for display
- if ($callback !== null) {
- $callback($query_buf, $res, $lineno);
- }
-
- // Check for COPY request
- if (pg_result_status($res) == 4) {
- // 4 == PGSQL_COPY_FROM
- while (!feof($fd)) {
- $copy = fgets($fd, 32768);
- $lineno++;
- pg_put_line($conn, $copy);
- if ($copy == "\\.\n" || $copy == "\\.\r\n") {
- pg_end_copy($conn);
- break;
- }
- }
- }
- }
-
- $query_buf = null;
- $query_start = $i + $thislen;
- }
-
- /*
- * keyword or identifier?
- * We grab the whole string so that we don't
- * mistakenly see $foo$ inside an identifier as the start
- * of a dollar quote.
- */
- // XXX: multibyte here
- else if (preg_match('/^[_[:alpha:]]$/', substr($line, $i, 1))) {
- $sub = substr($line, $i, $thislen);
- while (preg_match('/^[\$_A-Za-z0-9]$/', $sub)) {
- /* keep going while we still have identifier chars */
- $this->advance_1($i, $prevlen, $thislen);
- $sub = substr($line, $i, $thislen);
- }
- // Since we're now over the next character to be examined, it is necessary
- // to move back one space.
- $i -= $prevlen;
- }
- } // end for
-
- /* Put the rest of the line in the query buffer. */
- $subline = substr($line, $query_start);
- if ($in_quote || $dol_quote || strspn($subline, " \t\n\r") != strlen($subline)) {
- if (strlen($query_buf) > 0) {
- $query_buf .= "\n";
- }
-
- $query_buf .= $subline;
- }
-
- $line = null;
-
- } // end while
-
- /*
- * Process query at the end of file without a semicolon, so long as
- * it's non-empty.
- */
- if (strlen($query_buf) > 0 && strspn($query_buf, " \t\n\r") != strlen($query_buf)) {
- // Execute the query
- $res = @pg_query($conn, $query_buf);
-
- // Call the callback function for display
- if ($callback !== null) {
- $callback($query_buf, $res, $lineno);
- }
-
- // Check for COPY request
- if (pg_result_status($res) == 4) {
- // 4 == PGSQL_COPY_FROM
- while (!feof($fd)) {
- $copy = fgets($fd, 32768);
- $lineno++;
- pg_put_line($conn, $copy);
- if ($copy == "\\.\n" || $copy == "\\.\r\n") {
- pg_end_copy($conn);
- break;
- }
- }
- }
- }
-
- fclose($fd);
-
- return true;
- }
-
- /**
- * Generates the SQL for the 'select' function
- * @param $table The table from which to select
- * @param $show An array of columns to show. Empty array means all columns.
- * @param $values An array mapping columns to values
- * @param $ops An array of the operators to use
- * @param $orderby (optional) An array of column numbers or names (one based)
- * mapped to sort direction (asc or desc or '' or null) to order by
- * @return The SQL query
- */
- function getSelectSQL($table, $show, $values, $ops, $orderby = []) {
- $this->fieldArrayClean($show);
-
- // If an empty array is passed in, then show all columns
- if (sizeof($show) == 0) {
- if ($this->hasObjectID($table)) {
- $sql = "SELECT \"{$this->id}\", * FROM ";
- } else {
- $sql = "SELECT * FROM ";
- }
-
- } else {
- // Add oid column automatically to results for editing purposes
- if (!in_array($this->id, $show) && $this->hasObjectID($table)) {
- $sql = "SELECT \"{$this->id}\", \"";
- } else {
- $sql = "SELECT \"";
- }
-
- $sql .= join('","', $show) . "\" FROM ";
- }
-
- $this->fieldClean($table);
-
- if (isset($_REQUEST['schema'])) {
- $f_schema = $_REQUEST['schema'];
- $this->fieldClean($f_schema);
- $sql .= "\"{$f_schema}\".";
- }
- $sql .= "\"{$table}\"";
-
- // If we have values specified, add them to the WHERE clause
- $first = true;
- if (is_array($values) && sizeof($values) > 0) {
- foreach ($values as $k => $v) {
- if ($v != '' || $this->selectOps[$ops[$k]] == 'p') {
- $this->fieldClean($k);
- if ($first) {
- $sql .= " WHERE ";
- $first = false;
- } else {
- $sql .= " AND ";
- }
- // Different query format depending on operator type
- switch ($this->selectOps[$ops[$k]]) {
- case 'i':
- // Only clean the field for the inline case
- // this is because (x), subqueries need to
- // to allow 'a','b' as input.
- $this->clean($v);
- $sql .= "\"{$k}\" {$ops[$k]} '{$v}'";
- break;
- case 'p':
- $sql .= "\"{$k}\" {$ops[$k]}";
- break;
- case 'x':
- $sql .= "\"{$k}\" {$ops[$k]} ({$v})";
- break;
- case 't':
- $sql .= "\"{$k}\" {$ops[$k]}('{$v}')";
- break;
- default:
- // Shouldn't happen
- }
- }
- }
- }
-
- // ORDER BY
- if (is_array($orderby) && sizeof($orderby) > 0) {
- $sql .= " ORDER BY ";
- $first = true;
- foreach ($orderby as $k => $v) {
- if ($first) {
- $first = false;
- } else {
- $sql .= ', ';
- }
-
- if (preg_match('/^[0-9]+$/', $k)) {
- $sql .= $k;
- } else {
- $this->fieldClean($k);
- $sql .= '"' . $k . '"';
- }
- if (strtoupper($v) == 'DESC') {
- $sql .= " DESC";
- }
-
- }
- }
-
- return $sql;
- }
-
- /**
- * Returns a recordset of all columns in a query. Supports paging.
- * @param $type Either 'QUERY' if it is an SQL query, or 'TABLE' if it is a table identifier,
- * or 'SELECT" if it's a select query
- * @param $table The base table of the query. NULL for no table.
- * @param $query The query that is being executed. NULL for no query.
- * @param $sortkey The column number to sort by, or '' or null for no sorting
- * @param $sortdir The direction in which to sort the specified column ('asc' or 'desc')
- * @param $page The page of the relation to retrieve
- * @param $page_size The number of rows per page
- * @param &$max_pages (return-by-ref) The max number of pages in the relation
- * @return A recordset on success
- * @return -1 transaction error
- * @return -2 counting error
- * @return -3 page or page_size invalid
- * @return -4 unknown type
- * @return -5 failed setting transaction read only
- */
- function browseQuery($type, $table, $query, $sortkey, $sortdir, $page, $page_size, &$max_pages) {
- // Check that we're not going to divide by zero
- if (!is_numeric($page_size) || $page_size != (int) $page_size || $page_size <= 0) {
- return -3;
- }
-
- // If $type is TABLE, then generate the query
- switch ($type) {
- case 'TABLE':
- if (preg_match('/^[0-9]+$/', $sortkey) && $sortkey > 0) {
- $orderby = [$sortkey => $sortdir];
- } else {
- $orderby = [];
- }
-
- $query = $this->getSelectSQL($table, [], [], [], $orderby);
- break;
- case 'QUERY':
- case 'SELECT':
- // Trim query
- $query = trim($query);
- // Trim off trailing semi-colon if there is one
- if (substr($query, strlen($query) - 1, 1) == ';') {
- $query = substr($query, 0, strlen($query) - 1);
- }
-
- break;
- default:
- return -4;
- }
-
- // Generate count query
- $count = "SELECT COUNT(*) AS total FROM ($query) AS sub";
-
- // Open a transaction
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- // If backend supports read only queries, then specify read only mode
- // to avoid side effects from repeating queries that do writes.
- if ($this->hasReadOnlyQueries()) {
- $status = $this->execute("SET TRANSACTION READ ONLY");
- if ($status != 0) {
- $this->rollbackTransaction();
- return -5;
- }
- }
-
- // Count the number of rows
- $total = $this->browseQueryCount($query, $count);
- if ($total < 0) {
- $this->rollbackTransaction();
- return -2;
- }
-
- // Calculate max pages
- $max_pages = ceil($total / $page_size);
-
- // Check that page is less than or equal to max pages
- if (!is_numeric($page) || $page != (int) $page || $page > $max_pages || $page < 1) {
- $this->rollbackTransaction();
- return -3;
- }
-
- // Set fetch mode to NUM so that duplicate field names are properly returned
- // for non-table queries. Since the SELECT feature only allows selecting one
- // table, duplicate fields shouldn't appear.
- if ($type == 'QUERY') {
- $this->conn->setFetchMode(ADODB_FETCH_NUM);
- }
-
- // Figure out ORDER BY. Sort key is always the column number (based from one)
- // of the column to order by. Only need to do this for non-TABLE queries
- if ($type != 'TABLE' && preg_match('/^[0-9]+$/', $sortkey) && $sortkey > 0) {
- $orderby = " ORDER BY {$sortkey}";
- // Add sort order
- if ($sortdir == 'desc') {
- $orderby .= ' DESC';
- } else {
- $orderby .= ' ASC';
- }
-
- } else {
- $orderby = '';
- }
-
- // Actually retrieve the rows, with offset and limit
- $rs = $this->selectSet("SELECT * FROM ({$query}) AS sub {$orderby} LIMIT {$page_size} OFFSET " . ($page - 1) * $page_size);
- $status = $this->endTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- return $rs;
- }
-
- /**
- * Finds the number of rows that would be returned by a
- * query.
- * @param $query The SQL query
- * @param $count The count query
- * @return The count of rows
- * @return -1 error
- */
- function browseQueryCount($query, $count) {
- return $this->selectField($count, 'total');
- }
-
- /**
- * 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) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
-
- $sql = "SELECT * FROM \"{$f_schema}\".\"{$table}\"";
- if (is_array($key) && sizeof($key) > 0) {
- $sql .= " WHERE true";
- foreach ($key as $k => $v) {
- $this->fieldClean($k);
- $this->clean($v);
- $sql .= " AND \"{$k}\"='{$v}'";
- }
- }
-
- return $this->selectSet($sql);
- }
-
- // Type conversion routines
-
- /**
- * Change the value of a parameter to 't' or 'f' depending on whether it evaluates to true or false
- * @param $parameter the parameter
- */
- function dbBool(&$parameter) {
- if ($parameter) {
- $parameter = 't';
- } else {
- $parameter = 'f';
- }
-
- return $parameter;
- }
-
- /**
- * Change a parameter from 't' or 'f' to a boolean, (others evaluate to false)
- * @param $parameter the parameter
- */
- function phpBool($parameter) {
- $parameter = ($parameter == 't');
- return $parameter;
- }
-
- // interfaces Statistics collector functions
-
- /**
- * Fetches statistics for a database
- * @param $database The database to fetch stats for
- * @return A recordset
- */
- function getStatsDatabase($database) {
- $this->clean($database);
-
- $sql = "SELECT * FROM pg_stat_database WHERE datname='{$database}'";
-
- return $this->selectSet($sql);
- }
-
- /**
- * Fetches tuple statistics for a table
- * @param $table The table to fetch stats for
- * @return A recordset
- */
- function getStatsTableTuples($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "SELECT * FROM pg_stat_all_tables
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Sends a cancel or kill command to a process
+ * @param $pid The ID of the backend process
+ * @param $signal 'CANCEL'
+ * @return 0 success
+ * @return -1 invalid signal type
+ */
+ public function sendSignal($pid, $signal)
+ {
+ // Clean
+ $pid = (int) $pid;
+
+ if ($signal == 'CANCEL') {
+ $sql = "SELECT pg_catalog.pg_cancel_backend({$pid}) AS val";
+ } elseif ($signal == 'KILL') {
+ $sql = "SELECT pg_catalog.pg_terminate_backend({$pid}) AS val";
+ } else {
+ return -1;
+ }
+
+ // Execute the query
+ $val = $this->selectField($sql, 'val');
+
+ if ($val === 'f') {
+ return -1;
+ } elseif ($val === 't') {
+ return 0;
+ } else {
+ return -1;
+ }
+
+ }
+
+ // Misc functions
+
+ /**
+ * Sets the comment for an object in the database
+ * @pre All parameters must already be cleaned
+ * @param $obj_type One of 'TABLE' | 'COLUMN' | 'VIEW' | 'SCHEMA' | 'SEQUENCE' | 'TYPE' | 'FUNCTION' | 'AGGREGATE'
+ * @param $obj_name The name of the object for which to attach a comment.
+ * @param $table Name of table that $obj_name belongs to. Ignored unless $obj_type is 'TABLE' or 'COLUMN'.
+ * @param $comment The comment to add.
+ * @return 0 success
+ */
+ public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null)
+ {
+ $sql = "COMMENT ON {$obj_type} ";
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->clean($comment); // Passing in an already cleaned comment will lead to double escaped data
+ // So, while counter-intuitive, it is important to not clean comments before
+ // calling setComment. We will clean it here instead.
+ /*
+ $this->fieldClean($table);
+ $this->fieldClean($obj_name);
+ */
+
+ switch ($obj_type) {
+ case 'TABLE':
+ $sql .= "\"{$f_schema}\".\"{$table}\" IS ";
+ break;
+ case 'COLUMN':
+ $sql .= "\"{$f_schema}\".\"{$table}\".\"{$obj_name}\" IS ";
+ break;
+ case 'SEQUENCE':
+ case 'VIEW':
+ case 'TEXT SEARCH CONFIGURATION':
+ case 'TEXT SEARCH DICTIONARY':
+ case 'TEXT SEARCH TEMPLATE':
+ case 'TEXT SEARCH PARSER':
+ case 'TYPE':
+ $sql .= "\"{$f_schema}\".";
+ case 'DATABASE':
+ case 'ROLE':
+ case 'SCHEMA':
+ case 'TABLESPACE':
+ $sql .= "\"{$obj_name}\" IS ";
+ break;
+ case 'FUNCTION':
+ $sql .= "\"{$f_schema}\".{$obj_name} IS ";
+ break;
+ case 'AGGREGATE':
+ $sql .= "\"{$f_schema}\".\"{$obj_name}\" (\"{$basetype}\") IS ";
+ break;
+ default:
+ // Unknown object type
+ return -1;
+ }
+
+ if ($comment != '') {
+ $sql .= "'{$comment}';";
+ } else {
+ $sql .= 'NULL;';
+ }
+
+ return $this->execute($sql);
+
+ }
+
+ /**
+ * A private helper method for executeScript that advances the
+ * character by 1. In psql this is careful to take into account
+ * multibyte languages, but we don't at the moment, so this function
+ * is someone redundant, since it will always advance by 1
+ * @param &$i The current character position in the line
+ * @param &$prevlen Length of previous character (ie. 1)
+ * @param &$thislen Length of current character (ie. 1)
+ */
+ private function advance_1(&$i, &$prevlen, &$thislen)
+ {
+ $prevlen = $thislen;
+ $i += $thislen;
+ $thislen = 1;
+ }
+
+ /**
+ * Private helper method to detect a valid $foo$ quote delimiter at
+ * the start of the parameter dquote
+ * @return True if valid, false otherwise
+ */
+ private function valid_dolquote($dquote)
+ {
+ // XXX: support multibyte
+ return (preg_match('/^[$][$]/', $dquote) || preg_match('/^[$][_[:alpha:]][_[:alnum:]]*[$]/', $dquote));
+ }
+
+ /**
+ * Executes an SQL script as a series of SQL statements. Returns
+ * the result of the final step. This is a very complicated lexer
+ * based on the REL7_4_STABLE src/bin/psql/mainloop.c lexer in
+ * the PostgreSQL source code.
+ * XXX: It does not handle multibyte languages properly.
+ * @param $name Entry in $_FILES to use
+ * @param $callback (optional) Callback function to call with each query,
+ its result and line number.
+ * @return True for general success, false on any failure.
+ */
+ public function executeScript($name, $callback = null)
+ {
+
+ // This whole function isn't very encapsulated, but hey...
+ $conn = $this->conn->_connectionID;
+ if (!is_uploaded_file($_FILES[$name]['tmp_name'])) {
+ return false;
+ }
+
+ $fd = fopen($_FILES[$name]['tmp_name'], 'r');
+ if (!$fd) {
+ return false;
+ }
+
+ // Build up each SQL statement, they can be multiline
+ $query_buf = null;
+ $query_start = 0;
+ $in_quote = 0;
+ $in_xcomment = 0;
+ $bslash_count = 0;
+ $dol_quote = null;
+ $paren_level = 0;
+ $len = 0;
+ $i = 0;
+ $prevlen = 0;
+ $thislen = 0;
+ $lineno = 0;
+
+ // Loop over each line in the file
+ while (!feof($fd)) {
+ $line = fgets($fd);
+ $lineno++;
+
+ // Nothing left on line? Then ignore...
+ if (trim($line) == '') {
+ continue;
+ }
+
+ $len = strlen($line);
+ $query_start = 0;
+
+ /*
+ * Parse line, looking for command separators.
+ *
+ * The current character is at line[i], the prior character at line[i
+ * - prevlen], the next character at line[i + thislen].
+ */
+ $prevlen = 0;
+ $thislen = ($len > 0) ? 1 : 0;
+
+ for ($i = 0; $i < $len; $this->advance_1($i, $prevlen, $thislen)) {
+
+ /* was the previous character a backslash? */
+ if ($i > 0 && substr($line, $i - $prevlen, 1) == '\\') {
+ $bslash_count++;
+ } else {
+ $bslash_count = 0;
+ }
+
+ /*
+ * It is important to place the in_* test routines before the
+ * in_* detection routines. i.e. we have to test if we are in
+ * a quote before testing for comments.
+ */
+
+ /* in quote? */
+ if ($in_quote !== 0) {
+ /*
+ * end of quote if matching non-backslashed character.
+ * backslashes don't count for double quotes, though.
+ */
+ if (substr($line, $i, 1) == $in_quote &&
+ ($bslash_count % 2 == 0 || $in_quote == '"')) {
+ $in_quote = 0;
+ }
+
+ }
+
+ /* in or end of $foo$ type quote? */
+ else if ($dol_quote) {
+ if (strncmp(substr($line, $i), $dol_quote, strlen($dol_quote)) == 0) {
+ $this->advance_1($i, $prevlen, $thislen);
+ while (substr($line, $i, 1) != '$') {
+ $this->advance_1($i, $prevlen, $thislen);
+ }
+
+ $dol_quote = null;
+ }
+ }
+
+ /* start of extended comment? */
+ else if (substr($line, $i, 2) == '/*') {
+ $in_xcomment++;
+ if ($in_xcomment == 1) {
+ $this->advance_1($i, $prevlen, $thislen);
+ }
+
+ }
+
+ /* in or end of extended comment? */
+ else if ($in_xcomment) {
+ if (substr($line, $i, 2) == '*/' && !--$in_xcomment) {
+ $this->advance_1($i, $prevlen, $thislen);
+ }
+
+ }
+
+ /* start of quote? */
+ else if (substr($line, $i, 1) == '\'' || substr($line, $i, 1) == '"') {
+ $in_quote = substr($line, $i, 1);
+ }
+
+ /*
+ * start of $foo$ type quote?
+ */
+ else if (!$dol_quote && $this->valid_dolquote(substr($line, $i))) {
+ $dol_end = strpos(substr($line, $i + 1), '$');
+ $dol_quote = substr($line, $i, $dol_end + 1);
+ $this->advance_1($i, $prevlen, $thislen);
+ while (substr($line, $i, 1) != '$') {
+ $this->advance_1($i, $prevlen, $thislen);
+ }
+
+ }
+
+ /* single-line comment? truncate line */
+ else if (substr($line, $i, 2) == '--') {
+ $line = substr($line, 0, $i); /* remove comment */
+ break;
+ }
+
+ /* count nested parentheses */
+ else if (substr($line, $i, 1) == '(') {
+ $paren_level++;
+ } else if (substr($line, $i, 1) == ')' && $paren_level > 0) {
+ $paren_level--;
+ }
+
+ /* semicolon? then send query */
+ else if (substr($line, $i, 1) == ';' && !$bslash_count && !$paren_level) {
+ $subline = substr(substr($line, 0, $i), $query_start);
+ /* is there anything else on the line? */
+ if (strspn($subline, " \t\n\r") != strlen($subline)) {
+ /*
+ * insert a cosmetic newline, if this is not the first
+ * line in the buffer
+ */
+ if (strlen($query_buf) > 0) {
+ $query_buf .= "\n";
+ }
+
+ /* append the line to the query buffer */
+ $query_buf .= $subline;
+ $query_buf .= ';';
+
+ // Execute the query. PHP cannot execute
+ // empty queries, unlike libpq
+ $res = @pg_query($conn, $query_buf);
+
+ // Call the callback function for display
+ if ($callback !== null) {
+ $callback($query_buf, $res, $lineno);
+ }
+
+ // Check for COPY request
+ if (pg_result_status($res) == 4) {
+ // 4 == PGSQL_COPY_FROM
+ while (!feof($fd)) {
+ $copy = fgets($fd, 32768);
+ $lineno++;
+ pg_put_line($conn, $copy);
+ if ($copy == "\\.\n" || $copy == "\\.\r\n") {
+ pg_end_copy($conn);
+ break;
+ }
+ }
+ }
+ }
+
+ $query_buf = null;
+ $query_start = $i + $thislen;
+ }
+
+ /*
+ * keyword or identifier?
+ * We grab the whole string so that we don't
+ * mistakenly see $foo$ inside an identifier as the start
+ * of a dollar quote.
+ */
+ // XXX: multibyte here
+ else if (preg_match('/^[_[:alpha:]]$/', substr($line, $i, 1))) {
+ $sub = substr($line, $i, $thislen);
+ while (preg_match('/^[\$_A-Za-z0-9]$/', $sub)) {
+ /* keep going while we still have identifier chars */
+ $this->advance_1($i, $prevlen, $thislen);
+ $sub = substr($line, $i, $thislen);
+ }
+ // Since we're now over the next character to be examined, it is necessary
+ // to move back one space.
+ $i -= $prevlen;
+ }
+ } // end for
+
+ /* Put the rest of the line in the query buffer. */
+ $subline = substr($line, $query_start);
+ if ($in_quote || $dol_quote || strspn($subline, " \t\n\r") != strlen($subline)) {
+ if (strlen($query_buf) > 0) {
+ $query_buf .= "\n";
+ }
+
+ $query_buf .= $subline;
+ }
+
+ $line = null;
+
+ } // end while
+
+ /*
+ * Process query at the end of file without a semicolon, so long as
+ * it's non-empty.
+ */
+ if (strlen($query_buf) > 0 && strspn($query_buf, " \t\n\r") != strlen($query_buf)) {
+ // Execute the query
+ $res = @pg_query($conn, $query_buf);
+
+ // Call the callback function for display
+ if ($callback !== null) {
+ $callback($query_buf, $res, $lineno);
+ }
+
+ // Check for COPY request
+ if (pg_result_status($res) == 4) {
+ // 4 == PGSQL_COPY_FROM
+ while (!feof($fd)) {
+ $copy = fgets($fd, 32768);
+ $lineno++;
+ pg_put_line($conn, $copy);
+ if ($copy == "\\.\n" || $copy == "\\.\r\n") {
+ pg_end_copy($conn);
+ break;
+ }
+ }
+ }
+ }
+
+ fclose($fd);
+
+ return true;
+ }
+
+ /**
+ * Generates the SQL for the 'select' function
+ * @param $table The table from which to select
+ * @param $show An array of columns to show. Empty array means all columns.
+ * @param $values An array mapping columns to values
+ * @param $ops An array of the operators to use
+ * @param $orderby (optional) An array of column numbers or names (one based)
+ * mapped to sort direction (asc or desc or '' or null) to order by
+ * @return The SQL query
+ */
+ public function getSelectSQL($table, $show, $values, $ops, $orderby = [])
+ {
+ $this->fieldArrayClean($show);
+
+ // If an empty array is passed in, then show all columns
+ if (sizeof($show) == 0) {
+ if ($this->hasObjectID($table)) {
+ $sql = "SELECT \"{$this->id}\", * FROM ";
+ } else {
+ $sql = "SELECT * FROM ";
+ }
+
+ } else {
+ // Add oid column automatically to results for editing purposes
+ if (!in_array($this->id, $show) && $this->hasObjectID($table)) {
+ $sql = "SELECT \"{$this->id}\", \"";
+ } else {
+ $sql = "SELECT \"";
+ }
+
+ $sql .= join('","', $show) . "\" FROM ";
+ }
+
+ $this->fieldClean($table);
+
+ if (isset($_REQUEST['schema'])) {
+ $f_schema = $_REQUEST['schema'];
+ $this->fieldClean($f_schema);
+ $sql .= "\"{$f_schema}\".";
+ }
+ $sql .= "\"{$table}\"";
+
+ // If we have values specified, add them to the WHERE clause
+ $first = true;
+ if (is_array($values) && sizeof($values) > 0) {
+ foreach ($values as $k => $v) {
+ if ($v != '' || $this->selectOps[$ops[$k]] == 'p') {
+ $this->fieldClean($k);
+ if ($first) {
+ $sql .= " WHERE ";
+ $first = false;
+ } else {
+ $sql .= " AND ";
+ }
+ // Different query format depending on operator type
+ switch ($this->selectOps[$ops[$k]]) {
+ case 'i':
+ // Only clean the field for the inline case
+ // this is because (x), subqueries need to
+ // to allow 'a','b' as input.
+ $this->clean($v);
+ $sql .= "\"{$k}\" {$ops[$k]} '{$v}'";
+ break;
+ case 'p':
+ $sql .= "\"{$k}\" {$ops[$k]}";
+ break;
+ case 'x':
+ $sql .= "\"{$k}\" {$ops[$k]} ({$v})";
+ break;
+ case 't':
+ $sql .= "\"{$k}\" {$ops[$k]}('{$v}')";
+ break;
+ default:
+ // Shouldn't happen
+ }
+ }
+ }
+ }
+
+ // ORDER BY
+ if (is_array($orderby) && sizeof($orderby) > 0) {
+ $sql .= " ORDER BY ";
+ $first = true;
+ foreach ($orderby as $k => $v) {
+ if ($first) {
+ $first = false;
+ } else {
+ $sql .= ', ';
+ }
+
+ if (preg_match('/^[0-9]+$/', $k)) {
+ $sql .= $k;
+ } else {
+ $this->fieldClean($k);
+ $sql .= '"' . $k . '"';
+ }
+ if (strtoupper($v) == 'DESC') {
+ $sql .= " DESC";
+ }
+
+ }
+ }
+
+ return $sql;
+ }
+
+ /**
+ * Returns a recordset of all columns in a query. Supports paging.
+ * @param $type Either 'QUERY' if it is an SQL query, or 'TABLE' if it is a table identifier,
+ * or 'SELECT" if it's a select query
+ * @param $table The base table of the query. NULL for no table.
+ * @param $query The query that is being executed. NULL for no query.
+ * @param $sortkey The column number to sort by, or '' or null for no sorting
+ * @param $sortdir The direction in which to sort the specified column ('asc' or 'desc')
+ * @param $page The page of the relation to retrieve
+ * @param $page_size The number of rows per page
+ * @param &$max_pages (return-by-ref) The max number of pages in the relation
+ * @return A recordset on success
+ * @return -1 transaction error
+ * @return -2 counting error
+ * @return -3 page or page_size invalid
+ * @return -4 unknown type
+ * @return -5 failed setting transaction read only
+ */
+ public function browseQuery($type, $table, $query, $sortkey, $sortdir, $page, $page_size, &$max_pages)
+ {
+ // Check that we're not going to divide by zero
+ if (!is_numeric($page_size) || $page_size != (int) $page_size || $page_size <= 0) {
+ return -3;
+ }
+
+ // If $type is TABLE, then generate the query
+ switch ($type) {
+ case 'TABLE':
+ if (preg_match('/^[0-9]+$/', $sortkey) && $sortkey > 0) {
+ $orderby = [$sortkey => $sortdir];
+ } else {
+ $orderby = [];
+ }
+
+ $query = $this->getSelectSQL($table, [], [], [], $orderby);
+ break;
+ case 'QUERY':
+ case 'SELECT':
+ // Trim query
+ $query = trim($query);
+ // Trim off trailing semi-colon if there is one
+ if (substr($query, strlen($query) - 1, 1) == ';') {
+ $query = substr($query, 0, strlen($query) - 1);
+ }
+
+ break;
+ default:
+ return -4;
+ }
+
+ // Generate count query
+ $count = "SELECT COUNT(*) AS total FROM ($query) AS sub";
+
+ // Open a transaction
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ // If backend supports read only queries, then specify read only mode
+ // to avoid side effects from repeating queries that do writes.
+ if ($this->hasReadOnlyQueries()) {
+ $status = $this->execute("SET TRANSACTION READ ONLY");
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -5;
+ }
+ }
+
+ // Count the number of rows
+ $total = $this->browseQueryCount($query, $count);
+ if ($total < 0) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+
+ // Calculate max pages
+ $max_pages = ceil($total / $page_size);
+
+ // Check that page is less than or equal to max pages
+ if (!is_numeric($page) || $page != (int) $page || $page > $max_pages || $page < 1) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+
+ // Set fetch mode to NUM so that duplicate field names are properly returned
+ // for non-table queries. Since the SELECT feature only allows selecting one
+ // table, duplicate fields shouldn't appear.
+ if ($type == 'QUERY') {
+ $this->conn->setFetchMode(ADODB_FETCH_NUM);
+ }
+
+ // Figure out ORDER BY. Sort key is always the column number (based from one)
+ // of the column to order by. Only need to do this for non-TABLE queries
+ if ($type != 'TABLE' && preg_match('/^[0-9]+$/', $sortkey) && $sortkey > 0) {
+ $orderby = " ORDER BY {$sortkey}";
+ // Add sort order
+ if ($sortdir == 'desc') {
+ $orderby .= ' DESC';
+ } else {
+ $orderby .= ' ASC';
+ }
+
+ } else {
+ $orderby = '';
+ }
+
+ // Actually retrieve the rows, with offset and limit
+ $rs = $this->selectSet("SELECT * FROM ({$query}) AS sub {$orderby} LIMIT {$page_size} OFFSET " . ($page - 1) * $page_size);
+ $status = $this->endTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ return $rs;
+ }
+
+ /**
+ * Finds the number of rows that would be returned by a
+ * query.
+ * @param $query The SQL query
+ * @param $count The count query
+ * @return The count of rows
+ * @return -1 error
+ */
+ public function browseQueryCount($query, $count)
+ {
+ return $this->selectField($count, 'total');
+ }
+
+ /**
+ * 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
+ */
+ public function browseRow($table, $key)
+ {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ $sql = "SELECT * FROM \"{$f_schema}\".\"{$table}\"";
+ if (is_array($key) && sizeof($key) > 0) {
+ $sql .= " WHERE true";
+ foreach ($key as $k => $v) {
+ $this->fieldClean($k);
+ $this->clean($v);
+ $sql .= " AND \"{$k}\"='{$v}'";
+ }
+ }
+
+ return $this->selectSet($sql);
+ }
+
+ // Type conversion routines
+
+ /**
+ * Change the value of a parameter to 't' or 'f' depending on whether it evaluates to true or false
+ * @param $parameter the parameter
+ */
+ public function dbBool(&$parameter)
+ {
+ if ($parameter) {
+ $parameter = 't';
+ } else {
+ $parameter = 'f';
+ }
+
+ return $parameter;
+ }
+
+ /**
+ * Change a parameter from 't' or 'f' to a boolean, (others evaluate to false)
+ * @param $parameter the parameter
+ */
+ public function phpBool($parameter)
+ {
+ $parameter = ($parameter == 't');
+ return $parameter;
+ }
+
+ // interfaces Statistics collector functions
+
+ /**
+ * Fetches statistics for a database
+ * @param $database The database to fetch stats for
+ * @return A recordset
+ */
+ public function getStatsDatabase($database)
+ {
+ $this->clean($database);
+
+ $sql = "SELECT * FROM pg_stat_database WHERE datname='{$database}'";
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Fetches tuple statistics for a table
+ * @param $table The table to fetch stats for
+ * @return A recordset
+ */
+ public function getStatsTableTuples($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "SELECT * FROM pg_stat_all_tables
WHERE schemaname='{$c_schema}' AND relname='{$table}'";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Fetches I/0 statistics for a table
+ * @param $table The table to fetch stats for
+ * @return A recordset
+ */
+ public function getStatsTableIO($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "SELECT * FROM pg_statio_all_tables
+ WHERE schemaname='{$c_schema}' AND relname='{$table}'";
- /**
- * Fetches I/0 statistics for a table
- * @param $table The table to fetch stats for
- * @return A recordset
- */
- function getStatsTableIO($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Fetches tuple statistics for all indexes on a table
+ * @param $table The table to fetch index stats for
+ * @return A recordset
+ */
+ public function getStatsIndexTuples($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "SELECT * FROM pg_stat_all_indexes
+ WHERE schemaname='{$c_schema}' AND relname='{$table}' ORDER BY indexrelname";
- $sql = "SELECT * FROM pg_statio_all_tables
- WHERE schemaname='{$c_schema}' AND relname='{$table}'";
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Fetches I/0 statistics for all indexes on a table
+ * @param $table The table to fetch index stats for
+ * @return A recordset
+ */
+ public function getStatsIndexIO($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "SELECT * FROM pg_statio_all_indexes
+ WHERE schemaname='{$c_schema}' AND relname='{$table}'
+ ORDER BY indexrelname";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Fetches tuple statistics for all indexes on a table
- * @param $table The table to fetch index stats for
- * @return A recordset
- */
- function getStatsIndexTuples($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
+ // Capabilities
- $sql = "SELECT * FROM pg_stat_all_indexes
- WHERE schemaname='{$c_schema}' AND relname='{$table}' ORDER BY indexrelname";
+ public function hasAggregateSortOp()
+ {return true;}
- return $this->selectSet($sql);
- }
+ public function hasAlterAggregate()
+ {return true;}
- /**
- * Fetches I/0 statistics for all indexes on a table
- * @param $table The table to fetch index stats for
- * @return A recordset
- */
- function getStatsIndexIO($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
+ public function hasAlterColumnType()
+ {return true;}
- $sql = "SELECT * FROM pg_statio_all_indexes
- WHERE schemaname='{$c_schema}' AND relname='{$table}'
- ORDER BY indexrelname";
+ public function hasAlterDatabaseOwner()
+ {return true;}
+
+ public function hasAlterDatabaseRename()
+ {return true;}
+
+ public function hasAlterSchema()
+ {return true;}
+
+ public function hasAlterSchemaOwner()
+ {return true;}
+
+ public function hasAlterSequenceSchema()
+ {return true;}
+
+ public function hasAlterSequenceStart()
+ {return true;}
+
+ public function hasAlterTableSchema()
+ {return true;}
+
+ public function hasAutovacuum()
+ {return true;}
+
+ public function hasCreateTableLike()
+ {return true;}
+
+ public function hasCreateTableLikeWithConstraints()
+ {return true;}
+
+ public function hasCreateTableLikeWithIndexes()
+ {return true;}
+
+ public function hasCreateFieldWithConstraints()
+ {return true;}
+
+ public function hasDisableTriggers()
+ {return true;}
+
+ public function hasAlterDomains()
+ {return true;}
+
+ public function hasDomainConstraints()
+ {return true;}
+
+ public function hasEnumTypes()
+ {return true;}
+
+ public function hasFTS()
+ {return true;}
+
+ public function hasFunctionAlterOwner()
+ {return true;}
+
+ public function hasFunctionAlterSchema()
+ {return true;}
+
+ public function hasFunctionCosting()
+ {return true;}
+
+ public function hasFunctionGUC()
+ {return true;}
+
+ public function hasGrantOption()
+ {return true;}
+
+ public function hasNamedParams()
+ {return true;}
+
+ public function hasPrepare()
+ {return true;}
+
+ public function hasPreparedXacts()
+ {return true;}
+
+ public function hasReadOnlyQueries()
+ {return true;}
+
+ public function hasRecluster()
+ {return true;}
+
+ public function hasRoles()
+ {return true;}
+
+ public function hasServerAdminFuncs()
+ {return true;}
+
+ public function hasSharedComments()
+ {return true;}
+
+ public function hasQueryCancel()
+ {return true;}
+
+ public function hasTablespaces()
+ {return true;}
+
+ public function hasUserRename()
+ {return true;}
+
+ public function hasUserSignals()
+ {return true;}
+
+ public function hasVirtualTransactionId()
+ {return true;}
+
+ public function hasAlterDatabase()
+ {return $this->hasAlterDatabaseRename();}
+
+ public function hasDatabaseCollation()
+ {return true;}
+
+ public function hasMagicTypes()
+ {return true;}
+
+ public function hasQueryKill()
+ {return true;}
+
+ public function hasConcurrentIndexBuild()
+ {return true;}
+
+ public function hasForceReindex()
+ {return false;}
- return $this->selectSet($sql);
- }
-
- // Capabilities
-
- function hasAggregateSortOp() {return true;}
- function hasAlterAggregate() {return true;}
- function hasAlterColumnType() {return true;}
- function hasAlterDatabaseOwner() {return true;}
- function hasAlterDatabaseRename() {return true;}
- function hasAlterSchema() {return true;}
- function hasAlterSchemaOwner() {return true;}
- function hasAlterSequenceSchema() {return true;}
- function hasAlterSequenceStart() {return true;}
- function hasAlterTableSchema() {return true;}
- function hasAutovacuum() {return true;}
- function hasCreateTableLike() {return true;}
- function hasCreateTableLikeWithConstraints() {return true;}
- function hasCreateTableLikeWithIndexes() {return true;}
- function hasCreateFieldWithConstraints() {return true;}
- function hasDisableTriggers() {return true;}
- function hasAlterDomains() {return true;}
- function hasDomainConstraints() {return true;}
- function hasEnumTypes() {return true;}
- function hasFTS() {return true;}
- function hasFunctionAlterOwner() {return true;}
- function hasFunctionAlterSchema() {return true;}
- function hasFunctionCosting() {return true;}
- function hasFunctionGUC() {return true;}
- function hasGrantOption() {return true;}
- function hasNamedParams() {return true;}
- function hasPrepare() {return true;}
- function hasPreparedXacts() {return true;}
- function hasReadOnlyQueries() {return true;}
- function hasRecluster() {return true;}
- function hasRoles() {return true;}
- function hasServerAdminFuncs() {return true;}
- function hasSharedComments() {return true;}
- function hasQueryCancel() {return true;}
- function hasTablespaces() {return true;}
- function hasUserRename() {return true;}
- function hasUserSignals() {return true;}
- function hasVirtualTransactionId() {return true;}
- function hasAlterDatabase() {return $this->hasAlterDatabaseRename();}
- function hasDatabaseCollation() {return true;}
- function hasMagicTypes() {return true;}
- function hasQueryKill() {return true;}
- function hasConcurrentIndexBuild() {return true;}
- function hasForceReindex() {return false;}
- function hasByteaHexDefault() {return true;}
+ public function hasByteaHexDefault()
+ {return true;}
}
diff --git a/src/database/Postgres74.php b/src/database/Postgres74.php
index 9effcb75..c54ddbd5 100644
--- a/src/database/Postgres74.php
+++ b/src/database/Postgres74.php
@@ -1,5 +1,6 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* A class that implements the DB interface for Postgres
* Note: This class uses ADODB and returns RecordSets.
@@ -7,86 +8,82 @@ namespace PHPPgAdmin\Database;
* $Id: Postgres74.php,v 1.72 2008/02/20 21:06:18 ioguix Exp $
*/
-class Postgres74 extends Postgres80 {
-
- var $major_version = 7.4;
- // List of all legal privileges that can be applied to different types
- // of objects.
- var $privlist = [
- 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
- 'database' => ['CREATE', 'TEMPORARY', 'ALL PRIVILEGES'],
- 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
- 'language' => ['USAGE', 'ALL PRIVILEGES'],
- 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
- ];
-
- // Help functions
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc74.php';
- return $this->help_page;
- }
-
- // Database functions
-
- /**
- * Alters a database
- * the multiple return vals are for postgres 8+ which support more functionality in alter database
- * @param $dbName The name of the database
- * @param $newName new name for the database
- * @param $newOwner The new owner for the database
- * @return 0 success
- * @return -1 transaction error
- * @return -2 owner error
- * @return -3 rename error
- */
- function alterDatabase($dbName, $newName, $newOwner = '', $comment = '') {
- //ignore $newowner, not supported pre 8.0
- //ignore $comment, not supported pre 8.2
- $this->clean($dbName);
- $this->clean($newName);
-
- $status = $this->alterDatabaseRename($dbName, $newName);
- if ($status != 0) {
- return -3;
- } else {
- return 0;
- }
-
- }
-
- /**
- * Return all database available on the server
- * @return A list of databases, sorted alphabetically
- */
- function getDatabases($currentdatabase = NULL) {
- $conf = $this->conf;
- $server_info = $this->server_info;
-
- if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
- $username = $server_info['username'];
- $this->clean($username);
- $clause = " AND pu.usename='{$username}'";
- } else {
- $clause = '';
- }
-
- if ($currentdatabase != NULL) {
- $this->clean($currentdatabase);
- $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
- } else {
- $orderby = "ORDER BY pdb.datname";
- }
-
- if (!$conf['show_system']) {
- $where = ' AND NOT pdb.datistemplate';
- } else {
- $where = ' AND pdb.datallowconn';
- }
-
- $sql = "SELECT pdb.datname AS datname, pu.usename AS datowner, pg_encoding_to_char(encoding) AS datencoding,
+class Postgres74 extends Postgres80
+{
+
+ public $major_version = 7.4;
+ // List of all legal privileges that can be applied to different types
+ // of objects.
+ public $privlist = [
+ 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
+ 'database' => ['CREATE', 'TEMPORARY', 'ALL PRIVILEGES'],
+ 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
+ 'language' => ['USAGE', 'ALL PRIVILEGES'],
+ 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
+ ];
+
+ // Database functions
+
+ /**
+ * Alters a database
+ * the multiple return vals are for postgres 8+ which support more functionality in alter database
+ * @param $dbName The name of the database
+ * @param $newName new name for the database
+ * @param $newOwner The new owner for the database
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 owner error
+ * @return -3 rename error
+ */
+ public function alterDatabase($dbName, $newName, $newOwner = '', $comment = '')
+ {
+ //ignore $newowner, not supported pre 8.0
+ //ignore $comment, not supported pre 8.2
+ $this->clean($dbName);
+ $this->clean($newName);
+
+ $status = $this->alterDatabaseRename($dbName, $newName);
+ if ($status != 0) {
+ return -3;
+ } else {
+ return 0;
+ }
+
+ }
+
+ /**
+ * Return all database available on the server
+ * @return A list of databases, sorted alphabetically
+ */
+ public function getDatabases($currentdatabase = null)
+ {
+ $conf = $this->conf;
+ $server_info = $this->server_info;
+
+ if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
+ $username = $server_info['username'];
+ $this->clean($username);
+ $clause = " AND pu.usename='{$username}'";
+ } else {
+ $clause = '';
+ }
+
+ if ($currentdatabase != null) {
+ $this->clean($currentdatabase);
+ $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
+ } else {
+ $orderby = "ORDER BY pdb.datname";
+ }
+
+ if (!$conf['show_system']) {
+ $where = ' AND NOT pdb.datistemplate';
+ } else {
+ $where = ' AND pdb.datallowconn';
+ }
+
+ $sql = "SELECT pdb.datname AS datname, pu.usename AS datowner, pg_encoding_to_char(encoding) AS datencoding,
(SELECT description FROM pg_description pd WHERE pdb.oid=pd.objoid) AS datcomment
FROM pg_database pdb, pg_user pu
WHERE pdb.datdba = pu.usesysid
@@ -94,50 +91,51 @@ class Postgres74 extends Postgres80 {
{$clause}
{$orderby}";
- return $this->selectSet($sql);
- }
-
- /**
- * Searches all system catalogs to find objects that match a certain name.
- * @param $term The search term
- * @param $filter The object type to restrict to ('' means no restriction)
- * @return A recordset
- */
- function findObject($term, $filter) {
- $conf = $this->conf;
-
- /*about escaping:
- * SET standard_conforming_string is not available before 8.2
- * So we must use PostgreSQL specific notation :/
- * E'' notation is not available before 8.1
- * $$ is available since 8.0
- * Nothing specific from 7.4
- */
-
- // Escape search term for ILIKE match
- $term = str_replace('_', '\\_', $term);
- $term = str_replace('%', '\\%', $term);
- $this->clean($term);
- $this->clean($filter);
-
- // Exclude system relations if necessary
- if (!$conf['show_system']) {
- // XXX: The mention of information_schema here is in the wrong place, but
- // it's the quickest fix to exclude the info schema from 7.4
- $where = " AND pn.nspname NOT LIKE 'pg\\\\_%' AND pn.nspname != 'information_schema'";
- $lan_where = "AND pl.lanispl";
- } else {
- $where = '';
- $lan_where = '';
- }
-
- // Apply outer filter
- $sql = '';
- if ($filter != '') {
- $sql = "SELECT * FROM (";
- }
-
- $sql .= "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Searches all system catalogs to find objects that match a certain name.
+ * @param $term The search term
+ * @param $filter The object type to restrict to ('' means no restriction)
+ * @return A recordset
+ */
+ public function findObject($term, $filter)
+ {
+ $conf = $this->conf;
+
+ /*about escaping:
+ * SET standard_conforming_string is not available before 8.2
+ * So we must use PostgreSQL specific notation :/
+ * E'' notation is not available before 8.1
+ * $$ is available since 8.0
+ * Nothing specific from 7.4
+ */
+
+ // Escape search term for ILIKE match
+ $term = str_replace('_', '\\_', $term);
+ $term = str_replace('%', '\\%', $term);
+ $this->clean($term);
+ $this->clean($filter);
+
+ // Exclude system relations if necessary
+ if (!$conf['show_system']) {
+ // XXX: The mention of information_schema here is in the wrong place, but
+ // it's the quickest fix to exclude the info schema from 7.4
+ $where = " AND pn.nspname NOT LIKE 'pg\\\\_%' AND pn.nspname != 'information_schema'";
+ $lan_where = "AND pl.lanispl";
+ } else {
+ $where = '';
+ $lan_where = '';
+ }
+
+ // Apply outer filter
+ $sql = '';
+ if ($filter != '') {
+ $sql = "SELECT * FROM (";
+ }
+
+ $sql .= "
SELECT 'SCHEMA' AS type, oid, NULL AS schemaname, NULL AS relname, nspname AS name
FROM pg_catalog.pg_namespace pn WHERE nspname ILIKE '%{$term}%' {$where}
UNION ALL
@@ -194,9 +192,9 @@ class Postgres74 extends Postgres80 {
WHERE c.relkind='v' AND r.rulename != '_RETURN' AND r.rulename ILIKE '%{$term}%' {$where}
";
- // Add advanced objects if show_advanced is set
- if ($conf['show_advanced']) {
- $sql .= "
+ // Add advanced objects if show_advanced is set
+ if ($conf['show_advanced']) {
+ $sql .= "
UNION ALL
SELECT CASE WHEN pt.typtype='d' THEN 'DOMAIN' ELSE 'TYPE' END, pt.oid, pn.nspname, NULL,
pt.typname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn
@@ -221,10 +219,10 @@ class Postgres74 extends Postgres80 {
pg_catalog.pg_namespace pn WHERE po.opcnamespace=pn.oid
AND po.opcname ILIKE '%{$term}%' {$where}
";
- }
- // Otherwise just add domains
- else {
- $sql .= "
+ }
+ // Otherwise just add domains
+ else {
+ $sql .= "
UNION ALL
SELECT 'DOMAIN', pt.oid, pn.nspname, NULL,
pt.typname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn
@@ -232,178 +230,181 @@ class Postgres74 extends Postgres80 {
AND (pt.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = pt.typrelid))
{$where}
";
- }
+ }
- if ($filter != '') {
- // We use like to make RULE, CONSTRAINT and COLUMN searches work
- $sql .= ") AS sub WHERE type LIKE '{$filter}%' ";
- }
+ if ($filter != '') {
+ // We use like to make RULE, CONSTRAINT and COLUMN searches work
+ $sql .= ") AS sub WHERE type LIKE '{$filter}%' ";
+ }
- $sql .= "ORDER BY type, schemaname, relname, name";
+ $sql .= "ORDER BY type, schemaname, relname, name";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Returns table locks information in the current database
- * @return A recordset
- */
- function getLocks() {
- $conf = $this->conf;
+ /**
+ * Returns table locks information in the current database
+ * @return A recordset
+ */
+ public function getLocks()
+ {
+ $conf = $this->conf;
- if (!$conf['show_system']) {
- $where = "AND pn.nspname NOT LIKE 'pg\\\\_%'";
- } else {
- $where = "AND nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
- }
+ if (!$conf['show_system']) {
+ $where = "AND pn.nspname NOT LIKE 'pg\\\\_%'";
+ } else {
+ $where = "AND nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
+ }
- $sql = "SELECT pn.nspname, pc.relname AS tablename, pl.transaction, pl.pid, pl.mode, pl.granted
+ $sql = "SELECT pn.nspname, pc.relname AS tablename, pl.transaction, pl.pid, pl.mode, pl.granted
FROM pg_catalog.pg_locks pl, pg_catalog.pg_class pc, pg_catalog.pg_namespace pn
WHERE pl.relation = pc.oid AND pc.relnamespace=pn.oid {$where}
ORDER BY nspname,tablename";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns the current database encoding
- * @return The encoding. eg. SQL_ASCII, UTF-8, etc.
- */
- function getDatabaseEncoding() {
- $sql = "SELECT getdatabaseencoding() AS encoding";
-
- return $this->selectField($sql, 'encoding');
- }
-
- // Table functions
-
- /**
- * Protected method which alter a table
- * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
- * @param $tblrs The table recordSet returned by getTable()
- * @param $name The new name for the table
- * @param $owner The new owner for the table
- * @param $schema The new schema for the table
- * @param $comment The comment on the table
- * @param $tablespace The new tablespace for the table ('' means leave as is)
- * @return 0 success
- * @return -3 rename error
- * @return -4 comment error
- * @return -5 owner error
- */
- protected
- function _alterTable($tblrs, $name, $owner, $schema, $comment, $tablespace) {
-
- /* $schema and tablespace not supported in pg74- */
- $this->fieldArrayClean($tblrs->fields);
-
- // Comment
- $status = $this->setComment('TABLE', '', $tblrs->fields['relname'], $comment);
- if ($status != 0) {
- return -4;
- }
-
- // Owner
- $this->fieldClean($owner);
- $status = $this->alterTableOwner($tblrs, $owner);
- if ($status != 0) {
- return -5;
- }
-
- // Rename
- $this->fieldClean($name);
- $status = $this->alterTableName($tblrs, $name);
- if ($status != 0) {
- return -3;
- }
-
- return 0;
- }
-
- /**
- * Alters a column in a table OR view
- * @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 $oldnotnull (boolean) True if column is already not null, false otherwise
- * @param $default The new default for the column
- * @param $olddefault The old default for the column
- * @param $type The new type for the column
- * @param $array True if array type, false otherwise
- * @param $length The optional size of the column (ie. 30 for varchar(30))
- * @param $oldtype The old type for the column
- * @param $comment Comment for the column
- * @return 0 success
- * @return -2 set not null error
- * @return -3 set default error
- * @return -4 rename column error
- * @return -5 comment error
- * @return -6 transaction error
- */
- function alterColumn($table, $column, $name, $notnull, $oldnotnull, $default, $olddefault,
- $type, $length, $array, $oldtype, $comment) {
- $status = $this->beginTransaction();
- if ($status != 0) {
- return -1;
- }
-
- // @@ NEED TO HANDLE "NESTED" TRANSACTION HERE
- if ($notnull != $oldnotnull) {
- $status = $this->setColumnNull($table, $column, !$notnull);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -2;
- }
- }
-
- // Set default, if it has changed
- if ($default != $olddefault) {
- if ($default == '') {
- $status = $this->dropColumnDefault($table, $column);
- } else {
- $status = $this->setColumnDefault($table, $column, $default);
- }
-
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
- }
-
- // Rename the column, if it has been changed
- if ($column != $name) {
- $status = $this->renameColumn($table, $column, $name);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -4;
- }
- }
-
- // The $name and $table parameters must be cleaned for the setComment function.
- // It's ok to do that here since this is the last time these variables are used.
- $this->fieldClean($name);
- $this->fieldClean($table);
- $status = $this->setComment('COLUMN', $name, $table, $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -5;
- }
-
- return $this->endTransaction();
- }
-
- /**
- * Returns table information
- * @param $table The name of the table
- * @return A recordset
- */
- function getTable($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns the current database encoding
+ * @return The encoding. eg. SQL_ASCII, UTF-8, etc.
+ */
+ public function getDatabaseEncoding()
+ {
+ $sql = "SELECT getdatabaseencoding() AS encoding";
+
+ return $this->selectField($sql, 'encoding');
+ }
+
+ // Table functions
+
+ /**
+ * Protected method which alter a table
+ * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
+ * @param $tblrs The table recordSet returned by getTable()
+ * @param $name The new name for the table
+ * @param $owner The new owner for the table
+ * @param $schema The new schema for the table
+ * @param $comment The comment on the table
+ * @param $tablespace The new tablespace for the table ('' means leave as is)
+ * @return 0 success
+ * @return -3 rename error
+ * @return -4 comment error
+ * @return -5 owner error
+ */
+ protected function _alterTable($tblrs, $name, $owner, $schema, $comment, $tablespace)
+ {
+
+ /* $schema and tablespace not supported in pg74- */
+ $this->fieldArrayClean($tblrs->fields);
+
+ // Comment
+ $status = $this->setComment('TABLE', '', $tblrs->fields['relname'], $comment);
+ if ($status != 0) {
+ return -4;
+ }
+
+ // Owner
+ $this->fieldClean($owner);
+ $status = $this->alterTableOwner($tblrs, $owner);
+ if ($status != 0) {
+ return -5;
+ }
+
+ // Rename
+ $this->fieldClean($name);
+ $status = $this->alterTableName($tblrs, $name);
+ if ($status != 0) {
+ return -3;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Alters a column in a table OR view
+ * @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 $oldnotnull (boolean) True if column is already not null, false otherwise
+ * @param $default The new default for the column
+ * @param $olddefault The old default for the column
+ * @param $type The new type for the column
+ * @param $array True if array type, false otherwise
+ * @param $length The optional size of the column (ie. 30 for varchar(30))
+ * @param $oldtype The old type for the column
+ * @param $comment Comment for the column
+ * @return 0 success
+ * @return -2 set not null error
+ * @return -3 set default error
+ * @return -4 rename column error
+ * @return -5 comment error
+ * @return -6 transaction error
+ */
+ public function alterColumn($table, $column, $name, $notnull, $oldnotnull, $default, $olddefault,
+ $type, $length, $array, $oldtype, $comment) {
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ return -1;
+ }
+
+ // @@ NEED TO HANDLE "NESTED" TRANSACTION HERE
+ if ($notnull != $oldnotnull) {
+ $status = $this->setColumnNull($table, $column, !$notnull);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+ }
+
+ // Set default, if it has changed
+ if ($default != $olddefault) {
+ if ($default == '') {
+ $status = $this->dropColumnDefault($table, $column);
+ } else {
+ $status = $this->setColumnDefault($table, $column, $default);
+ }
+
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+ }
+
+ // Rename the column, if it has been changed
+ if ($column != $name) {
+ $status = $this->renameColumn($table, $column, $name);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -4;
+ }
+ }
+
+ // The $name and $table parameters must be cleaned for the setComment function.
+ // It's ok to do that here since this is the last time these variables are used.
+ $this->fieldClean($name);
+ $this->fieldClean($table);
+ $status = $this->setComment('COLUMN', $name, $table, $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -5;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Returns table information
+ * @param $table The name of the table
+ * @return A recordset
+ */
+ public function getTable($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "
SELECT
c.relname, n.nspname, u.usename AS relowner,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment
@@ -414,25 +415,26 @@ class Postgres74 extends Postgres80 {
AND n.nspname = '{$c_schema}'
AND c.relname = '{$table}'";
- return $this->selectSet($sql);
- }
-
- /**
- * Return all tables in current database (and schema)
- * @param $all True to fetch all tables, false for just in current schema
- * @return All tables, sorted alphabetically
- */
- function getTables($all = false) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- if ($all) {
- // Exclude pg_catalog and information_schema tables
- $sql = "SELECT schemaname AS nspname, tablename AS relname, tableowner AS relowner
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Return all tables in current database (and schema)
+ * @param $all True to fetch all tables, false for just in current schema
+ * @return All tables, sorted alphabetically
+ */
+ public function getTables($all = false)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ if ($all) {
+ // Exclude pg_catalog and information_schema tables
+ $sql = "SELECT schemaname AS nspname, tablename AS relname, tableowner AS relowner
FROM pg_catalog.pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
ORDER BY schemaname, tablename";
- } else {
- $sql = "SELECT c.relname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
+ } else {
+ $sql = "SELECT c.relname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment,
reltuples::bigint
FROM pg_catalog.pg_class c
@@ -440,38 +442,40 @@ class Postgres74 extends Postgres80 {
WHERE c.relkind = 'r'
AND nspname='{$c_schema}'
ORDER BY c.relname";
- }
-
- return $this->selectSet($sql);
- }
-
- /**
- * Returns the current default_with_oids setting
- * @return default_with_oids setting
- */
- function getDefaultWithOid() {
- // 8.0 is the first release to have this setting
- // Prior releases don't have this setting... oids always activated
- return 'on';
- }
-
- // Constraint functions
-
- /**
- * Returns a list of all constraints on a table,
- * including constraint name, definition, related col and referenced namespace,
- * table and col if needed
- * @param $table the table where we are looking for fk
- * @return a recordset
- */
- function getConstraintsWithFields($table) {
-
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- // get the max number of col used in a constraint for the table
- $sql = "SELECT DISTINCT
+ }
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns the current default_with_oids setting
+ * @return default_with_oids setting
+ */
+ public function getDefaultWithOid()
+ {
+ // 8.0 is the first release to have this setting
+ // Prior releases don't have this setting... oids always activated
+ return 'on';
+ }
+
+ // Constraint functions
+
+ /**
+ * Returns a list of all constraints on a table,
+ * including constraint name, definition, related col and referenced namespace,
+ * table and col if needed
+ * @param $table the table where we are looking for fk
+ * @return a recordset
+ */
+ public function getConstraintsWithFields($table)
+ {
+
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ // get the max number of col used in a constraint for the table
+ $sql = "SELECT DISTINCT
max(SUBSTRING(array_dims(c.conkey) FROM '^\\\\[.*:(.*)\\\\]$')) as nb
FROM pg_catalog.pg_constraint AS c
JOIN pg_catalog.pg_class AS r ON (c.conrelid=r.oid)
@@ -479,15 +483,15 @@ class Postgres74 extends Postgres80 {
WHERE
r.relname = '{$table}' AND ns.nspname='{$c_schema}'";
- $rs = $this->selectSet($sql);
+ $rs = $this->selectSet($sql);
- if ($rs->EOF) {
- $max_col = 0;
- } else {
- $max_col = $rs->fields['nb'];
- }
+ if ($rs->EOF) {
+ $max_col = 0;
+ } else {
+ $max_col = $rs->fields['nb'];
+ }
- $sql = '
+ $sql = '
SELECT
c.oid AS conid, c.contype, c.conname, pg_catalog.pg_get_constraintdef(c.oid, true) AS consrc,
ns1.nspname as p_schema, r1.relname as p_table, ns2.nspname as f_schema,
@@ -498,66 +502,68 @@ class Postgres74 extends Postgres80 {
pg_catalog.pg_constraint AS c
JOIN pg_catalog.pg_class AS r1 ON (c.conrelid=r1.oid)
JOIN pg_catalog.pg_attribute AS f1 ON (f1.attrelid=r1.oid AND (f1.attnum=c.conkey[1]';
- for ($i = 2; $i <= $rs->fields['nb']; $i++) {
- $sql .= " OR f1.attnum=c.conkey[$i]";
- }
- $sql .= '))
+ for ($i = 2; $i <= $rs->fields['nb']; $i++) {
+ $sql .= " OR f1.attnum=c.conkey[$i]";
+ }
+ $sql .= '))
JOIN pg_catalog.pg_namespace AS ns1 ON r1.relnamespace=ns1.oid
LEFT JOIN (
pg_catalog.pg_class AS r2 JOIN pg_catalog.pg_namespace AS ns2 ON (r2.relnamespace=ns2.oid)
) ON (c.confrelid=r2.oid)
LEFT JOIN pg_catalog.pg_attribute AS f2 ON
(f2.attrelid=r2.oid AND ((c.confkey[1]=f2.attnum AND c.conkey[1]=f1.attnum)';
- for ($i = 2; $i <= $rs->fields['nb']; $i++) {
- $sql .= " OR (c.confkey[$i]=f2.attnum AND c.conkey[$i]=f1.attnum)";
- }
+ for ($i = 2; $i <= $rs->fields['nb']; $i++) {
+ $sql .= " OR (c.confkey[$i]=f2.attnum AND c.conkey[$i]=f1.attnum)";
+ }
- $sql .= sprintf("))
+ $sql .= sprintf("))
WHERE
r1.relname = '%s' AND ns1.nspname='%s'
ORDER BY 1", $table, $c_schema);
- return $this->selectSet($sql);
- }
-
- // Sequence functions
-
- /**
- * Returns all sequences in the current database
- * @return A recordset
- */
- function getSequences($all = false) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- if ($all) {
- // Exclude pg_catalog and information_schema tables
- $sql = "SELECT n.nspname, c.relname AS seqname, u.usename AS seqowner
+ return $this->selectSet($sql);
+ }
+
+ // Sequence functions
+
+ /**
+ * Returns all sequences in the current database
+ * @return A recordset
+ */
+ public function getSequences($all = false)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ if ($all) {
+ // Exclude pg_catalog and information_schema tables
+ $sql = "SELECT n.nspname, c.relname AS seqname, u.usename AS seqowner
FROM pg_catalog.pg_class c, pg_catalog.pg_user u, pg_catalog.pg_namespace n
WHERE c.relowner=u.usesysid AND c.relnamespace=n.oid
AND c.relkind = 'S'
AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
ORDER BY nspname, seqname";
- } else {
- $sql = "SELECT c.relname AS seqname, u.usename AS seqowner, pg_catalog.obj_description(c.oid, 'pg_class') AS seqcomment
+ } else {
+ $sql = "SELECT c.relname AS seqname, u.usename AS seqowner, pg_catalog.obj_description(c.oid, 'pg_class') AS seqcomment
FROM pg_catalog.pg_class c, pg_catalog.pg_user u, pg_catalog.pg_namespace n
WHERE c.relowner=u.usesysid AND c.relnamespace=n.oid
AND c.relkind = 'S' AND n.nspname='{$c_schema}' ORDER BY seqname";
- }
+ }
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Function functions
+ // Function functions
- /**
- * Returns all details for a particular function
- * @param $func The name of the function to retrieve
- * @return Function info
- */
- function getFunction($function_oid) {
- $this->clean($function_oid);
+ /**
+ * Returns all details for a particular function
+ * @param $func The name of the function to retrieve
+ * @return Function info
+ */
+ public function getFunction($function_oid)
+ {
+ $this->clean($function_oid);
- $sql = "
+ $sql = "
SELECT
pc.oid AS prooid,
proname,
@@ -581,27 +587,28 @@ class Postgres74 extends Postgres80 {
AND n.oid = pc.pronamespace
";
- return $this->selectSet($sql);
- }
-
- /**
- * Returns a list of all casts in the database
- * @return All casts
- */
- function getCasts() {
- $conf = $this->conf;
-
- if ($conf['show_system']) {
- $where = '';
- } else {
- $where = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns a list of all casts in the database
+ * @return All casts
+ */
+ public function getCasts()
+ {
+ $conf = $this->conf;
+
+ if ($conf['show_system']) {
+ $where = '';
+ } else {
+ $where = "
AND n1.nspname NOT LIKE 'pg\\\\_%'
AND n2.nspname NOT LIKE 'pg\\\\_%'
AND n3.nspname NOT LIKE 'pg\\\\_%'
";
- }
+ }
- $sql = "
+ $sql = "
SELECT
c.castsource::pg_catalog.regtype AS castsource,
c.casttarget::pg_catalog.regtype AS casttarget,
@@ -624,18 +631,35 @@ class Postgres74 extends Postgres80 {
ORDER BY 1, 2
";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
+
+ // Capabilities
+
+ public function hasAlterColumnType()
+ {return false;}
+
+ public function hasCreateFieldWithConstraints()
+ {return false;}
+
+ public function hasAlterDatabaseOwner()
+ {return false;}
+
+ public function hasAlterSchemaOwner()
+ {return false;}
+
+ public function hasFunctionAlterOwner()
+ {return false;}
+
+ public function hasNamedParams()
+ {return false;}
+
+ public function hasQueryCancel()
+ {return false;}
- // Capabilities
+ public function hasTablespaces()
+ {return false;}
- function hasAlterColumnType() {return false;}
- function hasCreateFieldWithConstraints() {return false;}
- function hasAlterDatabaseOwner() {return false;}
- function hasAlterSchemaOwner() {return false;}
- function hasFunctionAlterOwner() {return false;}
- function hasNamedParams() {return false;}
- function hasQueryCancel() {return false;}
- function hasTablespaces() {return false;}
- function hasMagicTypes() {return false;}
+ public function hasMagicTypes()
+ {return false;}
}
diff --git a/src/database/Postgres80.php b/src/database/Postgres80.php
index 4bf4df20..3b1ff57c 100644
--- a/src/database/Postgres80.php
+++ b/src/database/Postgres80.php
@@ -1,88 +1,84 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 8.0 support
*
* $Id: Postgres80.php,v 1.28 2007/12/12 04:11:10 xzilla Exp $
*/
-class Postgres80 extends Postgres81 {
-
- var $major_version = 8.0;
- // Map of database encoding names to HTTP encoding names. If a
- // database encoding does not appear in this list, then its HTTP
- // encoding name is the same as its database encoding name.
- var $codemap = [
- 'ALT' => 'CP866',
- 'EUC_CN' => 'GB2312',
- 'EUC_JP' => 'EUC-JP',
- 'EUC_KR' => 'EUC-KR',
- 'EUC_TW' => 'EUC-TW',
- 'ISO_8859_5' => 'ISO-8859-5',
- 'ISO_8859_6' => 'ISO-8859-6',
- 'ISO_8859_7' => 'ISO-8859-7',
- 'ISO_8859_8' => 'ISO-8859-8',
- 'JOHAB' => 'CP1361',
- 'KOI8' => 'KOI8-R',
- 'LATIN1' => 'ISO-8859-1',
- 'LATIN2' => 'ISO-8859-2',
- 'LATIN3' => 'ISO-8859-3',
- 'LATIN4' => 'ISO-8859-4',
- // The following encoding map is a known error in PostgreSQL < 7.2
- // See the constructor for Postgres72.
- 'LATIN5' => 'ISO-8859-5',
- 'LATIN6' => 'ISO-8859-10',
- 'LATIN7' => 'ISO-8859-13',
- 'LATIN8' => 'ISO-8859-14',
- 'LATIN9' => 'ISO-8859-15',
- 'LATIN10' => 'ISO-8859-16',
- 'SQL_ASCII' => 'US-ASCII',
- 'TCVN' => 'CP1258',
- 'UNICODE' => 'UTF-8',
- 'WIN' => 'CP1251',
- 'WIN874' => 'CP874',
- 'WIN1256' => 'CP1256',
- ];
-
- // Help functions
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc80.php';
- return $this->help_page;
- }
-
- // Database functions
-
- /**
- * Return all database available on the server
- * @return A list of databases, sorted alphabetically
- */
- function getDatabases($currentdatabase = NULL) {
- $conf = $this->conf;
- $server_info = $this->server_info;
-
- if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
- $username = $server_info['username'];
- $this->clean($username);
- $clause = " AND pu.usename='{$username}'";
- } else {
- $clause = '';
- }
-
- if ($currentdatabase != NULL) {
- $this->clean($currentdatabase);
- $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
- } else {
- $orderby = "ORDER BY pdb.datname";
- }
-
- if (!$conf['show_system']) {
- $where = ' AND NOT pdb.datistemplate';
- } else {
- $where = ' AND pdb.datallowconn';
- }
-
- $sql = "SELECT pdb.datname AS datname, pu.usename AS datowner, pg_encoding_to_char(encoding) AS datencoding,
+class Postgres80 extends Postgres81
+{
+
+ public $major_version = 8.0;
+ // Map of database encoding names to HTTP encoding names. If a
+ // database encoding does not appear in this list, then its HTTP
+ // encoding name is the same as its database encoding name.
+ public $codemap = [
+ 'ALT' => 'CP866',
+ 'EUC_CN' => 'GB2312',
+ 'EUC_JP' => 'EUC-JP',
+ 'EUC_KR' => 'EUC-KR',
+ 'EUC_TW' => 'EUC-TW',
+ 'ISO_8859_5' => 'ISO-8859-5',
+ 'ISO_8859_6' => 'ISO-8859-6',
+ 'ISO_8859_7' => 'ISO-8859-7',
+ 'ISO_8859_8' => 'ISO-8859-8',
+ 'JOHAB' => 'CP1361',
+ 'KOI8' => 'KOI8-R',
+ 'LATIN1' => 'ISO-8859-1',
+ 'LATIN2' => 'ISO-8859-2',
+ 'LATIN3' => 'ISO-8859-3',
+ 'LATIN4' => 'ISO-8859-4',
+ // The following encoding map is a known error in PostgreSQL < 7.2
+ // See the constructor for Postgres72.
+ 'LATIN5' => 'ISO-8859-5',
+ 'LATIN6' => 'ISO-8859-10',
+ 'LATIN7' => 'ISO-8859-13',
+ 'LATIN8' => 'ISO-8859-14',
+ 'LATIN9' => 'ISO-8859-15',
+ 'LATIN10' => 'ISO-8859-16',
+ 'SQL_ASCII' => 'US-ASCII',
+ 'TCVN' => 'CP1258',
+ 'UNICODE' => 'UTF-8',
+ 'WIN' => 'CP1251',
+ 'WIN874' => 'CP874',
+ 'WIN1256' => 'CP1256',
+ ];
+
+ // Database functions
+
+ /**
+ * Return all database available on the server
+ * @return A list of databases, sorted alphabetically
+ */
+ public function getDatabases($currentdatabase = null)
+ {
+ $conf = $this->conf;
+ $server_info = $this->server_info;
+
+ if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
+ $username = $server_info['username'];
+ $this->clean($username);
+ $clause = " AND pu.usename='{$username}'";
+ } else {
+ $clause = '';
+ }
+
+ if ($currentdatabase != null) {
+ $this->clean($currentdatabase);
+ $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
+ } else {
+ $orderby = "ORDER BY pdb.datname";
+ }
+
+ if (!$conf['show_system']) {
+ $where = ' AND NOT pdb.datistemplate';
+ } else {
+ $where = ' AND pdb.datallowconn';
+ }
+
+ $sql = "SELECT pdb.datname AS datname, pu.usename AS datowner, pg_encoding_to_char(encoding) AS datencoding,
(SELECT description FROM pg_description pd WHERE pdb.oid=pd.objoid) AS datcomment,
(SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=pdb.dattablespace) AS tablespace
FROM pg_database pdb, pg_user pu
@@ -91,25 +87,26 @@ class Postgres80 extends Postgres81 {
{$clause}
{$orderby}";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Schema functions
+ // Schema functions
- /**
- * Return all schemas in the current database.
- * @return All schemas, sorted alphabetically
- */
- function getSchemas() {
- $conf = $this->conf;
+ /**
+ * Return all schemas in the current database.
+ * @return All schemas, sorted alphabetically
+ */
+ public function getSchemas()
+ {
+ $conf = $this->conf;
- if (!$conf['show_system']) {
- $where = "WHERE nspname NOT LIKE 'pg@_%' ESCAPE '@' AND nspname != 'information_schema'";
- } else {
- $where = "WHERE nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
- }
+ if (!$conf['show_system']) {
+ $where = "WHERE nspname NOT LIKE 'pg@_%' ESCAPE '@' AND nspname != 'information_schema'";
+ } else {
+ $where = "WHERE nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
+ }
- $sql = "
+ $sql = "
SELECT pn.nspname, pu.usename AS nspowner,
pg_catalog.obj_description(pn.oid, 'pg_namespace') AS nspcomment
FROM pg_catalog.pg_namespace pn
@@ -117,220 +114,222 @@ class Postgres80 extends Postgres81 {
{$where}
ORDER BY nspname";
- return $this->selectSet($sql);
- }
-
- /**
- * Return all information relating to a schema
- * @param $schema The name of the schema
- * @return Schema information
- */
- function getSchemaByName($schema) {
- $this->clean($schema);
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Return all information relating to a schema
+ * @param $schema The name of the schema
+ * @return Schema information
+ */
+ public function getSchemaByName($schema)
+ {
+ $this->clean($schema);
+ $sql = "
SELECT nspname, nspowner, u.usename AS ownername, nspacl,
pg_catalog.obj_description(pn.oid, 'pg_namespace') as nspcomment
FROM pg_catalog.pg_namespace pn
LEFT JOIN pg_shadow as u ON pn.nspowner = u.usesysid
WHERE nspname='{$schema}'";
- return $this->selectSet($sql);
- }
-
- // Table functions
-
- /**
- * Protected method which alter a table
- * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
- * @param $tblrs The table recordSet returned by getTable()
- * @param $name The new name for the table
- * @param $owner The new owner for the table
- * @param $schema The new schema for the table
- * @param $comment The comment on the table
- * @param $tablespace The new tablespace for the table ('' means leave as is)
- * @return 0 success
- * @return -3 rename error
- * @return -4 comment error
- * @return -5 owner error
- * @return -6 tablespace error
- */
- protected
- function _alterTable($tblrs, $name, $owner, $schema, $comment, $tablespace) {
-
- /* $schema not supported in pg80- */
-
- // Comment
- $status = $this->setComment('TABLE', '', $tblrs->fields['relname'], $comment);
- if ($status != 0) {
- return -4;
- }
-
- // Owner
- $this->fieldClean($owner);
- $status = $this->alterTableOwner($tblrs, $owner);
- if ($status != 0) {
- return -5;
- }
-
- // Tablespace
- $this->fieldClean($tablespace);
- $status = $this->alterTableTablespace($tblrs, $tablespace);
- if ($status != 0) {
- return -6;
- }
-
- // Rename
- $this->fieldClean($name);
- $status = $this->alterTableName($tblrs, $name);
- if ($status != 0) {
- return -3;
- }
-
- return 0;
- }
-
- // View functions
-
- /**
- * Protected method which alter a view
- * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
- * @param $vwrs The view recordSet returned by getView()
- * @param $name The new name for the view
- * @param $owner The new owner for the view
- * @param $comment The comment on the view
- * @return 0 success
- * @return -3 rename error
- * @return -4 comment error
- * @return -5 owner error
- */
- protected
- function _alterView($vwrs, $name, $owner, $schema, $comment) {
-
- /* $schema not supported in pg80- */
- $this->fieldArrayClean($vwrs->fields);
-
- // Comment
- if ($this->setComment('VIEW', $vwrs->fields['relname'], '', $comment) != 0) {
- return -4;
- }
-
- // Owner
- $this->fieldClean($owner);
- $status = $this->alterViewOwner($vwrs, $owner);
- if ($status != 0) {
- return -5;
- }
-
- // Rename
- $this->fieldClean($name);
- $status = $this->alterViewName($vwrs, $name);
- if ($status != 0) {
- return -3;
- }
-
- return 0;
- }
-
- // Sequence functions
-
- /**
- * Protected method which alter a sequence
- * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
- * @param $seqrs The sequence recordSet returned by getSequence()
- * @param $name The new name for the sequence
- * @param $comment The comment on the sequence
- * @param $owner The new owner for the sequence
- * @param $schema The new schema for the sequence
- * @param $increment The increment
- * @param $minvalue The min value
- * @param $maxvalue The max value
- * @param $restartvalue The starting value
- * @param $cachevalue The cache value
- * @param $cycledvalue True if cycled, false otherwise
- * @param $startvalue The sequence start value when issueing a restart
- * @return 0 success
- * @return -3 rename error
- * @return -4 comment error
- * @return -5 owner error
- * @return -6 get sequence props error
- * @return -7 schema error
- */
- protected
- function _alterSequence($seqrs, $name, $comment, $owner, $schema, $increment,
- $minvalue, $maxvalue, $restartvalue, $cachevalue, $cycledvalue, $startvalue) {
-
- /* $schema not supported in pg80- */
- $this->fieldArrayClean($seqrs->fields);
-
- // Comment
- $status = $this->setComment('SEQUENCE', $seqrs->fields['seqname'], '', $comment);
- if ($status != 0) {
- return -4;
- }
-
- // Owner
- $this->fieldClean($owner);
- $status = $this->alterSequenceOwner($seqrs, $owner);
- if ($status != 0) {
- return -5;
- }
-
- // Props
- $this->clean($increment);
- $this->clean($minvalue);
- $this->clean($maxvalue);
- $this->clean($restartvalue);
- $this->clean($cachevalue);
- $this->clean($cycledvalue);
- $this->clean($startvalue);
- $status = $this->alterSequenceProps($seqrs, $increment, $minvalue,
- $maxvalue, $restartvalue, $cachevalue, $cycledvalue, null);
- if ($status != 0) {
- return -6;
- }
-
- // Rename
- $this->fieldClean($name);
- $status = $this->alterSequenceName($seqrs, $name);
- if ($status != 0) {
- return -3;
- }
-
- return 0;
- }
-
- // Role, User/group functions
-
- /**
- * Changes a user's password
- * @param $username The username
- * @param $password The new password
- * @return 0 success
- */
- function changePassword($username, $password) {
- $enc = $this->_encryptPassword($username, $password);
- $this->fieldClean($username);
- $this->clean($enc);
-
- $sql = "ALTER USER \"{$username}\" WITH ENCRYPTED PASSWORD '{$enc}'";
-
- return $this->execute($sql);
- }
-
- // Aggregate functions
-
- /**
- * Gets all information for an aggregate
- * @param $name The name of the aggregate
- * @param $basetype The input data type of the aggregate
- * @return A recordset
- */
- function getAggregate($name, $basetype) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($name);
- $this->clean($basetype);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ // Table functions
+
+ /**
+ * Protected method which alter a table
+ * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
+ * @param $tblrs The table recordSet returned by getTable()
+ * @param $name The new name for the table
+ * @param $owner The new owner for the table
+ * @param $schema The new schema for the table
+ * @param $comment The comment on the table
+ * @param $tablespace The new tablespace for the table ('' means leave as is)
+ * @return 0 success
+ * @return -3 rename error
+ * @return -4 comment error
+ * @return -5 owner error
+ * @return -6 tablespace error
+ */
+ protected function _alterTable($tblrs, $name, $owner, $schema, $comment, $tablespace)
+ {
+
+ /* $schema not supported in pg80- */
+
+ // Comment
+ $status = $this->setComment('TABLE', '', $tblrs->fields['relname'], $comment);
+ if ($status != 0) {
+ return -4;
+ }
+
+ // Owner
+ $this->fieldClean($owner);
+ $status = $this->alterTableOwner($tblrs, $owner);
+ if ($status != 0) {
+ return -5;
+ }
+
+ // Tablespace
+ $this->fieldClean($tablespace);
+ $status = $this->alterTableTablespace($tblrs, $tablespace);
+ if ($status != 0) {
+ return -6;
+ }
+
+ // Rename
+ $this->fieldClean($name);
+ $status = $this->alterTableName($tblrs, $name);
+ if ($status != 0) {
+ return -3;
+ }
+
+ return 0;
+ }
+
+ // View functions
+
+ /**
+ * Protected method which alter a view
+ * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
+ * @param $vwrs The view recordSet returned by getView()
+ * @param $name The new name for the view
+ * @param $owner The new owner for the view
+ * @param $comment The comment on the view
+ * @return 0 success
+ * @return -3 rename error
+ * @return -4 comment error
+ * @return -5 owner error
+ */
+ protected function _alterView($vwrs, $name, $owner, $schema, $comment)
+ {
+
+ /* $schema not supported in pg80- */
+ $this->fieldArrayClean($vwrs->fields);
+
+ // Comment
+ if ($this->setComment('VIEW', $vwrs->fields['relname'], '', $comment) != 0) {
+ return -4;
+ }
+
+ // Owner
+ $this->fieldClean($owner);
+ $status = $this->alterViewOwner($vwrs, $owner);
+ if ($status != 0) {
+ return -5;
+ }
+
+ // Rename
+ $this->fieldClean($name);
+ $status = $this->alterViewName($vwrs, $name);
+ if ($status != 0) {
+ return -3;
+ }
+
+ return 0;
+ }
+
+ // Sequence functions
+
+ /**
+ * Protected method which alter a sequence
+ * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION
+ * @param $seqrs The sequence recordSet returned by getSequence()
+ * @param $name The new name for the sequence
+ * @param $comment The comment on the sequence
+ * @param $owner The new owner for the sequence
+ * @param $schema The new schema for the sequence
+ * @param $increment The increment
+ * @param $minvalue The min value
+ * @param $maxvalue The max value
+ * @param $restartvalue The starting value
+ * @param $cachevalue The cache value
+ * @param $cycledvalue True if cycled, false otherwise
+ * @param $startvalue The sequence start value when issueing a restart
+ * @return 0 success
+ * @return -3 rename error
+ * @return -4 comment error
+ * @return -5 owner error
+ * @return -6 get sequence props error
+ * @return -7 schema error
+ */
+ protected function _alterSequence($seqrs, $name, $comment, $owner, $schema, $increment,
+ $minvalue, $maxvalue, $restartvalue, $cachevalue, $cycledvalue, $startvalue) {
+
+ /* $schema not supported in pg80- */
+ $this->fieldArrayClean($seqrs->fields);
+
+ // Comment
+ $status = $this->setComment('SEQUENCE', $seqrs->fields['seqname'], '', $comment);
+ if ($status != 0) {
+ return -4;
+ }
+
+ // Owner
+ $this->fieldClean($owner);
+ $status = $this->alterSequenceOwner($seqrs, $owner);
+ if ($status != 0) {
+ return -5;
+ }
+
+ // Props
+ $this->clean($increment);
+ $this->clean($minvalue);
+ $this->clean($maxvalue);
+ $this->clean($restartvalue);
+ $this->clean($cachevalue);
+ $this->clean($cycledvalue);
+ $this->clean($startvalue);
+ $status = $this->alterSequenceProps($seqrs, $increment, $minvalue,
+ $maxvalue, $restartvalue, $cachevalue, $cycledvalue, null);
+ if ($status != 0) {
+ return -6;
+ }
+
+ // Rename
+ $this->fieldClean($name);
+ $status = $this->alterSequenceName($seqrs, $name);
+ if ($status != 0) {
+ return -3;
+ }
+
+ return 0;
+ }
+
+ // Role, User/group functions
+
+ /**
+ * Changes a user's password
+ * @param $username The username
+ * @param $password The new password
+ * @return 0 success
+ */
+ public function changePassword($username, $password)
+ {
+ $enc = $this->_encryptPassword($username, $password);
+ $this->fieldClean($username);
+ $this->clean($enc);
+
+ $sql = "ALTER USER \"{$username}\" WITH ENCRYPTED PASSWORD '{$enc}'";
+
+ return $this->execute($sql);
+ }
+
+ // Aggregate functions
+
+ /**
+ * Gets all information for an aggregate
+ * @param $name The name of the aggregate
+ * @param $basetype The input data type of the aggregate
+ * @return A recordset
+ */
+ public function getAggregate($name, $basetype)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($name);
+ $this->clean($basetype);
+
+ $sql = "
SELECT p.proname,
CASE p.proargtypes[0]
WHEN 'pg_catalog.\"any\"'::pg_catalog.regtype THEN NULL
@@ -346,18 +345,35 @@ class Postgres80 extends Postgres81 {
ELSE pg_catalog.format_type(p.proargtypes[0], NULL)
END ='{$basetype}'";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
+
+ // Capabilities
+
+ public function hasAggregateSortOp()
+ {return false;}
+
+ public function hasAlterTableSchema()
+ {return false;}
+
+ public function hasAutovacuum()
+ {return false;}
+
+ public function hasDisableTriggers()
+ {return false;}
+
+ public function hasFunctionAlterSchema()
+ {return false;}
+
+ public function hasPreparedXacts()
+ {return false;}
+
+ public function hasRoles()
+ {return false;}
- // Capabilities
+ public function hasAlterSequenceSchema()
+ {return false;}
- function hasAggregateSortOp() {return false;}
- function hasAlterTableSchema() {return false;}
- function hasAutovacuum() {return false;}
- function hasDisableTriggers() {return false;}
- function hasFunctionAlterSchema() {return false;}
- function hasPreparedXacts() {return false;}
- function hasRoles() {return false;}
- function hasAlterSequenceSchema() {return false;}
- function hasServerAdminFuncs() {return false;}
+ public function hasServerAdminFuncs()
+ {return false;}
}
diff --git a/src/database/Postgres81.php b/src/database/Postgres81.php
index f16a26f6..e4968a3c 100644
--- a/src/database/Postgres81.php
+++ b/src/database/Postgres81.php
@@ -1,83 +1,79 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 8.1 support
*
* $Id: Postgres81.php,v 1.21 2008/01/19 13:46:15 ioguix Exp $
*/
-class Postgres81 extends Postgres82 {
-
- var $major_version = 8.1;
- // List of all legal privileges that can be applied to different types
- // of objects.
- var $privlist = [
- 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
- 'database' => ['CREATE', 'TEMPORARY', 'ALL PRIVILEGES'],
- 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
- 'language' => ['USAGE', 'ALL PRIVILEGES'],
- 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
- 'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
- ];
- // List of characters in acl lists and the privileges they
- // refer to.
- var $privmap = [
- 'r' => 'SELECT',
- 'w' => 'UPDATE',
- 'a' => 'INSERT',
- 'd' => 'DELETE',
- 'R' => 'RULE',
- 'x' => 'REFERENCES',
- 't' => 'TRIGGER',
- 'X' => 'EXECUTE',
- 'U' => 'USAGE',
- 'C' => 'CREATE',
- 'T' => 'TEMPORARY',
- ];
- // Array of allowed index types
- var $typIndexes = ['BTREE', 'RTREE', 'GIST', 'HASH'];
-
- // Help functions
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc81.php';
- return $this->help_page;
- }
-
- // Database functions
-
- /**
- * Returns all databases available on the server
- * @return A list of databases, sorted alphabetically
- */
- function getDatabases($currentdatabase = NULL) {
- $conf = $this->conf;
- $server_info = $this->server_info;
-
- if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
- $username = $server_info['username'];
- $this->clean($username);
- $clause = " AND pr.rolname='{$username}'";
- } else {
- $clause = '';
- }
-
- if ($currentdatabase != NULL) {
- $this->clean($currentdatabase);
- $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
- } else {
- $orderby = "ORDER BY pdb.datname";
- }
-
- if (!$conf['show_system']) {
- $where = ' AND NOT pdb.datistemplate';
- } else {
- $where = ' AND pdb.datallowconn';
- }
-
- $sql = "SELECT pdb.datname AS datname, pr.rolname AS datowner, pg_encoding_to_char(encoding) AS datencoding,
+class Postgres81 extends Postgres82
+{
+
+ public $major_version = 8.1;
+ // List of all legal privileges that can be applied to different types
+ // of objects.
+ public $privlist = [
+ 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
+ 'database' => ['CREATE', 'TEMPORARY', 'ALL PRIVILEGES'],
+ 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
+ 'language' => ['USAGE', 'ALL PRIVILEGES'],
+ 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
+ 'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
+ ];
+ // List of characters in acl lists and the privileges they
+ // refer to.
+ public $privmap = [
+ 'r' => 'SELECT',
+ 'w' => 'UPDATE',
+ 'a' => 'INSERT',
+ 'd' => 'DELETE',
+ 'R' => 'RULE',
+ 'x' => 'REFERENCES',
+ 't' => 'TRIGGER',
+ 'X' => 'EXECUTE',
+ 'U' => 'USAGE',
+ 'C' => 'CREATE',
+ 'T' => 'TEMPORARY',
+ ];
+ // Array of allowed index types
+ public $typIndexes = ['BTREE', 'RTREE', 'GIST', 'HASH'];
+
+ // Database functions
+
+ /**
+ * Returns all databases available on the server
+ * @return A list of databases, sorted alphabetically
+ */
+ public function getDatabases($currentdatabase = null)
+ {
+ $conf = $this->conf;
+ $server_info = $this->server_info;
+
+ if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
+ $username = $server_info['username'];
+ $this->clean($username);
+ $clause = " AND pr.rolname='{$username}'";
+ } else {
+ $clause = '';
+ }
+
+ if ($currentdatabase != null) {
+ $this->clean($currentdatabase);
+ $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
+ } else {
+ $orderby = "ORDER BY pdb.datname";
+ }
+
+ if (!$conf['show_system']) {
+ $where = ' AND NOT pdb.datistemplate';
+ } else {
+ $where = ' AND pdb.datallowconn';
+ }
+
+ $sql = "SELECT pdb.datname AS datname, pr.rolname AS datowner, pg_encoding_to_char(encoding) AS datencoding,
(SELECT description FROM pg_catalog.pg_description pd WHERE pdb.oid=pd.objoid) AS datcomment,
(SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=pdb.dattablespace) AS tablespace,
pg_catalog.pg_database_size(pdb.oid) as dbsize
@@ -87,58 +83,59 @@ class Postgres81 extends Postgres82 {
{$clause}
{$orderby}";
- return $this->selectSet($sql);
- }
-
- /**
- * Alters a database
- * the multiple return vals are for postgres 8+ which support more functionality in alter database
- * @param $dbName The name of the database
- * @param $newName new name for the database
- * @param $newOwner The new owner for the database
- * @return 0 success
- * @return -1 transaction error
- * @return -2 owner error
- * @return -3 rename error
- */
- function alterDatabase($dbName, $newName, $newOwner = '', $comment = '') {
- $this->clean($dbName);
- $this->clean($newName);
- $this->clean($newOwner);
- //ignore $comment, not supported pre 8.2
-
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- if ($dbName != $newName) {
- $status = $this->alterDatabaseRename($dbName, $newName);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
- }
-
- $status = $this->alterDatabaseOwner($newName, $newOwner);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -2;
- }
- return $this->endTransaction();
- }
-
- // Autovacuum functions
-
- function saveAutovacuum($table, $vacenabled, $vacthreshold, $vacscalefactor,
- $anathresold, $anascalefactor, $vaccostdelay, $vaccostlimit) {
- $defaults = $this->getAutovacuum();
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $rs = $this->selectSet("
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Alters a database
+ * the multiple return vals are for postgres 8+ which support more functionality in alter database
+ * @param $dbName The name of the database
+ * @param $newName new name for the database
+ * @param $newOwner The new owner for the database
+ * @return 0 success
+ * @return -1 transaction error
+ * @return -2 owner error
+ * @return -3 rename error
+ */
+ public function alterDatabase($dbName, $newName, $newOwner = '', $comment = '')
+ {
+ $this->clean($dbName);
+ $this->clean($newName);
+ $this->clean($newOwner);
+ //ignore $comment, not supported pre 8.2
+
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ if ($dbName != $newName) {
+ $status = $this->alterDatabaseRename($dbName, $newName);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+ }
+
+ $status = $this->alterDatabaseOwner($newName, $newOwner);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -2;
+ }
+ return $this->endTransaction();
+ }
+
+ // Autovacuum functions
+
+ public function saveAutovacuum($table, $vacenabled, $vacthreshold, $vacscalefactor,
+ $anathresold, $anascalefactor, $vaccostdelay, $vaccostlimit) {
+ $defaults = $this->getAutovacuum();
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $rs = $this->selectSet("
SELECT c.oid
FROM pg_catalog.pg_class AS c
LEFT JOIN pg_catalog.pg_namespace AS n ON (n.oid=c.relnamespace)
@@ -146,45 +143,45 @@ class Postgres81 extends Postgres82 {
c.relname = '{$table}' AND n.nspname = '{$c_schema}'
");
- if ($rs->EOF) {
- return -1;
- }
+ if ($rs->EOF) {
+ return -1;
+ }
- $toid = $rs->fields('oid');
- unset($rs);
+ $toid = $rs->fields('oid');
+ unset($rs);
- if (empty($_POST['autovacuum_vacuum_threshold'])) {
- $_POST['autovacuum_vacuum_threshold'] = $defaults['autovacuum_vacuum_threshold'];
- }
+ if (empty($_POST['autovacuum_vacuum_threshold'])) {
+ $_POST['autovacuum_vacuum_threshold'] = $defaults['autovacuum_vacuum_threshold'];
+ }
- if (empty($_POST['autovacuum_vacuum_scale_factor'])) {
- $_POST['autovacuum_vacuum_scale_factor'] = $defaults['autovacuum_vacuum_scale_factor'];
- }
+ if (empty($_POST['autovacuum_vacuum_scale_factor'])) {
+ $_POST['autovacuum_vacuum_scale_factor'] = $defaults['autovacuum_vacuum_scale_factor'];
+ }
- if (empty($_POST['autovacuum_analyze_threshold'])) {
- $_POST['autovacuum_analyze_threshold'] = $defaults['autovacuum_analyze_threshold'];
- }
+ if (empty($_POST['autovacuum_analyze_threshold'])) {
+ $_POST['autovacuum_analyze_threshold'] = $defaults['autovacuum_analyze_threshold'];
+ }
- if (empty($_POST['autovacuum_analyze_scale_factor'])) {
- $_POST['autovacuum_analyze_scale_factor'] = $defaults['autovacuum_analyze_scale_factor'];
- }
+ if (empty($_POST['autovacuum_analyze_scale_factor'])) {
+ $_POST['autovacuum_analyze_scale_factor'] = $defaults['autovacuum_analyze_scale_factor'];
+ }
- if (empty($_POST['autovacuum_vacuum_cost_delay'])) {
- $_POST['autovacuum_vacuum_cost_delay'] = $defaults['autovacuum_vacuum_cost_delay'];
- }
+ if (empty($_POST['autovacuum_vacuum_cost_delay'])) {
+ $_POST['autovacuum_vacuum_cost_delay'] = $defaults['autovacuum_vacuum_cost_delay'];
+ }
- if (empty($_POST['autovacuum_vacuum_cost_limit'])) {
- $_POST['autovacuum_vacuum_cost_limit'] = $defaults['autovacuum_vacuum_cost_limit'];
- }
+ if (empty($_POST['autovacuum_vacuum_cost_limit'])) {
+ $_POST['autovacuum_vacuum_cost_limit'] = $defaults['autovacuum_vacuum_cost_limit'];
+ }
- $rs = $this->selectSet("SELECT vacrelid
+ $rs = $this->selectSet("SELECT vacrelid
FROM \"pg_catalog\".\"pg_autovacuum\"
WHERE vacrelid = {$toid};");
- $status = -1; // ini
- if ($rs->recordCount() and ($rs->fields['vacrelid'] == $toid)) {
- // table exists in pg_autovacuum, UPDATE
- $sql = sprintf("UPDATE \"pg_catalog\".\"pg_autovacuum\" SET
+ $status = -1; // ini
+ if ($rs->recordCount() and ($rs->fields['vacrelid'] == $toid)) {
+ // table exists in pg_autovacuum, UPDATE
+ $sql = sprintf("UPDATE \"pg_catalog\".\"pg_autovacuum\" SET
enabled = '%s',
vac_base_thresh = %s,
vac_scale_factor = %s,
@@ -194,97 +191,105 @@ class Postgres81 extends Postgres82 {
vac_cost_limit = %s
WHERE vacrelid = {$toid};
",
- ($_POST['autovacuum_enabled'] == 'on') ? 't' : 'f',
- $_POST['autovacuum_vacuum_threshold'],
- $_POST['autovacuum_vacuum_scale_factor'],
- $_POST['autovacuum_analyze_threshold'],
- $_POST['autovacuum_analyze_scale_factor'],
- $_POST['autovacuum_vacuum_cost_delay'],
- $_POST['autovacuum_vacuum_cost_limit']
- );
- $status = $this->execute($sql);
- } else {
- // table doesn't exists in pg_autovacuum, INSERT
- $sql = sprintf("INSERT INTO \"pg_catalog\".\"pg_autovacuum\"
+ ($_POST['autovacuum_enabled'] == 'on') ? 't' : 'f',
+ $_POST['autovacuum_vacuum_threshold'],
+ $_POST['autovacuum_vacuum_scale_factor'],
+ $_POST['autovacuum_analyze_threshold'],
+ $_POST['autovacuum_analyze_scale_factor'],
+ $_POST['autovacuum_vacuum_cost_delay'],
+ $_POST['autovacuum_vacuum_cost_limit']
+ );
+ $status = $this->execute($sql);
+ } else {
+ // table doesn't exists in pg_autovacuum, INSERT
+ $sql = sprintf("INSERT INTO \"pg_catalog\".\"pg_autovacuum\"
VALUES (%s, '%s', %s, %s, %s, %s, %s, %s)",
- $toid,
- ($_POST['autovacuum_enabled'] == 'on') ? 't' : 'f',
- $_POST['autovacuum_vacuum_threshold'],
- $_POST['autovacuum_vacuum_scale_factor'],
- $_POST['autovacuum_analyze_threshold'],
- $_POST['autovacuum_analyze_scale_factor'],
- $_POST['autovacuum_vacuum_cost_delay'],
- $_POST['autovacuum_vacuum_cost_limit']
- );
- $status = $this->execute($sql);
- }
-
- return $status;
- }
-
- /**
- * Returns all available process information.
- * @param $database (optional) Find only connections to specified database
- * @return A recordset
- */
- function getProcesses($database = null) {
- if ($database === null) {
- $sql = "SELECT datname, usename, procpid AS pid, current_query AS query, query_start,
+ $toid,
+ ($_POST['autovacuum_enabled'] == 'on') ? 't' : 'f',
+ $_POST['autovacuum_vacuum_threshold'],
+ $_POST['autovacuum_vacuum_scale_factor'],
+ $_POST['autovacuum_analyze_threshold'],
+ $_POST['autovacuum_analyze_scale_factor'],
+ $_POST['autovacuum_vacuum_cost_delay'],
+ $_POST['autovacuum_vacuum_cost_limit']
+ );
+ $status = $this->execute($sql);
+ }
+
+ return $status;
+ }
+
+ /**
+ * Returns all available process information.
+ * @param $database (optional) Find only connections to specified database
+ * @return A recordset
+ */
+ public function getProcesses($database = null)
+ {
+ if ($database === null) {
+ $sql = "SELECT datname, usename, procpid AS pid, current_query AS query, query_start,
case when (select count(*) from pg_locks where pid=pg_stat_activity.procpid and granted is false) > 0 then 't' else 'f' end as waiting
FROM pg_catalog.pg_stat_activity
ORDER BY datname, usename, procpid";
- } else {
- $this->clean($database);
- $sql = "SELECT datname, usename, procpid AS pid, current_query AS query, query_start
+ } else {
+ $this->clean($database);
+ $sql = "SELECT datname, usename, procpid AS pid, current_query AS query, query_start
case when (select count(*) from pg_locks where pid=pg_stat_activity.procpid and granted is false) > 0 then 't' else 'f' end as waiting
FROM pg_catalog.pg_stat_activity
WHERE datname='{$database}'
ORDER BY usename, procpid";
- }
+ }
- $rc = $this->selectSet($sql);
+ $rc = $this->selectSet($sql);
- return $rc;
- }
+ return $rc;
+ }
- // Tablespace functions
+ // Tablespace functions
- /**
- * Retrieves a tablespace's information
- * @return A recordset
- */
- function getTablespace($spcname) {
- $this->clean($spcname);
+ /**
+ * Retrieves a tablespace's information
+ * @return A recordset
+ */
+ public function getTablespace($spcname)
+ {
+ $this->clean($spcname);
- $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation
+ $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation
FROM pg_catalog.pg_tablespace WHERE spcname='{$spcname}'";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Retrieves information for all tablespaces
- * @param $all Include all tablespaces (necessary when moving objects back to the default space)
- * @return A recordset
- */
- function getTablespaces($all = false) {
- $conf = $this->conf;
+ /**
+ * Retrieves information for all tablespaces
+ * @param $all Include all tablespaces (necessary when moving objects back to the default space)
+ * @return A recordset
+ */
+ public function getTablespaces($all = false)
+ {
+ $conf = $this->conf;
- $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation
+ $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation
FROM pg_catalog.pg_tablespace";
- if (!$conf['show_system'] && !$all) {
- $sql .= ' WHERE spcname NOT LIKE $$pg\_%$$';
- }
+ if (!$conf['show_system'] && !$all) {
+ $sql .= ' WHERE spcname NOT LIKE $$pg\_%$$';
+ }
+
+ $sql .= " ORDER BY spcname";
+
+ return $this->selectSet($sql);
+ }
- $sql .= " ORDER BY spcname";
+ // Capabilities
- return $this->selectSet($sql);
- }
+ public function hasCreateTableLikeWithConstraints()
+ {return false;}
- // Capabilities
+ public function hasSharedComments()
+ {return false;}
- function hasCreateTableLikeWithConstraints() {return false;}
- function hasSharedComments() {return false;}
- function hasConcurrentIndexBuild() {return false;}
+ public function hasConcurrentIndexBuild()
+ {return false;}
}
diff --git a/src/database/Postgres82.php b/src/database/Postgres82.php
index 2a69e69b..fd06080f 100644
--- a/src/database/Postgres82.php
+++ b/src/database/Postgres82.php
@@ -1,116 +1,115 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 8.2 support
*
* $Id: Postgres82.php,v 1.10 2007/12/28 16:21:25 ioguix Exp $
*/
-class Postgres82 extends Postgres83 {
-
- var $major_version = 8.2;
+class Postgres82 extends Postgres83
+{
- // Select operators
- var $selectOps = ['=' => 'i', '!=' => 'i', '<' => 'i', '>' => 'i', '<=' => 'i', '>=' => 'i', '<<' => 'i', '>>' => 'i', '<<=' => 'i', '>>=' => 'i',
- 'LIKE' => 'i', 'NOT LIKE' => 'i', 'ILIKE' => 'i', 'NOT ILIKE' => 'i', 'SIMILAR TO' => 'i',
- 'NOT SIMILAR TO' => 'i', '~' => 'i', '!~' => 'i', '~*' => 'i', '!~*' => 'i',
- 'IS NULL' => 'p', 'IS NOT NULL' => 'p', 'IN' => 'x', 'NOT IN' => 'x'];
+ public $major_version = 8.2;
- // Help functions
+ // Select operators
+ public $selectOps = ['=' => 'i', '!=' => 'i', '<' => 'i', '>' => 'i', '<=' => 'i', '>=' => 'i', '<<' => 'i', '>>' => 'i', '<<=' => 'i', '>>=' => 'i',
+ 'LIKE' => 'i', 'NOT LIKE' => 'i', 'ILIKE' => 'i', 'NOT ILIKE' => 'i', 'SIMILAR TO' => 'i',
+ 'NOT SIMILAR TO' => 'i', '~' => 'i', '!~' => 'i', '~*' => 'i', '!~*' => 'i',
+ 'IS NULL' => 'p', 'IS NOT NULL' => 'p', 'IN' => 'x', 'NOT IN' => 'x'];
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc82.php';
- return $this->help_page;
- }
+ // Database functions
- // Database functions
+ /**
+ * Returns table locks information in the current database
+ * @return A recordset
+ */
+ public function getLocks()
+ {
+ $conf = $this->conf;
- /**
- * Returns table locks information in the current database
- * @return A recordset
- */
- function getLocks() {
- $conf = $this->conf;
+ if (!$conf['show_system']) {
+ $where = 'AND pn.nspname NOT LIKE $$pg\_%$$';
+ } else {
+ $where = "AND nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
+ }
- if (!$conf['show_system']) {
- $where = 'AND pn.nspname NOT LIKE $$pg\_%$$';
- } else {
- $where = "AND nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
- }
-
- $sql = "SELECT pn.nspname, pc.relname AS tablename, pl.transaction, pl.pid, pl.mode, pl.granted
+ $sql = "SELECT pn.nspname, pc.relname AS tablename, pl.transaction, pl.pid, pl.mode, pl.granted
FROM pg_catalog.pg_locks pl, pg_catalog.pg_class pc, pg_catalog.pg_namespace pn
WHERE pl.relation = pc.oid AND pc.relnamespace=pn.oid {$where}
ORDER BY nspname,tablename";
- return $this->selectSet($sql);
- }
-
- // Sequence functions
-
- /**
- * Rename a sequence
- * @param $seqrs The sequence RecordSet returned by getSequence()
- * @param $name The new name for the sequence
- * @return 0 success
- */
- function alterSequenceName($seqrs, $name) {
- /* vars are cleaned in _alterSequence */
- if (!empty($name) && ($seqrs->fields['seqname'] != $name)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status == 0) {
- $seqrs->fields['seqname'] = $name;
- } else {
- return $status;
- }
-
- }
- return 0;
- }
-
- // View functions
-
- /**
- * Rename a view
- * @param $vwrs The view recordSet returned by getView()
- * @param $name The new view's name
- * @return -1 Failed
- * @return 0 success
- */
- function alterViewName($vwrs, $name) {
- // Rename (only if name has changed)
- /* $vwrs and $name are cleaned in _alterView */
- if (!empty($name) && ($name != $vwrs->fields['relname'])) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$vwrs->fields['relname']}\" RENAME TO \"{$name}\"";
- $status = $this->execute($sql);
- if ($status == 0) {
- $vwrs->fields['relname'] = $name;
- } else {
- return $status;
- }
-
- }
- return 0;
- }
-
- // Trigger functions
-
- /**
- * Grabs a list of triggers on a table
- * @param $table The name of a table whose triggers to retrieve
- * @return A recordset
- */
- function getTriggers($table = '') {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "SELECT
+ return $this->selectSet($sql);
+ }
+
+ // Sequence functions
+
+ /**
+ * Rename a sequence
+ * @param $seqrs The sequence RecordSet returned by getSequence()
+ * @param $name The new name for the sequence
+ * @return 0 success
+ */
+ public function alterSequenceName($seqrs, $name)
+ {
+ /* vars are cleaned in _alterSequence */
+ if (!empty($name) && ($seqrs->fields['seqname'] != $name)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status == 0) {
+ $seqrs->fields['seqname'] = $name;
+ } else {
+ return $status;
+ }
+
+ }
+ return 0;
+ }
+
+ // View functions
+
+ /**
+ * Rename a view
+ * @param $vwrs The view recordSet returned by getView()
+ * @param $name The new view's name
+ * @return -1 Failed
+ * @return 0 success
+ */
+ public function alterViewName($vwrs, $name)
+ {
+ // Rename (only if name has changed)
+ /* $vwrs and $name are cleaned in _alterView */
+ if (!empty($name) && ($name != $vwrs->fields['relname'])) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$vwrs->fields['relname']}\" RENAME TO \"{$name}\"";
+ $status = $this->execute($sql);
+ if ($status == 0) {
+ $vwrs->fields['relname'] = $name;
+ } else {
+ return $status;
+ }
+
+ }
+ return 0;
+ }
+
+ // Trigger functions
+
+ /**
+ * Grabs a list of triggers on a table
+ * @param $table The name of a table whose triggers to retrieve
+ * @return A recordset
+ */
+ public function getTriggers($table = '')
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "SELECT
t.tgname, pg_catalog.pg_get_triggerdef(t.oid) AS tgdef, t.tgenabled, p.oid AS prooid,
p.proname || ' (' || pg_catalog.oidvectortypes(p.proargtypes) || ')' AS proproto,
ns.nspname AS pronamespace
@@ -124,20 +123,21 @@ class Postgres82 extends Postgres83 {
AND p.oid=t.tgfoid
AND p.pronamespace = ns.oid";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Function functions
+ // Function functions
- /**
- * Returns all details for a particular function
- * @param $func The name of the function to retrieve
- * @return Function info
- */
- function getFunction($function_oid) {
- $this->clean($function_oid);
+ /**
+ * Returns all details for a particular function
+ * @param $func The name of the function to retrieve
+ * @return Function info
+ */
+ public function getFunction($function_oid)
+ {
+ $this->clean($function_oid);
- $sql = "SELECT
+ $sql = "SELECT
pc.oid AS prooid,
proname,
pg_catalog.pg_get_userbyid(proowner) AS proowner,
@@ -161,143 +161,146 @@ class Postgres82 extends Postgres83 {
AND pc.pronamespace = pn.oid
";
- return $this->selectSet($sql);
- }
-
- /**
- * Creates a new function.
- * @param $funcname The name of the function to create
- * @param $args A comma separated string of types
- * @param $returns The return type
- * @param $definition The definition for the new function
- * @param $language The language the function is written for
- * @param $flags An array of optional flags
- * @param $setof True if it returns a set, false otherwise
- * @param $rows number of rows planner should estimate will be returned
- * @param $cost cost the planner should use in the function execution step
- * @param $comment The comment on the function
- * @param $replace (optional) True if OR REPLACE, false for normal
- * @return 0 success
- * @return -1 create function failed
- * @return -4 set comment failed
- */
- function createFunction($funcname, $args, $returns, $definition, $language, $flags, $setof, $cost, $rows, $comment, $replace = false) {
-
- // Begin a transaction
- $status = $this->beginTransaction();
- if ($status != 0) {
- $this->rollbackTransaction();
- return -1;
- }
-
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($funcname);
- $this->clean($args);
- $this->fieldClean($language);
- $this->arrayClean($flags);
-
- $sql = "CREATE";
- if ($replace) {
- $sql .= " OR REPLACE";
- }
-
- $sql .= " FUNCTION \"{$f_schema}\".\"{$funcname}\" (";
-
- if ($args != '') {
- $sql .= $args;
- }
-
- // For some reason, the returns field cannot have quotes...
- $sql .= ") RETURNS ";
- if ($setof) {
- $sql .= "SETOF ";
- }
-
- $sql .= "{$returns} AS ";
-
- if (is_array($definition)) {
- $this->arrayClean($definition);
- $sql .= "'" . $definition[0] . "'";
- if ($definition[1]) {
- $sql .= ",'" . $definition[1] . "'";
- }
- } else {
- $this->clean($definition);
- $sql .= "'" . $definition . "'";
- }
-
- $sql .= " LANGUAGE \"{$language}\"";
-
- // Add flags
- foreach ($flags as $v) {
- // Skip default flags
- if ($v == '') {
- continue;
- } else {
- $sql .= "\n{$v}";
- }
-
- }
-
- $status = $this->execute($sql);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -3;
- }
-
- /* set the comment */
- $status = $this->setComment('FUNCTION', "\"{$funcname}\"({$args})", null, $comment);
- if ($status != 0) {
- $this->rollbackTransaction();
- return -4;
- }
-
- return $this->endTransaction();
- }
-
- // Index functions
-
- /**
- * Clusters an index
- * @param $index The name of the index
- * @param $table The table the index is on
- * @return 0 success
- */
- function clusterIndex($table = '', $index = '') {
-
- $sql = 'CLUSTER';
-
- // We don't bother with a transaction here, as there's no point rolling
- // back an expensive cluster if a cheap analyze fails for whatever reason
-
- if (!empty($table)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $this->fieldClean($table);
-
- if (!empty($index)) {
- $this->fieldClean($index);
- $sql .= " \"{$index}\" ON \"{$f_schema}\".\"{$table}\"";
- } else {
- $sql .= " \"{$f_schema}\".\"{$table}\"";
- }
- }
-
- return $this->execute($sql);
- }
-
- // Operator functions
-
- /**
- * Returns all details for a particular operator
- * @param $operator_oid The oid of the operator
- * @return Function info
- */
- function getOperator($operator_oid) {
- $this->clean($operator_oid);
-
- $sql = "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a new function.
+ * @param $funcname The name of the function to create
+ * @param $args A comma separated string of types
+ * @param $returns The return type
+ * @param $definition The definition for the new function
+ * @param $language The language the function is written for
+ * @param $flags An array of optional flags
+ * @param $setof True if it returns a set, false otherwise
+ * @param $rows number of rows planner should estimate will be returned
+ * @param $cost cost the planner should use in the function execution step
+ * @param $comment The comment on the function
+ * @param $replace (optional) True if OR REPLACE, false for normal
+ * @return 0 success
+ * @return -1 create function failed
+ * @return -4 set comment failed
+ */
+ public function createFunction($funcname, $args, $returns, $definition, $language, $flags, $setof, $cost, $rows, $comment, $replace = false)
+ {
+
+ // Begin a transaction
+ $status = $this->beginTransaction();
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -1;
+ }
+
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($funcname);
+ $this->clean($args);
+ $this->fieldClean($language);
+ $this->arrayClean($flags);
+
+ $sql = "CREATE";
+ if ($replace) {
+ $sql .= " OR REPLACE";
+ }
+
+ $sql .= " FUNCTION \"{$f_schema}\".\"{$funcname}\" (";
+
+ if ($args != '') {
+ $sql .= $args;
+ }
+
+ // For some reason, the returns field cannot have quotes...
+ $sql .= ") RETURNS ";
+ if ($setof) {
+ $sql .= "SETOF ";
+ }
+
+ $sql .= "{$returns} AS ";
+
+ if (is_array($definition)) {
+ $this->arrayClean($definition);
+ $sql .= "'" . $definition[0] . "'";
+ if ($definition[1]) {
+ $sql .= ",'" . $definition[1] . "'";
+ }
+ } else {
+ $this->clean($definition);
+ $sql .= "'" . $definition . "'";
+ }
+
+ $sql .= " LANGUAGE \"{$language}\"";
+
+ // Add flags
+ foreach ($flags as $v) {
+ // Skip default flags
+ if ($v == '') {
+ continue;
+ } else {
+ $sql .= "\n{$v}";
+ }
+
+ }
+
+ $status = $this->execute($sql);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -3;
+ }
+
+ /* set the comment */
+ $status = $this->setComment('FUNCTION', "\"{$funcname}\"({$args})", null, $comment);
+ if ($status != 0) {
+ $this->rollbackTransaction();
+ return -4;
+ }
+
+ return $this->endTransaction();
+ }
+
+ // Index functions
+
+ /**
+ * Clusters an index
+ * @param $index The name of the index
+ * @param $table The table the index is on
+ * @return 0 success
+ */
+ public function clusterIndex($table = '', $index = '')
+ {
+
+ $sql = 'CLUSTER';
+
+ // We don't bother with a transaction here, as there's no point rolling
+ // back an expensive cluster if a cheap analyze fails for whatever reason
+
+ if (!empty($table)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->fieldClean($table);
+
+ if (!empty($index)) {
+ $this->fieldClean($index);
+ $sql .= " \"{$index}\" ON \"{$f_schema}\".\"{$table}\"";
+ } else {
+ $sql .= " \"{$f_schema}\".\"{$table}\"";
+ }
+ }
+
+ return $this->execute($sql);
+ }
+
+ // Operator functions
+
+ /**
+ * Returns all details for a particular operator
+ * @param $operator_oid The oid of the operator
+ * @return Function info
+ */
+ public function getOperator($operator_oid)
+ {
+ $this->clean($operator_oid);
+
+ $sql = "
SELECT
po.oid, po.oprname,
oprleft::pg_catalog.regtype AS oprleftname,
@@ -319,19 +322,20 @@ class Postgres82 extends Postgres83 {
po.oid='{$operator_oid}'
";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Operator Class functions
+ // Operator Class functions
- /**
- * Gets all opclasses
- * @return A recordset
- */
- function getOpClasses() {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $sql = "
+ /**
+ * Gets all opclasses
+ * @return A recordset
+ */
+ public function getOpClasses()
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $sql = "
SELECT
pa.amname,
po.opcname,
@@ -347,16 +351,27 @@ class Postgres82 extends Postgres83 {
ORDER BY 1,2
";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
+
+ // Capabilities
+
+ public function hasCreateTableLikeWithIndexes()
+ {return false;}
+
+ public function hasEnumTypes()
+ {return false;}
+
+ public function hasFTS()
+ {return false;}
+
+ public function hasFunctionCosting()
+ {return false;}
- // Capabilities
+ public function hasFunctionGUC()
+ {return false;}
- function hasCreateTableLikeWithIndexes() {return false;}
- function hasEnumTypes() {return false;}
- function hasFTS() {return false;}
- function hasFunctionCosting() {return false;}
- function hasFunctionGUC() {return false;}
- function hasVirtualTransactionId() {return false;}
+ public function hasVirtualTransactionId()
+ {return false;}
}
diff --git a/src/database/Postgres83.php b/src/database/Postgres83.php
index 199dccc4..6bdfd7ec 100644
--- a/src/database/Postgres83.php
+++ b/src/database/Postgres83.php
@@ -1,85 +1,81 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 8.3 support
*
* $Id: Postgres82.php,v 1.10 2007/12/28 16:21:25 ioguix Exp $
*/
-class Postgres83 extends Postgres84 {
-
- var $major_version = 8.3;
-
- // List of all legal privileges that can be applied to different types
- // of objects.
- var $privlist = [
- 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
- 'database' => ['CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'],
- 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
- 'language' => ['USAGE', 'ALL PRIVILEGES'],
- 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
- 'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
- ];
- // List of characters in acl lists and the privileges they
- // refer to.
- var $privmap = [
- 'r' => 'SELECT',
- 'w' => 'UPDATE',
- 'a' => 'INSERT',
- 'd' => 'DELETE',
- 'R' => 'RULE',
- 'x' => 'REFERENCES',
- 't' => 'TRIGGER',
- 'X' => 'EXECUTE',
- 'U' => 'USAGE',
- 'C' => 'CREATE',
- 'T' => 'TEMPORARY',
- 'c' => 'CONNECT',
- ];
-
- // Help functions
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc83.php';
- return $this->help_page;
- }
-
- // Databse functions
-
- /**
- * Return all database available on the server
- * @param $currentdatabase database name that should be on top of the resultset
- *
- * @return A list of databases, sorted alphabetically
- */
- function getDatabases($currentdatabase = NULL) {
- $conf = $this->conf;
- $server_info = $this->server_info;
-
- if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
- $username = $server_info['username'];
- $this->clean($username);
- $clause = " AND pr.rolname='{$username}'";
- } else {
- $clause = '';
- }
-
- if ($currentdatabase != NULL) {
- $this->clean($currentdatabase);
- $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
- } else {
- $orderby = "ORDER BY pdb.datname";
- }
-
- if (!$conf['show_system']) {
- $where = ' AND NOT pdb.datistemplate';
- } else {
- $where = ' AND pdb.datallowconn';
- }
-
- $sql = "
+class Postgres83 extends Postgres84
+{
+
+ public $major_version = 8.3;
+
+ // List of all legal privileges that can be applied to different types
+ // of objects.
+ public $privlist = [
+ 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
+ 'database' => ['CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'],
+ 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
+ 'language' => ['USAGE', 'ALL PRIVILEGES'],
+ 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
+ 'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
+ ];
+ // List of characters in acl lists and the privileges they
+ // refer to.
+ public $privmap = [
+ 'r' => 'SELECT',
+ 'w' => 'UPDATE',
+ 'a' => 'INSERT',
+ 'd' => 'DELETE',
+ 'R' => 'RULE',
+ 'x' => 'REFERENCES',
+ 't' => 'TRIGGER',
+ 'X' => 'EXECUTE',
+ 'U' => 'USAGE',
+ 'C' => 'CREATE',
+ 'T' => 'TEMPORARY',
+ 'c' => 'CONNECT',
+ ];
+
+ // Databse functions
+
+ /**
+ * Return all database available on the server
+ * @param $currentdatabase database name that should be on top of the resultset
+ *
+ * @return A list of databases, sorted alphabetically
+ */
+ public function getDatabases($currentdatabase = null)
+ {
+ $conf = $this->conf;
+ $server_info = $this->server_info;
+
+ if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser()) {
+ $username = $server_info['username'];
+ $this->clean($username);
+ $clause = " AND pr.rolname='{$username}'";
+ } else {
+ $clause = '';
+ }
+
+ if ($currentdatabase != null) {
+ $this->clean($currentdatabase);
+ $orderby = "ORDER BY pdb.datname = '{$currentdatabase}' DESC, pdb.datname";
+ } else {
+ $orderby = "ORDER BY pdb.datname";
+ }
+
+ if (!$conf['show_system']) {
+ $where = ' AND NOT pdb.datistemplate';
+ } else {
+ $where = ' AND pdb.datallowconn';
+ }
+
+ $sql = "
SELECT pdb.datname AS datname, pr.rolname AS datowner, pg_encoding_to_char(encoding) AS datencoding,
(SELECT description FROM pg_catalog.pg_shdescription pd WHERE pdb.oid=pd.objoid AND pd.classoid='pg_database'::regclass) AS datcomment,
(SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=pdb.dattablespace) AS tablespace,
@@ -90,24 +86,25 @@ class Postgres83 extends Postgres84 {
{$clause}
{$orderby}";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Administration functions
+ // Administration functions
- /**
- * Returns all available autovacuum per table information.
- * @return A recordset
- */
- function getTableAutovacuum($table = '') {
- $sql = '';
+ /**
+ * Returns all available autovacuum per table information.
+ * @return A recordset
+ */
+ public function getTableAutovacuum($table = '')
+ {
+ $sql = '';
- if ($table !== '') {
- $this->clean($table);
- $c_schema = $this->_schema;
- $this->clean($c_schema);
+ if ($table !== '') {
+ $this->clean($table);
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
- $sql = "
+ $sql = "
SELECT vacrelid, nspname, relname,
CASE enabled
WHEN 't' THEN 'on'
@@ -122,8 +119,8 @@ class Postgres83 extends Postgres84 {
WHERE c.relname = '{$table}' AND n.nspname = '{$c_schema}'
ORDER BY nspname, relname
";
- } else {
- $sql = "
+ } else {
+ $sql = "
SELECT vacrelid, nspname, relname,
CASE enabled
WHEN 't' THEN 'on'
@@ -137,19 +134,19 @@ class Postgres83 extends Postgres84 {
join pg_namespace AS n on (n.oid=c.relnamespace)
ORDER BY nspname, relname
";
- }
+ }
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- function saveAutovacuum($table, $vacenabled, $vacthreshold, $vacscalefactor, $anathresold,
- $anascalefactor, $vaccostdelay, $vaccostlimit) {
- $defaults = $this->getAutovacuum();
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
+ public function saveAutovacuum($table, $vacenabled, $vacthreshold, $vacscalefactor, $anathresold,
+ $anascalefactor, $vaccostdelay, $vaccostlimit) {
+ $defaults = $this->getAutovacuum();
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
- $rs = $this->selectSet("
+ $rs = $this->selectSet("
SELECT c.oid
FROM pg_catalog.pg_class AS c
LEFT JOIN pg_catalog.pg_namespace AS n ON (n.oid=c.relnamespace)
@@ -157,53 +154,53 @@ class Postgres83 extends Postgres84 {
c.relname = '{$table}' AND n.nspname = '{$c_schema}'
");
- if ($rs->EOF) {
- return -1;
- }
+ if ($rs->EOF) {
+ return -1;
+ }
- $toid = $rs->fields('oid');
- unset($rs);
+ $toid = $rs->fields('oid');
+ unset($rs);
- if (empty($_POST['autovacuum_vacuum_threshold'])) {
- $_POST['autovacuum_vacuum_threshold'] = $defaults['autovacuum_vacuum_threshold'];
- }
+ if (empty($_POST['autovacuum_vacuum_threshold'])) {
+ $_POST['autovacuum_vacuum_threshold'] = $defaults['autovacuum_vacuum_threshold'];
+ }
- if (empty($_POST['autovacuum_vacuum_scale_factor'])) {
- $_POST['autovacuum_vacuum_scale_factor'] = $defaults['autovacuum_vacuum_scale_factor'];
- }
+ if (empty($_POST['autovacuum_vacuum_scale_factor'])) {
+ $_POST['autovacuum_vacuum_scale_factor'] = $defaults['autovacuum_vacuum_scale_factor'];
+ }
- if (empty($_POST['autovacuum_analyze_threshold'])) {
- $_POST['autovacuum_analyze_threshold'] = $defaults['autovacuum_analyze_threshold'];
- }
+ if (empty($_POST['autovacuum_analyze_threshold'])) {
+ $_POST['autovacuum_analyze_threshold'] = $defaults['autovacuum_analyze_threshold'];
+ }
- if (empty($_POST['autovacuum_analyze_scale_factor'])) {
- $_POST['autovacuum_analyze_scale_factor'] = $defaults['autovacuum_analyze_scale_factor'];
- }
+ if (empty($_POST['autovacuum_analyze_scale_factor'])) {
+ $_POST['autovacuum_analyze_scale_factor'] = $defaults['autovacuum_analyze_scale_factor'];
+ }
- if (empty($_POST['autovacuum_vacuum_cost_delay'])) {
- $_POST['autovacuum_vacuum_cost_delay'] = $defaults['autovacuum_vacuum_cost_delay'];
- }
+ if (empty($_POST['autovacuum_vacuum_cost_delay'])) {
+ $_POST['autovacuum_vacuum_cost_delay'] = $defaults['autovacuum_vacuum_cost_delay'];
+ }
- if (empty($_POST['autovacuum_vacuum_cost_limit'])) {
- $_POST['autovacuum_vacuum_cost_limit'] = $defaults['autovacuum_vacuum_cost_limit'];
- }
+ if (empty($_POST['autovacuum_vacuum_cost_limit'])) {
+ $_POST['autovacuum_vacuum_cost_limit'] = $defaults['autovacuum_vacuum_cost_limit'];
+ }
- if (empty($_POST['vacuum_freeze_min_age'])) {
- $_POST['vacuum_freeze_min_age'] = $defaults['vacuum_freeze_min_age'];
- }
+ if (empty($_POST['vacuum_freeze_min_age'])) {
+ $_POST['vacuum_freeze_min_age'] = $defaults['vacuum_freeze_min_age'];
+ }
- if (empty($_POST['autovacuum_freeze_max_age'])) {
- $_POST['autovacuum_freeze_max_age'] = $defaults['autovacuum_freeze_max_age'];
- }
+ if (empty($_POST['autovacuum_freeze_max_age'])) {
+ $_POST['autovacuum_freeze_max_age'] = $defaults['autovacuum_freeze_max_age'];
+ }
- $rs = $this->selectSet("SELECT vacrelid
+ $rs = $this->selectSet("SELECT vacrelid
FROM \"pg_catalog\".\"pg_autovacuum\"
WHERE vacrelid = {$toid};");
- $status = -1; // ini
- if ($rs->recordCount() and ($rs->fields['vacrelid'] == $toid)) {
- // table exists in pg_autovacuum, UPDATE
- $sql = sprintf("UPDATE \"pg_catalog\".\"pg_autovacuum\" SET
+ $status = -1; // ini
+ if ($rs->recordCount() and ($rs->fields['vacrelid'] == $toid)) {
+ // table exists in pg_autovacuum, UPDATE
+ $sql = sprintf("UPDATE \"pg_catalog\".\"pg_autovacuum\" SET
enabled = '%s',
vac_base_thresh = %s,
vac_scale_factor = %s,
@@ -215,44 +212,45 @@ class Postgres83 extends Postgres84 {
freeze_max_age = %s
WHERE vacrelid = {$toid};
",
- ($_POST['autovacuum_enabled'] == 'on') ? 't' : 'f',
- $_POST['autovacuum_vacuum_threshold'],
- $_POST['autovacuum_vacuum_scale_factor'],
- $_POST['autovacuum_analyze_threshold'],
- $_POST['autovacuum_analyze_scale_factor'],
- $_POST['autovacuum_vacuum_cost_delay'],
- $_POST['autovacuum_vacuum_cost_limit'],
- $_POST['vacuum_freeze_min_age'],
- $_POST['autovacuum_freeze_max_age']
- );
- $status = $this->execute($sql);
- } else {
- // table doesn't exists in pg_autovacuum, INSERT
- $sql = sprintf("INSERT INTO \"pg_catalog\".\"pg_autovacuum\"
+ ($_POST['autovacuum_enabled'] == 'on') ? 't' : 'f',
+ $_POST['autovacuum_vacuum_threshold'],
+ $_POST['autovacuum_vacuum_scale_factor'],
+ $_POST['autovacuum_analyze_threshold'],
+ $_POST['autovacuum_analyze_scale_factor'],
+ $_POST['autovacuum_vacuum_cost_delay'],
+ $_POST['autovacuum_vacuum_cost_limit'],
+ $_POST['vacuum_freeze_min_age'],
+ $_POST['autovacuum_freeze_max_age']
+ );
+ $status = $this->execute($sql);
+ } else {
+ // table doesn't exists in pg_autovacuum, INSERT
+ $sql = sprintf("INSERT INTO \"pg_catalog\".\"pg_autovacuum\"
VALUES (%s, '%s', %s, %s, %s, %s, %s, %s, %s, %s )",
- $toid,
- ($_POST['autovacuum_enabled'] == 'on') ? 't' : 'f',
- $_POST['autovacuum_vacuum_threshold'],
- $_POST['autovacuum_vacuum_scale_factor'],
- $_POST['autovacuum_analyze_threshold'],
- $_POST['autovacuum_analyze_scale_factor'],
- $_POST['autovacuum_vacuum_cost_delay'],
- $_POST['autovacuum_vacuum_cost_limit'],
- $_POST['vacuum_freeze_min_age'],
- $_POST['autovacuum_freeze_max_age']
- );
- $status = $this->execute($sql);
- }
-
- return $status;
- }
-
- function dropAutovacuum($table) {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $rs = $this->selectSet("
+ $toid,
+ ($_POST['autovacuum_enabled'] == 'on') ? 't' : 'f',
+ $_POST['autovacuum_vacuum_threshold'],
+ $_POST['autovacuum_vacuum_scale_factor'],
+ $_POST['autovacuum_analyze_threshold'],
+ $_POST['autovacuum_analyze_scale_factor'],
+ $_POST['autovacuum_vacuum_cost_delay'],
+ $_POST['autovacuum_vacuum_cost_limit'],
+ $_POST['vacuum_freeze_min_age'],
+ $_POST['autovacuum_freeze_max_age']
+ );
+ $status = $this->execute($sql);
+ }
+
+ return $status;
+ }
+
+ public function dropAutovacuum($table)
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $rs = $this->selectSet("
SELECT c.oid
FROM pg_catalog.pg_class AS c
LEFT JOIN pg_catalog.pg_namespace AS n ON (n.oid=c.relnamespace)
@@ -260,93 +258,95 @@ class Postgres83 extends Postgres84 {
c.relname = '{$table}' AND n.nspname = '{$c_schema}'
");
- return $this->deleteRow('pg_autovacuum', ['vacrelid' => $rs->fields['oid']], 'pg_catalog');
- }
-
- // Sequence functions
-
- /**
- * Alter a sequence's properties
- * @param $seqrs The sequence RecordSet returned by getSequence()
- * @param $increment The sequence incremental value
- * @param $minvalue The sequence minimum value
- * @param $maxvalue The sequence maximum value
- * @param $restartvalue The sequence current value
- * @param $cachevalue The sequence cache value
- * @param $cycledvalue Sequence can cycle ?
- * @param $startvalue The sequence start value when issueing a restart (ignored)
- * @return 0 success
- */
- function alterSequenceProps($seqrs, $increment, $minvalue, $maxvalue,
- $restartvalue, $cachevalue, $cycledvalue, $startvalue) {
-
- $sql = '';
- /* vars are cleaned in _alterSequence */
- if (!empty($increment) && ($increment != $seqrs->fields['increment_by'])) {
- $sql .= " INCREMENT {$increment}";
- }
-
- if (!empty($minvalue) && ($minvalue != $seqrs->fields['min_value'])) {
- $sql .= " MINVALUE {$minvalue}";
- }
-
- if (!empty($maxvalue) && ($maxvalue != $seqrs->fields['max_value'])) {
- $sql .= " MAXVALUE {$maxvalue}";
- }
-
- if (!empty($restartvalue) && ($restartvalue != $seqrs->fields['last_value'])) {
- $sql .= " RESTART {$restartvalue}";
- }
-
- if (!empty($cachevalue) && ($cachevalue != $seqrs->fields['cache_value'])) {
- $sql .= " CACHE {$cachevalue}";
- }
-
- // toggle cycle yes/no
- if (!is_null($cycledvalue)) {
- $sql .= (!$cycledvalue ? ' NO ' : '') . " CYCLE";
- }
-
- if ($sql != '') {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" {$sql}";
- return $this->execute($sql);
- }
- return 0;
- }
-
- /**
- * Alter a sequence's owner
- * @param $seqrs The sequence RecordSet returned by getSequence()
- * @param $name The new owner for the sequence
- * @return 0 success
- */
- function alterSequenceOwner($seqrs, $owner) {
- // If owner has been changed, then do the alteration. We are
- // careful to avoid this generally as changing owner is a
- // superuser only function.
- /* vars are cleaned in _alterSequence */
- if (!empty($owner) && ($seqrs->fields['seqowner'] != $owner)) {
- $f_schema = $this->_schema;
- $this->fieldClean($f_schema);
- $sql = "ALTER TABLE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" OWNER TO \"{$owner}\"";
- return $this->execute($sql);
- }
- return 0;
- }
-
- // Function functions
-
- /**
- * Returns all details for a particular function
- * @param $func The name of the function to retrieve
- * @return Function info
- */
- function getFunction($function_oid) {
- $this->clean($function_oid);
-
- $sql = "
+ return $this->deleteRow('pg_autovacuum', ['vacrelid' => $rs->fields['oid']], 'pg_catalog');
+ }
+
+ // Sequence functions
+
+ /**
+ * Alter a sequence's properties
+ * @param $seqrs The sequence RecordSet returned by getSequence()
+ * @param $increment The sequence incremental value
+ * @param $minvalue The sequence minimum value
+ * @param $maxvalue The sequence maximum value
+ * @param $restartvalue The sequence current value
+ * @param $cachevalue The sequence cache value
+ * @param $cycledvalue Sequence can cycle ?
+ * @param $startvalue The sequence start value when issueing a restart (ignored)
+ * @return 0 success
+ */
+ public function alterSequenceProps($seqrs, $increment, $minvalue, $maxvalue,
+ $restartvalue, $cachevalue, $cycledvalue, $startvalue) {
+
+ $sql = '';
+ /* vars are cleaned in _alterSequence */
+ if (!empty($increment) && ($increment != $seqrs->fields['increment_by'])) {
+ $sql .= " INCREMENT {$increment}";
+ }
+
+ if (!empty($minvalue) && ($minvalue != $seqrs->fields['min_value'])) {
+ $sql .= " MINVALUE {$minvalue}";
+ }
+
+ if (!empty($maxvalue) && ($maxvalue != $seqrs->fields['max_value'])) {
+ $sql .= " MAXVALUE {$maxvalue}";
+ }
+
+ if (!empty($restartvalue) && ($restartvalue != $seqrs->fields['last_value'])) {
+ $sql .= " RESTART {$restartvalue}";
+ }
+
+ if (!empty($cachevalue) && ($cachevalue != $seqrs->fields['cache_value'])) {
+ $sql .= " CACHE {$cachevalue}";
+ }
+
+ // toggle cycle yes/no
+ if (!is_null($cycledvalue)) {
+ $sql .= (!$cycledvalue ? ' NO ' : '') . " CYCLE";
+ }
+
+ if ($sql != '') {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER SEQUENCE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" {$sql}";
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ /**
+ * Alter a sequence's owner
+ * @param $seqrs The sequence RecordSet returned by getSequence()
+ * @param $name The new owner for the sequence
+ * @return 0 success
+ */
+ public function alterSequenceOwner($seqrs, $owner)
+ {
+ // If owner has been changed, then do the alteration. We are
+ // careful to avoid this generally as changing owner is a
+ // superuser only function.
+ /* vars are cleaned in _alterSequence */
+ if (!empty($owner) && ($seqrs->fields['seqowner'] != $owner)) {
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $sql = "ALTER TABLE \"{$f_schema}\".\"{$seqrs->fields['seqname']}\" OWNER TO \"{$owner}\"";
+ return $this->execute($sql);
+ }
+ return 0;
+ }
+
+ // Function functions
+
+ /**
+ * Returns all details for a particular function
+ * @param $func The name of the function to retrieve
+ * @return Function info
+ */
+ public function getFunction($function_oid)
+ {
+ $this->clean($function_oid);
+
+ $sql = "
SELECT
pc.oid AS prooid, proname, pg_catalog.pg_get_userbyid(proowner) AS proowner,
nspname as proschema, lanname as prolanguage, procost, prorows,
@@ -364,11 +364,16 @@ class Postgres83 extends Postgres84 {
AND pc.pronamespace = pn.oid
";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
+
+ // Capabilities
+ public function hasQueryKill()
+ {return false;}
+
+ public function hasDatabaseCollation()
+ {return false;}
- // Capabilities
- function hasQueryKill() {return false;}
- function hasDatabaseCollation() {return false;}
- function hasAlterSequenceStart() {return false;}
+ public function hasAlterSequenceStart()
+ {return false;}
}
diff --git a/src/database/Postgres84.php b/src/database/Postgres84.php
index 82c80513..defe0f5a 100644
--- a/src/database/Postgres84.php
+++ b/src/database/Postgres84.php
@@ -1,49 +1,45 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 8.4 support
*
* $Id: Postgres82.php,v 1.10 2007/12/28 16:21:25 ioguix Exp $
*/
-class Postgres84 extends Postgres90 {
-
- var $major_version = 8.4;
-
- // List of all legal privileges that can be applied to different types
- // of objects.
- var $privlist = [
- 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
- 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
- 'database' => ['CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'],
- 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
- 'language' => ['USAGE', 'ALL PRIVILEGES'],
- 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
- 'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
- 'column' => ['SELECT', 'INSERT', 'UPDATE', 'REFERENCES', 'ALL PRIVILEGES'],
- ];
-
- // Help functions
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc84.php';
- return $this->help_page;
- }
-
- // Database functions
-
- /**
- * Grabs a list of triggers on a table
- * @param $table The name of a table whose triggers to retrieve
- * @return A recordset
- */
- function getTriggers($table = '') {
- $c_schema = $this->_schema;
- $this->clean($c_schema);
- $this->clean($table);
-
- $sql = "SELECT
+class Postgres84 extends Postgres90
+{
+
+ public $major_version = 8.4;
+
+ // List of all legal privileges that can be applied to different types
+ // of objects.
+ public $privlist = [
+ 'table' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'view' => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'],
+ 'sequence' => ['SELECT', 'UPDATE', 'ALL PRIVILEGES'],
+ 'database' => ['CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'],
+ 'function' => ['EXECUTE', 'ALL PRIVILEGES'],
+ 'language' => ['USAGE', 'ALL PRIVILEGES'],
+ 'schema' => ['CREATE', 'USAGE', 'ALL PRIVILEGES'],
+ 'tablespace' => ['CREATE', 'ALL PRIVILEGES'],
+ 'column' => ['SELECT', 'INSERT', 'UPDATE', 'REFERENCES', 'ALL PRIVILEGES'],
+ ];
+
+ // Database functions
+
+ /**
+ * Grabs a list of triggers on a table
+ * @param $table The name of a table whose triggers to retrieve
+ * @return A recordset
+ */
+ public function getTriggers($table = '')
+ {
+ $c_schema = $this->_schema;
+ $this->clean($c_schema);
+ $this->clean($table);
+
+ $sql = "SELECT
t.tgname, pg_catalog.pg_get_triggerdef(t.oid) AS tgdef,
CASE WHEN t.tgenabled = 'D' THEN FALSE ELSE TRUE END AS tgenabled, p.oid AS prooid,
p.proname || ' (' || pg_catalog.oidvectortypes(p.proargtypes) || ')' AS proproto,
@@ -58,52 +54,53 @@ class Postgres84 extends Postgres90 {
AND p.oid=t.tgfoid
AND p.pronamespace = ns.oid";
- return $this->selectSet($sql);
- }
-
- /**
- * Searches all system catalogs to find objects that match a certain name.
- * @param $term The search term
- * @param $filter The object type to restrict to ('' means no restriction)
- * @return A recordset
- */
- function findObject($term, $filter) {
- $conf = $this->conf;
-
- /*about escaping:
- * SET standard_conforming_string is not available before 8.2
- * So we must use PostgreSQL specific notation :/
- * E'' notation is not available before 8.1
- * $$ is available since 8.0
- * Nothing specific from 7.4
- */
-
- // Escape search term for ILIKE match
- $this->clean($term);
- $this->clean($filter);
- $term = str_replace('_', '\_', $term);
- $term = str_replace('%', '\%', $term);
-
- // Exclude system relations if necessary
- if (!$conf['show_system']) {
- // XXX: The mention of information_schema here is in the wrong place, but
- // it's the quickest fix to exclude the info schema from 7.4
- $where = " AND pn.nspname NOT LIKE \$_PATERN_\$pg\_%\$_PATERN_\$ AND pn.nspname != 'information_schema'";
- $lan_where = "AND pl.lanispl";
- } else {
- $where = '';
- $lan_where = '';
- }
-
- // Apply outer filter
- $sql = '';
- if ($filter != '') {
- $sql = "SELECT * FROM (";
- }
-
- $term = "\$_PATERN_\$%{$term}%\$_PATERN_\$";
-
- $sql .= "
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Searches all system catalogs to find objects that match a certain name.
+ * @param $term The search term
+ * @param $filter The object type to restrict to ('' means no restriction)
+ * @return A recordset
+ */
+ public function findObject($term, $filter)
+ {
+ $conf = $this->conf;
+
+ /*about escaping:
+ * SET standard_conforming_string is not available before 8.2
+ * So we must use PostgreSQL specific notation :/
+ * E'' notation is not available before 8.1
+ * $$ is available since 8.0
+ * Nothing specific from 7.4
+ */
+
+ // Escape search term for ILIKE match
+ $this->clean($term);
+ $this->clean($filter);
+ $term = str_replace('_', '\_', $term);
+ $term = str_replace('%', '\%', $term);
+
+ // Exclude system relations if necessary
+ if (!$conf['show_system']) {
+ // XXX: The mention of information_schema here is in the wrong place, but
+ // it's the quickest fix to exclude the info schema from 7.4
+ $where = " AND pn.nspname NOT LIKE \$_PATERN_\$pg\_%\$_PATERN_\$ AND pn.nspname != 'information_schema'";
+ $lan_where = "AND pl.lanispl";
+ } else {
+ $where = '';
+ $lan_where = '';
+ }
+
+ // Apply outer filter
+ $sql = '';
+ if ($filter != '') {
+ $sql = "SELECT * FROM (";
+ }
+
+ $term = "\$_PATERN_\$%{$term}%\$_PATERN_\$";
+
+ $sql .= "
SELECT 'SCHEMA' AS type, oid, NULL AS schemaname, NULL AS relname, nspname AS name
FROM pg_catalog.pg_namespace pn WHERE nspname ILIKE {$term} {$where}
UNION ALL
@@ -160,9 +157,9 @@ class Postgres84 extends Postgres90 {
WHERE c.relkind='v' AND r.rulename != '_RETURN' AND r.rulename ILIKE {$term} {$where}
";
- // Add advanced objects if show_advanced is set
- if ($conf['show_advanced']) {
- $sql .= "
+ // Add advanced objects if show_advanced is set
+ if ($conf['show_advanced']) {
+ $sql .= "
UNION ALL
SELECT CASE WHEN pt.typtype='d' THEN 'DOMAIN' ELSE 'TYPE' END, pt.oid, pn.nspname, NULL,
pt.typname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn
@@ -187,10 +184,10 @@ class Postgres84 extends Postgres90 {
pg_catalog.pg_namespace pn WHERE po.opcnamespace=pn.oid
AND po.opcname ILIKE {$term} {$where}
";
- }
- // Otherwise just add domains
- else {
- $sql .= "
+ }
+ // Otherwise just add domains
+ else {
+ $sql .= "
UNION ALL
SELECT 'DOMAIN', pt.oid, pn.nspname, NULL,
pt.typname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn
@@ -198,20 +195,21 @@ class Postgres84 extends Postgres90 {
AND (pt.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = pt.typrelid))
{$where}
";
- }
+ }
- if ($filter != '') {
- // We use like to make RULE, CONSTRAINT and COLUMN searches work
- $sql .= ") AS sub WHERE type LIKE '{$filter}%' ";
- }
+ if ($filter != '') {
+ // We use like to make RULE, CONSTRAINT and COLUMN searches work
+ $sql .= ") AS sub WHERE type LIKE '{$filter}%' ";
+ }
- $sql .= "ORDER BY type, schemaname, relname, name";
+ $sql .= "ORDER BY type, schemaname, relname, name";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Capabilities
+ // Capabilities
- function hasByteaHexDefault() {return false;}
+ public function hasByteaHexDefault()
+ {return false;}
}
diff --git a/src/database/Postgres90.php b/src/database/Postgres90.php
index ee6b6586..8777198d 100644
--- a/src/database/Postgres90.php
+++ b/src/database/Postgres90.php
@@ -1,22 +1,15 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 9.0 support
*
* $Id: Postgres82.php,v 1.10 2007/12/28 16:21:25 ioguix Exp $
*/
-class Postgres90 extends Postgres91 {
-
- var $major_version = 9.0;
-
- // Help functions
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc90.php';
- return $this->help_page;
- }
+class Postgres90 extends Postgres91
+{
- // Capabilities
+ public $major_version = 9.0;
}
diff --git a/src/database/Postgres91.php b/src/database/Postgres91.php
index 3e44a28f..2b108bd7 100644
--- a/src/database/Postgres91.php
+++ b/src/database/Postgres91.php
@@ -1,84 +1,83 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 9.1 support
*
* $Id: Postgres82.php,v 1.10 2007/12/28 16:21:25 ioguix Exp $
*/
-class Postgres91 extends Postgres92 {
-
- var $major_version = 9.1;
-
- // Help functions
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc91.php';
- return $this->help_page;
- }
-
- // Administration functions
- /**
- * Returns all available process information.
- * @param $database (optional) Find only connections to specified database
- * @return A recordset
- */
- function getProcesses($database = null) {
- if ($database === null) {
- $sql = "SELECT datname, usename, procpid AS pid, waiting, current_query AS query, query_start
+class Postgres91 extends Postgres92
+{
+
+ public $major_version = 9.1;
+
+ // Administration functions
+ /**
+ * Returns all available process information.
+ * @param $database (optional) Find only connections to specified database
+ * @return A recordset
+ */
+ public function getProcesses($database = null)
+ {
+ if ($database === null) {
+ $sql = "SELECT datname, usename, procpid AS pid, waiting, current_query AS query, query_start
FROM pg_catalog.pg_stat_activity
ORDER BY datname, usename, procpid";
- } else {
- $this->clean($database);
- $sql = "SELECT datname, usename, procpid AS pid, waiting, current_query AS query, query_start
+ } else {
+ $this->clean($database);
+ $sql = "SELECT datname, usename, procpid AS pid, waiting, current_query AS query, query_start
FROM pg_catalog.pg_stat_activity
WHERE datname='{$database}'
ORDER BY usename, procpid";
- }
+ }
- $rc = $this->selectSet($sql);
+ $rc = $this->selectSet($sql);
- return $rc;
- }
+ return $rc;
+ }
- // Tablespace functions
+ // Tablespace functions
- /**
- * Retrieves information for all tablespaces
- * @param $all Include all tablespaces (necessary when moving objects back to the default space)
- * @return A recordset
- */
- function getTablespaces($all = false) {
- $conf = $this->conf;
+ /**
+ * Retrieves information for all tablespaces
+ * @param $all Include all tablespaces (necessary when moving objects back to the default space)
+ * @return A recordset
+ */
+ public function getTablespaces($all = false)
+ {
+ $conf = $this->conf;
- $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation,
+ $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation,
(SELECT description FROM pg_catalog.pg_shdescription pd WHERE pg_tablespace.oid=pd.objoid AND pd.classoid='pg_tablespace'::regclass) AS spccomment
FROM pg_catalog.pg_tablespace";
- if (!$conf['show_system'] && !$all) {
- $sql .= ' WHERE spcname NOT LIKE $$pg\_%$$';
- }
+ if (!$conf['show_system'] && !$all) {
+ $sql .= ' WHERE spcname NOT LIKE $$pg\_%$$';
+ }
- $sql .= " ORDER BY spcname";
+ $sql .= " ORDER BY spcname";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- /**
- * Retrieves a tablespace's information
- * @return A recordset
- */
- function getTablespace($spcname) {
- $this->clean($spcname);
+ /**
+ * Retrieves a tablespace's information
+ * @return A recordset
+ */
+ public function getTablespace($spcname)
+ {
+ $this->clean($spcname);
- $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation,
+ $sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation,
(SELECT description FROM pg_catalog.pg_shdescription pd WHERE pg_tablespace.oid=pd.objoid AND pd.classoid='pg_tablespace'::regclass) AS spccomment
FROM pg_catalog.pg_tablespace WHERE spcname='{$spcname}'";
- return $this->selectSet($sql);
- }
+ return $this->selectSet($sql);
+ }
- // Capabilities
- function hasUserSignals() {return false;}
+ // Capabilities
+ public function hasUserSignals()
+ {return false;}
}
diff --git a/src/database/Postgres92.php b/src/database/Postgres92.php
index c1122cf5..fb53098f 100644
--- a/src/database/Postgres92.php
+++ b/src/database/Postgres92.php
@@ -1,19 +1,14 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 9.2 support
*
*/
-class Postgres92 extends Postgres93 {
-
- var $major_version = 9.2;
-
- // Help functions
+class Postgres92 extends Postgres93
+{
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc92.php';
- return $this->help_page;
- }
+ public $major_version = 9.2;
}
diff --git a/src/database/Postgres93.php b/src/database/Postgres93.php
index 7ec326f8..e1477a13 100644
--- a/src/database/Postgres93.php
+++ b/src/database/Postgres93.php
@@ -1,19 +1,14 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 9.3 support
*
*/
-class Postgres93 extends Postgres {
-
- var $major_version = 9.3;
-
- // Help functions
+class Postgres93 extends Postgres94
+{
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc93.php';
- return $this->help_page;
- }
+ public $major_version = 9.3;
}
diff --git a/src/database/Postgres94.php b/src/database/Postgres94.php
index f1632507..f10fefff 100644
--- a/src/database/Postgres94.php
+++ b/src/database/Postgres94.php
@@ -1,19 +1,14 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 9.4 support
*
*/
-class Postgres94 extends Postgres {
-
- var $major_version = 9.4;
-
- // Help functions
+class Postgres94 extends Postgres95
+{
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc94.php';
- return $this->help_page;
- }
+ public $major_version = 9.4;
}
diff --git a/src/database/Postgres95.php b/src/database/Postgres95.php
index 7b6d242b..30475268 100644
--- a/src/database/Postgres95.php
+++ b/src/database/Postgres95.php
@@ -1,19 +1,14 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 9.5 support
*
*/
-class Postgres95 extends Postgres {
-
- var $major_version = 9.5;
-
- // Help functions
+class Postgres95 extends Postgres96
+{
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc95.php';
- return $this->help_page;
- }
+ public $major_version = 9.5;
}
diff --git a/src/database/Postgres96.php b/src/database/Postgres96.php
index d2c3468a..31a87329 100644
--- a/src/database/Postgres96.php
+++ b/src/database/Postgres96.php
@@ -1,45 +1,40 @@
<?php
namespace PHPPgAdmin\Database;
+
/**
* PostgreSQL 9.5 support
*
*/
-class Postgres96 extends Postgres {
-
- var $major_version = 9.6;
-
- // Help functions
-
- function getHelpPages() {
- include_once BASE_PATH . '/src/help/PostgresDoc96.php';
-
- return $this->help_page;
- }
-
- // Administration functions
- /**
- * Returns all available process information.
- * @param $database (optional) Find only connections to specified database
- * @return A recordset
- */
- function getProcesses($database = null) {
- if ($database === null) {
- $sql = "SELECT datid, datname, pid, usename, application_name, client_addr, state, wait_event_type, wait_event, state_change as query_start,
+class Postgres96 extends Postgres
+{
+
+ public $major_version = 9.6;
+
+ // Administration functions
+ /**
+ * Returns all available process information.
+ * @param $database (optional) Find only connections to specified database
+ * @return A recordset
+ */
+ public function getProcesses($database = null)
+ {
+ if ($database === null) {
+ $sql = "SELECT datid, datname, pid, usename, application_name, client_addr, state, wait_event_type, wait_event, state_change as query_start,
CASE when state='idle in transaction' then ' in transaction' else query end as query
FROM pg_catalog.pg_stat_activity
ORDER BY datname, usename, pid";
- } else {
- $this->clean($database);
- $sql = "SELECT datid, datname, pid, usename, application_name, client_addr, state, wait_event_type, wait_event, state_change as query_start,
+ } else {
+ $this->clean($database);
+ $sql = "SELECT datid, datname, pid, usename, application_name, client_addr, state, wait_event_type, wait_event, state_change as query_start,
CASE when state='idle in transaction' then ' in transaction' else query end as query
FROM pg_catalog.pg_stat_activity
WHERE datname='{$database}'
ORDER BY usename, pid";
- }
+ }
- $rc = $this->selectSet($sql);
+ $rc = $this->selectSet($sql);
- return $rc;
- }
+ return $rc;
+ }
}
diff --git a/src/help/PostgresDoc74.php b/src/help/PostgresDoc74.php
index bfc05f53..134e45c7 100644
--- a/src/help/PostgresDoc74.php
+++ b/src/help/PostgresDoc74.php
@@ -1,155 +1,177 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 7.4 documentation
*/
-
-$this->help_base = sprintf($this->conf['help_base'], strval($this->major_version));
-
-# TODO: Check and fix links
-
-$this->help_page = [
-
- 'pg.database' => 'managing-databases.html',
- 'pg.database.create' => ['sql-createdatabase.html', 'manage-ag-createdb.html'],
- 'pg.database.alter' => 'sql-alterdatabase.html',
- 'pg.database.drop' => ['sql-dropdatabase.html', 'manage-ag-dropdb.html'],
-
- 'pg.admin.analyze' => 'sql-analyze.html',
- 'pg.admin.vacuum' => 'sql-vacuum.html',
-
- 'pg.cast' => ['sql-expressions.html#SQL-SYNTAX-TYPE-CASTS', 'sql-createcast.html'],
- 'pg.cast.create' => 'sql-createcast.html',
- 'pg.cast.drop' => 'sql-dropcast.html',
-
- 'pg.column.add' => ['ddl-alter.html#AEN2115', 'sql-altertable.html'],
- 'pg.column.alter' => ['ddl-alter.html', 'sql-altertable.html'],
- 'pg.column.drop' => ['ddl-alter.html#AEN2124', 'sql-altertable.html'],
-
- 'pg.constraint' => 'ddl-constraints.html',
- 'pg.constraint.add' => 'ddl-alter.html#AEN2131',
- 'pg.constraint.check' => 'ddl-constraints.html#AEN1895',
- 'pg.constraint.drop' => 'ddl-alter.html#AEN2140',
- 'pg.constraint.foreign_key' => 'ddl-constraints.html#DDL-CONSTRAINTS-FK',
- 'pg.constraint.primary_key' => 'ddl-constraints.html#AEN1972',
- 'pg.constraint.unique_key' => 'ddl-constraints.html#AEN1950',
-
- 'pg.conversion' => 'multibyte.html',
- 'pg.conversion.alter' => 'sql-alterconversion.html',
- 'pg.conversion.create' => 'sql-createconversion.html',
- 'pg.conversion.drop' => 'sql-dropconversion.html',
-
- 'pg.domain' => 'extend-type-system.html#AEN28657',
- 'pg.domain.alter' => 'sql-alterdomain.html',
- 'pg.domain.create' => 'sql-createdomain.html',
- 'pg.domain.drop' => 'sql-dropdomain.html',
-
- 'pg.function' => ['xfunc.html', 'functions.html', 'sql-expressions.html#AEN1599'],
- 'pg.function.alter' => 'sql-alterfunction.html',
- 'pg.function.create' => 'sql-createfunction.html',
- 'pg.function.create.c' => ['xfunc-c.html', 'sql-createfunction.html'],
- 'pg.function.create.internal' => ['xfunc-internal.html', 'sql-createfunction.html'],
- 'pg.function.create.pl' => ['xfunc-sql.html', 'xfunc-pl.html', 'sql-createfunction.html'],
- 'pg.function.drop' => 'sql-dropfunction.html',
-
- 'pg.group' => 'groups.html',
- 'pg.group.alter' => ['sql-altergroup.html', 'groups.html'],
- 'pg.group.create' => 'sql-creategroup.html',
- 'pg.group.drop' => 'sql-dropgroup.html',
-
- 'pg.index' => 'indexes.html',
- 'pg.index.cluster' => 'sql-cluster.html',
- 'pg.index.drop' => 'sql-dropindex.html',
- 'pg.index.create' => 'sql-createindex.html',
- 'pg.index.reindex' => 'sql-reindex.html',
-
- 'pg.language' => 'xplang.html',
- 'pg.language.alter' => 'sql-alterlanguage.html',
- 'pg.language.create' => 'sql-createlanguage.html',
- 'pg.language.drop' => 'sql-droplanguage.html',
-
- 'pg.opclass' => 'indexes-opclass.html',
- 'pg.opclass.alter' => 'sql-alteropclass.html',
- 'pg.opclass.create' => 'sql-createopclass.html',
- 'pg.opclass.drop' => 'sql-dropopclass.html',
-
- 'pg.operator' => ['xoper.html', 'functions.html', 'sql-expressions.html#AEN1570'],
- 'pg.operator.alter' => 'sql-alteroperator.html',
- 'pg.operator.create' => 'sql-createoperator.html',
- 'pg.operator.drop' => 'sql-dropoperator.html',
-
- 'pg.pl' => 'xplang.html',
- 'pg.pl.plperl' => 'plperl.html',
- 'pg.pl.plpgsql' => 'plpgsql.html',
- 'pg.pl.plpython' => 'plpython.html',
- 'pg.pl.pltcl' => 'pltcl.html',
-
- 'pg.privilege' => ['privileges.html', 'ddl-priv.html'],
- 'pg.privilege.grant' => 'sql-grant.html',
- 'pg.privilege.revoke' => 'sql-revoke.html',
-
- 'pg.process' => 'monitoring.html',
-
- 'pg.rule' => 'rules.html',
- 'pg.rule.create' => 'sql-createrule.html',
- 'pg.rule.drop' => 'sql-droprule.html',
-
- 'pg.schema' => 'ddl-schemas.html',
- 'pg.schema.alter' => 'sql-alterschema.html',
- 'pg.schema.create' => ['sql-createschema.html', 'ddl-schemas.html#DDL-SCHEMAS-CREATE'],
- 'pg.schema.drop' => 'sql-dropschema.html',
- 'pg.schema.search_path' => 'ddl-schemas.html#DDL-SCHEMAS-PATH',
-
- 'pg.sequence' => 'functions-sequence.html',
- 'pg.sequence.alter' => 'sql-altersequence.html',
- 'pg.sequence.create' => 'sql-createsequence.html',
- 'pg.sequence.drop' => 'sql-dropsequence.html',
-
- 'pg.sql' => ['sql.html', 'sql-commands.html'],
- 'pg.sql.insert' => 'sql-insert.html',
- 'pg.sql.select' => 'sql-select.html',
- 'pg.sql.update' => 'sql-update.html',
-
- 'pg.table' => 'ddl.html#DDL-BASICS',
- 'pg.table.alter' => 'sql-altertable.html',
- 'pg.table.create' => 'sql-createtable.html',
- 'pg.table.drop' => 'sql-droptable.html',
- 'pg.table.empty' => 'sql-truncate.html',
-
- 'pg.tablespace' => 'manage-ag-tablespaces.html',
- 'pg.tablespace.alter' => 'sql-altertablespace.html',
- 'pg.tablespace.create' => 'sql-createtablespace.html',
- 'pg.tablespace.drop' => 'sql-droptablespace.html',
-
- 'pg.trigger' => 'triggers.html',
- 'pg.trigger.alter' => 'sql-altertrigger.html',
- 'pg.trigger.create' => 'sql-createtrigger.html',
- 'pg.trigger.drop' => 'sql-droptrigger.html',
-
- 'pg.type' => ['xtypes.html', 'datatype.html', 'extend-type-system.html'],
- 'pg.type.alter' => 'sql-altertype.html',
- 'pg.type.create' => 'sql-createtype.html',
- 'pg.type.drop' => 'sql-droptype.html',
-
- 'pg.user.alter' => ['sql-alteruser.html', 'user-attributes.html'],
- 'pg.user.create' => ['sql-createuser.html', 'user-manag.html#DATABASE-USERS'],
- 'pg.user.drop' => ['sql-dropuser.html', 'user-manag.html#DATABASE-USERS'],
-
- 'pg.variable' => 'runtime-config.html',
-
- 'pg.view' => 'tutorial-views.html',
- 'pg.view.alter' => ['sql-createview.html', 'sql-altertable.html'],
- 'pg.view.create' => 'sql-createview.html',
- 'pg.view.drop' => 'sql-dropview.html',
-
- 'pg.aggregate' => ['xaggr.html', 'tutorial-agg.html', 'functions-aggregate.html', 'sql-expressions.html#SYNTAX-AGGREGATES'],
- 'pg.aggregate.create' => 'sql-createaggregate.html',
- 'pg.aggregate.drop' => 'sql-dropaggregate.html',
- 'pg.aggregate.alter' => 'sql-alteraggregate.html',
-
- 'pg.server' => 'admin.html',
-
- 'pg.user' => 'user-manag.html',
-
- 'pg.locks' => 'view-pg-locks.html',
-];
+class PostgresDoc74
+{
+ private $major_version;
+ private $help_page;
+ private $conf;
+
+ public function __construct($conf, $major_version)
+ {
+ $this->major_version = $major_version;
+ $this->conf = $conf;
+
+ # TODO: Check and fix links
+ $this->help_page = [
+
+ 'pg.database' => 'managing-databases.html',
+ 'pg.database.create' => ['sql-createdatabase.html', 'manage-ag-createdb.html'],
+ 'pg.database.alter' => 'sql-alterdatabase.html',
+ 'pg.database.drop' => ['sql-dropdatabase.html', 'manage-ag-dropdb.html'],
+
+ 'pg.admin.analyze' => 'sql-analyze.html',
+ 'pg.admin.vacuum' => 'sql-vacuum.html',
+
+ 'pg.cast' => ['sql-expressions.html#SQL-SYNTAX-TYPE-CASTS', 'sql-createcast.html'],
+ 'pg.cast.create' => 'sql-createcast.html',
+ 'pg.cast.drop' => 'sql-dropcast.html',
+
+ 'pg.column.add' => ['ddl-alter.html#AEN2115', 'sql-altertable.html'],
+ 'pg.column.alter' => ['ddl-alter.html', 'sql-altertable.html'],
+ 'pg.column.drop' => ['ddl-alter.html#AEN2124', 'sql-altertable.html'],
+
+ 'pg.constraint' => 'ddl-constraints.html',
+ 'pg.constraint.add' => 'ddl-alter.html#AEN2131',
+ 'pg.constraint.check' => 'ddl-constraints.html#AEN1895',
+ 'pg.constraint.drop' => 'ddl-alter.html#AEN2140',
+ 'pg.constraint.foreign_key' => 'ddl-constraints.html#DDL-CONSTRAINTS-FK',
+ 'pg.constraint.primary_key' => 'ddl-constraints.html#AEN1972',
+ 'pg.constraint.unique_key' => 'ddl-constraints.html#AEN1950',
+
+ 'pg.conversion' => 'multibyte.html',
+ 'pg.conversion.alter' => 'sql-alterconversion.html',
+ 'pg.conversion.create' => 'sql-createconversion.html',
+ 'pg.conversion.drop' => 'sql-dropconversion.html',
+
+ 'pg.domain' => 'extend-type-system.html#AEN28657',
+ 'pg.domain.alter' => 'sql-alterdomain.html',
+ 'pg.domain.create' => 'sql-createdomain.html',
+ 'pg.domain.drop' => 'sql-dropdomain.html',
+
+ 'pg.function' => ['xfunc.html', 'functions.html', 'sql-expressions.html#AEN1599'],
+ 'pg.function.alter' => 'sql-alterfunction.html',
+ 'pg.function.create' => 'sql-createfunction.html',
+ 'pg.function.create.c' => ['xfunc-c.html', 'sql-createfunction.html'],
+ 'pg.function.create.internal' => ['xfunc-internal.html', 'sql-createfunction.html'],
+ 'pg.function.create.pl' => ['xfunc-sql.html', 'xfunc-pl.html', 'sql-createfunction.html'],
+ 'pg.function.drop' => 'sql-dropfunction.html',
+
+ 'pg.group' => 'groups.html',
+ 'pg.group.alter' => ['sql-altergroup.html', 'groups.html'],
+ 'pg.group.create' => 'sql-creategroup.html',
+ 'pg.group.drop' => 'sql-dropgroup.html',
+
+ 'pg.index' => 'indexes.html',
+ 'pg.index.cluster' => 'sql-cluster.html',
+ 'pg.index.drop' => 'sql-dropindex.html',
+ 'pg.index.create' => 'sql-createindex.html',
+ 'pg.index.reindex' => 'sql-reindex.html',
+
+ 'pg.language' => 'xplang.html',
+ 'pg.language.alter' => 'sql-alterlanguage.html',
+ 'pg.language.create' => 'sql-createlanguage.html',
+ 'pg.language.drop' => 'sql-droplanguage.html',
+
+ 'pg.opclass' => 'indexes-opclass.html',
+ 'pg.opclass.alter' => 'sql-alteropclass.html',
+ 'pg.opclass.create' => 'sql-createopclass.html',
+ 'pg.opclass.drop' => 'sql-dropopclass.html',
+
+ 'pg.operator' => ['xoper.html', 'functions.html', 'sql-expressions.html#AEN1570'],
+ 'pg.operator.alter' => 'sql-alteroperator.html',
+ 'pg.operator.create' => 'sql-createoperator.html',
+ 'pg.operator.drop' => 'sql-dropoperator.html',
+
+ 'pg.pl' => 'xplang.html',
+ 'pg.pl.plperl' => 'plperl.html',
+ 'pg.pl.plpgsql' => 'plpgsql.html',
+ 'pg.pl.plpython' => 'plpython.html',
+ 'pg.pl.pltcl' => 'pltcl.html',
+
+ 'pg.privilege' => ['privileges.html', 'ddl-priv.html'],
+ 'pg.privilege.grant' => 'sql-grant.html',
+ 'pg.privilege.revoke' => 'sql-revoke.html',
+
+ 'pg.process' => 'monitoring.html',
+
+ 'pg.rule' => 'rules.html',
+ 'pg.rule.create' => 'sql-createrule.html',
+ 'pg.rule.drop' => 'sql-droprule.html',
+
+ 'pg.schema' => 'ddl-schemas.html',
+ 'pg.schema.alter' => 'sql-alterschema.html',
+ 'pg.schema.create' => ['sql-createschema.html', 'ddl-schemas.html#DDL-SCHEMAS-CREATE'],
+ 'pg.schema.drop' => 'sql-dropschema.html',
+ 'pg.schema.search_path' => 'ddl-schemas.html#DDL-SCHEMAS-PATH',
+
+ 'pg.sequence' => 'functions-sequence.html',
+ 'pg.sequence.alter' => 'sql-altersequence.html',
+ 'pg.sequence.create' => 'sql-createsequence.html',
+ 'pg.sequence.drop' => 'sql-dropsequence.html',
+
+ 'pg.sql' => ['sql.html', 'sql-commands.html'],
+ 'pg.sql.insert' => 'sql-insert.html',
+ 'pg.sql.select' => 'sql-select.html',
+ 'pg.sql.update' => 'sql-update.html',
+
+ 'pg.table' => 'ddl.html#DDL-BASICS',
+ 'pg.table.alter' => 'sql-altertable.html',
+ 'pg.table.create' => 'sql-createtable.html',
+ 'pg.table.drop' => 'sql-droptable.html',
+ 'pg.table.empty' => 'sql-truncate.html',
+
+ 'pg.tablespace' => 'manage-ag-tablespaces.html',
+ 'pg.tablespace.alter' => 'sql-altertablespace.html',
+ 'pg.tablespace.create' => 'sql-createtablespace.html',
+ 'pg.tablespace.drop' => 'sql-droptablespace.html',
+
+ 'pg.trigger' => 'triggers.html',
+ 'pg.trigger.alter' => 'sql-altertrigger.html',
+ 'pg.trigger.create' => 'sql-createtrigger.html',
+ 'pg.trigger.drop' => 'sql-droptrigger.html',
+
+ 'pg.type' => ['xtypes.html', 'datatype.html', 'extend-type-system.html'],
+ 'pg.type.alter' => 'sql-altertype.html',
+ 'pg.type.create' => 'sql-createtype.html',
+ 'pg.type.drop' => 'sql-droptype.html',
+
+ 'pg.user.alter' => ['sql-alteruser.html', 'user-attributes.html'],
+ 'pg.user.create' => ['sql-createuser.html', 'user-manag.html#DATABASE-USERS'],
+ 'pg.user.drop' => ['sql-dropuser.html', 'user-manag.html#DATABASE-USERS'],
+
+ 'pg.variable' => 'runtime-config.html',
+
+ 'pg.view' => 'tutorial-views.html',
+ 'pg.view.alter' => ['sql-createview.html', 'sql-altertable.html'],
+ 'pg.view.create' => 'sql-createview.html',
+ 'pg.view.drop' => 'sql-dropview.html',
+
+ 'pg.aggregate' => ['xaggr.html', 'tutorial-agg.html', 'functions-aggregate.html', 'sql-expressions.html#SYNTAX-AGGREGATES'],
+ 'pg.aggregate.create' => 'sql-createaggregate.html',
+ 'pg.aggregate.drop' => 'sql-dropaggregate.html',
+ 'pg.aggregate.alter' => 'sql-alteraggregate.html',
+
+ 'pg.server' => 'admin.html',
+
+ 'pg.user' => 'user-manag.html',
+
+ 'pg.locks' => 'view-pg-locks.html',
+ ];
+ }
+
+ public function getHelpBase()
+ {
+
+ return sprintf($this->conf['help_base'], strval($this->major_version));
+ }
+
+ public function getHelpPage()
+ {
+ return $this->help_page;
+ }
+}
diff --git a/src/help/PostgresDoc80.php b/src/help/PostgresDoc80.php
index f3f64fe5..53583d82 100644
--- a/src/help/PostgresDoc80.php
+++ b/src/help/PostgresDoc80.php
@@ -1,24 +1,33 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 8.0 documentation
*
* $Id: PostgresDoc80.php,v 1.5 2005/02/16 10:27:44 jollytoad Exp $
*/
+class PostgresDoc80 extends PostgresDoc74
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
-include BASE_PATH . '/src/help/PostgresDoc74.php';
+ $this->help_page['pg.column.add'][0] = 'ddl-alter.html#AEN2217';
+ $this->help_page['pg.column.drop'][0] = 'ddl-alter.html#AEN2226';
-$this->help_page['pg.column.add'][0] = 'ddl-alter.html#AEN2217';
-$this->help_page['pg.column.drop'][0] = 'ddl-alter.html#AEN2226';
+ $this->help_page['pg.constraint.add'] = 'ddl-alter.html#AEN2217';
+ $this->help_page['pg.constraint.check'] = 'ddl-constraints.html#AEN1978';
+ $this->help_page['pg.constraint.drop'] = 'ddl-alter.html#AEN2226';
+ $this->help_page['pg.constraint.primary_key'] = 'ddl-constraints.html#AEN2055';
+ $this->help_page['pg.constraint.unique_key'] = 'ddl-constraints.html#AEN2033';
-$this->help_page['pg.constraint.add'] = 'ddl-alter.html#AEN2217';
-$this->help_page['pg.constraint.check'] = 'ddl-constraints.html#AEN1978';
-$this->help_page['pg.constraint.drop'] = 'ddl-alter.html#AEN2226';
-$this->help_page['pg.constraint.primary_key'] = 'ddl-constraints.html#AEN2055';
-$this->help_page['pg.constraint.unique_key'] = 'ddl-constraints.html#AEN2033';
+ $this->help_page['pg.domain'] = 'extend-type-system.html#AEN27940';
-$this->help_page['pg.domain'] = 'extend-type-system.html#AEN27940';
+ $this->help_page['pg.function'][2] = 'sql-expressions.html#AEN1652';
-$this->help_page['pg.function'][2] = 'sql-expressions.html#AEN1652';
+ $this->help_page['pg.operator'][2] = 'sql-expressions.html#AEN1623';
+ }
-$this->help_page['pg.operator'][2] = 'sql-expressions.html#AEN1623';
+}
diff --git a/src/help/PostgresDoc81.php b/src/help/PostgresDoc81.php
index ec119acf..df4c4b00 100644
--- a/src/help/PostgresDoc81.php
+++ b/src/help/PostgresDoc81.php
@@ -1,14 +1,23 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 8.1 documentation
*
* $Id: PostgresDoc81.php,v 1.3 2006/12/28 04:26:55 xzilla Exp $
*/
+class PostgresDoc81 extends PostgresDoc80
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
-include BASE_PATH . '/src/help/PostgresDoc80.php';
+ $this->help_page['pg.role'] = 'user-manag.html';
+ $this->help_page['pg.role.create'] = ['sql-createrole.html', 'user-manag.html#DATABASE-ROLES'];
+ $this->help_page['pg.role.alter'] = ['sql-alterrole.html', 'role-attributes.html'];
+ $this->help_page['pg.role.drop'] = ['sql-droprole.html', 'user-manag.html#DATABASE-ROLES'];
+ }
-$this->help_page['pg.role'] = 'user-manag.html';
-$this->help_page['pg.role.create'] = ['sql-createrole.html', 'user-manag.html#DATABASE-ROLES'];
-$this->help_page['pg.role.alter'] = ['sql-alterrole.html', 'role-attributes.html'];
-$this->help_page['pg.role.drop'] = ['sql-droprole.html', 'user-manag.html#DATABASE-ROLES'];
+}
diff --git a/src/help/PostgresDoc82.php b/src/help/PostgresDoc82.php
index 529ad377..b4dc2f79 100644
--- a/src/help/PostgresDoc82.php
+++ b/src/help/PostgresDoc82.php
@@ -1,9 +1,18 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 8.2 documentation
*
* $Id: PostgresDoc82.php,v 1.3 2007/11/30 15:27:26 soranzo Exp $
*/
+class PostgresDoc82 extends PostgresDoc81
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+ }
-include BASE_PATH . '/src/help/PostgresDoc81.php';
+}
diff --git a/src/help/PostgresDoc83.php b/src/help/PostgresDoc83.php
index 06ef537b..f3edd313 100644
--- a/src/help/PostgresDoc83.php
+++ b/src/help/PostgresDoc83.php
@@ -1,24 +1,33 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 8.3 documentation
*
* $Id: PostgresDoc83.php,v 1.3 2008/03/17 21:35:48 ioguix Exp $
*/
+class PostgresDoc83 extends PostgresDoc82
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
-include BASE_PATH . '/src/help/PostgresDoc82.php';
+ $this->help_page['pg.fts'] = 'textsearch.html';
-$this->help_page['pg.fts'] = 'textsearch.html';
+ $this->help_page['pg.ftscfg'] = 'textsearch-intro.html#TEXTSEARCH-INTRO-CONFIGURATIONS';
+ $this->help_page['pg.ftscfg.example'] = 'textsearch-configuration.html';
+ $this->help_page['pg.ftscfg.drop'] = 'sql-droptsconfig.html';
+ $this->help_page['pg.ftscfg.create'] = 'sql-createtsconfig.html';
+ $this->help_page['pg.ftscfg.alter'] = 'sql-altertsconfig.html';
-$this->help_page['pg.ftscfg'] = 'textsearch-intro.html#TEXTSEARCH-INTRO-CONFIGURATIONS';
-$this->help_page['pg.ftscfg.example'] = 'textsearch-configuration.html';
-$this->help_page['pg.ftscfg.drop'] = 'sql-droptsconfig.html';
-$this->help_page['pg.ftscfg.create'] = 'sql-createtsconfig.html';
-$this->help_page['pg.ftscfg.alter'] = 'sql-altertsconfig.html';
+ $this->help_page['pg.ftsdict'] = 'textsearch-dictionaries.html';
+ $this->help_page['pg.ftsdict.drop'] = 'sql-droptsdictionary.html';
+ $this->help_page['pg.ftsdict.create'] = ['sql-createtsdictionary.html', 'sql-createtstemplate.html'];
+ $this->help_page['pg.ftsdict.alter'] = 'sql-altertsdictionary.html';
-$this->help_page['pg.ftsdict'] = 'textsearch-dictionaries.html';
-$this->help_page['pg.ftsdict.drop'] = 'sql-droptsdictionary.html';
-$this->help_page['pg.ftsdict.create'] = ['sql-createtsdictionary.html', 'sql-createtstemplate.html'];
-$this->help_page['pg.ftsdict.alter'] = 'sql-altertsdictionary.html';
+ $this->help_page['pg.ftsparser'] = 'textsearch-parsers.html';
+ }
-$this->help_page['pg.ftsparser'] = 'textsearch-parsers.html';
+}
diff --git a/src/help/PostgresDoc84.php b/src/help/PostgresDoc84.php
index 34cbbb55..2a1d54ae 100644
--- a/src/help/PostgresDoc84.php
+++ b/src/help/PostgresDoc84.php
@@ -1,9 +1,18 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 8.4 documentation
*
* $Id: PostgresDoc84.php,v 1.3 2008/11/18 21:35:48 ioguix Exp $
*/
+class PostgresDoc84 extends PostgresDoc83
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+ }
-include BASE_PATH . '/src/help/PostgresDoc83.php';
+}
diff --git a/src/help/PostgresDoc90.php b/src/help/PostgresDoc90.php
index 519dbee3..aed033fb 100644
--- a/src/help/PostgresDoc90.php
+++ b/src/help/PostgresDoc90.php
@@ -1,9 +1,18 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 9.0 documentation
*
* $Id: PostgresDoc84.php,v 1.3 2008/11/18 21:35:48 ioguix Exp $
*/
+class PostgresDoc90 extends PostgresDoc84
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+ }
-include BASE_PATH . '/src/help/PostgresDoc84.php';
+}
diff --git a/src/help/PostgresDoc91.php b/src/help/PostgresDoc91.php
index 226a11d8..494bc795 100644
--- a/src/help/PostgresDoc91.php
+++ b/src/help/PostgresDoc91.php
@@ -1,9 +1,18 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 9.1 documentation
*
* $Id: PostgresDoc84.php,v 1.3 2008/11/18 21:35:48 ioguix Exp $
*/
+class PostgresDoc91 extends PostgresDoc90
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+ }
-include BASE_PATH . '/src/help/PostgresDoc90.php';
+}
diff --git a/src/help/PostgresDoc92.php b/src/help/PostgresDoc92.php
index 08b76448..67f29d89 100644
--- a/src/help/PostgresDoc92.php
+++ b/src/help/PostgresDoc92.php
@@ -1,9 +1,18 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 9.2 documentation
*
* $Id: PostgresDoc84.php,v 1.3 2008/11/18 21:35:48 ioguix Exp $
*/
+class PostgresDoc92 extends PostgresDoc91
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+ }
-include BASE_PATH . '/src/help/PostgresDoc91.php';
+}
diff --git a/src/help/PostgresDoc93.php b/src/help/PostgresDoc93.php
index 0de70635..a43c12f3 100644
--- a/src/help/PostgresDoc93.php
+++ b/src/help/PostgresDoc93.php
@@ -1,9 +1,18 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 9.3 documentation
*
* $Id: PostgresDoc84.php,v 1.3 2008/11/18 21:35:48 ioguix Exp $
*/
+class PostgresDoc93 extends PostgresDoc92
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+ }
-include BASE_PATH . '/src/help/PostgresDoc92.php';
+}
diff --git a/src/help/PostgresDoc94.php b/src/help/PostgresDoc94.php
index 25116772..10b64f18 100644
--- a/src/help/PostgresDoc94.php
+++ b/src/help/PostgresDoc94.php
@@ -1,9 +1,18 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 9.4 documentation
*
* $Id: PostgresDoc84.php,v 1.3 2008/11/18 21:35:48 ioguix Exp $
*/
+class PostgresDoc94 extends PostgresDoc93
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+ }
-include BASE_PATH . '/src/help/PostgresDoc93.php';
+}
diff --git a/src/help/PostgresDoc95.php b/src/help/PostgresDoc95.php
index 9a71a862..a456dbfb 100644
--- a/src/help/PostgresDoc95.php
+++ b/src/help/PostgresDoc95.php
@@ -1,10 +1,20 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
* Help links for PostgreSQL 9.5 documentation
*
*/
+class PostgresDoc95 extends PostgresDoc94
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+
+ $this->help_page['pg.matview'] = 'sql-creatematerializedview.html';
-include BASE_PATH . '/src/help/PostgresDoc94.php';
+ }
-$this->help_page['pg.matview'] = 'sql-creatematerializedview.html';
+}
diff --git a/src/help/PostgresDoc96.php b/src/help/PostgresDoc96.php
index 087dcd33..6206ef00 100644
--- a/src/help/PostgresDoc96.php
+++ b/src/help/PostgresDoc96.php
@@ -1,8 +1,17 @@
<?php
+namespace PHPPgAdmin\Help;
+
/**
- * Help links for PostgreSQL 9.5 documentation
+ * Help links for PostgreSQL 9.6 documentation
*
*/
+class PostgresDoc96 extends PostgresDoc95
+{
+
+ public function __construct($conf, $major_version)
+ {
+ parent::__construct($conf, $major_version);
+ }
-include BASE_PATH . '/src/help/PostgresDoc95.php';
+}