1
0
Fork 0

Initial commit

This commit is contained in:
admin 2011-03-29 21:51:22 +04:00
commit b5f9941788
422 changed files with 128744 additions and 0 deletions

4
php/bin/parse_artist.php Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/php
<?php
echo 1;

View File

@ -0,0 +1,114 @@
<?php
/*****************************************************************
Пример использования:
RemoteFile::setHeaders(array(
'X-Requested-With: XMLHttpRequest',
'Origin: http://vkontakte.ru',
'Content-Type: application/x-www-form-urlencoded'
));
$headers = RemoteFile::getHeaders('http://cs4603.vkontakte.ru/u50132690/audio/432e2b109b94.mp3');
$html = RemoteFile::getData('http://vkontakte.ru/audio', array(
'act' =>'search',
'q' => urlencode($this->_query)
))
*****************************************************************/
/**
* Класс для работы с удаленными файлами
* Реализован через библиотеку cURL
*
* @package classes
* @author chez
**/
class RemoteFile {
private static $_timeout = 5; // Таймаут ответа от сервера
private static $_headers = array(); // Заголовки для отправки на сервер
/**
* Отправка запроса и получение ответа от сервера
* Умеет возвращать текст ответа или заголовки
*
* @param string $url URL запроса
* @param bool $headers Флаг: возвращать заголовки, а не текст
* @param array $post_params Массив POST-параметров, если установлен, то метод меняется на POST
* @return string Ответ от сервера
* @author chez
**/
private static function _exec($url, $headers = false, $post_params = array()) {
if (count($post_params) > 0) {
$p = '';
foreach ($post_params as $key => $val) {
$p .= '&'. $key .'='. $val;
}
$post_params = substr($p, 1);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, self::$_headers);
if ($headers) {
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
}
if (is_string($post_params)) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_params);
}
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, self::$_timeout);
$r = curl_exec($ch);
curl_close($ch);
return $r;
}
/**
* Получение HTTP-заголовков ответа от сервера
*
* @param string $url URL запроса
* @param array $post_params Массив POST-параметров, если установлен, то метод меняется на POST
* @return array Распарсеный массив заголовков
* @author chez
**/
public static function getHeaders($url, $post_params = array()) {
$headers = explode("\r\n", self::_exec($url, true));
$headers_array = array();
while(list($i, $header) = each($headers)) {
if (substr($header, 0, 5) == 'HTTP/') {
$header = explode(' ', $header);
$headers_array['http'] = $header[1];
} elseif ($header != '') {
preg_match('/^([a-z0-9\-]*):\s(.*)$/Ui', $header, $m);
$headers_array[strtolower(str_replace('-', '_', $m[1]))] = $m[2];
}
}
return $headers_array;
}
/**
* Получение ответа от сервера
*
* @param string $url URL запроса
* @param array $post_params Массив POST-параметров, если установлен, то метод меняется на POST
* @return string Тело ответа от сервера
* @author chez
**/
public static function getData($url, $post_params = array()) {
return self::_exec($url, false, $post_params);
}
/**
* Запись заголовков, которые будет отправлены вместе с запросом
*
* @param array $headers Индексный массив заголовков
* @return void
* @author chez
**/
public static function setHeaders($headers) {
self::$_headers = $headers;
}
}

View File

@ -0,0 +1,99 @@
<?php
/*****************************************************************
Пример использования:
$weight_calc = new TrackWeight();
$weight_calc->setTrackData('Blondie', 'Call Me', 210);
$weight_calc->setFiles($files); // Файлы, полученные от парсера
$weight_calc->calculateWeight();
$files = $weight_calc->getFiles();
*****************************************************************/
/**
* Класс посчета веса файла (коэфициента, определяющего релевантность)
*
* @package classes
* @author chez
**/
class TrackWeight {
private $_artist; // Имя исполнителя
private $_track; // Название трека
private $_duration; // Длительность трека в секундах
private $_files; // Массив файлов для сравнения
/**
* Задает параметры оригинального трека
*
* @param string $artist Имя исполнителя
* @param string $track Запрос
* @param int $duration Длительность трека в секундах
* @return void
* @author chez
**/
public function setTrackData($artist, $track, $duration) {
$this->_artist = $artist;
$this->_track = $track;
$this->_duration = $duration;
}
/**
* Задает массив файлов для сравнения
*
* @param array $files Массив файлов для сравнения
* @return void
* @author chez
**/
public function setFiles($files) {
$this->_files = $files;
}
/**
* Возвращает файлы с проставленным весом
*
* @return array $files Массив файлов
* @author chez
**/
public function getFiles() {
return $this->_files;
}
/**
* Рассчитывает вес для каждого файла
*
* @return void
* @author chez
**/
public function calculateWeight() {
foreach ($this->_files as $i => $file) {
$weight = 0;
if ($file['artist'] == $this->_artist) {
$weight += 10;
} elseif (strpos($file['artist'], $this->_artist) !== false) {
$weight += 5;
} elseif (strpos($file['track'], $this->_artist) !== false) {
$weight += 4;
}
if ($file['track'] == $this->_track) {
$weight += 10;
} elseif (strpos($file['track'], $this->_track) !== false) {
$weight += 5;
}
if ($file['duration'] == $this->_duration) {
$weight += 10;
} else {
$delta = abs($file['duration'] - $this->_duration);
if ($delta < 5) {
$weight += (5 - $delta);
}
}
$this->_files[$i]['weight'] = $weight;
}
}
}

View File

@ -0,0 +1,108 @@
<?php
/*****************************************************************
Пример использования:
$files = VkontakteMP3::check($files);
*****************************************************************/
/**
* Класс для постобработки массива треков от контакта
* Проверяет файлы, рассчитывает битрейт и релевантность
*
* @package classes
* @author chez
**/
class VkontakeMP3 {
private static $_bitrates = array( // Массив стандартных битрейтов
8, 16, 24, 32, 40, 48, 56,
64, 80, 96, 112, 128, 144,
160, 192, 224, 256, 320
);
/**
* Рассчитывает средний битрейт файла
* Приводит полученый битрейт к одному из стандартных
*
* @param int $size Размер файла в байтах
* @param int $length Длина трека в секундах
* @return int Битрейт в килобитах в секунду
* @author chez
**/
public static function calculateBitrate($size, $length) {
$br = round($size * 8 / 1024 / $length);
$found_br = 0;
for ($i = 1; $i < count(self::$_bitrates); $i++) {
if (self::$_bitrates[$i] > $br && ! $found_br) {
$delta = self::$_bitrates[$i] - $br;
$br_delta = self::$_bitrates[$i] - self::$_bitrates[$i-1];
if (round($br_delta / 3) > $delta) {
$found_br = self::$_bitrates[$i];
} else {
$found_br = self::$_bitrates[$i-1];
}
} elseif ($i == count(self::$_bitrates) - 1 && self::$_bitrates[$i] < $br && ! $found_br) {
$delta = $br - self::$_bitrates[$i];
if ($delta < 32) {
$found_br = self::$_bitrates[$i];
} else {
$found_br = $br;
}
}
}
return $found_br;
}
/**
* Проверяет файлы, рассчитывает битрейт и релевантность
*
* @param array $files Массив файлов для обработки
* @return array Обработанный массив файлов
* @author chez
**/
public static function check($files) {
$m = new Match();
$m->setTrackData('Blondie', 'Call Me', 210);
$m->setFiles($files);
$m->calculateWeight();
$files = $m->getFiles();
uasort($files, function($a, $b){
return $a['weight'] < $b['weight'];
});
foreach ($files as $i => $file) {
$files[$i]['length'] = self::convertDuration($file['duration']);
$files[$i]['bitrate'] = self::calculateBitrate($file['size'], $files[$i]['length']);
}
return $files;
}
/**
* Чистит строку для максимально точного сравнения
*
* @param string $str Необработанная строка
* @return string Чистая строка
* @author chez
**/
public static function prepareQuery($str) {
$str = trim($str);
while(strpos($str, ' ') !== false) {
$str = str_replace(' ', ' ', $str);
}
return $str;
}
/**
* Преобразует длину из формата мм:сс в ссс
*
* @param string $duration Читабельная длина
* @return int Длина в секундах
* @author chez
**/
public static function convertDuration($duration) {
}
}

View File

@ -0,0 +1,127 @@
<?php
/*****************************************************************
Пример использования:
$vk_parser = new Vkontakte();
$vk_parser->parse('Blondie - Call Me');
$files = $weight_calc->getFiles();
*****************************************************************/
/**
* Класс парсинга вконтактика
*
* @package classes
* @author chez
**/
class Vkontakte {
private $_cookies; // Куки, ассоциативный массив
private $_query; // Запрос, plain text
private $_html; // HTML, полученый от вконтактика
private $_files; // Распарсеные массивы с информацией о файле
/**
* Оболочка парсера
*
* @param string $q Запрос
* @return array Массив с файлами
* @author chez
**/
public function parse($q) {
$this->_query = $q;
$this->auth();
$cookie = array();
foreach ($this->_cookies as $key => $val) {
$cookie[] = $key .'='. $val;
}
RemoteFile::setHeaders(array(
'Cookie: '. implode('; ', $cookie),
'Referer: http://vkontakte.ru/audio?album_id=0',
'X-Requested-With: XMLHttpRequest',
'Origin: http://vkontakte.ru',
'Content-Type: application/x-www-form-urlencoded',
'User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16',
'Connection: close'
));
$this->setHtml(RemoteFile::getData('http://vkontakte.ru/audio', array(
'act' =>'search',
'al' =>'1',
'gid' =>'0',
'id' =>'5728795',
'offset' =>'0',
'q' => urlencode($this->_query),
'sort' =>'2'
)));
$this->parseHtml();
return $this->_files;
}
/**
* Пишет полученый html в член объекта
*
* @param string $html HTML
* @return void
* @author chez
**/
public function setHtml($html) {
$this->_html = $html;
}
/**
* Возвращает хранимый html
*
* @return string HTML
* @author chez
**/
public function getHtml() {
return $this->_html;
}
/**
* Возвращает хранимый массив файлов
*
* @return array Список файлов
* @author chez
**/
public function getFiles() {
return $this->_files;
}
/**
* Проводит авторизацию на вконтактике и получает куки
* Пока костыль, потом нужно будет переписать
*
* @return array Ассоциативный массив с куками
* @author chez
**/
private function auth() {
$this->_cookies = array(
'remixchk' => 5,
'remixsid' => 'c68c4362f62f218a25802bae87201d1bc46fadd0b5c64f71678430c9b63b'
);
}
/**
* Разбирает HTML, полученый от вконтактика
*
* @return array Список файлов
* @author chez
**/
public function parseHtml() {
preg_match_all('/<tr>(.*)<\/tr>/Usi', $this->_html, $m);
$files = array();
foreach ($m[0] as $res) {
preg_match('/<input.*value=\"(.*)\,(\d{2,4})\".*<div\sclass=\"duration.*>(.*)<\/div>.*<a.*>(.*)<\/a>.*\s-\s(.*)<\/div>/Usi', $res, $m1);
$duration = explode(':', $m1[3]);
$files[] = array(
'url' => $m1[1],
'duration' => $duration[0] * 60 + $duration[1],
'artist' => strip_tags($m1[4]),
'track' => strip_tags($m1[5])
);
}
$this->_files = $files;
}
}

15
php/debug.php Normal file
View File

@ -0,0 +1,15 @@
<?
require_once 'classes/Vkontakte.class.php';
require_once 'classes/File.class.php';
require_once 'classes/Match.class.php';
$q = 'Blondie';
$p = new Vkontakte();
$p->setHtml(file_get_contents('dump/html/'. $q .'.html'));
$p->parseHtml();
$f = $p->getFiles();
echo '<pre>';
print_r($f);

File diff suppressed because one or more lines are too long

3
php/dump/data/Blondie.data Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

3825
php/dump/html/Blondie.html Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3825
php/dump/html/Jet - Timothy.html Executable file

File diff suppressed because it is too large Load Diff

BIN
php/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

73
php/index.php Normal file
View File

@ -0,0 +1,73 @@
<?php
date_default_timezone_set('Europe/Moscow');
$artist = 'Foo Fighters';
if (isset($_GET['q']) && $_GET['q'] != '') {
$q = $_GET['q'];
} else {
$q = $artist;
}
$c = pg_connect('host=localhost port=5432 dbname=beatheaven user=postgres password=password');
$t = pg_query($c, "SELECT * FROM beatheaven.bh_artist WHERE name = '{$q}'");
$artist = pg_fetch_assoc($t);
$t = pg_query($c, "SELECT * FROM beatheaven.bh_release_group WHERE artist_id = {$artist['id']} AND type = 1");
$release_groups = array();
$release_group_ids = array();
while ($row = pg_fetch_assoc($t)) {
$row['releases'] = array();
$release_groups[$row['id']] = $row;
$release_group_ids[] = $row['id'];
}
$t = pg_query($c, "SELECT * FROM beatheaven.bh_release WHERE release_group IN (". implode(',', $release_group_ids) .") AND type=1 ORDER BY date");
while ($row = pg_fetch_assoc($t)) {
$row['tracks'] = array();
$release_groups[$row['release_group']]['releases'][$row['id']] = $row;
$t1 = pg_query($c, "SELECT * FROM beatheaven.bh_track WHERE release_id = '{$row['id']}' ORDER BY position");
while ($row1 = pg_fetch_assoc($t1)) {
$release_groups[$row['release_group']]['releases'][$row['id']]['tracks'][$row1['position']] = $row1;
}
}
usort($release_groups, function($a, $b){
return strtotime($a['year']) > strtotime($b['year']);
});
$artist['albums'] = array();
while(list( $i, $rg ) = each($release_groups)) {
$t_list = array();
$b_list = array();
$tracks = array();
$bonus = array();
$r = current($rg['releases']);
if (count($r['tracks']) > 0) {
while(list( $j, $t ) = each($r['tracks'])) if ($t['name'] != '[silence]') {
$t_list[] = strtolower($t['name']);
$tracks[] = array('id' => $t['id'], 'name' => $t['name'], 'duration' => round($t['length'] / 1000));
}
while(list( $j, $r ) = each($rg['releases'])) {
while(list( $k, $t ) = each($r['tracks'])) if ($t['name'] != '[silence]') {
if (!in_array(strtolower($t['name']), $t_list) && !in_array(strtolower($t['name']), $b_list)) {
$bonus[] = array('id' => $t['id'], 'name' => $t['name'], 'duration' => round($t['length'] / 1000));
$b_list[] = strtolower($t['name']);
}
}
}
}
$artist['albums'][] = array(
'name' => $rg['name'],
'year' => $rg['year'],
'tracks' => $tracks,
'bonus' => $bonus
);
}
include 'tpl/index.php';

105
php/pgadmin/CREDITS Normal file
View File

@ -0,0 +1,105 @@
CREDITS
-------
Project Administration & Major Projects
- Robert Treat
- Jehan-Guillaume (ioguix) De Rorthais
Translators
- Kuo Chaoyi (Chinese Utf8)
- Angelo Rigo (Brazilan Portuguese)
- Chan Min Wai (Chinese)
- He Wei Ping (Chinese)
- Chih-Hsin Lee (Trad. Chinese)
- Hugo Jonker (Dutch)
- Pascal Peyre (French)
- Guillaume Lelarge (French)
- ioguix (French)
- H. Etzel, Markus Bertheau (German)
- Kalef (Italian)
- Tadashi Jokagi (Japanese)
- Rafal Slubowski (Polish)
- Alexander Khodorisky (Russian)
- Martin Marqués (Spanish)
- Andrej Misovic (Slovak)
- Devrim Gunduz (Turkish)
- Libor Vanek (Czech)
- Marek Cernocký (Czech)
- Stefan Malmqvist (Swedish)
- Nicola Soranzo (Italian)
- Petri Jooste (Afrikaans)
- Sulyok Péter (Hungarian)
- Zaki Almuallim (Arabic)
- Erdenemandal Bat-Erdene (Mongolian)
- Alex Rootoff (Ukrainian)
- Jonatan (Hebrew)
- Alin Vaida (Romanian)
- Arne Eckmann (Danish)
- Francisco Cabrita (Portuguese)
- Bernat Pegueroles (Catalan)
- Fernando Wendt (Brazilan Portuguese)
- Adamantios Diamantidis (Greek)
- Marek ¿ernocký (Czech)
- Alexey Baturin (Russian UTF8)
- Adrián Chaves Fernández (Galician)
Look & Feel
- Davey (CSS)
- ioguix (Cappuccino theme)
- Tomasz Pala (Gotar theme)
Contributors
- Dan Wilson
- Christopher Kings-Lynne
- Felix Meinhold
- Jean-Michel Poure
- Rafal Slubowski
- Brett Toolin
- Mark Gibson (Pop-up SQL window)
- Nicola Soranzo
- Oliver Meyer & Sven Kiera (Table icons link to browse table)
- Bryan Encina (SQL window improvements, bug fixes, admin)
- Dan Boren (Object comments)
- Adrian Nida (Fix time outs)
- Russell Smith
- Guillaume Lelarge
- Ian Barwick
- Javier Carlos
- Eric Kinolik
- John Jawed
- Karl O. Pinc
- Tomasz Pala
- Ivan Zolotukhin
- Kristoffer `spq` Janke
- Leonardo Augusto Sapiras (Improve phpPgAdmin ergonomy during the GSoC 2010, with ioguix as mentor)
Third Party Libraries
- Highlight.php (Jacob D. Cohen of rafb.net)
- XLoadTree2 (Erik Arvidsson & Emil A Eklund of webfx.eae.net)
- jQuery (http://jquery.com/)
Corporate Sponsors
Project resources:
- Sourceforge.net - Hosting, source package provider, Bug and Feature request tracker, hosting mailing lists (and ex code repository)
- github.com - Official GIT repository hosting
- Kattare Internet (http://www.kattare.com/) - Hosting the demo server
Ongoing contributors:
- Omniti ( http://omniti.com/ ) - sponsors developpment as Robert Treat employer
- Dalibo ( http://dalibo.com ) - sponsors developpment as Jehan-Guillaume (ioguix) de Rorthais employer
Feature contributors:
- SpikeSource (www.spikesource.com) - Slony support
- Google Summer of Code (http://code.google.com/soc/2006/pgsql/appinfo.html?csaid=DB096D908B948D89) - phpPgAdmin Improvements
- Google Summer of Code (http://code.google.com/soc/2007/postgres/appinfo.html?csaid=E89B3D5E2DC4170A) - Full Text Search in PostgreSQL GUI Tools
- Google Summer of Code (http://code.google.com/p/google-summer-of-code-2010-postgresql/we_dont_have_the_complete_link_yet) - Improve phpPgAdmin ergonomy

163
php/pgadmin/DEVELOPERS Normal file
View File

@ -0,0 +1,163 @@
DEVELOPER INFO
--------------
phpPgAdmin is Free/Open Source software, so you're invited to contribute to it.
Many great features have been written by other people and you too can help to
make phpPgAdmin a better tool.
If you're planning to contribute source code, please read the following
information:
The following method is preferred for new developers:
- fetch the current CVS tree over anonymous CVS:
cvs -d :pserver:anonymous@phppgadmin.cvs.sourceforge.net:/cvsroot/phppgadmin login
[Password: ] simply press the Enter key!
cvs -z3 -d :pserver:anonymous@phppgadmin.cvs.sourceforge.net:/cvsroot/phppgadmin co -d phpPgAdmin webdb
[This will create a new sub-directory named phpPgAdmin]
- Add your stuff
- Send us the file(s) you've modified or send us a patch (preferred). To
generate a patch, in your 'phpPgAdmin' directory do:
cvs diff -c > file.txt
Then, just send us 'file.txt' .
Please note that submitting code is considered a transfer of copyright to the
phpPgAdmin project.
Write access to the CVS tree is granted only to developers who have already
contributed something useful to phpPgAdmin. If you're interested in that,
please contact us.
These project developers can access the CVS tree via SSH:
export CVS_RSH=ssh
Login once with
ssh developername@phppgadmin.cvs.sourceforge.net
to create required user directories on the server. Then fetch the current CVS
tree:
cvs -z3 -d developername@phppgadmin.cvs.sourceforge.net:/cvsroot/phppgadmin co -d phpPgAdmin webdb
For further information, refer to:
http://sourceforge.net/projects/phppgadmin
TIPS FOR DEVELOPERS
-------------------
When you submit code to phpPgAdmin, we do expect it to adhere to the existing
coding standards in the source. So, instead of using your personal favourite
code layout style, please format it to look like surrounding code.
In general, we want the code to be portable, standard compliant (e.g. to W3C
(X)HTML and CSS) and independent of specific configurations of PHP, the web
server, PostgreSQL or the user browser. We also try to support as many versions
as possible of these applications.
Test your code properly! For example, if you are developing a feature to create
domains, try naming your domain all of the following:
* "
* '
* \
* words with spaces
* <br><br><br>
If you are adding a new class function, be sure to use the "clean",
"fieldClean", "arrayClean" and "fieldArrayClean" functions to properly escape
odd characters in user input. Examine existing functions that do similar
things to yours to get yours right.
When writing data to the display, you should always urlencode() variables in
HREFs and htmlspecialchars() variables in forms. Rather than use action=""
attributes in HTML form elements use action="thisformname.php". This
ensures that browsers remove query strings when expanding the given
relative URL into a full URL.
When working on database classes, always schema qualifing your SQL where it is
possible with the current schema ($data->_schema) for pg73+ classes. Then don't
forget to write your method for older classes which doesn't suppport schemas.
When working with CVS, always make sure to do a 'cvs update' both before you
start; so you have the latest code to work with; and also again before you
create your patch; to minimize the chance of having conflicts.
COMMON VARIABLES
----------------
$data - A data connection to the current or default database.
$misc - Contains miscellaneous functions. eg. printing headers & footers, etc.
$lang - Global array containing translated strings. The strings in this array
have already been converted to HTML, so you should not
htmlspecialchars() them.
$conf - Global array of configuration options.
WORKING WITH RECORDSETS
-----------------------
phpPgAdmin uses the ADODB database library for all its database access. We have
also written our own wrapper around the ADODB library to make it more object
oriented (ADODB_base.pclass).
This is the general form for looping over a recordset:
$rs = $class->getResults();
if (is_object($rs) && $rs->recordCount() > 0) {
while (!$rs->EOF) {
echo $rs->fields['field'];
$rs->moveNext();
}
}
else echo "No results.";
UPDATING LANGUAGE FILES FOR THE MONO-LINGUAL
--------------------------------------------
If you need to add or modify language strings for a new feature, the preferred
method is:
* cd into lang/ subdirectory
* modify english.php file only!
* run "make english" (this will recode the english.php file, and place an
updated copy in lang/recode/)
If you've done it correctly, when you create your patch, it should only have
diffs of lang/english.php and lang/recode/english.php files. For more
information on how the language system works, please see the TRANSLATORS file.
UNDERSTANDING THE WORK/BRANCH/TAG/RELEASE PROCESS
-------------------------------------------------
All new work for phpPgAdmin is done against the CVS HEAD branch. When we feel
we are ready to do a new release, we create a branch (ex. REL_4-1). This
becomes the stable branch for all future 4.1.x releases, and any bugfixes needed
for 4.1 would go in that branch.
When we release a new revision, we tag that at release time (REL_4-1-1), so a
checkout of any tag should give you the same files that downloading the release
would have given you. As a general rule, we do not introduce new features into
existing stable branches, only bugfixes and language updates. This means if you
want to work on new features, you should be working against CVS HEAD.
Eventually we will call for another release, and that will be branched (REL_4-2)
and the cycle will start over.
On occasion we have created out-of-band branches, typically labeled as DEV_foo.
These were used for temporary, concurrent development of large features, and
should not be used by other developers. When development of those features is
completed, the branches get merged in as appropriate, so no further development
should occur on those branches.
GETTING HELP
------------
We prefer most discussion of development to take place on the phpPgAdmin
mailing list, so that discussions can be archived and be searchable.
However, if you are into IRC, a couple of us hang out on #phppgadmin on
freenode, and occasionally discuss things there.

217
php/pgadmin/FAQ Normal file
View File

@ -0,0 +1,217 @@
phpPgAdmin Frequently Asked Questions
-------------------------------------
Installation errors
-------------------
Q: I've installed phpPgAdmin but when I try to use it I get an error message
telling me that I have not compiled proper database support into my
PHP installation.
A: This means that you have not properly compiled Postgres support into
your PHP. The correct configure flag to use is '--with-pgsql'. Read the
PHP manual and website for more help with this.
Postgres support can be also compiled into PHP as a dynamic extension,
so if you have precompiled version (Linux RPM, or Windows binary), there
are still chances, that only thing you should do is to enable loading it
automagically.
It can be done by editing your php.ini file (under Windows, usually in
C:\WINDOWS or C:\WINNT, under Linux /etc/php.ini) and uncommenting this
line:
;extension=php_pgsql.dll ;under Windows
;extension=pgsql.so ;under Linux
so it would look like that:
extension=php_pgsql.dll ;under Windows
extension=pgsql.so ;under Linux
In Linux distributions based on Red Hat or Fedora, PHP extensions are
automatically configured in /etc/php.d/pgsql.ini, simply install the
php-pgsql package.
See http://www.php.net/manual/en/pgsql.setup.php for more information
on setting up Postgres support in PHP.
Q: I get a warning like this when using phpPgAdmin on Windows:
"Warning: session_start() [function.session-start]:
open(/tmp\sess_5a401ef1e67fb7a176a95236116fe348, O_RDWR) failed"
A: You need to edit your PHP.INI file (usually in c:\windows) and change this
line:
session.save_path = "/tmp"
to:
session.save_path = "c:\windows\temp"
And make sure that the folder c:\windows\temp actually exists.
Login errors
------------
Q: I always get "Login failed" even though I'm _sure_ I'm using the right
username and password.
A: There are a number of reasons why you might not be able to connect, typically
having nothing to do with phpPgAdmin itself. First check the Postgres log
on your server, it should contain a FATAL error message detailing the exact
reason why the login is failing. You will probably need to either adjust the
username or password, add LOGIN permissions to the role, or adjust your
pg_hba.conf file in your Postgres data dir; so follow the directions laid
out in the FATAL message.
If you do not have any FATAL error messages, and you have verified that you
are looking at the properly configured logfile, then this means you are not
connecting to your database. If you are connecting via TCP/IP sockets (for
example if you have installed phpPgAdmin on a different computer than your
database) make sure that Postgres is accepting connection over TCP/IP. On
older versions of Postgres, you need to change this line in your
postgresql.conf file:
#tcpip_socket = false
to:
tcpip_socket = true
on newer versions of Postgres, this setting has been replaced by the
listen_addresses setting, so you will need to change that setting instead
(likely changing it to "*"). Be sure to restart Postgres after changing
either of these settings!
If that still doesn't get you connected, then there is likely something
interfering between PHP and Postgres. Check to make sure that you don't have
a firewall preventing connectivity, or that you don't have some other
security setup (ie. SELinux policy) that prevents PHP from connecting.
Q: For some users I get a "Login disallowed for security" message.
A: Logins via phpPgAdmin with no password or certain usernames (pgsql,
postgres, root, administrator) are denied by default. Before changing this
behaviour (setting $conf['extra_login_security'] to false in the
config.inc.php file) please read the Postgres documentation about client
authentication and understand how to change Postgres's pg_hba.conf to
enable passworded local connections.
Q: I can use any password to log in!
A: Postgres, by default, runs in trust mode. That means that it doesn't
ask for passwords for local connections. We highly recommend that you
edit your pg_hba.conf file, and change the login type to 'md5'. Note
that if you change the 'local' login type to 'md5', then you might need
to enter a password to start Postgres. Get around this by using a
.pgpass file - explained in the Postgres documentation.
Other errors
------------
Q: When I enter non-ASCII data into the database via a form, it's inserted
as hexadecimal or &#1234; format!
A: You have not created your database in the correct encoding. This problem
will occur when you try to enter an umlaut into an SQL_ASCII database, or
SJIS Japanese into an EUC-JP database, etc.
Q: When I drop and re-create a table with the same name, it fails.
A: You need to drop the sequence attached to the SERIAL column of the table
as well. Postgres 7.3 and above do this automatically. If you have
upgraded to Postgres 7.3 from an earlier version, you need to run the
contrib/adddepend script to record all dependencies.
Q: When browsing a table, the 'edit' and 'delete' links do not appear.
A: In order, phpPgAdmin will prefer the following as unique row identifiers:
1. Primary keys
2. Unique keys (cannot be parital or expressional indexes)
3. OID column (will require a sequential scan to update, unless you
index the OID column)
Furthermore, any NULL values in the unique index will mean that that row
will be uneditable. Also, since OIDs can become duplicated in a table,
phpPgAdmin will alter the row, and then check to ensure that exactly one
row has been modified - otherwise rollback will occur.
Questions on dumps
------------------
Q: What happened to the database dump feature?
A: You need to configure phpPgAdmin (in the config.inc.php file) to point
to the location of the pg_dump and pg_dumpall utilities on your web server.
Once you have done that, the database export feature will appear.
Q: I would like to use the pg_dump integration for database and table
dumps on Windows. How do I get pg_dump.exe on Windows?
A: To get the pg_dump utilities on Windows, you need to install Postgres 8.0
or higher (we recommend the latest release) for Windows, available for
download from the
<a href="http://www.postgresql.org/download/windows">Postgres web site</a>.
Once you have installed that, set the pg_dump and pg_dumpall locations
in the config.inc.php file to
'C:\\Program Files\\Postgres\\8.0\\bin\\pg_dump.exe' and
'C:\\Program Files\\Postgres\\8.0\\bin\\pg_dumpall.exe', or wherever you
installed them.
Q: Why can't I reload the SQL script I dumped in the SQL window?
A: The following limitations currently exist in SQL script execution:
* Only uploaded SQL scripts can contain COPY commands and for
this to work, you must have PHP 4.2 or higher.
* 'psql' commands such as '\connect' will not work at all.
* Multiline SQL statements will not work, eg:
CREATE TABLE example (
a INTEGER
);
* You cannot change the current database or current user during
the execution of the script.
We do intend to work on some of these limitations in the future, but
some of them are Postgres restrictions and we recommend using the
'psql' utility to restore your full SQL dumps.
Other questions
---------------
Q: When inserting a row, what does the 'Value' or 'Expression' box mean?
A: Choosing 'Expression' means that you can use functions, operators, other
field names, etc. in your value - you need to properly quote any literal
values yourself. 'Value' on the other hand, means that no matter what you
enter as the value, it will be inserted as-is into the database.
Q: Why is there never any information on the 'Info' page of a table?
A: The Info page will show you what other tables have foreign keys to the
current table and some data from the Postgres statistics collector.
In older versions of Postgres, the stats collector is not enabled by default.
To enable it, look in your postgresql.conf file for the stats_* options.
Just make them all 'true' and restart Postgres.
Q: Why can't I download data from queries executed in the SQL window?
A: You need to check the 'Paginate results' option to allow downloads.
Q: I would like to help out with the development of phpPgAdmin. How should I
proceed?
A: We really would like your help! Please read the DEVELOPERS and TRANSLATORS
files.

794
php/pgadmin/HISTORY Normal file
View File

@ -0,0 +1,794 @@
phpPgAdmin History
------------------
Version 5.0.2
-------------
Released: 3rd January 2011
Some bug fixes.
* Fix a css typo & error in cappuccino theme
* Fix #3139003 "Autocomplete doesn't insert value", report and patch by Aleksander Machniak
* Fix bad inheritance between pg83 -> pg instead of pg83 -> pg84 in the database access classes. This bug was breaking some functionnalities with 8.3
* Fix a lot of nonstandard escaped string in the database access classes
Version 5.0.1
-------------
Released: 14th December 2010
Minor bug fix and update version.
* Fix #3124417 "Wrong german translation", reported by schnoesel
* Fix (officialy) a bug where non-super user roles cannot check ownership on objects
* Add forgotten Galician language to the target "all" of lang/Makefile
* Update jQuery library to current stable 1.4.4
* remove useless date from the topbar informations.
This was the only place that did PHP 5.3 complain about bad timezone configuration
(a non-PPA related warning). As it was a totaly useless information, we decide to
remove it.
Version 5.0
-----------
Released: 29th November 2010
Features
* Support for PostgreSQL 8.4 and 9.0
* Support for database level collation for 8.4+
* Support for schema level export
* Add ability to alter schema ownership
* Clean up domain support and improve interface
* Add support for commenting on functions
* Allow user to rename role/users and set new passwords at the same time
* Greatly enhanced Full-Text-Search capabilities (ioguix, Loomis_K)
* Overhauled Selenium Test suite to support multiple database versions
* Optimized application graphics (Limo Driver)
* Support for Column Level Privileges
* Allow users to specify a template database at database creation time
* Support killing processes
* Add ability to create indexes concurrently
* Much better support of autovacuum configuration
* Add an admin page for table level
* Refactored autocompletion:
* fix support for cross-schema objects
* support multi-field FK
* support for pagination of values in the auto-complete list
* Allow user to logicaly group their server under custom named node in the browser tree
* New themes (Cappuccino and Gotar) and a theme switcher on the introduction page
* Auto refresh Locks page
* Auto refresh Processes page
* Link in the bottom of the page to go to top of page
* Browsing on Foreign Keys (When browsing a table, clicking on a FK value, jump to the PK row)
Bugs
* Fix problems with query tracking on overly long queries
* Ensure pg_dump paths are valid
* Fix multiple bugs about quoting and escaping database objects names with special chars
* Fix multiple bugs in the browser tree
* Fix multiple bugs on the SQL and script file import form
* One security fix about code injection
* Don't allow inserting on a table without fields
* Some fix about commenting databases
* removed deprecated functions from PHP 5.3
* Lot of code cleanup
* Many other small minor bugs found on our way
* Fix the operator property page
Translations
* Czech (Marek Cernocky)
* Greek (Adamantios Diamantidis)
* Brazillian Portuguese (Fernando Wendt)
* Galician (Adrián Chaves Fernández)
Incompatabilities
* No longer support PHP < 5.0
* No longer support Postgres < 7.4
Version 4.2
-----------
Features
* Add Analyze to Table Level Actions (ioguix)
* Add support for multiple actions on main pages (ioguix, Robert Treat)
* Added favicon for Mozilla and a backwards compatible version for IE.
* Allow browsers to save different usernames and passwords for different servers.
* Pagination selection available for reports
* You can configure reports db, schema and table names
* Add support for creating a table using an exsting one (ioguix)
* Auto-expand a node in the tree browser if there are no other nodes (Tomasz Pala)
* Add column about fields constraints type + links in table properties page (ioguix)
* Support for built-in Full Text Search (Ivan Zolotukhin)
* Add alter name, owner & comment on views (ioguix)
* Add column about called procedure + links to their definition in the triggers
properties page (ioguix)
* Add Support for Enum type creation (ioguix,xzilla)
* Add alter name, owner, comment and properties for sequences (ioguix)
* Add function costing options (xzilla)
* Add alter owner & schema on function (xzilla)
* Add a popup window for the session requests history (karl, ioguix)
* Add alter table, view, sequence schema (ioguix)
Bugs
* Fix inability to assign a field type/domain of a different schema
* Can't edit a report and set its comment to empty
* Fix PHP5 Strict mode complaints
* Fix IN/NOT IN to accept text input lists 'a','b'
* Fix bytea doesn't display as NULL when NULL
* Schema qualifing every object to avoid non wanted behaviour about users' rights
and schema_path
* Remove shared credentials when logging out of single server, to prevent automatic re-login
* Improved SSL connection handling, fix problems with connections from older php builds
* Fix bug with long role name truncation
* Fix bug with DELETE FROM when dropping a row (spq)
* Fix problems when deleteing PUBLIC schema
* Fix several bugs in aggregate support
* Improve autocompletion support
* Tighten up use of global scope variables
Translations
* utf traditional chinese (Kuo Chaoyi)
* utf simplified chinese (Kuo Chaoyi)
* Italian (Nicola Soranzo)
* Catalan (Bernat Pegueroles)
* French (ioguix)
* German (Albe Laurenz, spq)
* Japanese (Tadashi Jokagi)
* Hungarian (Sulyok Peti)
Version 4.1.3
-------------
Bugs
* Eliminate use of $_SERVER['PHP_SELF']. This fixes a regression in 4.1.2 for
non-mainstream locales (including SQL_ASCII)
* Validate client supplied server against entries in config.inc.php
* Fix undefined variable when altering a field in a table on PostgreSQL < 8.0
Version 4.1.2
-------------
Bugs
* Fix inability to assign a field type/domain of a different schema
* Fix PHP5 Strict mode complaints
* Fix IN/NOT IN to accept text input lists 'a','b'.
* Fix bytea doesn't display as NULL when NULL
* Fix bug in view creation wizard
* Fix XSS vulnerability:
http://www.securityfocus.com/bid/24115/
Escape HTML special characters before using $_SERVER['PHP_SELF']
Version 4.1.1
-------------
Bugs
* Fix problem where failed update would report as duplicate update error and
fail to return edit screen
* Fix error when using $conf[owned_only] on 8.1 & 8.2
* Fix error displaying schema names for parents of inherited tables
* Clean up non-standard escape warnings for PostgreSQL 8.2
* Fix improper text quoting for droping roles and aggregates
* Fix bug when dumping mixed case table names in PostgreSQL 8.2
Version 4.1
-----------
Features
* New icons by Niko <ennixo@free.fr>, from the graphics repository on pgFoundry.
* Added icons to bread crumb trail and tabs.
* Send encrypted passwords over the wire wherever possible.
* Alter sequence, nextval and setval (Guillaume)
* Auto-select 'WITHOUT OIDS' if 'default_with_oids' setting is false (Guillaume)
* Autovacuum configuration support (Robert Treat)
* Basic ROLE support (Chris Kings-Lynne, Javier Carlos)
* Add support for SSL connections (Eric Kinolik)
* Display content of pg_locks view (Javier Carlos)
* Add labels for checkboxes/radio buttons for improved usability (Guillaume)
* Display Prepared Transactions (Javier Carlos)
* Re-enable table browsing from tree icons (ioguix)
* Add Support For IN/OUT Parameters (John Jawed)
* Add column level information into the tree browser (ioguix)
* Promote column level interaction into its own page (ioguix)
* Add automatic lookup of foreign key values in insert/update fields (John Jawed)
* Add ability to create/drop/alter custom aggregates (Javier Carlos)
* Add enable/disable trigger (John Jawed)
* Add global comments for databases and tablespaces
Translations
* Catalan from Bernat
* Romanian from Alin Vaida
Version 4.0
-----------
Features
* Slony replication support (Thanks to sponsorship from SpikeSource)
* Allow current database to be at the top
* Allow base URL of PostgreSQL documentation to be configured
* Allow variable size textarea when editing values (Juergen Weigert)
* Allow SQL script upload to parse arbitrary SQL, including multiline
SQL statements. Improve output to show every command as its executed
and SELECT results.
* Add rudimentary support for PostgreSQL 8.1 and 8.2
* primary key and unique key at table creation (Andreas Huber)
* Add row|statement level options to create trigger for >= 7.4 (Robert Treat)
* Allow altering name (for >= 7.4) and owner (for >= 8.0) of a database (Bryan Encina)
* Allow login to several servers simultaneously
* Rearrange frame layout to suit multi-server support
* New browser tree with dynamically loading branches
(Using XLoadTree2 from http://webfx.eae.net/)
* Allow language change from the intro page at any time
* Avoid getting and setting encoding queries if possible
* Avoid version query in PHP 5 / PostgreSQL 7.4+
* Avoid query for superuser status in PHP 5 / PostgreSQL 7.4+
* Put PostgreSQL 7.4+ in read only mode for pagination of results
to avoid executing selects that have write side effects.
* Allow re-using username and password for all servers - saves re-entering
username and password for every server in a pool.
* Make default language 'auto' indicating auto detect. If a language is
deliberately specifed, then that will always be used and no detection will
occur.
* ADOdb library updated to version 4.65
Bugs
* Tree Icons are displayed middle instead of top
* Ensure login frame is always at top level (Russell Smith)
* Fix non-ASCII characters inserted in Unicode databases as HTML entities with
non-UTF8 web servers (Markus Bertheau)
* Fix export to work with release candidates and beta releases as well as finals
(Russell Smith)
* Fix port selection for local connections
* Fix timeouts on long running operations (Adrian Nida)
* Allow Multiline character and character varying editing and inserting
* Add automatic browser language selection for all languages
* Stop duplicate insert on re-POST of data
* Fix bug with exporting schema for servers < 7.3
* Fix opclasses on 7.2 and below
* Fix listing of opaque functions in 7.2
* Actually fix PHP 4.4.0's new strict references
Translations
* Japanese from Tadashi Jokagi
* Danish from Arne Eckmann
* Arabic from Zaki
* Romanian from Alin
* Afrikaans from Petri
* Polish from Rafal (utf-8 encoding)
* Slovak from Andrej
* German from Markus
* Spanish From Martin
* Hungarian from Sulyok
* Turkish from Devrim
Version 3.5.6
-------------
Bugs
* Actually fix PHP 4.4.0's new strict references
Version 3.5.5
-------------
Bugs
* Fix for PHP 4.4.0's new strict references
* Small improvement to Opera browser detection in the tree
* Fix listing of opaque functions in 7.2
* Fix listing of opclasses and functions pre 7.3
Version 3.5.4
-------------
Bugs
* Fix security hole in include() of language file:
http://secunia.com/advisories/15941/
Check now requires that the language filename be in the list
of known allowed filenames.
* Fix that functions returning cstring were not being listed
* Make parsing of PostgreSQL 1-dimensional arrays correct. Makes
named function parameter use more reliable.
* Fix downloading of the results of multiline queries.
Version 3.5.3
-------------
Bugs
* Fix using schema enabled dump on non-schema enabled backend
* Don't try setting no timeout when in safe mode
* Reload browser after executing arbitrary SQL
* Fix browser in RTL languages
* Fix inability to drop database using the drop link
* Fix last internal oid value for PostgreSQL 8.0
* Fix (again) dumping on v8 for windows, exclude dumping some objects.
Translations
* Portuguese from Francisco
Version 3.5.2
-------------
Bugs
* Fix export to work with release candidates and beta releases as well as finals
(Russell Smith)
* Fix port selection for local connections (Russell Smith)
* Fix timeouts on long running operations (Adrian Nida)
* Allow Multiline character and character varying editing and inserting
* Do browser language detection for all languages
Translations
* Japanese from Tadashi
* Danish from Arne
Version 3.5.1
-------------
Bugs
* Support 8.0beta5 schema tablespace changes
* Help link fixes
* Estimated row count in 7.0 and 7.1 fixes
* Priviliges nav fix
* Function privileges fix
* Search path fix
* pg_dump on win32 8.0 native fix
Translations
* Romanian from Alin
* Italian updates from Nicola
Version 3.5
-----------
Features
* Context-sensitive online help system
* Use language preferencies from browser (Markus Bertheau, Nicola Soranzo)
* Tablespace support for 8.0
* Support cancelling backend processes in 8.0
* Allow setting privileges on databases
* Allow setting schema search path in SQL window
* Allow filtering find results by object type
* Show function arguments in find results
* Support 8.0's named function arguments
* "Sticky" navigation. phpPgAdmin will now remember while tab you are
looking at (eg. 'Indexes') when you change which table you are viewing.
* New fast navigation bar. A breadcrumb style navigation bar for fast
jumping between areas.
* Much improved grant/revoke feature
* Allow creating and viewing composite types
* pg_dumpall integration. Now you can download the entire cluster via
phpPgAdmin.
* Show line numbers when viewing functions
* Syntax highlighting for PL/SQL, PL/PgSQL, PL/PHP, PL/Ruby, PL/Java,
PL/J, PL/Python and PL/Perl functions, thanks to Jacob D. Cohen's
BSD-licensed highlighting code on rafb.net
* Add page navigation links at the bottom as well as the top of the page
when browsing results.
* Support for 8.0's alter column type
* Support for 8.0's add columns with defaults and not null
Translations
* Romanian from Alin
* Arabic from Zaki
* Japanese from Tadashi
* Spanish from Robert & Martin
* Mongolian from Erdenemandal
* Ukrainian from Alex Rootoff
* Hebrew from jonatan
* Hungarian from Sulyok
* French from Pascal
* Afrikaans from Petri
* Turkish from Devrim
* Slovak from Andrej
* German from Markus
* Italian from Nicola
* Polish from Rafal
Bugs
* Fix that non-Auto mode import didn't work (Adrian Nida)
* Fix inability to drop constraints when using a non-english translation
* Work around MSIE's failure to handle downloads in SSL mode
* Allow insert, update, delete, references and trigger to be granted
and revoked on views.
Version 3.4.1
-------------
Bugs
* Fix export of mixed case tables pre 7.4
* Fix table export problems pre 7.3
* Fix join clause created by view wizard for pre 7.3
* Fix reindex of mixed case indexes
* Show domains in type lists in appropriate places
* Fix for multiline CDATA parsing in XML import
* Fix missing _schema notice in reports
Version 3.4
-----------
Features
* Add CACHE and CYCLE parameters in sequence creation
* View, add, edit and delete comments on tables, views, schemas,
aggregates, conversions, operators, functions, types,
opclasses, sequences and columns (Dan Boren & ChrisKL)
* Add config file option for turning off the display of comments
* Allow creating array columns in tables
* Allow adding array columns to tables
* Allow creating domains with type length and arrays
* Show domain base type and comment in domains list
* Allow import of CSV, Tabbed and XML data. "Auto" mode chooses
import mode based on the file extension.
* Allow upload and execution of _basic_ SQL scripts
* More admin features available: vacuum, analyze, cluster all and reindex
(with all options) (Bryan Encina)
* Fix SQL popup window to reload when the database is changed so
that the correct page encoding is used.
* Create view wizard (Bryan Encina)
* Allow specification of MATCH, DEFERRABLE and INITIALLY DEFERRED on
foreign keys.
* Automatically uncheck the NULL checkbox when data is typed in the value
field while editing data.
* Show query runtime when executing arbitrary SQL
* Allow renaming functions when backend supports it
* Views are now more like tables. They are listed in the browser,
you can view the virtual columns of the view and its column defaults.
Columns in view can also be renamed and have defaults set.
* Allow viewing, dropping and creation of rules on views.
* Support for 8.0-dev ALTER COLUMN TYPE, adding of SERIAL and BIGSERIAL
columns, adding NOT NULL columns and adding columns with defaults.
Bugs
* Fix pg_dump output for PostgreSQL 7.0.x and 7.1.x
* In 7.4 pg_dump, specify schema when dumping tables
* Fix bug in displaying array types in 7.0.x
* Fix bug where views appeared as tables in 7.0.x search results
* Fix bug where find object SQL on < 7.2 was broken
* Fix Find for domain constraints
* Fix popup SQL window so that two different phpPgAdmin instances should
not want to use the same pop-up.
* Fix create table if you don't supply as many fields as you originally
specified.
* Fix schema support for views
Translations
* Trad. Chinese from Chih-Hsin Lee
* Italian from Nicola
* Spanish from Martin
* Slovak from Andrej
* German from Markus
* Turkish from Devrim
* Hungarian from Sulyok
* French from Pascal
* Polish from Rafal
* Russian from Alex
Version 3.3.1
-------------
Bugs
* Fix table stats for <= 7.2
Translations
* Spanish from Martin
Version 3.3
-----------
Features
* Database dump feature, which uses pg_dump
* Large speed improvements by reducing number of database
connections and using external style sheet.
* SQL pop-up window now defaults to the current database
* Display aggregates and operator classes
* Integration with the PostgreSQL statistics collector. See
table and index performance and usage information.
* Display user session defaults for PostgreSQL >= 7.3
* Rename user feature for PostgreSQL >= 7.4
* Create functions returning arrays and table types
* Allow editing Select results by oid
* Allow pagination of queries entered in the SQL box
* Allow EXPLAIN ANALYZE of SQL queries (in both SQL boxes)
* Default cursor conveniently in SQL box and Find
Bugs
* Object browser fixed for databases with no schemas
* Properly detect that reports database is missing
* Fix for alter column on PostgreSQL 7.1
* phpPgAdmin now works without '.' in the include_path
* Can now remove expire dates on user accounts
* Properties of mixed case named views work in 7.4
Translations
* Spanish from Martin Marques
* Japanese from Tadashi Jokagi
* Swedish from Stefan Malmqvist
* Slovak from Andrej Misovik
* Hungarian from Sulyok Peter
* Trad. Chinese from Chih-Hsin Lee
* Italian from Nicola Soranzo
* Afrikaans from Petri Jooste
* Turkish from Devrim Gunduz
* German from Markus Bertheau
* Czech from Libor Vanek
* Russian from Alex Khodorivsky
Version 3.2.1
-------------
Bugs
* Trailing newline problem in chinese-sim translation fixed
Translations
* French from Pascal
* Russian from Step
Version 3.2
-----------
Features
* PostgreSQL 8.0 CVS support
* Option to dump table structure, data or structure and data
* Set datestyle and extra_float_digits when dumping data
* Results of table browse, table select, view browsing and report browsing
can now ALL be sorted by column
* Result rows of table selects can now be edited and deleted
* Extra login security to prevent logging into servers as postgres and
no password - a VERY common newbie error.
* Cluster indexes and indexed constraints (with analyze)
* Display clustered status of indexes and indexed constraints
* Table info - shows tables that reference the table, parent tables,
and child tables.
* Choice of operator when performing a Select
* 'Select All' feature of table selects now available on view
selects.
* Removed any trace of MySQL support
* Show casts
* Show conversions
* Show languages
* Make table icon link to browse table
* New show_advanced option that allows the hiding or display of
"advanced" objects such as conversions, types, operators, casts and
languages.
* Find Object feature can now find conversions, languages, domains,
constraints, indexes, rules and triggers.
* Better language Makefile for translators
* The SQL box now remembers your query when you click 'Back'.
Bugs
* Added legal DOCTYPE
* Allow creating foreign keys to tables not in current schema
* Always add brackets around CHECK () constraints
* Never display an index in both Indexes and Constraints
* BIGSERIAL missing from PostgreSQL 7.2
* Types lengths (eg. varchar(255)) weren't being displayed properly
in PostgreSQL 7.0.x
* Resetting sequence on 7.1+ now restarts at 1, not 2
* Remove deprecated column default 'now' from SQL script
* Properly escape pg_ in internal queries
Translations
* Afrikaans from Petri Jooste
* Hungarian from Sulyok Péter
* German update from Markus Bertheau
* Trad. Chinese from Chih-Hsin Lee
* Hungarian from Peti
* Spanish update from Martin Marques
* Slovak update from Andrej Misovic
* Turkish update from Devrim
* Swedish update from Stefan
* Italian update from Nicola
Version 3.1
-----------
Bug Fixes:
* Table browsing for 7.4 fixed
* Synch script for translators disabled due to bugginess. If you want
to use it, just comment out the warning lines from the script itself.
* Change HTML download to XHTML and make it a 100% conforming document, with DTD
* Alter XML format to allow future features
Translations:
* Trad. Chinese
* Dutch
* Spanish
* Swedish
* Turkish
* French
* Japanese
Version 3.1-rc-1
----------------
Bug Fixes
* Table browsing for != 7.3
* SQL window improvements
* Translation improvements
Version 3.1-beta-1
------------------
Features:
* Add first & last links to nav. Double number of pages shown.
* Allow granting privileges WITH GRANT OPTION for 7.4
* Allow revoking GRANT OPTION with CASCADE option for 7.4
* Display new PostgreSQL 7.4 grant options and grantor in privileges
* Find object feature
* Support for domains in 7.3 and domain constraints and alter domain in 7.4
* Add/drop users to/from groups
* Alter (rename) triggers
* Pop-up SQL window from Mark Gibson
* Superusers can always see all databases
* Default database encoding for languages
* Convert our images to PNG format
* Allow creating tables WITHOUT OIDS
* Show boolean values as TRUE or FALSE when viewing data
* Allow renaming table and changing table owner
* Refresh feature on table browse
* Support better formatted view dumps in 7.4
* When browsing data, numeric types are aligned right
* Ability to create unique and partial indexes
* View and edit table comments
* Changed XML format significantly. Now doesn't use field names as
tag names, outputs column type information, and is in correct XML format!
* Save result sets as views and reports in most cases
* Download the results of selects and reports
* Tick all box on Select feature
* Export in HTML format
* Allow listing of operators
* Add a robots.txt file to prevent search engine indexation
* Can now safely edit row based on OID. Guards are in place against duplicate OIDs.
* Works properly if you have cookies disabled
Bug Fixes:
* Lots of NULL value in table dump fixes (XML format changed slightly)
* Boolean default values and general boolean field handling fixes
* Support zero column tables
* Correctly display the contents of bytea fields
* Consider information_schema to be a system object
* Remember fields if index creation fails
* Fix saving and loading function volatility
* Don't list domains under types
* Lots of reports fixes (titles, page reloads, etc.)
* Selecting for NULL values in Select feature
Translations:
* Italian translation update from Nicola Soranzo
* German update from Markus Bertheau
* Spanish update from Martin Marques
* Trad. Chinese update from Chih-Hsin Lee
* Russian update from Step
* Slovak update from Andrej
* Polish update from Rafal
* Swedish translation from Stefan Malqvist
* Turkish update from Devrim Gunduz
* German update from Markus Bertheau
* Traditional Chinese update from Chih-Hsin Lee
* Spanish update from Martin
Version 3.0.1
-------------
Bug Fixes
* Lots of NULL value in table dump fixes (XML format changed slightly)
* Support zero column tables
* Correctly display the contents of bytea fields
* Error in ADODB_base.php
* Fix saving and loading function volatility
* Don't list domains under types
Version 3.0
-----------
* German update from Markus Bertheau
* Russian update from Alexander Khodorivsky
Version 3.0-rc-2
----------------
* Slovak update from Andrej Misovic
* Japanese update from Tadashi Jokagi
* Added 'defaultdb' per-connection variable
for installations where connection to template1
is disabled.
* Removed uses of call time pass by reference,
since it is a deprecated feature of PHP.
Version 3.0-rc-1
----------------
* Fix drop database reload browser bug
* Look & Feel upgrade from Davey
* Value & expression on edit row
* Chinese update from Chih-Hsin Lee
* Fixed support for functions and sequences
containing bizarre characters
Version 3.0-beta-1
-------------------
* Cascade drop on columns and constraints
* Czech translation
* Preserve spaces when displaying data
* Greatly improved PostgreSQL 7.2, 7.1 and 7.0 support
* Italian translation
* Show database version in top bar
* Many features useful for PostgreSQL hosting:
- Hide reports
- Filter for owned reports
- Hide admin for non-super users
- Easy for a user to change their own password
- Enforceable minimum password length
* Switched to PEAR's HTML_TreeMenu to avoid license issue
* Function editor can handle setof functions, and all
function properties for volatility, etc.
* Manage permissions on functions
* Massive table browsing improvements:
- Sort ascending and descending by clicking
on field name
- Trim long strings. Use 'expand' and 'collapse' to
see full strings or trimmed strings.
* Revoke on objects. Grant or revoke to multiple groups
and users at once.
* Brazilian Portuguese translation from Angelo Rigo
Version 3.0.0-dev-4
-------------------
* Sort on a column when browsing a table
* Slovak translation
* Turkish translation
* German translation
* Reload browser after create/drop of database, schemas and tables
* Select on views
* Add foreign key constraint, with actions
* Cascade drop on all objects
Version 3.0.0-dev-3
-------------------
* French translation
* Russian translations
* Japanese translations
* Trigger definitions
* ADODB upgrade
* Allow editing of non-null unique
Version 3.0.0-dev-2
-------------------
* Language files now use an array of strings
* Almost complete Chinese translation
* Create sequence
* Create trigger
* Create index
* Add check constraint
* Lots of small fixes
* Add column
Version 3.0.0-dev-1
-------------------
* Renamed to phpPgAdmin from WebDB
* Heaps of other stuff
Version 0.6 - 24-Dec-2002
-------------------------
* Support short_tags off
* Fix browsing tables, pagination, etc.
* Fix all error handling
* Fix problems with apostrophes in database, usernames or passwords
Version 0.5 - 20-Dec-2002
-------------------------
* Initial public release
* Still many problems making it unsuitable for production.
Version 0.1 - Early 2002
------------------------
* Initial development version

80
php/pgadmin/INSTALL Normal file
View File

@ -0,0 +1,80 @@
phpPgAdmin Installation Guide
-----------------------------
1. Unpack your download
If you've downloaded a tar.gz package, execute from a terminal:
gunzip phpPgAdmin-*.tar.gz
tar -xvf phpPgAdmin-*.tar
Else, if you've downloaded a tar.bz2 package, execute from a terminal:
bunzip2 phpPgAdmin-*.tar.bz2
tar -xvf phpPgAdmin-*.tar
Else, if you've downloaded a zip package, execute from a terminal:
unzip phpPgAdmin-*.zip
2. Configure phpPgAdmin
edit phpPgAdmin/conf/config.inc.php
If you mess up the configuration file, you can recover it from the
config.inc.php-dist file.
3. Set up the reports database.
If you want to enable reports (which are a useful feature) then go to
the 'sql' subdirectory and view the SQL script for your database. It
will contain instructions on how to set up the reports database.
4. If you run your PHP installation in safe mode, in order that the database
dump feature can work correctly, you need to set the 'safe_mode_allowed_env_vars'
php.ini variable to include the PGPASSWORD and PGUSER environmental variables
and the safe_mode_exec_dir to include /usr/bin (or wherever the pg_dump
binaries are found).
eg. safe_mode_allowed_env_vars = PHP_,PG
safe_mode_exec_dir = /usr/bin
Given that you usually don't want to allow everything in /usr/bin to
be executed, you might want to copy the pg_dump and pg_dumpall utilities
to a directory by themselves.
Also, you will need to ensure that your 'pg_dump' and 'pg_dumpall' utilities
are executable by the PHP process, if you want dump support in phpPgAdmin.
Lastly, if you run phpPgAdmin in safe mode, very long running imports,
exports and transactions may time out and be aborted.
5. Enable the statistics collector in PostgreSQL. phpPgAdmin will display
table and index performance and usage statistics if you have enabled the
PostgreSQL statistics collector. To enable the collector, uncomment the
following lines in your postgresql.conf and enable them:
stats_start_collector = true
stats_command_string = true
stats_block_level = true
stats_row_level = true
6. Browse to the phpPgAdmin installation using a web browser. You might
need cookies enabled for phpPgAdmin to work.
7. IMPORTANT - SECURITY
PostgreSQL by default does not require you to use a password to log in.
We STRONGLY recomment that you enable md5 passwords for local connections
in your pg_hba.conf, and set a password for the default superuser account.
Due to the large number of phpPgAdmin installations that have not set
passwords on local connections, there is now a configuration file
option called 'extra_login_security', which is TRUE by default. While
this option is enabled, you will be unable to log in to phpPgAdmin as
the 'root', 'administrator', 'pgsql' or 'postgres' users and empty passwords
will not work.
Once you are certain you have properly secured your database server, you
can then disable 'extra_login_security' so that you can log in as your
database administrator using the administrator password.

12
php/pgadmin/LICENSE Normal file
View File

@ -0,0 +1,12 @@
Copyright (c) 2002, 2003, 2004, 2005 The phpPgAdmin Project
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License <http://www.opensource.org/gpl-license.html>
for more details.

241
php/pgadmin/TODO Normal file
View File

@ -0,0 +1,241 @@
PHPPGADMIN TODO LIST FOR DEVELOPERS
-----------------------------------
phpPgAdmin is an open source project which means that if you see something on
this list that you would like to implement, just send us a patch. You can find
our project page here:
http://sourceforge.net/projects/phppgadmin/
An item is marked 'claimed' when a username in brackets is put after the TODO
item. If you want to work a claimed item, please contact the developers list.
An item is marked with a '-' if it has been completed.
Cluster
-------
* Allow reading of postgresql.conf and pg_hba.conf per pg_read_file() in 8.1
* Support pg_reload_conf(), pg_rotate_logfile() 8.1 commands
* Add support for default db to connect to on login page (we had several users complaining about that lately)
Export
------
* Switch to SPARQL format:
http://www.w3.org/TR/2005/WD-rdf-sparql-XMLres-20050801/
Actually...SQL/XML is maybe better.
Import
------
* Allow import of data via compressed (bzip/gzip/zip) files
Users
-----
* user variables (eg. ALTER USER SET .. TO ...)
Groups
------
Roles
-----
Permissions
-----------
* Grant ... on all tables, views, ... to user, group, public
Databases
---------
* Add alter database variables
* Add database stats
* REASSIGN OWNED & DROP OWNED support for 8.2+
- http://www.postgresql.org/docs/8.2/interactive/sql-reassign-owned.html
- http://www.postgresql.org/docs/8.2/interactive/sql-drop-owned.html
Schemas
-------
Large Objects
-------------
* Add support for large objects
(review patch from Dmitry Koterov https://github.com/DmitryKoterov/phppgadmin/commit/3072e666bd2b291feb91823b41f1fdb8ec7f492d )
Tables
------
* Rewrite WITHOUT OIDs with more natural WITH OIDS
* Allow FKs during create table (Jawed)
* When adding a column or creating a table, prevent size on non-size types (eg. integer(2)). You can find these by looking at format_type in the postgresql source code.
* Add WITH storage_parameter option to create table [8.2]
* Add last vacuum and analyze information from statistics tables [8.2]
* Restrict operators (from $selectOps array) to appropriate types (ie. no LIKE for int4 fields)
* Alter column should handle types with implicit cast types distinctly from those requiring a USING clause
* Where ENUM types are an option, restrict choice to enum values [8.3]
Columns
-------
* Add column constraints during creation and altering of columns
Views
-----
* Support temporary views per 8.1?
* Support updateable views, see http://gerrybthunkings.blogspot.com/2010/01/how-should-postgresql-pgadmin-iii-deal.html
Sequences
---------
Functions
---------
* Remove options for OUT/INOUT params in older servers
* Clean up javascript html spec warnings
* GUC settings [8.3]
* Default param values
Indexes
-------
* Support 8.1 Reindex System commands
* Expressional indexes
* Create Index Asc/Desc, Nulls First/Last [8.3]
Types
-----
* Suppres psuedo-type options in type list for creating composite types. (done ?)
Operators
---------
* Create
* Create/Alter/Drop Operator Family
Operator Classes
----------------
* Create
Triggers
--------
* Allow functions from other schemas.
* Support replica trigger modes (8.3)
Aggregates
----------
* Allow for multi-column aggregates [8.2]
* Rewrite the aggregate edition page ! It is using input tetxt everywhere presently, even for owner and schéma !
Languages
---------
* Drop
* Create
* Alter owner [8.3]
* Alter name [8.3]
Domains
-------
* Alter DOMAIN SET SCHEMA support
Conversions
-----------
* Properties
* Drop
* Create
Casts
-----
* Properties
* Drop
* Create
Full Text Search (8.3)
----------------------
* Create/Alter/Drop parser
* Alter Owner
Miscellaneous
-------------
* Audit for PHP 5.3.x compatability
* Support 8.1 standard compliant strings (E'')
* Support per-database connection limits per 8.1
* Put a 'What's blocking this query' on Processes view
* Show prepared statements on database view [8.2]
* Show cursors on database view [8.2]
* Show NOTICES on queries in SQL window/file
* Printable view of things
* Show comments for all objects (Dan Boren)
* Allow setting/dropping comments for all objects (Dan Boren)
* Show owner for all objects
* Allow changing owner for objects that have this feature [7.4+ generally]
* Add CASCADE option to Truncate [8.2]
* Add ONLY option to Truncate [8.4]
* Add information about synch tool to TRANSLATORS
* Translated FAQ
* Pull FAQ/HISTORY/CREDITS/etc... from CVS for website.
* Add support for csvlogs [8.3]
* Add executed file scripts in history
Exotic
------
* Support contrib/tsearch2 for easy full text indexes
* Pivot reports (ADODB has a feature for this)
* Parameterized reports (use prepared queries)
* Full web accessability conformance
Principles
----------
* register_globals off support
* maximum error_reporting support - enforces code quality, reduces bugs and
improves security
* PHP 5.0 features used
* No HTML font, colour, layout tags. Use CSS for everything
* One day we should make it all XHTML
* everything properly escaped - prevent sql injection and cross-site scripting
probs
* Support Postgres 7.4 and upwards
* psql -E is a cool way of seeing how to do schema queries
* Checking out older versions of describe.c in src/bin/psql in the postgres
distro is a good way of seeing how to query older versions of postgres for
schema information
* Put functions in the highest class possible. For instance, simple selects
should be in Postgres, whereas something that works for < 8.2 should be in the
8.1 class. This will minimise bugs and duplicated code.
* Adhere to current coding standards
* Avoid using global variables if possible

84
php/pgadmin/TRANSLATORS Normal file
View File

@ -0,0 +1,84 @@
Translator Info
---------------
If you like phpPgAdmin, then why not translate it into your native language?
Translation is slightly complicated in phpPgAdmin compared to other PHP
software, since we support viewing database encodings that are different to
your language encoding.
Also, there are quite a large number of strings to be translated. Partial
translations are better than no translations at all, and a rough guide is that
the strings are in the order from most important to least important in the
language file. You can ask the developers list if you don't know what a
certain string means.
To translate messages, you will need to install GNU Recode on your computer.
GNU Recode: http://www.gnu.org/software/recode/recode.html
Your favourite OS should have a GNU Recode package available. (See bottom for
details.)
Once you have Recode installed, these are the steps to creating a new
translation:
1. Go to the lang/ subdirectory
2. Copy english.php to yourlanguage.php
3. Update the comment at the top of the file. Put yourself as the language
maintainer. Edit the 'applang' variable and put your language's name in it,
in your language.
Edit the 'appcharset' variable and put in the name of the encoding for your
language.
4. Go through as much of the rest of the file as you wish, replacing the
English strings with strings in your native language.
At this point, you can send the yourlanguage.php file to us and we will take
care of testing and recoding the translation. Please only do that if you
find the rest of these steps too difficult.
5. Edit the Makefile in the lang/ directory and add an entry for your new
language. Note that the parameter for Recode is "yourcharset..HTML".
6. Run the Makefile by typing 'make yourlanguage'. A recoded language file
will appear in the lang/recoded/ directory. If the recoding fails, then
fix the error in your language file and try again.
7. The HTML encoded language file is what phpPgAdmin actually uses to display
localised strings. Have a look at the recoded file to see how the HTML
encoding works. By encoding your language like this, we can display your
language's characters as well as the characters of the language in your
database.
8. To add your language to phpPgAdmin, edit the lang/translations.php file
and add your language to the $appLangFiles array.
You must include the HTML encoded version of your language's name. You can
get this from the recoded version of your translated strings file.
Also, add your language to the $availableLanguages array for
browser auto detection.
9. Send your contribution to us. We need the lib.inc.php entry as well as the
yourlanguage.php file in lang/. We don't need the recoded file as we can
recode it ourselves before committing it. Email to the developers list:
phppgadmin-devel@lists.sourceforge.net
10. Thank you for your contribution! You have just made phpPgAdmin accessible
to thousands more users!
11. There exists a tool named 'langcheck' in the lang/ directory. To run it,
just type 'php langcheck <language>'. It will give you a report about
which strings are missing from your language file and which need to be
deleted.
Appendix A: Ways to Get Recode
------------------------------
* FreeBSD: cd /usr/ports/converters/recode; make install clean
* BSD: ftp.gnu.org/gnu/recode/
* Red Hat: rpm -Uvh recode-3.6-6.i386.rpm
* Debian: Available via apt-get
* Win32: http://unxutils.sourceforge.net

741
php/pgadmin/admin.php Normal file
View File

@ -0,0 +1,741 @@
<?php
$script = ''; // init global value script
/**
* Show confirmation of cluster and perform cluster
*/
function doCluster($type, $confirm=false) {
global $script, $data, $misc, $lang;
if (($type == 'table') && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
doDefault($lang['strspecifytabletocluster']);
return;
}
if ($confirm) {
if (isset($_REQUEST['ma'])) {
$misc->printTrail('schema');
$misc->printTitle($lang['strclusterindex'], 'pg.index.cluster');
echo "<form action=\"{$script}\" method=\"post\">\n";
foreach($_REQUEST['ma'] as $v) {
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
echo "<p>", sprintf($lang['strconfclustertable'], $misc->printVal($a['table'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table[]\" value=\"", htmlspecialchars($a['table']), "\" />\n";
}
} // END if multi cluster
else {
$misc->printTrail($type);
$misc->printTitle($lang['strclusterindex'], 'pg.index.cluster');
echo "<form action=\"{$script}\" method=\"post\">\n";
if ($type == 'table') {
echo "<p>", sprintf($lang['strconfclustertable'], $misc->printVal($_REQUEST['object'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['object']), "\" />\n";
}
else {
echo "<p>", sprintf($lang['strconfclusterdatabase'], $misc->printVal($_REQUEST['object'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table\" value=\"\" />\n";
}
}
echo "<input type=\"hidden\" name=\"action\" value=\"cluster\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"cluster\" value=\"{$lang['strcluster']}\" />\n"; //TODO
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
} // END single cluster
else {
//If multi table cluster
if ($type == 'table') { // cluster one or more table
if (is_array($_REQUEST['table'])) {
$msg='';
foreach($_REQUEST['table'] as $o) {
$status = $data->clusterIndex($o);
if ($status == 0)
$msg.= sprintf('%s: %s<br />', htmlentities($o), $lang['strclusteredgood']);
else {
doDefault($type, sprintf('%s%s: %s<br />', $msg, htmlentities($o), $lang['strclusteredbad']));
return;
}
}
// Everything went fine, back to the Default page....
doDefault($msg);
}
else {
$status = $data->clusterIndex($_REQUEST['object']);
if ($status == 0) {
doAdmin($type, $lang['strclusteredgood']);
}
else
doAdmin($type, $lang['strclusteredbad']);
}
}
else { // Cluster all tables in database
$status = $data->clusterIndex();
if ($status == 0) {
doAdmin($type, $lang['strclusteredgood']);
}
else
doAdmin($type, $lang['strclusteredbad']);
}
}
}
/**
* Show confirmation of reindex and perform reindex
*/
function doReindex($type, $confirm=false) {
global $script, $data, $misc, $lang, $_reload_browser;
if (($type == 'table') && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
doDefault($lang['strspecifytabletoreindex']);
return;
}
if ($confirm) {
if (isset($_REQUEST['ma'])) {
$misc->printTrail('schema');
$misc->printTitle($lang['strreindex'], 'pg.reindex');
echo "<form action=\"{$script}\" method=\"post\">\n";
foreach($_REQUEST['ma'] as $v) {
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
echo "<p>", sprintf($lang['strconfreindextable'], $misc->printVal($a['table'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table[]\" value=\"", htmlspecialchars($a['table']), "\" />\n";
}
} // END if multi reindex
else {
$misc->printTrail($type);
$misc->printTitle($lang['strreindex'], 'pg.reindex');
echo "<form action=\"{$script}\" method=\"post\">\n";
if ($type == 'table') {
echo "<p>", sprintf($lang['strconfreindextable'], $misc->printVal($_REQUEST['object'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['object']), "\" />\n";
}
else {
echo "<p>", sprintf($lang['strconfreindexdatabase'], $misc->printVal($_REQUEST['object'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table\" value=\"\" />\n";
}
}
echo "<input type=\"hidden\" name=\"action\" value=\"reindex\" />\n";
if ($data->hasForceReindex())
echo "<p><input type=\"checkbox\" id=\"reindex_force\" name=\"reindex_force\" /><label for=\"reindex_force\">{$lang['strforce']}</label></p>\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"reindex\" value=\"{$lang['strreindex']}\" />\n"; //TODO
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
} // END single reindex
else {
//If multi table reindex
if (($type == 'table') && is_array($_REQUEST['table'])) {
$msg='';
foreach($_REQUEST['table'] as $o) {
$status = $data->reindex(strtoupper($type), $o, isset($_REQUEST['reindex_force']));
if ($status == 0)
$msg.= sprintf('%s: %s<br />', htmlentities($o), $lang['strreindexgood']);
else {
doDefault($type, sprintf('%s%s: %s<br />', $msg, htmlentities($o), $lang['strreindexbad']));
return;
}
}
// Everything went fine, back to the Default page....
$_reload_browser = true;
doDefault($msg);
}
else {
$status = $data->reindex(strtoupper($type), $_REQUEST['object'], isset($_REQUEST['reindex_force']));
if ($status == 0) {
$_reload_browser = true;
doAdmin($type, $lang['strreindexgood']);
}
else
doAdmin($type, $lang['strreindexbad']);
}
}
}
/**
* Show confirmation of analyze and perform analyze
*/
function doAnalyze($type, $confirm=false) {
global $script, $data, $misc, $lang, $_reload_browser;
if (($type == 'table') && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
doDefault($lang['strspecifytabletoanalyze']);
return;
}
if ($confirm) {
if (isset($_REQUEST['ma'])) {
$misc->printTrail('schema');
$misc->printTitle($lang['stranalyze'], 'pg.analyze');
echo "<form action=\"{$script}\" method=\"post\">\n";
foreach($_REQUEST['ma'] as $v) {
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
echo "<p>", sprintf($lang['strconfanalyzetable'], $misc->printVal($a['table'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table[]\" value=\"", htmlspecialchars($a['table']), "\" />\n";
}
} // END if multi analyze
else {
$misc->printTrail($type);
$misc->printTitle($lang['stranalyze'], 'pg.analyze');
echo "<form action=\"{$script}\" method=\"post\">\n";
if ($type == 'table') {
echo "<p>", sprintf($lang['strconfanalyzetable'], $misc->printVal($_REQUEST['object'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['object']), "\" />\n";
}
else {
echo "<p>", sprintf($lang['strconfanalyzedatabase'], $misc->printVal($_REQUEST['object'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table\" value=\"\" />\n";
}
}
echo "<input type=\"hidden\" name=\"action\" value=\"analyze\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"analyze\" value=\"{$lang['stranalyze']}\" />\n"; //TODO
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
} // END single analyze
else {
//If multi table analyze
if (($type == 'table') && is_array($_REQUEST['table'])) {
$msg='';
foreach($_REQUEST['table'] as $o) {
$status = $data->analyzeDB($o);
if ($status == 0)
$msg.= sprintf('%s: %s<br />', htmlentities($o), $lang['stranalyzegood']);
else {
doDefault($type, sprintf('%s%s: %s<br />', $msg, htmlentities($o), $lang['stranalyzebad']));
return;
}
}
// Everything went fine, back to the Default page....
$_reload_browser = true;
doDefault($msg);
}
else {
//we must pass table here. When empty, analyze the whole db
$status = $data->analyzeDB($_REQUEST['table']);
if ($status == 0) {
$_reload_browser = true;
doAdmin($type, $lang['stranalyzegood']);
}
else
doAdmin($type, $lang['stranalyzebad']);
}
}
}
/**
* Show confirmation of vacuum and perform actual vacuum
*/
function doVacuum($type, $confirm = false) {
global $script, $data, $misc, $lang, $_reload_browser;
if (($type == 'table') && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
doDefault($lang['strspecifytabletovacuum']);
return;
}
if ($confirm) {
if (isset($_REQUEST['ma'])) {
$misc->printTrail('schema');
$misc->printTitle($lang['strvacuum'], 'pg.vacuum');
echo "<form action=\"{$script}\" method=\"post\">\n";
foreach($_REQUEST['ma'] as $v) {
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
echo "<p>", sprintf($lang['strconfvacuumtable'], $misc->printVal($a['table'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table[]\" value=\"", htmlspecialchars($a['table']), "\" />\n";
}
} // END if multi vacuum
else {
$misc->printTrail($type);
$misc->printTitle($lang['strvacuum'], 'pg.vacuum');
echo "<form action=\"{$script}\" method=\"post\">\n";
if ($type == 'table') {
echo "<p>", sprintf($lang['strconfvacuumtable'], $misc->printVal($_REQUEST['object'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['object']), "\" />\n";
}
else {
echo "<p>", sprintf($lang['strconfvacuumdatabase'], $misc->printVal($_REQUEST['object'])), "</p>\n";
echo "<input type=\"hidden\" name=\"table\" value=\"\" />\n";
}
}
echo "<input type=\"hidden\" name=\"action\" value=\"vacuum\" />\n";
echo $misc->form;
echo "<p><input type=\"checkbox\" id=\"vacuum_full\" name=\"vacuum_full\" /> <label for=\"vacuum_full\">{$lang['strfull']}</label></p>\n";
echo "<p><input type=\"checkbox\" id=\"vacuum_analyze\" name=\"vacuum_analyze\" /> <label for=\"vacuum_analyze\">{$lang['stranalyze']}</label></p>\n";
echo "<p><input type=\"checkbox\" id=\"vacuum_freeze\" name=\"vacuum_freeze\" /><label for=\"vacuum_freeze\">{$lang['strfreeze']}</label></p>\n";
echo "<input type=\"submit\" name=\"vacuum\" value=\"{$lang['strvacuum']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
} // END single vacuum
else {
//If multi drop
if (is_array($_REQUEST['table'])) {
$msg='';
foreach($_REQUEST['table'] as $t) {
$status = $data->vacuumDB($t, isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze']));
if ($status == 0)
$msg.= sprintf('%s: %s<br />', htmlentities($t), $lang['strvacuumgood']);
else {
doDefault($type, sprintf('%s%s: %s<br />', $msg, htmlentities($t), $lang['strvacuumbad']));
return;
}
}
// Everything went fine, back to the Default page....
$_reload_browser = true;
doDefault($msg);
}
else {
//we must pass table here. When empty, vacuum the whole db
$status = $data->vacuumDB($_REQUEST['table'], isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze']));
if ($status == 0) {
$_reload_browser = true;
doAdmin($type, $lang['strvacuumgood']);
}
else
doAdmin($type, $lang['strvacuumbad']);
}
}
}
/**
* Add or Edit autovacuum params and save them
*/
function doEditAutovacuum($type, $confirm, $msg='') {
global $script, $data, $misc, $lang;
if (empty($_REQUEST['table'])) {
doAdmin($type, '', $lang['strspecifyeditvacuumtable']);
return;
}
$script = ($type == 'database')? 'database.php' : 'tables.php';
if ($confirm) {
$misc->printTrail($type);
$misc->printTitle(sprintf($lang['streditvacuumtable'], $misc->printVal($_REQUEST['table'])));
$misc->printMsg(sprintf($msg, $misc->printVal($_REQUEST['table'])));
if (empty($_REQUEST['table'])) {
doAdmin($type, '', $lang['strspecifyeditvacuumtable']);
return;
}
$old_val = $data->getTableAutovacuum($_REQUEST['table']);
$defaults = $data->getAutovacuum();
$old_val = $old_val->fields;
if (isset($old_val['autovacuum_enabled']) and ($old_val['autovacuum_enabled'] == 'off')) {
$enabled = '';
$disabled = 'checked="checked"';
}
else {
$enabled = 'checked="checked"';
$disabled = '';
}
if (!isset($old_val['autovacuum_vacuum_threshold'])) $old_val['autovacuum_vacuum_threshold'] = '';
if (!isset($old_val['autovacuum_vacuum_scale_factor'])) $old_val['autovacuum_vacuum_scale_factor'] = '';
if (!isset($old_val['autovacuum_analyze_threshold'])) $old_val['autovacuum_analyze_threshold'] = '';
if (!isset($old_val['autovacuum_analyze_scale_factor'])) $old_val['autovacuum_analyze_scale_factor'] = '';
if (!isset($old_val['autovacuum_vacuum_cost_delay'])) $old_val['autovacuum_vacuum_cost_delay'] = '';
if (!isset($old_val['autovacuum_vacuum_cost_limit'])) $old_val['autovacuum_vacuum_cost_limit'] = '';
echo "<form action=\"{$script}\" method=\"post\">\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"editautovac\" />\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo "<br />\n<br />\n<table>\n";
echo "\t<tr><td>&nbsp;</td>\n";
echo "<th class=\"data\">{$lang['strnewvalues']}</th><th class=\"data\">{$lang['strdefaultvalues']}</th></tr>\n";
echo "\t<tr><th class=\"data left\">{$lang['strenable']}</th>\n";
echo "<td class=\"data1\">\n";
echo "<label for=\"on\">on</label><input type=\"radio\" name=\"autovacuum_enabled\" id=\"on\" value=\"on\" {$enabled} />\n";
echo "<label for=\"off\">off</label><input type=\"radio\" name=\"autovacuum_enabled\" id=\"off\" value=\"off\" {$disabled} /></td>\n";
echo "<th class=\"data left\">{$defaults['autovacuum']}</th></tr>\n";
echo "\t<tr><th class=\"data left\">{$lang['strvacuumbasethreshold']}</th>\n";
echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_threshold\" value=\"{$old_val['autovacuum_vacuum_threshold']}\" /></td>\n";
echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_threshold']}</th></tr>\n";
echo "\t<tr><th class=\"data left\">{$lang['strvacuumscalefactor']}</th>\n";
echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_scale_factor\" value=\"{$old_val['autovacuum_vacuum_scale_factor']}\" /></td>\n";
echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_scale_factor']}</th></tr>\n";
echo "\t<tr><th class=\"data left\">{$lang['stranalybasethreshold']}</th>\n";
echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_analyze_threshold\" value=\"{$old_val['autovacuum_analyze_threshold']}\" /></td>\n";
echo "<th class=\"data left\">{$defaults['autovacuum_analyze_threshold']}</th></tr>\n";
echo "\t<tr><th class=\"data left\">{$lang['stranalyzescalefactor']}</th>\n";
echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_analyze_scale_factor\" value=\"{$old_val['autovacuum_analyze_scale_factor']}\" /></td>\n";
echo "<th class=\"data left\">{$defaults['autovacuum_analyze_scale_factor']}</th></tr>\n";
echo "\t<tr><th class=\"data left\">{$lang['strvacuumcostdelay']}</th>\n";
echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_cost_delay\" value=\"{$old_val['autovacuum_vacuum_cost_delay']}\" /></td>\n";
echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_cost_delay']}</th></tr>\n";
echo "\t<tr><th class=\"data left\">{$lang['strvacuumcostlimit']}</th>\n";
echo "<td class=\"datat1\"><input type=\"text\" name=\"autovacuum_vacuum_cost_limit\" value=\"{$old_val['autovacuum_vacuum_cost_limit']}\" /></td>\n";
echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_cost_limit']}</th></tr>\n";
echo "</table>\n";
echo "<br />";
echo "<br />";
echo "<input type=\"submit\" name=\"save\" value=\"{$lang['strsave']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
else {
$status = $data->saveAutovacuum($_REQUEST['table'], $_POST['autovacuum_enabled'], $_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']);
if ($status == 0)
doAdmin($type, '', sprintf($lang['strsetvacuumtablesaved'], $_REQUEST['table']));
else
doEditAutovacuum($type, true, $lang['strsetvacuumtablefail']);
}
}
/**
* confirm drop autovacuum params for a table and drop it
*/
function doDropAutovacuum($type, $confirm) {
global $script, $data, $misc, $lang;
if (empty($_REQUEST['table'])) {
doAdmin($type, '', $lang['strspecifydelvacuumtable']);
return;
}
if ($confirm) {
$misc->printTrail($type);
$misc->printTabs($type,'admin');
$script = ($type == 'database')? 'database.php' : 'tables.php';
printf("<p>{$lang['strdelvacuumtable']}</p>\n",
$misc->printVal("\"{$_GET['schema']}"."{$_GET['table']}\""));
echo "<form style=\"float: left\" action=\"{$script}\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"delautovac\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo "<input type=\"hidden\" name=\"rel\" value=\"", htmlspecialchars(serialize(array($_REQUEST['schema'], $_REQUEST['table']))), "\" />\n";
echo "<input type=\"submit\" name=\"yes\" value=\"{$lang['stryes']}\" />\n";
echo "</form>\n";
echo "<form action=\"{$script}\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"admin\" />\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"no\" value=\"{$lang['strno']}\" />\n";
echo "</form>\n";
}
else {
$status = $data->dropAutovacuum($_POST['table']);
if ($status == 0) {
doAdmin($type, '', sprintf($lang['strvacuumtablereset'], $misc->printVal($_POST['table'])));
}
else
doAdmin($type, '', sprintf($lang['strdelvacuumtablefail'], $misc->printVal($_POST['table'])));
}
}
/**
* database/table administration and tuning tasks
*
* $Id: admin.php
*/
function doAdmin($type, $msg = '') {
global $script, $data, $misc, $lang;
$misc->printTrail($type);
$misc->printTabs($type,'admin');
$misc->printMsg($msg);
if ($type == 'database')
printf("<p>{$lang['stradminondatabase']}</p>\n", $misc->printVal($_REQUEST['object']));
else
printf("<p>{$lang['stradminontable']}</p>\n", $misc->printVal($_REQUEST['object']));
echo "<table style=\"width: 50%\">\n";
echo "<tr>\n";
echo "<th class=\"data\">";
$misc->printHelp($lang['strvacuum'],'pg.admin.vacuum')."</th>\n";
echo "</th>";
echo "<th class=\"data\">";
$misc->printHelp($lang['stranalyze'],'pg.admin.analyze');
echo "</th>";
if ($data->hasRecluster()){
echo "<th class=\"data\">";
$misc->printHelp($lang['strclusterindex'],'pg.index.cluster');
echo "</th>";
}
echo "<th class=\"data\">";
$misc->printHelp($lang['strreindex'],'pg.index.reindex');
echo "</th>";
echo "</tr>";
// Vacuum
echo "<tr class=\"row1\">\n";
echo "<td style=\"text-align: center; vertical-align: bottom\">\n";
echo "<form action=\"{$script}\" method=\"post\">\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"confirm_vacuum\" />\n";
echo $misc->form;
if ($type == 'table') {
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['object']), "\" />\n";
echo "<input type=\"hidden\" name=\"subject\" value=\"table\" />\n";
}
echo "<input type=\"submit\" value=\"{$lang['strvacuum']}\" /></p>\n";
echo "</form>\n";
echo "</td>\n";
// Analyze
echo "<td style=\"text-align: center; vertical-align: bottom\">\n";
echo "<form action=\"{$script}\" method=\"post\">\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"confirm_analyze\" />\n";
echo $misc->form;
if ($type == 'table') {
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['object']), "\" />\n";
echo "<input type=\"hidden\" name=\"subject\" value=\"table\" />\n";
}
echo "<input type=\"submit\" value=\"{$lang['stranalyze']}\" /></p>\n";
echo "</form>\n";
echo "</td>\n";
// Cluster
if ($data->hasRecluster()){
$disabled = '';
echo "<td style=\"text-align: center; vertical-align: bottom\">\n";
echo "<form action=\"{$script}\" method=\"post\">\n";
echo $misc->form;
if ($type == 'table') {
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['object']), "\" />\n";
echo "<input type=\"hidden\" name=\"subject\" value=\"table\" />\n";
if (!$data->alreadyClustered($_REQUEST['object'])) {
$disabled = 'disabled="disabled" ';
echo "{$lang['strnoclusteravailable']}<br />";
}
}
echo "<p><input type=\"hidden\" name=\"action\" value=\"confirm_cluster\" />\n";
echo "<input type=\"submit\" value=\"{$lang['strclusterindex']}\" $disabled/></p>\n";
echo "</form>\n";
echo "</td>\n";
}
// Reindex
echo "<td style=\"text-align: center; vertical-align: bottom\">\n";
echo "<form action=\"{$script}\" method=\"post\">\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"confirm_reindex\" />\n";
echo $misc->form;
if ($type == 'table') {
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['object']), "\" />\n";
echo "<input type=\"hidden\" name=\"subject\" value=\"table\" />\n";
}
echo "<input type=\"submit\" value=\"{$lang['strreindex']}\" /></p>\n";
echo "</form>\n";
echo "</td>\n";
echo "</tr>\n";
echo "</table>\n";
// Autovacuum
if($data->hasAutovacuum()) {
// get defaults values for autovacuum
$defaults = $data->getAutovacuum();
// Fetch the autovacuum properties from the database or table if != ''
if ($type == 'table') $autovac = $data->getTableAutovacuum($_REQUEST['table']);
else $autovac = $data->getTableAutovacuum();
echo "<br /><br /><h2>{$lang['strvacuumpertable']}</h2>";
echo '<p>' . (($defaults['autovacuum'] == 'on') ? $lang['strturnedon'] : $lang['strturnedoff'] ) . '</p>';
echo "<p class=\"message\">{$lang['strnotdefaultinred']}</p>";
function enlight($f, $p) {
if ( isset($f[$p[0]]) and ($f[$p[0]] != $p[1]))
return "<span style=\"color:#F33;font-weight:bold\">". htmlspecialchars($f[$p[0]]) ."</span>";
return htmlspecialchars($p[1]);
}
$columns = array(
'namespace' => array(
'title' => $lang['strschema'],
'field' => field('nspname'),
'url' => "redirect.php?subject=schema&amp;{$misc->href}&amp;",
'vars' => array('schema' => 'nspname'),
),
'relname' => array(
'title' => $lang['strtable'],
'field' => field('relname'),
'url' => "redirect.php?subject=table&amp;{$misc->href}&amp;",
'vars' => array('table' => 'relname', 'schema' => 'nspname'),
),
'autovacuum_enabled' => array(
'title' => $lang['strenabled'],
'field' => callback('enlight', array('autovacuum_enabled', $defaults['autovacuum'])),
'type' => 'verbatim'
),
'autovacuum_vacuum_threshold' => array(
'title' => $lang['strvacuumbasethreshold'],
'field' => callback('enlight', array('autovacuum_vacuum_threshold', $defaults['autovacuum_vacuum_threshold'])),
'type' => 'verbatim'
),
'autovacuum_vacuum_scale_factor' => array(
'title' => $lang['strvacuumscalefactor'],
'field' => callback('enlight', array('autovacuum_vacuum_scale_factor', $defaults['autovacuum_vacuum_scale_factor'])),
'type' => 'verbatim'
),
'autovacuum_analyze_threshold' => array(
'title' => $lang['stranalybasethreshold'],
'field' => callback('enlight', array('autovacuum_analyze_threshold', $defaults['autovacuum_analyze_threshold'])),
'type' => 'verbatim'
),
'autovacuum_analyze_scale_factor' => array(
'title' => $lang['stranalyzescalefactor'],
'field' => callback('enlight', array('autovacuum_analyze_scale_factor', $defaults['autovacuum_analyze_scale_factor'])),
'type' => 'verbatim'
),
'autovacuum_vacuum_cost_delay' => array(
'title' => $lang['strvacuumcostdelay'],
'field' => concat(callback('enlight', array('autovacuum_vacuum_cost_delay', $defaults['autovacuum_vacuum_cost_delay'])), 'ms'),
'type' => 'verbatim'
),
'autovacuum_vacuum_cost_limit' => array(
'title' => $lang['strvacuumcostlimit'],
'field' => callback('enlight', array('autovacuum_vacuum_cost_limit', $defaults['autovacuum_vacuum_cost_limit'])),
'type' => 'verbatim'
),
);
// Maybe we need to check permissions here?
$columns['actions'] = array('title' => $lang['stractions']);
$actions = array(
'edit' => array(
'title' => $lang['stredit'],
'url' => "{$script}?action=confeditautovac&amp;{$misc->href}&amp;subject={$type}&amp;",
'vars' => array(
'schema' => 'nspname',
'table' => 'relname'
)
),
'delete' => array(
'title' => $lang['strdelete'],
'url' => "{$script}?action=confdelautovac&amp;{$misc->href}&amp;subject={$type}&amp;",
'vars' => array(
'schema' => 'nspname',
'table' => 'relname'
)
)
);
if ($type == 'table') {
unset($actions['edit']['vars']['schema'],
$actions['delete']['vars']['schema'],
$columns['namespace'],
$columns['relname']
);
}
$misc->printTable($autovac, $columns, $actions, $lang['strnovacuumconf']);
if (($type == 'table') and ($autovac->recordCount() == 0)) {
echo "<br />";
echo "<a href=\"tables.php?action=confeditautovac&amp;{$misc->href}&amp;table=", htmlspecialchars($_REQUEST['table'])
,"\">{$lang['straddvacuumtable']}</a>";
}
}
}
function adminActions($action, $type) {
global $script;
if ($type == 'database') {
$_REQUEST['object'] = $_REQUEST['database'];
$script = 'database.php';
}
else {
// $_REQUEST['table'] is no set if we are in the schema page
$_REQUEST['object'] = (isset($_REQUEST['table']) ? $_REQUEST['table']:'');
$script = 'tables.php';
}
switch ($action) {
case 'confirm_cluster':
doCluster($type, true);
break;
case 'confirm_reindex':
doReindex($type, true);
break;
case 'confirm_analyze':
doAnalyze($type, true);
break;
case 'confirm_vacuum':
doVacuum($type, true);
break;
case 'cluster':
if (isset($_POST['cluster'])) doCluster($type);
// if multi-action from table canceled: back to the schema default page
else if (($type == 'table') && is_array($_REQUEST['object']) ) doDefault();
else doAdmin($type);
break;
case 'reindex':
if (isset($_POST['reindex'])) doReindex($type);
// if multi-action from table canceled: back to the schema default page
else if (($type == 'table') && is_array($_REQUEST['object']) ) doDefault();
else doAdmin($type);
break;
case 'analyze':
if (isset($_POST['analyze'])) doAnalyze($type);
// if multi-action from table canceled: back to the schema default page
else if (($type == 'table') && is_array($_REQUEST['object']) ) doDefault();
else doAdmin($type);
break;
case 'vacuum':
if (isset($_POST['vacuum'])) doVacuum($type);
// if multi-action from table canceled: back to the schema default page
else if (($type == 'table') && is_array($_REQUEST['object']) ) doDefault();
else doAdmin($type);
break;
case 'admin':
doAdmin($type);
break;
case 'confeditautovac':
doEditAutovacuum($type, true);
break;
case 'confdelautovac':
doDropAutovacuum($type, true);
break;
case 'confaddautovac':
doAddAutovacuum(true);
break;
case 'editautovac':
if (isset($_POST['save'])) doEditAutovacuum($type, false);
else doAdmin($type);
break;
case 'delautovac':
doDropAutovacuum($type, false);
break;
default:
return false;
}
return true;
}
?>

384
php/pgadmin/aggregates.php Normal file
View File

@ -0,0 +1,384 @@
<?php
/**
* Manage aggregates in a database
*
* $Id: aggregates.php,v 1.27 2008/01/19 13:46:15 ioguix Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (!isset($msg)) $msg = '';
/**
* Actually creates the new aggregate in the database
*/
function doSaveCreate() {
global $data, $lang, $_reload_browser;
// Check inputs
if (trim($_REQUEST['name']) == '') {
doCreate($lang['straggrneedsname']);
return;
}
else if (trim($_REQUEST['basetype']) == '') {
doCreate($lang['straggrneedsbasetype']);
return;
}
else if (trim($_REQUEST['sfunc']) == '') {
doCreate($lang['straggrneedssfunc']);
return;
}
else if (trim($_REQUEST['stype']) == '') {
doCreate($lang['straggrneedsstype']);
return;
}
$status = $data->createAggregate($_REQUEST['name'], $_REQUEST['basetype'], $_REQUEST['sfunc'], $_REQUEST['stype'],
$_REQUEST['ffunc'], $_REQUEST['initcond'], $_REQUEST['sortop'], $_REQUEST['aggrcomment']);
if ($status == 0) {
$_reload_browser = true;
doDefault($lang['straggrcreated']);
}
else {
doCreate($lang['straggrcreatedbad']);
}
}
/**
* Displays a screen for create a new aggregate function
*/
function doCreate($msg = '') {
global $data, $misc;
global $lang;
if (!isset($_REQUEST['name'])) $_REQUEST['name'] = '';
if (!isset($_REQUEST['basetype'])) $_REQUEST['basetype'] = '';
if (!isset($_REQUEST['sfunc'])) $_REQUEST['sfunc'] = '';
if (!isset($_REQUEST['stype'])) $_REQUEST['stype'] = '';
if (!isset($_REQUEST['ffunc'])) $_REQUEST['ffunc'] = '';
if (!isset($_REQUEST['initcond'])) $_REQUEST['initcond'] = '';
if (!isset($_REQUEST['sortop'])) $_REQUEST['sortop'] = '';
if (!isset($_REQUEST['aggrcomment'])) $_REQUEST['aggrcomment'] = '';
$misc->printTrail('schema');
$misc->printTitle($lang['strcreateaggregate'], 'pg.aggregate.create');
$misc->printMsg($msg);
echo "<form action=\"aggregates.php\" method=\"post\">\n";
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
echo "\t\t<td class=\"data\"><input name=\"name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['name']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['straggrbasetype']}</th>\n";
echo "\t\t<td class=\"data\"><input name=\"basetype\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['basetype']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['straggrsfunc']}</th>\n";
echo "\t\t<td class=\"data\"><input name=\"sfunc\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['sfunc']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['straggrstype']}</th>\n";
echo "\t\t<td class=\"data\"><input name=\"stype\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['stype']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['straggrffunc']}</th>\n";
echo "\t\t<td class=\"data\"><input name=\"ffunc\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['ffunc']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['straggrinitcond']}</th>\n";
echo "\t\t<td class=\"data\"><input name=\"initcond\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['initcond']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['straggrsortop']}</th>\n";
echo "\t\t<td class=\"data\"><input name=\"sortop\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['sortop']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
echo "\t\t<td><textarea name=\"aggrcomment\" rows=\"3\" cols=\"32\">",
htmlspecialchars($_REQUEST['aggrcomment']), "</textarea></td>\n\t</tr>\n";
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
/**
* Function to save after altering an aggregate
*/
function doSaveAlter() {
global $data, $lang;
// Check inputs
if (trim($_REQUEST['aggrname']) == '') {
doAlter($lang['straggrneedsname']);
return;
}
$status = $data->alterAggregate($_REQUEST['aggrname'], $_REQUEST['aggrtype'], $_REQUEST['aggrowner'],
$_REQUEST['aggrschema'], $_REQUEST['aggrcomment'], $_REQUEST['newaggrname'], $_REQUEST['newaggrowner'],
$_REQUEST['newaggrschema'], $_REQUEST['newaggrcomment']);
if ($status == 0)
doDefault($lang['straggraltered']);
else {
doAlter($lang['straggralteredbad']);
return;
}
}
/**
* Function to allow editing an aggregate function
*/
function doAlter($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('aggregate');
$misc->printTitle($lang['stralter'], 'pg.aggregate.alter');
$misc->printMsg($msg);
echo "<form action=\"aggregates.php\" method=\"post\">\n";
$aggrdata = $data->getAggregate($_REQUEST['aggrname'], $_REQUEST['aggrtype']);
if($aggrdata->recordCount() > 0 ) {
// Output table header
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data required\">{$lang['strname']}</th>";
echo "<th class=\"data required\">{$lang['strowner']}</th>";
echo "<th class=\"data required\">{$lang['strschema']}</th>\n\t</tr>\n";
// Display aggregate's name, owner and schema
echo "\t<tr>\n\t\t<td><input name=\"newaggrname\" size=\"32\" maxlength=\"32\" value=\"", htmlspecialchars($_REQUEST['aggrname']), "\" /></td>";
echo "<td><input name=\"newaggrowner\" size=\"32\" maxlength=\"32\" value=\"", htmlspecialchars($aggrdata->fields['usename']), "\" /></td>";
echo "<td><input name=\"newaggrschema\" size=\"32\" maxlength=\"32\" value=\"", htmlspecialchars($_REQUEST['schema']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
echo "\t\t<td><textarea name=\"newaggrcomment\" rows=\"3\" cols=\"32\">",
htmlspecialchars($aggrdata->fields['aggrcomment']), "</textarea></td>\n\t</tr>\n";
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_alter\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"aggrname\" value=\"", htmlspecialchars($_REQUEST['aggrname']), "\" />\n";
echo "<input type=\"hidden\" name=\"aggrtype\" value=\"", htmlspecialchars($_REQUEST['aggrtype']), "\" />\n";
echo "<input type=\"hidden\" name=\"aggrowner\" value=\"", htmlspecialchars($aggrdata->fields['usename']), "\" />\n";
echo "<input type=\"hidden\" name=\"aggrschema\" value=\"", htmlspecialchars($_REQUEST['schema']), "\" />\n";
echo "<input type=\"hidden\" name=\"aggrcomment\" value=\"", htmlspecialchars($aggrdata->fields['aggrcomment']), "\" />\n";
echo "<input type=\"submit\" name=\"alter\" value=\"{$lang['stralter']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
} else {
echo "<p>{$lang['strnodata']}</p>\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strback']}\" /></p>\n";
}
echo "</form>\n";
}
/**
* Show confirmation of drop and perform actual drop of the aggregate function selected
*/
function doDrop($confirm) {
global $data, $misc;
global $lang, $_reload_browser;
if ($confirm) {
$misc->printTrail('aggregate');
$misc->printTitle($lang['strdrop'], 'pg.aggregate.drop');
echo "<p>", sprintf($lang['strconfdropaggregate'], htmlspecialchars($_REQUEST['aggrname'])), "</p>\n";
echo "<form action=\"aggregates.php\" method=\"post\">\n";
echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"aggrname\" value=\"", htmlspecialchars($_REQUEST['aggrname']), "\" />\n";
echo "<input type=\"hidden\" name=\"aggrtype\" value=\"", htmlspecialchars($_REQUEST['aggrtype']), "\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
else {
$status = $data->dropAggregate($_POST['aggrname'], $_POST['aggrtype'], isset($_POST['cascade']));
if ($status == 0) {
$_reload_browser = true;
doDefault($lang['straggregatedropped']);
}
else
doDefault($lang['straggregatedroppedbad']);
}
}
/**
* Show the properties of an aggregate
*/
function doProperties($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('aggregate');
$misc->printTitle($lang['strproperties'],'pg.aggregate');
$misc->printMsg($msg);
$aggrdata = $data->getAggregate($_REQUEST['aggrname'], $_REQUEST['aggrtype']);
if($aggrdata->recordCount() > 0 ) {
// Display aggregate's info
echo "<table>\n";
echo "<tr>\n\t<th class=\"data left\">{$lang['strname']}</th>\n";
echo "\t<td class=\"data1\">", htmlspecialchars($_REQUEST['aggrname']), "</td>\n</tr>\n";
echo "<tr>\n\t<th class=\"data left\">{$lang['straggrbasetype']}</th>\n";
echo "\t<td class=\"data1\">", htmlspecialchars($_REQUEST['aggrtype']), "</td>\n</tr>\n";
echo "<tr>\n\t<th class=\"data left\">{$lang['straggrsfunc']}</th>\n";
echo "\t<td class=\"data1\">", htmlspecialchars($aggrdata->fields['aggtransfn']), "</td>\n</tr>\n";
echo "<tr>\n\t<th class=\"data left\">{$lang['straggrstype']}</th>\n";
echo "\t<td class=\"data1\">", htmlspecialchars($aggrdata->fields['aggstype']), "</td>\n</tr>\n";
echo "<tr>\n\t<th class=\"data left\">{$lang['straggrffunc']}</th>\n";
echo "\t<td class=\"data1\">", htmlspecialchars($aggrdata->fields['aggfinalfn']), "</td>\n</tr>\n";
echo "<tr>\n\t<th class=\"data left\">{$lang['straggrinitcond']}</th>\n";
echo "\t<td class=\"data1\">", htmlspecialchars($aggrdata->fields['agginitval']), "</td>\n</tr>\n";
if($data->hasAggregateSortOp()) {
echo "<tr>\n\t<th class=\"data left\">{$lang['straggrsortop']}</th>\n";
echo "\t<td class=\"data1\">", htmlspecialchars($aggrdata->fields['aggsortop']), "</td>\n</tr>\n";
}
echo "<tr>\n\t<th class=\"data left\">{$lang['strowner']}</th>\n";
echo "\t<td class=\"data1\">", htmlspecialchars($aggrdata->fields['usename']), "</td>\n</tr>\n";
echo "<tr>\n\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
echo "\t<td class=\"data1\">", $misc->printVal($aggrdata->fields['aggrcomment']), "</td>\n</tr>\n";
echo "</table>\n";
}
else echo "<p>{$lang['strnodata']}</p>\n";
echo "<ul class=\"navlink\">\n\t<li><a class=\"navlink\" href=\"aggregates.php?{$misc->href}\">{$lang['straggrshowall']}</a></li>\n";
if ($data->hasAlterAggregate()) {
echo "\t<li><a class=\"navlink\" href=\"aggregates.php?action=alter&amp;{$misc->href}&amp;aggrname=",
urlencode($_REQUEST['aggrname']), "&amp;aggrtype=", urlencode($_REQUEST['aggrtype']), "\">{$lang['stralter']}</a></li>\n";
}
echo "\t<li><a class=\"navlink\" href=\"aggregates.php?action=confirm_drop&amp;{$misc->href}&amp;aggrname=",
urlencode($_REQUEST['aggrname']), "&amp;aggrtype=", urlencode($_REQUEST['aggrtype']), "\">{$lang['strdrop']}</a></li>\n</ul>\n";
}
/**
* Show default list of aggregate functions in the database
*/
function doDefault($msg = '') {
global $data, $conf, $misc;
global $lang;
$misc->printTrail('schema');
$misc->printTabs('schema', 'aggregates');
$misc->printMsg($msg);
$aggregates = $data->getAggregates();
$columns = array(
'aggrname' => array(
'title' => $lang['strname'],
'field' => field('proname'),
'url' => "redirect.php?subject=aggregate&amp;action=properties&amp;{$misc->href}&amp;",
'vars' => array('aggrname' => 'proname', 'aggrtype' => 'proargtypes'),
),
'aggrtype' => array(
'title' => $lang['strtype'],
'field' => field('proargtypes'),
),
'aggrtransfn' => array(
'title' => $lang['straggrsfunc'],
'field' => field('aggtransfn'),
),
'owner' => array(
'title' => $lang['strowner'],
'field' => field('usename'),
),
'actions' => array(
'title' => $lang['stractions'],
),
'comment' => array(
'title' => $lang['strcomment'],
'field' => field('aggrcomment'),
),
);
$actions = array(
'alter' => array(
'title' => $lang['stralter'],
'url' => "aggregates.php?action=alter&amp;{$misc->href}&amp;",
'vars' => array('aggrname' => 'proname', 'aggrtype' => 'proargtypes'),
),
'drop' => array(
'title' => $lang['strdrop'],
'url' => "aggregates.php?action=confirm_drop&amp;{$misc->href}&amp;",
'vars' => array('aggrname' => 'proname', 'aggrtype' => 'proargtypes'),
)
);
if (!$data->hasAlterAggregate()) unset($actions['alter']);
$misc->printTable($aggregates, $columns, $actions, $lang['strnoaggregates']);
echo "<p><a class=\"navlink\" href=\"aggregates.php?action=create&amp;{$misc->href}\">{$lang['strcreateaggregate']}</a></p>\n";
}
/**
* Generate XML for the browser tree.
*/
function doTree() {
global $misc, $data;
$aggregates = $data->getAggregates();
$proto = concat(field('proname'), ' (', field('proargtypes'), ')');
$reqvars = $misc->getRequestVars('aggregate');
$attrs = array(
'text' => $proto,
'icon' => 'Aggregate',
'toolTip' => field('aggcomment'),
'action' => url('redirect.php',
$reqvars,
array(
'action' => 'properties',
'aggrname' => field('proname'),
'aggrtype' => field('proargtypes')
)
)
);
$misc->printTreeXML($aggregates, $attrs);
exit;
}
if ($action == 'tree') doTree();
$misc->printHeader($lang['straggregates']);
$misc->printBody();
switch ($action) {
case 'create':
doCreate();
break;
case 'save_create':
if (isset($_POST['cancel'])) doDefault();
else doSaveCreate();
break;
case 'alter':
doAlter();
break;
case 'save_alter':
if (isset($_POST['alter'])) doSaveAlter();
else doProperties();
break;
case 'drop':
if (isset($_POST['drop'])) doDrop(false);
else doDefault();
break;
case 'confirm_drop':
doDrop(true);
break;
default:
doDefault();
break;
case 'properties':
doProperties();
break;
}
$misc->printFooter();
?>

View File

@ -0,0 +1,86 @@
<?php
include_once('./libraries/lib.inc.php');
if(isset($_POST['offset']))
$offset = " OFFSET {$_POST['offset']}";
else {
$_POST['offset'] = 0;
$offset = " OFFSET 0";
}
$keynames = array();
foreach ($_POST['fkeynames'] as $k => $v) {
$fkeynames[$k] = html_entity_decode($v, ENT_QUOTES);
}
$keyspos = array_combine($fkeynames, $_POST['keys']);
$f_schema = html_entity_decode($_POST['f_schema'], ENT_QUOTES);
$data->fieldClean($f_schema);
$f_table = html_entity_decode($_POST['f_table'], ENT_QUOTES);
$data->fieldClean($f_table);
$f_attname = $fkeynames[$_POST['fattpos'][0]];
$data->fieldClean($f_attname);
$q = "SELECT *
FROM \"{$f_schema}\".\"{$f_table}\"
WHERE \"{$f_attname}\"::text LIKE '{$_POST['fvalue']}%'
ORDER BY \"{$f_attname}\" LIMIT 12 {$offset};";
$res = $data->selectSet($q);
if (!$res->EOF) {
echo "<table class=\"ac_values\">";
echo '<tr>';
foreach (array_keys($res->fields) as $h) {
echo '<th>';
if (in_array($h, $fkeynames))
echo '<img src="'. $misc->icon('ForeignKey') .'" alt="[referenced key]" />';
echo htmlentities($h), '</th>';
}
echo "</tr>\n";
$i=0;
while ((!$res->EOF) && ($i < 11)) {
echo "<tr class=\"acline\">";
foreach ($res->fields as $n => $v) {
if (in_array($n, $fkeynames))
echo "<td><a href=\"javascript:void(0)\" class=\"fkval\" name=\"{$keyspos[$n]}\">",htmlentities($v), "</a></td>";
else
echo "<td><a href=\"javascript:void(0)\">", htmlentities($v), "</a></td>";
}
echo "</tr>\n";
$i++;
$res->moveNext();
}
echo "</table>\n";
$page_tests='';
$js = "<script type=\"text/javascript\">\n";
if ($_POST['offset']) {
echo "<a href=\"javascript:void(0)\" id=\"fkprev\">&lt;&lt; Prev</a>";
$js.= "fkl_hasprev=true;\n";
}
else
$js.= "fkl_hasprev=false;\n";
if ($res->recordCount() == 12) {
$js.= "fkl_hasnext=true;\n";
echo "&nbsp;&nbsp;&nbsp;<a href=\"javascript:void(0)\" id=\"fknext\">Next &gt;&gt;</a>";
}
else
$js.= "fkl_hasnext=false;\n";
echo $js ."</script>";
}
else {
printf("<p>{$lang['strnofkref']}</p>", "\"{$_POST['f_schema']}\".\"{$_POST['f_table']}\".\"{$fkeynames[$_POST['fattpos']]}\"");
if ($_POST['offset'])
echo "<a href=\"javascript:void(0)\" class=\"fkprev\">Prev &lt;&lt;</a>";
}
?>

501
php/pgadmin/all_db.php Normal file
View File

@ -0,0 +1,501 @@
<?php
/**
* Manage databases within a server
*
* $Id: all_db.php,v 1.59 2007/10/17 21:40:19 ioguix Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (!isset($msg)) $msg = '';
/**
* Display a form for alter and perform actual alter
*/
function doAlter($confirm) {
global $data, $misc, $_reload_browser;
global $lang;
if ($confirm) {
$misc->printTrail('database');
$misc->printTitle($lang['stralter'], 'pg.database.alter');
echo "<form action=\"all_db.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data left required\">{$lang['strname']}</th>\n";
echo "<td class=\"data1\">";
echo "<input name=\"newname\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['alterdatabase']), "\" /></td></tr>\n";
$server_info = $misc->getServerInfo();
if ($data->hasAlterDatabaseOwner() && $data->isSuperUser($server_info['username'])) {
// Fetch all users
$rs = $data->getDatabaseOwner($_REQUEST['alterdatabase']);
$owner = isset($rs->fields['usename']) ? $rs->fields['usename'] : '';
$users = $data->getUsers();
echo "<tr><th class=\"data left required\">{$lang['strowner']}</th>\n";
echo "<td class=\"data1\"><select name=\"owner\">";
while (!$users->EOF) {
$uname = $users->fields['usename'];
echo "<option value=\"", htmlspecialchars($uname), "\"",
($uname == $owner) ? ' selected="selected"' : '', ">", htmlspecialchars($uname), "</option>\n";
$users->moveNext();
}
echo "</select></td></tr>\n";
}
if ($data->hasSharedComments()){
$rs = $data->getDatabaseComment($_REQUEST['alterdatabase']);
$comment = isset($rs->fields['description']) ? $rs->fields['description'] : '';
echo "<tr><th class=\"data left\">{$lang['strcomment']}</th>\n";
echo "<td class=\"data1\">";
echo "<textarea rows=\"3\" cols=\"32\" name=\"dbcomment\">",
htmlspecialchars($comment), "</textarea></td></tr>\n";
}
echo "</table>\n";
echo "<input type=\"hidden\" name=\"action\" value=\"alter\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"oldname\" value=\"",
htmlspecialchars($_REQUEST['alterdatabase']), "\" />\n";
echo "<input type=\"submit\" name=\"alter\" value=\"{$lang['stralter']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
}
else {
if (!isset($_POST['owner'])) $_POST['owner'] = '';
if (!isset($_POST['dbcomment'])) $_POST['dbcomment'] = '';
if ($data->alterDatabase($_POST['oldname'], $_POST['newname'], $_POST['owner'], $_POST['dbcomment']) == 0) {
$_reload_browser = true;
doDefault($lang['strdatabasealtered']);
}
else
doDefault($lang['strdatabasealteredbad']);
}
}
/**
* Show confirmation of drop and perform actual drop
*/
function doDrop($confirm) {
global $data, $misc;
global $lang, $_reload_drop_database;
if (empty($_REQUEST['dropdatabase']) && empty($_REQUEST['ma'])) {
doDefault($lang['strspecifydatabasetodrop']);
exit();
}
if ($confirm) {
$misc->printTrail('database');
$misc->printTitle($lang['strdrop'], 'pg.database.drop');
echo "<form action=\"all_db.php\" method=\"post\">\n";
//If multi drop
if (isset($_REQUEST['ma'])) {
foreach($_REQUEST['ma'] as $v) {
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
echo "<p>", sprintf($lang['strconfdropdatabase'], $misc->printVal($a['database'])), "</p>\n";
printf('<input type="hidden" name="dropdatabase[]" value="%s" />', htmlspecialchars($a['database']));
}
} else {
echo "<p>", sprintf($lang['strconfdropdatabase'], $misc->printVal($_REQUEST['dropdatabase'])), "</p>\n";
echo "<input type=\"hidden\" name=\"dropdatabase\" value=\"", htmlspecialchars($_REQUEST['dropdatabase']), "\" />\n";
}// END if multi drop
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
} // END confirm
else {
//If multi drop
if (is_array($_REQUEST['dropdatabase'])) {
$msg = '';
foreach($_REQUEST['dropdatabase'] as $d) {
$status = $data->dropDatabase($d);
if ($status == 0)
$msg.= sprintf('%s: %s<br />', htmlentities($d), $lang['strdatabasedropped']);
else {
doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($d), $lang['strdatabasedroppedbad']));
return;
}
}// Everything went fine, back to Default page...
$_reload_drop_database = true;
doDefault($msg);
} else {
$status = $data->dropDatabase($_POST['dropdatabase']);
if ($status == 0) {
$_reload_drop_database = true;
doDefault($lang['strdatabasedropped']);
}
else
doDefault($lang['strdatabasedroppedbad']);
}
}//END DROP
}// END FUNCTION
/**
* Displays a screen where they can enter a new database
*/
function doCreate($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('server');
$misc->printTitle($lang['strcreatedatabase'], 'pg.database.create');
$misc->printMsg($msg);
if (!isset($_POST['formName'])) $_POST['formName'] = '';
// Default encoding is that in language file
if (!isset($_POST['formEncoding'])) {
if (isset($lang['appdbencoding']))
$_POST['formEncoding'] = $lang['appdbencoding'];
else
$_POST['formEncoding'] = '';
}
if (!isset($_POST['formTemplate'])) $_POST['formTemplate'] = 'template1';
if (!isset($_POST['formSpc'])) $_POST['formSpc'] = '';
if (!isset($_POST['formComment'])) $_POST['formComment'] = '';
// Fetch a list of databases in the cluster
$templatedbs = $data->getDatabases(false);
// Fetch all tablespaces from the database
if ($data->hasTablespaces()) $tablespaces = $data->getTablespaces();
echo "<form action=\"all_db.php\" method=\"post\">\n";
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
echo "\t\t<td class=\"data1\"><input name=\"formName\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_POST['formName']), "\" /></td>\n\t</tr>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strtemplatedb']}</th>\n";
echo "\t\t<td class=\"data1\">\n";
echo "\t\t\t<select name=\"formTemplate\">\n";
// Always offer template0 and template1
echo "\t\t\t\t<option value=\"template0\"",
($_POST['formTemplate'] == 'template0') ? ' selected="selected"' : '', ">template0</option>\n";
echo "\t\t\t\t<option value=\"template1\"",
($_POST['formTemplate'] == 'template1') ? ' selected="selected"' : '', ">template1</option>\n";
while (!$templatedbs->EOF) {
$dbname = htmlspecialchars($templatedbs->fields['datname']);
if ($dbname != 'template1') {
// filter out for $conf[show_system] users so we dont get duplicates
echo "\t\t\t\t<option value=\"{$dbname}\"",
($dbname == $_POST['formTemplate']) ? ' selected="selected"' : '', ">{$dbname}</option>\n";
}
$templatedbs->moveNext();
}
echo "\t\t\t</select>\n";
echo "\t\t</td>\n\t</tr>\n";
// ENCODING
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strencoding']}</th>\n";
echo "\t\t<td class=\"data1\">\n";
echo "\t\t\t<select name=\"formEncoding\">\n";
echo "\t\t\t\t<option value=\"\"></option>\n";
while (list ($key) = each ($data->codemap)) {
echo "\t\t\t\t<option value=\"", htmlspecialchars($key), "\"",
($key == $_POST['formEncoding']) ? ' selected="selected"' : '', ">",
$misc->printVal($key), "</option>\n";
}
echo "\t\t\t</select>\n";
echo "\t\t</td>\n\t</tr>\n";
if ($data->hasDatabaseCollation()) {
if (!isset($_POST['formCollate'])) $_POST['formCollate'] = '';
if (!isset($_POST['formCType'])) $_POST['formCType'] = '';
// LC_COLLATE
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcollation']}</th>\n";
echo "\t\t<td class=\"data1\">\n";
echo "\t\t\t<input name=\"formCollate\" value=\"", htmlspecialchars($_POST['formCollate']), "\" />\n";
echo "\t\t</td>\n\t</tr>\n";
// LC_CTYPE
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strctype']}</th>\n";
echo "\t\t<td class=\"data1\">\n";
echo "\t\t\t<input name=\"formCType\" value=\"", htmlspecialchars($_POST['formCType']), "\" />\n";
echo "\t\t</td>\n\t</tr>\n";
}
// Tablespace (if there are any)
if ($data->hasTablespaces() && $tablespaces->recordCount() > 0) {
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strtablespace']}</th>\n";
echo "\t\t<td class=\"data1\">\n\t\t\t<select name=\"formSpc\">\n";
// Always offer the default (empty) option
echo "\t\t\t\t<option value=\"\"",
($_POST['formSpc'] == '') ? ' selected="selected"' : '', "></option>\n";
// Display all other tablespaces
while (!$tablespaces->EOF) {
$spcname = htmlspecialchars($tablespaces->fields['spcname']);
echo "\t\t\t\t<option value=\"{$spcname}\"",
($spcname == $_POST['formSpc']) ? ' selected="selected"' : '', ">{$spcname}</option>\n";
$tablespaces->moveNext();
}
echo "\t\t\t</select>\n\t\t</td>\n\t</tr>\n";
}
// Comments (if available)
if ($data->hasSharedComments()) {
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
echo "\t\t<td><textarea name=\"formComment\" rows=\"3\" cols=\"32\">",
htmlspecialchars($_POST['formComment']), "</textarea></td>\n\t</tr>\n";
}
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
/**
* Actually creates the new view in the database
*/
function doSaveCreate() {
global $data, $lang, $_reload_browser;
// Default tablespace to null if it isn't set
if (!isset($_POST['formSpc'])) $_POST['formSpc'] = null;
// Default comment to blank if it isn't set
if (!isset($_POST['formComment'])) $_POST['formComment'] = null;
// Default collate to blank if it isn't set
if (!isset($_POST['formCollate'])) $_POST['formCollate'] = null;
// Default ctype to blank if it isn't set
if (!isset($_POST['formCType'])) $_POST['formCType'] = null;
// Check that they've given a name and a definition
if ($_POST['formName'] == '') doCreate($lang['strdatabaseneedsname']);
else {
$status = $data->createDatabase($_POST['formName'], $_POST['formEncoding'], $_POST['formSpc'],
$_POST['formComment'], $_POST['formTemplate'], $_POST['formCollate'], $_POST['formCType']);
if ($status == 0) {
$_reload_browser = true;
doDefault($lang['strdatabasecreated']);
}
else
doCreate($lang['strdatabasecreatedbad']);
}
}
/**
* Displays options for cluster download
*/
function doExport($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('server');
$misc->printTabs('server','export');
$misc->printMsg($msg);
echo "<form action=\"dbexport.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data\">{$lang['strformat']}</th><th class=\"data\">{$lang['stroptions']}</th></tr>\n";
// Data only
echo "<tr><th class=\"data left\" rowspan=\"2\">";
echo "<input type=\"radio\" id=\"what1\" name=\"what\" value=\"dataonly\" checked=\"checked\" /><label for=\"what1\">{$lang['strdataonly']}</label></th>\n";
echo "<td>{$lang['strformat']}\n";
echo "<select name=\"d_format\">\n";
echo "<option value=\"copy\">COPY</option>\n";
echo "<option value=\"sql\">SQL</option>\n";
echo "</select>\n</td>\n</tr>\n";
echo "<tr><td><input type=\"checkbox\" id=\"d_oids\" name=\"d_oids\" /><label for=\"d_oids\">{$lang['stroids']}</label></td>\n</tr>\n";
// Structure only
echo "<tr><th class=\"data left\"><input type=\"radio\" id=\"what2\" name=\"what\" value=\"structureonly\" /><label for=\"what2\">{$lang['strstructureonly']}</label></th>\n";
echo "<td><input type=\"checkbox\" id=\"s_clean\" name=\"s_clean\" /><label for=\"s_clean\">{$lang['strdrop']}</label></td>\n</tr>\n";
// Structure and data
echo "<tr><th class=\"data left\" rowspan=\"3\">";
echo "<input type=\"radio\" id=\"what3\" name=\"what\" value=\"structureanddata\" /><label for=\"what3\">{$lang['strstructureanddata']}</label></th>\n";
echo "<td>{$lang['strformat']}\n";
echo "<select name=\"sd_format\">\n";
echo "<option value=\"copy\">COPY</option>\n";
echo "<option value=\"sql\">SQL</option>\n";
echo "</select>\n</td>\n</tr>\n";
echo "<tr><td><input type=\"checkbox\" id=\"sd_clean\" name=\"sd_clean\" /><label for=\"sd_clean\">{$lang['strdrop']}</label></td>\n</tr>\n";
echo "<tr><td><input type=\"checkbox\" id=\"sd_oids\" name=\"sd_oids\" /><label for=\"sd_oids\">{$lang['stroids']}</label></td>\n</tr>\n";
echo "</table>\n";
echo "<h3>{$lang['stroptions']}</h3>\n";
echo "<p><input type=\"radio\" id=\"output1\" name=\"output\" value=\"show\" checked=\"checked\" /><label for=\"output1\">{$lang['strshow']}</label>\n";
echo "<br/><input type=\"radio\" id=\"output2\" name=\"output\" value=\"download\" /><label for=\"output2\">{$lang['strdownload']}</label></p>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
echo "<input type=\"hidden\" name=\"subject\" value=\"server\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
echo "</form>\n";
}
/**
* Show default list of databases in the server
*/
function doDefault($msg = '') {
global $data, $conf, $misc;
global $lang;
$misc->printTrail('server');
$misc->printTabs('server','databases');
$misc->printMsg($msg);
$databases = $data->getDatabases();
$columns = array(
'database' => array(
'title' => $lang['strdatabase'],
'field' => field('datname'),
'url' => "redirect.php?subject=database&amp;{$misc->href}&amp;",
'vars' => array('database' => 'datname'),
),
'owner' => array(
'title' => $lang['strowner'],
'field' => field('datowner'),
),
'encoding' => array(
'title' => $lang['strencoding'],
'field' => field('datencoding'),
),
'lc_collate' => array(
'title' => $lang['strcollation'],
'field' => field('datcollate'),
),
'lc_ctype' => array(
'title' => $lang['strctype'],
'field' => field('datctype'),
),
'tablespace' => array(
'title' => $lang['strtablespace'],
'field' => field('tablespace'),
),
'dbsize' => array(
'title' => $lang['strsize'],
'field' => field('dbsize'),
'type' => 'prettysize',
),
'actions' => array(
'title' => $lang['stractions'],
),
'comment' => array(
'title' => $lang['strcomment'],
'field' => field('datcomment'),
),
);
$actions = array(
'multiactions' => array(
'keycols' => array('database' => 'datname'),
'url' => 'all_db.php',
'default' => null,
),
'drop' => array(
'title' => $lang['strdrop'],
'url' => "all_db.php?action=confirm_drop&amp;subject=database&amp;{$misc->href}&amp;",
'vars' => array('dropdatabase' => 'datname'),
'multiaction' => 'confirm_drop',
),
'privileges' => array(
'title' => $lang['strprivileges'],
'url' => "privileges.php?subject=database&amp;{$misc->href}&amp;",
'vars' => array('database' => 'datname'),
)
);
if ($data->hasAlterDatabase() ) {
$actions['alter'] = array(
'title' => $lang['stralter'],
'url' => "all_db.php?action=confirm_alter&amp;subject=database&amp;{$misc->href}&amp;",
'vars' => array('alterdatabase' => 'datname')
);
}
if (!$data->hasTablespaces()) unset($columns['tablespace']);
if (!$data->hasServerAdminFuncs()) unset($columns['dbsize']);
if (!$data->hasDatabaseCollation()) unset($columns['lc_collate'], $columns['lc_ctype']);
if (!isset($data->privlist['database'])) unset($actions['privileges']);
$misc->printTable($databases, $columns, $actions, $lang['strnodatabases']);
echo "<p><a class=\"navlink\" href=\"all_db.php?action=create&amp;{$misc->href}\">{$lang['strcreatedatabase']}</a></p>\n";
}
function doTree() {
global $misc, $data, $lang;
$databases = $data->getDatabases();
$reqvars = $misc->getRequestVars('database');
$attrs = array(
'text' => field('datname'),
'icon' => 'Database',
'toolTip'=> field('datcomment'),
'action' => url('redirect.php',
$reqvars,
array('database' => field('datname'))
),
'branch' => url('database.php',
$reqvars,
array(
'action' => 'tree',
'database' => field('datname')
)
),
);
$misc->printTreeXML($databases, $attrs);
exit;
}
if ($action == 'tree') doTree();
$misc->printHeader($lang['strdatabases']);
$misc->printBody();
switch ($action) {
case 'export':
doExport();
break;
case 'save_create':
if (isset($_POST['cancel'])) doDefault();
else doSaveCreate();
break;
case 'create':
doCreate();
break;
case 'drop':
if (isset($_REQUEST['drop'])) doDrop(false);
else doDefault();
break;
case 'confirm_drop':
doDrop(true);
break;
case 'alter':
if (isset($_POST['oldname']) && isset($_POST['newname']) && !isset($_POST['cancel']) ) doAlter(false);
else doDefault();
break;
case 'confirm_alter':
doAlter(true);
break;
default:
doDefault();
break;
}
$misc->printFooter();
?>

87
php/pgadmin/browser.php Normal file
View File

@ -0,0 +1,87 @@
<?php
/**
* Main object browser. This page first shows a list of databases and then
* if you click on a database it shows a list of database objects in that
* database.
*
* $Id: browser.php,v 1.59 2008/02/13 23:03:05 ioguix Exp $
*/
// Include application functions
$_no_db_connection = true;
$_no_bottom_link = true;
include_once('./libraries/lib.inc.php');
if (isset($conf['srv_groups'])) {
$treeaction = 'groupstree';
}
else {
$treeaction = 'tree';
}
// Output header
$misc->printHeader('', '
<script src="xloadtree/xtree2.js" type="text/javascript"></script>
<script src="xloadtree/xloadtree2.js" type="text/javascript"></script>
<style type="text/css">
.webfx-tree-children { background-image: url("' . $misc->icon('I') . '"); }
</style>');
$misc->printBody('browser');
echo "<div dir=\"ltr\">\n";
?>
<div class="logo"><a href="intro.php" target="detail"><img src="<?php echo $misc->icon('title') ?>" width="200" height="50" alt="<?php echo htmlspecialchars($appName) ?>" title="<?php echo htmlspecialchars($appName) ?>" /></a></div>
<div class="refreshTree"><a href="browser.php" target="browser" ><img src="<?php echo $misc->icon('Refresh'); ?>" alt="<?php echo $lang['strrefresh']; ?>" title="<?php echo $lang['strrefresh']; ?>" /></a></div>
<script type="text/javascript">
webFXTreeConfig.rootIcon = "<?php echo $misc->icon('Servers') ?>";
webFXTreeConfig.openRootIcon = "<?php echo $misc->icon('Servers') ?>";
webFXTreeConfig.folderIcon = "";
webFXTreeConfig.openFolderIcon = "";
webFXTreeConfig.fileIcon = "";
webFXTreeConfig.iIcon = "<?php echo $misc->icon('I') ?>";
webFXTreeConfig.lIcon = "<?php echo $misc->icon('L') ?>";
webFXTreeConfig.lMinusIcon = "<?php echo $misc->icon('Lminus') ?>";
webFXTreeConfig.lPlusIcon = "<?php echo $misc->icon('Lplus') ?>";
webFXTreeConfig.tIcon = "<?php echo $misc->icon('T') ?>";
webFXTreeConfig.tMinusIcon = "<?php echo $misc->icon('Tminus') ?>";
webFXTreeConfig.tPlusIcon = "<?php echo $misc->icon('Tplus') ?>";
webFXTreeConfig.blankIcon = "<?php echo $misc->icon('blank') ?>";
webFXTreeConfig.loadingIcon = "<?php echo $misc->icon('Loading') ?>";
webFXTreeConfig.loadingText = "<?php echo $lang['strloading'] ?>";
webFXTreeConfig.errorIcon = "<?php echo $misc->icon('ObjectNotFound') ?>";
webFXTreeConfig.errorLoadingText = "<?php echo $lang['strerrorloading'] ?>";
webFXTreeConfig.reloadText = "<?php echo $lang['strclicktoreload'] ?>";
// Set default target frame:
WebFXTreeAbstractNode.prototype.target = 'detail';
// Disable double click:
WebFXTreeAbstractNode.prototype._ondblclick = function(){}
// Show tree XML on double click - for debugging purposes only
/*
// UNCOMMENT THIS FOR DEBUGGING (SHOWS THE SOURCE XML)
WebFXTreeAbstractNode.prototype._ondblclick = function(e){
var el = e.target || e.srcElement;
if (this.src != null)
window.open(this.src, this.target || "_self");
return false;
};
*/
var tree = new WebFXLoadTree("<?php echo $lang['strservers']; ?>", "servers.php?action=<?php echo $treeaction ?>", "servers.php");
tree.write();
tree.setExpanded(true);
</script>
<?php
// Output footer
echo "</div>\n";
$misc->printFooter();
?>

107
php/pgadmin/build_tests.php Normal file
View File

@ -0,0 +1,107 @@
#!/usr/bin/php
<?php
/**
* Build the test files for each servers in conf/config.inc.php according to the pg backend version.
*/
require('./conf/config.inc.php');
$test_dir = './tests/selenium/';
$test_src_dir = "{$test_dir}src/";
$test_static_dir = "{$test_dir}static/";
$testsuite_file = "{$test_static_dir}TestSuite.html";
if(isset($argv[1]) && ($argv[1] == 'clean')) {
echo "Cleaning...";
/* delete server directories */
foreach ($conf['servers'] as $server) {
$dir = "{$test_static_dir}{$server['desc']}";
while(is_dir($dir)) {
$dh = opendir($dir);
while($file = readdir($dh))
if (($file != '.') && ($file != '..')) unlink("{$dir}/{$file}");
rmdir($dir);
}
}
/* delete the TestSuite.html file */
@unlink($testsuite_file);
echo "done.\n";
exit;
}
// Include application functions
require('./tests/selenium/config.test.php');
define('ADODB_ERROR_HANDLER','');
require('./classes/database/Connection.php');
require('./lang/recoded/english.php');
require('./tests/selenium/testBuilder.class.php');
/* create directory for tests static files */
if(!is_dir($test_static_dir))
mkdir($test_static_dir);
/* create the TestSuite.html file with its html header */
$fd = fopen($testsuite_file, 'w');
fprintf($fd, "<table border=\"1\">
<tr>
<th>Test suite for PPA</th>
</tr>\n");
fclose($fd);
/* Loop on the servers given in the conf/config.inc.conf file */
foreach ($conf['servers'] as $server) {
// Is this server in our list of configured servers?
if (!in_array($server['desc'],$test_servers))
continue;
/* connect to the server to get its version
* and test its feature along the tests */
$_c = new Connection($server['host'],
$server['port'],
$server['sslmode'],
$super_user[$server['desc']],
$super_pass[$server['desc']],
$server['defaultdb']
);
$_type = $data = null;
if (! $_c->conn->isConnected())
die ("Connection to {$server['desc']} failed !\n");
else {
if (($_type = $_c->getDriver($platform)) === null) {
die( printf($lang['strpostgresqlversionnotsupported'], $postgresqlMinVer));
}
/* create the database handler we are going to use in the tests creator scripts */
include_once('./classes/database/' . $_type . '.php');
$data = new $_type($_c->conn);
$data->platform = $_c->platform;
}
fprintf(STDERR, "Connected to %s...\n", $server['desc']);
if (!is_dir("{$test_static_dir}/{$server['desc']}"))
mkdir("{$test_static_dir}/{$server['desc']}");
$fd = opendir($test_src_dir);
$files = array();
while ($file = readdir($fd))
if (($file != '.') && ($file != '..'))
$files[] = $file;
sort($files);
/* include the tests creator scripts here
* in the order you want them executed.
* Each script append itself to the TestSuite.html file.
**/
foreach ($files as $testgroupfile)
require("{$test_src_dir}/{$testgroupfile}");
}
/* close the TestSuite.html file */
$fd = fopen($testsuite_file, 'a');
fprintf($fd, "</table>");
fclose($fd);
/* Tests ready to be runned on all your configured servers !!!! */
?>

103
php/pgadmin/casts.php Normal file
View File

@ -0,0 +1,103 @@
<?php
/**
* Manage casts in a database
*
* $Id: casts.php,v 1.16 2007/09/25 16:08:05 ioguix Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (!isset($msg)) $msg = '';
/**
* Show default list of casts in the database
*/
function doDefault($msg = '') {
global $data, $misc, $database;
global $lang;
function renderCastContext($val) {
global $lang;
switch ($val) {
case 'e': return $lang['strno'];
case 'a': return $lang['strinassignment'];
default: return $lang['stryes'];
}
}
$misc->printTrail('database');
$misc->printTabs('database','casts');
$misc->printMsg($msg);
$casts = $data->getCasts();
$columns = array(
'source_type' => array(
'title' => $lang['strsourcetype'],
'field' => field('castsource'),
),
'target_type' => array(
'title' => $lang['strtargettype'],
'field' => field('casttarget'),
),
'function' => array(
'title' => $lang['strfunction'],
'field' => field('castfunc'),
'params'=> array('null' => $lang['strbinarycompat']),
),
'implicit' => array(
'title' => $lang['strimplicit'],
'field' => field('castcontext'),
'type' => 'callback',
'params'=> array('function' => 'renderCastContext', 'align' => 'center'),
),
'comment' => array(
'title' => $lang['strcomment'],
'field' => field('castcomment'),
),
);
$actions = array();
$misc->printTable($casts, $columns, $actions, $lang['strnocasts']);
}
/**
* Generate XML for the browser tree.
*/
function doTree() {
global $misc, $data;
$casts = $data->getCasts();
$proto = concat(field('castsource'), ' AS ', field('casttarget'));
$attrs = array(
'text' => $proto,
'icon' => 'Cast'
);
$misc->printTreeXML($casts, $attrs);
exit;
}
if ($action == 'tree') doTree();
$misc->printHeader($lang['strcasts']);
$misc->printBody();
switch ($action) {
case 'tree':
doTree();
break;
default:
doDefault();
break;
}
$misc->printFooter();
?>

View File

@ -0,0 +1,32 @@
<?php
/**
* Really simple RecordSet to allow printTable of arrays.
*
* $Id: ArrayRecordSet.php,v 1.3 2007/01/10 01:46:28 soranzo Exp $
*/
class ArrayRecordSet {
var $_array;
var $_count;
var $EOF = false;
var $fields;
function ArrayRecordSet($data) {
$this->_array = $data;
$this->_count = count($this->_array);
$this->fields = reset($this->_array);
if ($this->fields === false) $this->EOF = true;
}
function recordCount() {
return $this->_count;
}
function moveNext() {
$this->fields = next($this->_array);
if ($this->fields === false) $this->EOF = true;
}
}
?>

View File

@ -0,0 +1,48 @@
<?php
/**
* Class to handle basic HTML GUI functions
*
* $Id: Gui.php,v 1.2 2004/06/07 20:03:22 soranzo Exp $
*/
class GUI {
/**
*Constructor
*/
function GUI () {}
/**
* Finds a particular report
* @param $arrOptions associative array storing options and values of combo should be Option => Value
* @param $szName string to specify the name of the form element
* @param (optional) $bBlankEntry bool to specify whether or not we want a blank selection
* @param (optional) $szDefault string to specify the default VALUE selected
* @param (optional) $bMultiple bool to specify whether or not we want a multi select combo box
* @param (optional) $iSize int to specify the size IF a multi select combo
* @return string with the generated HTML select box
*/
function printCombo(&$arrOptions, $szName, $bBlankEntry = true, $szDefault = '', $bMultiple = false, $iSize = 10) {
$htmlOut = '';
if ($bMultiple) // If multiple select combo
$htmlOut .= "<select name=\"$szName\" id=\"$szName\" multiple=\"multiple\" size=\"$iSize\">\n";
else
$htmlOut .= "<select name=\"$szName\" id=\"$szName\">\n";
if ($bBlankEntry)
$htmlOut .= "<option value=\"\"></option>\n";
foreach ($arrOptions AS $curKey => $curVal) {
$curVal = htmlspecialchars($curVal);
$curKey = htmlspecialchars($curKey);
if ($curVal == $szDefault) {
$htmlOut .= "<option value=\"$curVal\" selected=\"selected\">$curKey</option>\n";
}
else {
$htmlOut .= "<option value=\"$curVal\">$curKey</option>\n";
}
}
$htmlOut .= "</select>\n";
return $htmlOut;
}
}
?>

2259
php/pgadmin/classes/Misc.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
<?php
/**
* Class to manage reports. Note how this class is designed to use
* the functions provided by the database driver exclusively, and hence
* will work with any database without modification.
*
* $Id: Reports.php,v 1.18 2007/04/16 11:02:35 mr-russ Exp $
*/
class Reports {
// A database driver
var $driver;
var $reports_db = 'phppgadmin';
var $reports_schema = 'public';
var $reports_table = 'ppa_reports';
/* Constructor */
function Reports(&$status) {
global $conf, $misc, $data;
// Get data from config if it's been defined
if (isset($conf['reports_db'])) {
$this->reports_db = $conf['reports_db'];
}
if (isset($conf['reports_schema'])) {
$this->reports_schema = $conf['reports_schema'];
}
if (isset($conf['reports_table'])) {
$this->reports_table = $conf['reports_table'];
}
// Check to see if the reports database exists
$rs = $data->getDatabase($this->reports_db);
if ($rs->recordCount() != 1) $status = -1;
else {
// Create a new database access object.
$this->driver = $misc->getDatabaseAccessor($this->reports_db);
// Reports database should have been created in public schema
$this->driver->setSchema($this->reports_schema);
$status = 0;
}
}
/**
* Finds all reports
* @return A recordset
*/
function getReports() {
global $conf, $misc;
// Filter for owned reports if necessary
if ($conf['owned_reports_only']) {
$server_info = $misc->getServerInfo();
$filter['created_by'] = $server_info['username'];
$ops = array('created_by' => '=');
}
else $filter = $ops = array();
$sql = $this->driver->getSelectSQL($this->reports_table,
array('report_id', 'report_name', 'db_name', 'date_created', 'created_by', 'descr', 'report_sql', 'paginate'),
$filter, $ops, array('db_name' => 'asc', 'report_name' => 'asc'));
return $this->driver->selectSet($sql);
}
/**
* Finds a particular report
* @param $report_id The ID of the report to find
* @return A recordset
*/
function getReport($report_id) {
$sql = $this->driver->getSelectSQL($this->reports_table,
array('report_id', 'report_name', 'db_name', 'date_created', 'created_by', 'descr', 'report_sql', 'paginate'),
array('report_id' => $report_id), array('report_id' => '='), array());
return $this->driver->selectSet($sql);
}
/**
* Creates a report
* @param $report_name The name of the report
* @param $db_name The name of the database
* @param $descr The comment on the report
* @param $report_sql The SQL for the report
* @param $paginate The report should be paginated
* @return 0 success
*/
function createReport($report_name, $db_name, $descr, $report_sql, $paginate) {
global $misc;
$server_info = $misc->getServerInfo();
$temp = array(
'report_name' => $report_name,
'db_name' => $db_name,
'created_by' => $server_info['username'],
'report_sql' => $report_sql,
'paginate' => $paginate ? 'true' : 'false',
);
if ($descr != '') $temp['descr'] = $descr;
return $this->driver->insert($this->reports_table, $temp);
}
/**
* Alters a report
* @param $report_id The ID of the report
* @param $report_name The name of the report
* @param $db_name The name of the database
* @param $descr The comment on the report
* @param $report_sql The SQL for the report
* @param $paginate The report should be paginated
* @return 0 success
*/
function alterReport($report_id, $report_name, $db_name, $descr, $report_sql, $paginate) {
global $misc;
$server_info = $misc->getServerInfo();
$temp = array(
'report_name' => $report_name,
'db_name' => $db_name,
'created_by' => $server_info['username'],
'report_sql' => $report_sql,
'paginate' => $paginate ? 'true' : 'false',
'descr' => $descr
);
return $this->driver->update($this->reports_table, $temp,
array('report_id' => $report_id));
}
/**
* Drops a report
* @param $report_id The ID of the report to drop
* @return 0 success
*/
function dropReport($report_id) {
return $this->driver->delete($this->reports_table, array('report_id' => $report_id));
}
}
?>

View File

@ -0,0 +1,217 @@
<?php
/**
* XHtmlSimpleElement
*
* Used to generate Xhtml-Code for simple xhtml elements
* (i.e. elements, that can't contain child elements)
*
*
* @author Felix Meinhold
*
*/
class XHtmlSimpleElement {
var $_element;
var $_siblings = array();
var $_htmlcode;
var $_attributes = array();
/**
* Constructor
*
* @param string The element's name. Defaults to name of the
* derived class
*
*/
function XHtmlSimpleElement($element = null) {
$this->_element = $this->is_element();
}
function set_style($style) {
$this->set_attribute('style', $style);
}
function set_class($class) {
$this->set_attribute('class', $class);
}
function is_element() {
return
str_replace('xhtml_', '', strtolower(get_class($this)));
}
/**
* Private function generates xhtml
* @access private
*/
function _html() {
$this->_htmlcode = "<";
foreach ($this->_attributeCollection as $attribute => $value) {
if (!empty($value)) $this->_htmlcode .= " {$attribute}=\"{$value}\"";
}
$this->_htmlcode .= "/>";
return $this->_htmlcode;
}
/**
* Returns xhtml code
*
*/
function fetch() {
return $this->_html();
}
/**
* Echoes xhtml
*
*/
function show() {
echo $this->fetch();
}
function set_attribute($attr, $value) {
$this->_attributes[$attr] = $value;
}
}
/**
* XHtmlElement
*
* Used to generate Xhtml-Code for xhtml elements
* that can contain child elements
*
*
*/
class XHtmlElement extends XHtmlSimpleElement {
var $_text = null;
var $_htmlcode = "";
var $_siblings = array();
function XHtmlElement($text = null) {
XHtmlSimpleElement::XHtmlSimpleElement();
if ($text) $this->set_text($text);
}
/*
* Adds an xhtml child to element
*
* @param XHtmlElement The element to become a child of element
*/
function add(&$object) {
array_push($this->_siblings, $object);
}
/*
* The CDATA section of Element
*
* @param string Text
*/
function set_text($text) {
if ($text) $this->_text = htmlspecialchars($text);
}
function fetch() {
return $this->_html();
}
function _html() {
$this->_htmlcode = "<{$this->_element}";
foreach ($this->_attributes as $attribute =>$value) {
if (!empty($value)) $this->_htmlcode .= " {$attribute} =\"{$value}\"";
}
$this->_htmlcode .= ">";
if ($this->_text) {
$this->_htmlcode .= $this->_text;
}
foreach ($this->_siblings as $obj) {
$this->_htmlcode .= $obj->fetch();
}
$this->_htmlcode .= "</{$this->_element}>";
return $this->_htmlcode;
}
/*
* Returns siblings of Element
*
*/
function get_siblings() {
return $this->_siblings;
}
function has_siblings() {
return (count($this->_siblings) != 0);
}
}
class XHTML_Button extends XHtmlElement {
function XHTML_Button ($name, $text = null) {
parent::XHtmlElement();
$this->set_attribute("name", $name);
if ($text) $this->set_text($text);
}
}
class XHTML_Option extends XHtmlElement {
function XHTML_Option($text, $value = null) {
XHtmlElement::XHtmlElement(null);
$this->set_text($text);
}
}
class XHTML_Select extends XHTMLElement {
var $_data;
function XHTML_Select ($name, $multiple = false, $size = null) {
XHtmlElement::XHtmlElement();
$this->set_attribute("name", $name);
if ($multiple) $this->set_attribute("multiple","multiple");
if ($size) $this->set_attribute("size",$size);
}
function set_data(&$data, $delim = ",") {
switch (gettype($data)) {
case "string":
$this->_data = explode($delim, $data);
break;
case "array":
$this->_data = $data;
break;
default:
break;
}
}
function fetch() {
if (isset($this->_data) && $this->_data) {
foreach ($this->_data as $value) { $this->add(new XHTML_Option($value)); }
}
return parent::fetch();
}
}
?>

View File

@ -0,0 +1,359 @@
<?php
/*
* Parent class of all ADODB objects.
*
* $Id: ADODB_base.php,v 1.24 2008/02/20 20:43:10 ioguix Exp $
*/
include_once('./libraries/errorhandler.inc.php');
include_once('./libraries/adodb/adodb.inc.php');
class ADODB_base {
var $conn;
// The backend platform. Set to UNKNOWN by default.
var $platform = 'UNKNOWN';
/**
* Base constructor
* @param &$conn The connection object
*/
function ADODB_base(&$conn) {
$this->conn = $conn;
}
/**
* Turns on or off query debugging
* @param $debug True to turn on debugging, false otherwise
*/
function setDebug($debug) {
$this->conn->debug = $debug;
}
/**
* Cleans (escapes) a string
* @param $str The string to clean, by reference
* @return The cleaned string
*/
function clean(&$str) {
$str = addslashes($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) {
$str = str_replace('"', '""', $str);
return $str;
}
/**
* Cleans (escapes) an array
* @param $arr The array to clean, by reference
* @return The cleaned array
*/
function arrayClean(&$arr) {
reset($arr);
while(list($k, $v) = each($arr))
$arr[$k] = addslashes($v);
return $arr;
}
/**
* Executes a query on the underlying connection
* @param $sql The SQL query to execute
* @return A recordset
*/
function execute($sql) {
// Execute the statement
$rs = $this->conn->Execute($sql);
// If failure, return error value
return $this->conn->ErrorNo();
}
/**
* Closes the connection the database class
* relies on.
*/
function close() {
$this->conn->close();
}
/**
* Retrieves a ResultSet from a query
* @param $sql The SQL statement to be executed
* @return A recordset
*/
function selectSet($sql) {
// Execute the statement
$rs = $this->conn->Execute($sql);
if (!$rs) return $this->conn->ErrorNo();
return $rs;
}
/**
* Retrieves a single value from a query
*
* @@ assumes that the query will return only one row - returns field value in the first row
*
* @param $sql The SQL statement to be executed
* @param $field The field name to be returned
* @return A single field value
* @return -1 No rows were found
*/
function selectField($sql, $field) {
// Execute the statement
$rs = $this->conn->Execute($sql);
// If failure, or no rows returned, return error value
if (!$rs) return $this->conn->ErrorNo();
elseif ($rs->RecordCount() == 0) return -1;
return $rs->fields[$field];
}
/**
* Delete from the database
* @param $table The name of the table
* @param $conditions (array) A map of field names to conditions
* @param $schema (optional) The table's schema
* @return 0 success
* @return -1 on referential integrity violation
* @return -2 on no rows deleted
*/
function delete($table, $conditions, $schema = '') {
$this->fieldClean($table);
reset($conditions);
if (!empty($schema)) {
$this->fieldClean($schema);
$schema = "\"{$schema}\".";
}
// Build clause
$sql = '';
while(list($key, $value) = each($conditions)) {
$this->clean($key);
$this->clean($value);
if ($sql) $sql .= " AND \"{$key}\"='{$value}'";
else $sql = "DELETE FROM {$schema}\"{$table}\" WHERE \"{$key}\"='{$value}'";
}
// Check for failures
if (!$this->conn->Execute($sql)) {
// Check for referential integrity failure
if (stristr($this->conn->ErrorMsg(), 'referential'))
return -1;
}
// Check for no rows modified
if ($this->conn->Affected_Rows() == 0) return -2;
return $this->conn->ErrorNo();
}
/**
* Insert a set of values into the database
* @param $table The table to insert into
* @param $vars (array) A mapping of the field names to the values to be inserted
* @return 0 success
* @return -1 if a unique constraint is violated
* @return -2 if a referential constraint is violated
*/
function insert($table, $vars) {
$this->fieldClean($table);
// Build clause
if (sizeof($vars) > 0) {
$fields = '';
$values = '';
foreach($vars as $key => $value) {
$this->clean($key);
$this->clean($value);
if ($fields) $fields .= ", \"{$key}\"";
else $fields = "INSERT INTO \"{$table}\" (\"{$key}\"";
if ($values) $values .= ", '{$value}'";
else $values = ") VALUES ('{$value}'";
}
$sql = $fields . $values . ')';
}
// Check for failures
if (!$this->conn->Execute($sql)) {
// Check for unique constraint failure
if (stristr($this->conn->ErrorMsg(), 'unique'))
return -1;
// Check for referential integrity failure
elseif (stristr($this->conn->ErrorMsg(), 'referential'))
return -2;
}
return $this->conn->ErrorNo();
}
/**
* Update a row in the database
* @param $table The table that is to be updated
* @param $vars (array) A mapping of the field names to the values to be updated
* @param $where (array) A mapping of field names to values for the where clause
* @param $nulls (array, optional) An array of fields to be set null
* @return 0 success
* @return -1 if a unique constraint is violated
* @return -2 if a referential constraint is violated
* @return -3 on no rows deleted
*/
function update($table, $vars, $where, $nulls = array()) {
$this->fieldClean($table);
$setClause = '';
$whereClause = '';
// Populate the syntax arrays
reset($vars);
while(list($key, $value) = each($vars)) {
$this->fieldClean($key);
$this->clean($value);
if ($setClause) $setClause .= ", \"{$key}\"='{$value}'";
else $setClause = "UPDATE \"{$table}\" SET \"{$key}\"='{$value}'";
}
reset($nulls);
while(list(, $value) = each($nulls)) {
$this->fieldClean($value);
if ($setClause) $setClause .= ", \"{$value}\"=NULL";
else $setClause = "UPDATE \"{$table}\" SET \"{$value}\"=NULL";
}
reset($where);
while(list($key, $value) = each($where)) {
$this->fieldClean($key);
$this->clean($value);
if ($whereClause) $whereClause .= " AND \"{$key}\"='{$value}'";
else $whereClause = " WHERE \"{$key}\"='{$value}'";
}
// Check for failures
if (!$this->conn->Execute($setClause . $whereClause)) {
// Check for unique constraint failure
if (stristr($this->conn->ErrorMsg(), 'unique'))
return -1;
// Check for referential integrity failure
elseif (stristr($this->conn->ErrorMsg(), 'referential'))
return -2;
}
// Check for no rows modified
if ($this->conn->Affected_Rows() == 0) return -3;
return $this->conn->ErrorNo();
}
/**
* Begin a transaction
* @return 0 success
*/
function beginTransaction() {
return !$this->conn->BeginTrans();
}
/**
* End a transaction
* @return 0 success
*/
function endTransaction() {
return !$this->conn->CommitTrans();
}
/**
* Roll back a transaction
* @return 0 success
*/
function rollbackTransaction() {
return !$this->conn->RollbackTrans();
}
/**
* Get the backend platform
* @return The backend platform
*/
function getPlatform() {
//return $this->conn->platform;
return "UNKNOWN";
}
// Type conversion routines
/**
* Change the value of a parameter to database representation depending on whether it evaluates to true or false
* @param $parameter the parameter
*/
function dbBool(&$parameter) {
return $parameter;
}
/**
* Change a parameter from database representation to a boolean, (others evaluate to false)
* @param $parameter the parameter
*/
function phpBool($parameter) {
return $parameter;
}
/**
* Change a db array into a PHP array
* @param $arr String representing the DB array
* @return A PHP array
*/
function phpArray($dbarr) {
// Take off the first and last characters (the braces)
$arr = substr($dbarr, 1, strlen($dbarr) - 2);
// Pick out array entries by carefully parsing. This is necessary in order
// to cope with double quotes and commas, etc.
$elements = array();
$i = $j = 0;
$in_quotes = false;
while ($i < strlen($arr)) {
// If current char is a double quote and it's not escaped, then
// enter quoted bit
$char = substr($arr, $i, 1);
if ($char == '"' && ($i == 0 || substr($arr, $i - 1, 1) != '\\'))
$in_quotes = !$in_quotes;
elseif ($char == ',' && !$in_quotes) {
// Add text so far to the array
$elements[] = substr($arr, $j, $i - $j);
$j = $i + 1;
}
$i++;
}
// Add final text to the array
$elements[] = substr($arr, $j);
// Do one further loop over the elements array to remote double quoting
// and escaping of double quotes and backslashes
for ($i = 0; $i < sizeof($elements); $i++) {
$v = $elements[$i];
if (strpos($v, '"') === 0) {
$v = substr($v, 1, strlen($v) - 2);
$v = str_replace('\\"', '"', $v);
$v = str_replace('\\\\', '\\', $v);
$elements[$i] = $v;
}
}
return $elements;
}
}
?>

View File

@ -0,0 +1,115 @@
<?php
/**
* Class to represent a database connection
*
* $Id: Connection.php,v 1.15 2008/02/18 21:42:47 ioguix Exp $
*/
include_once('./classes/database/ADODB_base.php');
class Connection {
var $conn;
// The backend platform. Set to UNKNOWN by default.
var $platform = 'UNKNOWN';
/**
* Creates a new connection. Will actually make a database connection.
* @param $fetchMode Defaults to associative. Override for different behaviour
*/
function Connection($host, $port, $sslmode, $user, $password, $database, $fetchMode = ADODB_FETCH_ASSOC) {
$this->conn = &ADONewConnection('postgres7');
$this->conn->setFetchMode($fetchMode);
// Ignore host if null
if ($host === null || $host == '')
if ($port !== null && $port != '')
$pghost = ':'.$port;
else
$pghost = '';
else
$pghost = "{$host}:{$port}";
// Add sslmode to $pghost as needed
if (($sslmode == 'disable') || ($sslmode == 'allow') || ($sslmode == 'prefer') || ($sslmode == 'require')) {
$pghost .= ':'.$sslmode;
} elseif ($sslmode == 'legacy') {
$pghost .= ' requiressl=1';
}
$this->conn->connect($pghost, $user, $password, $database);
}
/**
* Gets the name of the correct database driver to use. As a side effect,
* sets the platform.
* @param (return-by-ref) $description A description of the database and version
* @return The class name of the driver eg. Postgres84
* @return null if version is < 7.4
* @return -3 Database-specific failure
*/
function getDriver(&$description) {
// If we're on a recent enough PHP 5, and against PostgreSQL 7.4 or
// higher, we don't need to query for the version. This gives a great
// speed up.
if (function_exists('pg_version')) {
$v = pg_version($this->conn->_connectionID);
if (isset($v['server'])) $version = $v['server'];
}
// If we didn't manage to get the version without a query, query...
if (!isset($version)) {
$adodb = new ADODB_base($this->conn);
$sql = "SELECT VERSION() AS version";
$field = $adodb->selectField($sql, 'version');
// Check the platform, if it's mingw, set it
if (preg_match('/ mingw /i', $field))
$this->platform = 'MINGW';
$params = explode(' ', $field);
if (!isset($params[1])) return -3;
$version = $params[1]; // eg. 8.4.4
}
$description = "PostgreSQL {$version}";
// Detect version and choose appropriate database driver
switch (substr($version,0,3)) {
case '8.4': return 'Postgres'; break;
case '8.3': return 'Postgres83'; break;
case '8.2': return 'Postgres82'; break;
case '8.1': return 'Postgres81'; break;
case '8.0':
case '7.5': return 'Postgres80'; break;
case '7.4': return 'Postgres74'; break;
}
/* All <7.4 versions are not supported */
// if major version is 7 or less and wasn't catch in the
// switch/case block, we have an unsupported version.
if ((int)substr($version, 0, 1) < 8)
return null;
// If unknown version, then default to latest driver
return 'Postgres';
}
/**
* Get the last error in the connection
* @return Error string
*/
function getLastError() {
if (function_exists('pg_errormessage'))
return pg_errormessage($this->conn->_connectionID);
else
return pg_last_error($this->conn->_connectionID);
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,627 @@
<?php
/**
* A class that implements the DB interface for Postgres
* Note: This class uses ADODB and returns RecordSets.
*
* $Id: Postgres74.php,v 1.72 2008/02/20 21:06:18 ioguix Exp $
*/
include_once('./classes/database/Postgres80.php');
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 = array(
'table' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'),
'view' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'),
'sequence' => array('SELECT', 'UPDATE', 'ALL PRIVILEGES'),
'database' => array('CREATE', 'TEMPORARY', 'ALL PRIVILEGES'),
'function' => array('EXECUTE', 'ALL PRIVILEGES'),
'language' => array('USAGE', 'ALL PRIVILEGES'),
'schema' => array('CREATE', 'USAGE', 'ALL PRIVILEGES')
);
/**
* Constructor
* @param $conn The database connection
*/
function Postgres74($conn) {
$this->Postgres80($conn);
}
// Help functions
function getHelpPages() {
include_once('./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) {
global $conf, $misc;
$server_info = $misc->getServerInfo();
if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($server_info['username'])) {
$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
{$where}
{$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) {
global $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
SELECT CASE WHEN relkind='r' THEN 'TABLE' WHEN relkind='v' THEN 'VIEW' WHEN relkind='S' THEN 'SEQUENCE' END, pc.oid,
pn.nspname, NULL, pc.relname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn
WHERE pc.relnamespace=pn.oid AND relkind IN ('r', 'v', 'S') AND relname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT CASE WHEN pc.relkind='r' THEN 'COLUMNTABLE' ELSE 'COLUMNVIEW' END, NULL, pn.nspname, pc.relname, pa.attname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn,
pg_catalog.pg_attribute pa WHERE pc.relnamespace=pn.oid AND pc.oid=pa.attrelid
AND pa.attname ILIKE '%{$term}%' AND pa.attnum > 0 AND NOT pa.attisdropped AND pc.relkind IN ('r', 'v') {$where}
UNION ALL
SELECT 'FUNCTION', pp.oid, pn.nspname, NULL, pp.proname || '(' || pg_catalog.oidvectortypes(pp.proargtypes) || ')' FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pn
WHERE pp.pronamespace=pn.oid AND NOT pp.proisagg AND pp.proname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT 'INDEX', NULL, pn.nspname, pc.relname, pc2.relname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn,
pg_catalog.pg_index pi, pg_catalog.pg_class pc2 WHERE pc.relnamespace=pn.oid AND pc.oid=pi.indrelid
AND pi.indexrelid=pc2.oid
AND NOT EXISTS (
SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
WHERE d.classid = pc2.tableoid AND d.objid = pc2.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p')
)
AND pc2.relname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT 'CONSTRAINTTABLE', NULL, pn.nspname, pc.relname, pc2.conname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn,
pg_catalog.pg_constraint pc2 WHERE pc.relnamespace=pn.oid AND pc.oid=pc2.conrelid AND pc2.conrelid != 0
AND CASE WHEN pc2.contype IN ('f', 'c') THEN TRUE ELSE NOT EXISTS (
SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
WHERE d.classid = pc2.tableoid AND d.objid = pc2.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p')
) END
AND pc2.conname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT 'CONSTRAINTDOMAIN', pt.oid, pn.nspname, pt.typname, pc.conname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn,
pg_catalog.pg_constraint pc WHERE pt.typnamespace=pn.oid AND pt.oid=pc.contypid AND pc.contypid != 0
AND pc.conname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT 'TRIGGER', NULL, pn.nspname, pc.relname, pt.tgname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn,
pg_catalog.pg_trigger pt WHERE pc.relnamespace=pn.oid AND pc.oid=pt.tgrelid
AND ( pt.tgisconstraint = 'f' OR NOT EXISTS
(SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
WHERE d.classid = pt.tableoid AND d.objid = pt.oid AND d.deptype = 'i' AND c.contype = 'f'))
AND pt.tgname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT 'RULETABLE', NULL, pn.nspname AS schemaname, c.relname AS tablename, r.rulename FROM pg_catalog.pg_rewrite r
JOIN pg_catalog.pg_class c ON c.oid = r.ev_class
LEFT JOIN pg_catalog.pg_namespace pn ON pn.oid = c.relnamespace
WHERE c.relkind='r' AND r.rulename != '_RETURN' AND r.rulename ILIKE '%{$term}%' {$where}
UNION ALL
SELECT 'RULEVIEW', NULL, pn.nspname AS schemaname, c.relname AS tablename, r.rulename FROM pg_catalog.pg_rewrite r
JOIN pg_catalog.pg_class c ON c.oid = r.ev_class
LEFT JOIN pg_catalog.pg_namespace pn ON pn.oid = c.relnamespace
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 .= "
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
WHERE pt.typnamespace=pn.oid AND typname ILIKE '%{$term}%'
AND (pt.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = pt.typrelid))
{$where}
UNION ALL
SELECT 'OPERATOR', po.oid, pn.nspname, NULL, po.oprname FROM pg_catalog.pg_operator po, pg_catalog.pg_namespace pn
WHERE po.oprnamespace=pn.oid AND oprname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT 'CONVERSION', pc.oid, pn.nspname, NULL, pc.conname FROM pg_catalog.pg_conversion pc,
pg_catalog.pg_namespace pn WHERE pc.connamespace=pn.oid AND conname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT 'LANGUAGE', pl.oid, NULL, NULL, pl.lanname FROM pg_catalog.pg_language pl
WHERE lanname ILIKE '%{$term}%' {$lan_where}
UNION ALL
SELECT DISTINCT ON (p.proname) 'AGGREGATE', p.oid, pn.nspname, NULL, p.proname FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace pn ON p.pronamespace=pn.oid
WHERE p.proisagg AND p.proname ILIKE '%{$term}%' {$where}
UNION ALL
SELECT DISTINCT ON (po.opcname) 'OPCLASS', po.oid, pn.nspname, NULL, po.opcname FROM pg_catalog.pg_opclass po,
pg_catalog.pg_namespace pn WHERE po.opcnamespace=pn.oid
AND po.opcname ILIKE '%{$term}%' {$where}
";
}
// 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
WHERE pt.typnamespace=pn.oid AND pt.typtype='d' AND typname ILIKE '%{$term}%'
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}%' ";
}
$sql .= "ORDER BY type, schemaname, relname, name";
return $this->selectSet($sql);
}
// Database functions
/**
* Returns table locks information in the current database
* @return A recordset
*/
function getLocks() {
global $conf;
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
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);
}
// 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 = "
SELECT
c.relname, n.nspname, u.usename AS relowner,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
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
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,
pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment,
reltuples::bigint
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
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
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)
JOIN pg_catalog.pg_namespace AS ns ON (r.relnamespace=ns.oid)
WHERE
r.relname = '{$table}' AND ns.nspname='{$c_schema}'";
$rs = $this->selectSet($sql);
if ($rs->EOF) $max_col = 0;
else $max_col = $rs->fields['nb'];
$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,
r2.relname as f_table, f1.attname as p_field, f1.attnum AS p_attnum, f2.attname as f_field,
f2.attnum AS f_attnum, pg_catalog.obj_description(c.oid, \'pg_constraint\') AS constcomment,
c.conrelid, c.confrelid
FROM
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.= '))
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)";
$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
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
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 );
}
// 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 = "
SELECT
pc.oid AS prooid,
proname,
pg_catalog.pg_get_userbyid(proowner) AS proowner,
nspname as proschema,
lanname as prolanguage,
pg_catalog.format_type(prorettype, NULL) as proresult,
prosrc,
probin,
proretset,
proisstrict,
provolatile,
prosecdef,
pg_catalog.oidvectortypes(pc.proargtypes) AS proarguments,
pg_catalog.obj_description(pc.oid, 'pg_proc') AS procomment
FROM
pg_catalog.pg_proc pc, pg_catalog.pg_language pl, pg_catalog.pg_namespace n
WHERE
pc.oid = '$function_oid'::oid
AND pc.prolang = pl.oid
AND n.oid = pc.pronamespace
";
return $this->selectSet($sql);
}
/**
* Returns a list of all casts in the database
* @return All casts
*/
function getCasts() {
global $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 = "
SELECT
c.castsource::pg_catalog.regtype AS castsource,
c.casttarget::pg_catalog.regtype AS casttarget,
CASE WHEN c.castfunc=0 THEN NULL
ELSE c.castfunc::pg_catalog.regprocedure END AS castfunc,
c.castcontext,
obj_description(c.oid, 'pg_cast') as castcomment
FROM
(pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p ON c.castfunc=p.oid JOIN pg_catalog.pg_namespace n3 ON p.pronamespace=n3.oid),
pg_catalog.pg_type t1,
pg_catalog.pg_type t2,
pg_catalog.pg_namespace n1,
pg_catalog.pg_namespace n2
WHERE
c.castsource=t1.oid
AND c.casttarget=t2.oid
AND t1.typnamespace=n1.oid
AND t2.typnamespace=n2.oid
{$where}
ORDER BY 1, 2
";
return $this->selectSet($sql);
}
// Capabilities
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; }
}
?>

View File

@ -0,0 +1,360 @@
<?php
/**
* PostgreSQL 8.0 support
*
* $Id: Postgres80.php,v 1.28 2007/12/12 04:11:10 xzilla Exp $
*/
include_once('./classes/database/Postgres81.php');
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 = array(
'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'
);
/**
* Constructor
* @param $conn The database connection
*/
function Postgres80($conn) {
$this->Postgres81($conn);
}
// Help functions
function getHelpPages() {
include_once('./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) {
global $conf, $misc;
$server_info = $misc->getServerInfo();
if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($server_info['username'])) {
$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
WHERE pdb.datdba = pu.usesysid
{$where}
{$clause}
{$orderby}";
return $this->selectSet($sql);
}
// Schema functions
/**
* Return all schemas in the current database.
* @return All schemas, sorted alphabetically
*/
function getSchemas() {
global $conf, $slony;
if (!$conf['show_system']) {
$where = "WHERE nspname NOT LIKE 'pg@_%' ESCAPE '@' AND nspname != 'information_schema'";
if (isset($slony) && $slony->isEnabled()) {
$temp = $slony->slony_schema;
$this->clean($temp);
$where .= " AND nspname != '{$temp}'";
}
}
else $where = "WHERE nspname !~ '^pg_t(emp_[0-9]+|oast)$'";
$sql = "
SELECT pn.nspname, pu.usename AS nspowner,
pg_catalog.obj_description(pn.oid, 'pg_namespace') AS nspcomment
FROM pg_catalog.pg_namespace pn
LEFT JOIN pg_catalog.pg_user pu ON (pn.nspowner = pu.usesysid)
{$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 = "
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 = "
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, format_type(a.aggtranstype, NULL) AS aggstype,
a.aggfinalfn, a.agginitval, 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}'
AND p.proname='{$name}'
AND CASE p.proargtypes[0]
WHEN 'pg_catalog.\"any\"'::pg_catalog.regtype THEN ''
ELSE pg_catalog.format_type(p.proargtypes[0], NULL)
END ='{$basetype}'";
return $this->selectSet($sql);
}
// Capabilities
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; }
}
?>

View File

@ -0,0 +1,183 @@
<?php
/**
* PostgreSQL 8.1 support
*
* $Id: Postgres81.php,v 1.21 2008/01/19 13:46:15 ioguix Exp $
*/
include_once('./classes/database/Postgres82.php');
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 = array(
'table' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'),
'view' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'),
'sequence' => array('SELECT', 'UPDATE', 'ALL PRIVILEGES'),
'database' => array('CREATE', 'TEMPORARY', 'ALL PRIVILEGES'),
'function' => array('EXECUTE', 'ALL PRIVILEGES'),
'language' => array('USAGE', 'ALL PRIVILEGES'),
'schema' => array('CREATE', 'USAGE', 'ALL PRIVILEGES'),
'tablespace' => array('CREATE', 'ALL PRIVILEGES')
);
// List of characters in acl lists and the privileges they
// refer to.
var $privmap = array(
'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 = array('BTREE', 'RTREE', 'GIST', 'HASH');
/**
* Constructor
* @param $conn The database connection
*/
function Postgres81($conn) {
$this->Postgres82($conn);
}
// Help functions
function getHelpPages() {
include_once('./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) {
global $conf, $misc;
$server_info = $misc->getServerInfo();
if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($server_info['username'])) {
$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
FROM pg_catalog.pg_database pdb LEFT JOIN pg_catalog.pg_roles pr ON (pdb.datdba = pr.oid)
WHERE true
{$where}
{$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();
}
// Tablespace functions
/**
* Retrieves a tablespace's information
* @return A recordset
*/
function getTablespace($spcname) {
$this->clean($spcname);
$sql = "SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation
FROM pg_catalog.pg_tablespace WHERE spcname='{$spcname}'";
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) {
global $conf;
$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\_%$$';
}
$sql .= " ORDER BY spcname";
return $this->selectSet($sql);
}
// Capabilities
function hasCreateTableLikeWithConstraints() {return false;}
function hasSharedComments() {return false;}
function hasConcurrentIndexBuild() {return false;}
}
?>

View File

@ -0,0 +1,359 @@
<?php
/**
* PostgreSQL 8.2 support
*
* $Id: Postgres82.php,v 1.10 2007/12/28 16:21:25 ioguix Exp $
*/
include_once('./classes/database/Postgres83.php');
class Postgres82 extends Postgres83 {
var $major_version = 8.2;
// Select operators
var $selectOps = array('=' => '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');
/**
* Constructor
* @param $conn The database connection
*/
function Postgres82($conn) {
$this->Postgres($conn);
}
// Help functions
function getHelpPages() {
include_once('./help/PostgresDoc82.php');
return $this->help_page;
}
// Database functions
/**
* Returns table locks information in the current database
* @return A recordset
*/
function getLocks() {
global $conf;
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
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
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
FROM pg_catalog.pg_trigger t, pg_catalog.pg_proc p, pg_catalog.pg_namespace ns
WHERE t.tgrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname='{$table}'
AND relnamespace=(SELECT oid FROM pg_catalog.pg_namespace WHERE nspname='{$c_schema}'))
AND (NOT tgisconstraint OR NOT EXISTS
(SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))
AND p.oid=t.tgfoid
AND p.pronamespace = ns.oid";
return $this->selectSet($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 = "SELECT
pc.oid AS prooid,
proname,
pg_catalog.pg_get_userbyid(proowner) AS proowner,
nspname as proschema,
lanname as prolanguage,
pg_catalog.format_type(prorettype, NULL) as proresult,
prosrc,
probin,
proretset,
proisstrict,
provolatile,
prosecdef,
pg_catalog.oidvectortypes(pc.proargtypes) AS proarguments,
proargnames AS proargnames,
pg_catalog.obj_description(pc.oid, 'pg_proc') AS procomment
FROM
pg_catalog.pg_proc pc, pg_catalog.pg_language pl, pg_catalog.pg_namespace pn
WHERE
pc.oid = '{$function_oid}'::oid
AND pc.prolang = pl.oid
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 = "
SELECT
po.oid, po.oprname,
oprleft::pg_catalog.regtype AS oprleftname,
oprright::pg_catalog.regtype AS oprrightname,
oprresult::pg_catalog.regtype AS resultname,
po.oprcanhash,
oprcom::pg_catalog.regoperator AS oprcom,
oprnegate::pg_catalog.regoperator AS oprnegate,
oprlsortop::pg_catalog.regoperator AS oprlsortop,
oprrsortop::pg_catalog.regoperator AS oprrsortop,
oprltcmpop::pg_catalog.regoperator AS oprltcmpop,
oprgtcmpop::pg_catalog.regoperator AS oprgtcmpop,
po.oprcode::pg_catalog.regproc AS oprcode,
po.oprrest::pg_catalog.regproc AS oprrest,
po.oprjoin::pg_catalog.regproc AS oprjoin
FROM
pg_catalog.pg_operator po
WHERE
po.oid='{$operator_oid}'
";
return $this->selectSet($sql);
}
// Operator Class functions
/**
* Gets all opclasses
* @return A recordset
*/
function getOpClasses() {
$c_schema = $this->_schema;
$this->clean($c_schema);
$sql = "
SELECT
pa.amname,
po.opcname,
po.opcintype::pg_catalog.regtype AS opcintype,
po.opcdefault,
pg_catalog.obj_description(po.oid, 'pg_opclass') AS opccomment
FROM
pg_catalog.pg_opclass po, pg_catalog.pg_am pa, pg_catalog.pg_namespace pn
WHERE
po.opcamid=pa.oid
AND po.opcnamespace=pn.oid
AND pn.nspname='{$c_schema}'
ORDER BY 1,2
";
return $this->selectSet($sql);
}
// Capabilities
function hasCreateTableLikeWithIndexes() {return false;}
function hasEnumTypes() {return false;}
function hasFTS() {return false;}
function hasFunctionCosting() {return false;}
function hasFunctionGUC() {return false;}
function hasVirtualTransactionId() {return false;}
}
?>

View File

@ -0,0 +1,332 @@
<?php
/**
* PostgreSQL 8.3 support
*
* $Id: Postgres82.php,v 1.10 2007/12/28 16:21:25 ioguix Exp $
*/
include_once('./classes/database/Postgres84.php');
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 = array(
'table' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'),
'view' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'),
'sequence' => array('SELECT', 'UPDATE', 'ALL PRIVILEGES'),
'database' => array('CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'),
'function' => array('EXECUTE', 'ALL PRIVILEGES'),
'language' => array('USAGE', 'ALL PRIVILEGES'),
'schema' => array('CREATE', 'USAGE', 'ALL PRIVILEGES'),
'tablespace' => array('CREATE', 'ALL PRIVILEGES')
);
// List of characters in acl lists and the privileges they
// refer to.
var $privmap = array(
'r' => 'SELECT',
'w' => 'UPDATE',
'a' => 'INSERT',
'd' => 'DELETE',
'R' => 'RULE',
'x' => 'REFERENCES',
't' => 'TRIGGER',
'X' => 'EXECUTE',
'U' => 'USAGE',
'C' => 'CREATE',
'T' => 'TEMPORARY',
'c' => 'CONNECT'
);
/**
* Constructor
* @param $conn The database connection
*/
function Postgres83($conn) {
$this->Postgres($conn);
}
// Help functions
function getHelpPages() {
include_once('./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) {
global $conf, $misc;
$server_info = $misc->getServerInfo();
if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($server_info['username'])) {
$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) 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
FROM pg_catalog.pg_database pdb LEFT JOIN pg_catalog.pg_roles pr ON (pdb.datdba = pr.oid)
WHERE true
{$where}
{$clause}
{$orderby}";
return $this->selectSet($sql);
}
// Administration functions
/**
* Returns all available autovacuum per table information.
* @return A recordset
*/
function getTableAutovacuum($table='') {
$sql = '';
if ($table !== '') {
$this->clean($table);
$c_schema = $this->_schema;
$this->clean($c_schema);
$sql = "
SELECT vacrelid, nspname, relname,
CASE enabled
WHEN 't' THEN 'on'
ELSE 'off'
END AS autovacuum_enabled, vac_base_thresh AS autovacuum_vacuum_threshold,
vac_scale_factor AS autovacuum_vacuum_scale_factor, anl_base_thresh AS autovacuum_analyze_threshold,
anl_scale_factor AS autovacuum_analyze_scale_factor, vac_cost_delay AS autovacuum_vacuum_cost_delay,
vac_cost_limit AS autovacuum_vacuum_cost_limit
FROM pg_autovacuum AS a
join pg_class AS c on (c.oid=a.vacrelid)
join pg_namespace AS n on (n.oid=c.relnamespace)
WHERE c.relname = '{$table}' AND n.nspname = '{$c_schema}'
ORDER BY nspname, relname
";
}
else {
$sql = "
SELECT vacrelid, nspname, relname,
CASE enabled
WHEN 't' THEN 'on'
ELSE 'off'
END AS autovacuum_enabled, vac_base_thresh AS autovacuum_vacuum_threshold,
vac_scale_factor AS autovacuum_vacuum_scale_factor, anl_base_thresh AS autovacuum_analyze_threshold,
anl_scale_factor AS autovacuum_analyze_scale_factor, vac_cost_delay AS autovacuum_vacuum_cost_delay,
vac_cost_limit AS autovacuum_vacuum_cost_limit
FROM pg_autovacuum AS a
join pg_class AS c on (c.oid=a.vacrelid)
join pg_namespace AS n on (n.oid=c.relnamespace)
ORDER BY nspname, relname
";
}
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);
$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)
WHERE
c.relname = '{$table}' AND n.nspname = '{$c_schema}'
");
if ($rs->EOF)
return -1;
$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_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_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_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['autovacuum_freeze_max_age']))
$_POST['autovacuum_freeze_max_age'] = $defaults['autovacuum_freeze_max_age'];
$rs = $this->selectSet("SELECT vacrelid
FROM \"pg_catalog\".\"pg_autovacuum\"
WHERE vacrelid = {$toid};");
$status = -1; // ini
if (isset($rs->fields['vacrelid']) 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,
anl_base_thresh = %s,
anl_scale_factor = %s,
vac_cost_delay = %s,
vac_cost_limit = %s,
freeze_min_age = %s,
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\"
VALUES (%s, '%s', %s, %s, %s, %s, %s, %s, %s, %s )
WHERE
c.relname = '{$table}' AND n.nspname = '{$c_schema}';",
$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("
SELECT c.oid
FROM pg_catalog.pg_class AS c
LEFT JOIN pg_catalog.pg_namespace AS n ON (n.oid=c.relnamespace)
WHERE
c.relname = '{$table}' AND n.nspname = '{$c_schema}'
");
return $this->deleteRow('pg_autovacuum', array('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 hasQueryKill() { return false; }
function hasDatabaseCollation() { return false; }
function hasAlterSequenceStart() { return false; }
}
?>

View File

@ -0,0 +1,229 @@
<?php
/**
* PostgreSQL 8.4 support
*
* $Id: Postgres82.php,v 1.10 2007/12/28 16:21:25 ioguix Exp $
*/
include_once('./classes/database/Postgres.php');
class Postgres84 extends Postgres {
var $major_version = 8.4;
// List of all legal privileges that can be applied to different types
// of objects.
var $privlist = array(
'table' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'),
'view' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'),
'sequence' => array('SELECT', 'UPDATE', 'ALL PRIVILEGES'),
'database' => array('CREATE', 'TEMPORARY', 'CONNECT', 'ALL PRIVILEGES'),
'function' => array('EXECUTE', 'ALL PRIVILEGES'),
'language' => array('USAGE', 'ALL PRIVILEGES'),
'schema' => array('CREATE', 'USAGE', 'ALL PRIVILEGES'),
'tablespace' => array('CREATE', 'ALL PRIVILEGES'),
'column' => array('SELECT', 'INSERT', 'UPDATE', 'REFERENCES','ALL PRIVILEGES')
);
/**
* Constructor
* @param $conn The database connection
*/
function Postgres84($conn) {
$this->Postgres($conn);
}
// Help functions
function getHelpPages() {
include_once('./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
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,
ns.nspname AS pronamespace
FROM pg_catalog.pg_trigger t, pg_catalog.pg_proc p, pg_catalog.pg_namespace ns
WHERE t.tgrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname='{$table}'
AND relnamespace=(SELECT oid FROM pg_catalog.pg_namespace WHERE nspname='{$c_schema}'))
AND (NOT tgisconstraint OR NOT EXISTS
(SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))
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) {
global $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
SELECT CASE WHEN relkind='r' THEN 'TABLE' WHEN relkind='v' THEN 'VIEW' WHEN relkind='S' THEN 'SEQUENCE' END, pc.oid,
pn.nspname, NULL, pc.relname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn
WHERE pc.relnamespace=pn.oid AND relkind IN ('r', 'v', 'S') AND relname ILIKE {$term} {$where}
UNION ALL
SELECT CASE WHEN pc.relkind='r' THEN 'COLUMNTABLE' ELSE 'COLUMNVIEW' END, NULL, pn.nspname, pc.relname, pa.attname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn,
pg_catalog.pg_attribute pa WHERE pc.relnamespace=pn.oid AND pc.oid=pa.attrelid
AND pa.attname ILIKE {$term} AND pa.attnum > 0 AND NOT pa.attisdropped AND pc.relkind IN ('r', 'v') {$where}
UNION ALL
SELECT 'FUNCTION', pp.oid, pn.nspname, NULL, pp.proname || '(' || pg_catalog.oidvectortypes(pp.proargtypes) || ')' FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pn
WHERE pp.pronamespace=pn.oid AND NOT pp.proisagg AND pp.proname ILIKE {$term} {$where}
UNION ALL
SELECT 'INDEX', NULL, pn.nspname, pc.relname, pc2.relname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn,
pg_catalog.pg_index pi, pg_catalog.pg_class pc2 WHERE pc.relnamespace=pn.oid AND pc.oid=pi.indrelid
AND pi.indexrelid=pc2.oid
AND NOT EXISTS (
SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
WHERE d.classid = pc2.tableoid AND d.objid = pc2.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p')
)
AND pc2.relname ILIKE {$term} {$where}
UNION ALL
SELECT 'CONSTRAINTTABLE', NULL, pn.nspname, pc.relname, pc2.conname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn,
pg_catalog.pg_constraint pc2 WHERE pc.relnamespace=pn.oid AND pc.oid=pc2.conrelid AND pc2.conrelid != 0
AND CASE WHEN pc2.contype IN ('f', 'c') THEN TRUE ELSE NOT EXISTS (
SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
WHERE d.classid = pc2.tableoid AND d.objid = pc2.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p')
) END
AND pc2.conname ILIKE {$term} {$where}
UNION ALL
SELECT 'CONSTRAINTDOMAIN', pt.oid, pn.nspname, pt.typname, pc.conname FROM pg_catalog.pg_type pt, pg_catalog.pg_namespace pn,
pg_catalog.pg_constraint pc WHERE pt.typnamespace=pn.oid AND pt.oid=pc.contypid AND pc.contypid != 0
AND pc.conname ILIKE {$term} {$where}
UNION ALL
SELECT 'TRIGGER', NULL, pn.nspname, pc.relname, pt.tgname FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pn,
pg_catalog.pg_trigger pt WHERE pc.relnamespace=pn.oid AND pc.oid=pt.tgrelid
AND ( NOT pt.tgisconstraint OR NOT EXISTS
(SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
WHERE d.classid = pt.tableoid AND d.objid = pt.oid AND d.deptype = 'i' AND c.contype = 'f'))
AND pt.tgname ILIKE {$term} {$where}
UNION ALL
SELECT 'RULETABLE', NULL, pn.nspname AS schemaname, c.relname AS tablename, r.rulename FROM pg_catalog.pg_rewrite r
JOIN pg_catalog.pg_class c ON c.oid = r.ev_class
LEFT JOIN pg_catalog.pg_namespace pn ON pn.oid = c.relnamespace
WHERE c.relkind='r' AND r.rulename != '_RETURN' AND r.rulename ILIKE {$term} {$where}
UNION ALL
SELECT 'RULEVIEW', NULL, pn.nspname AS schemaname, c.relname AS tablename, r.rulename FROM pg_catalog.pg_rewrite r
JOIN pg_catalog.pg_class c ON c.oid = r.ev_class
LEFT JOIN pg_catalog.pg_namespace pn ON pn.oid = c.relnamespace
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 .= "
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
WHERE pt.typnamespace=pn.oid AND typname ILIKE {$term}
AND (pt.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = pt.typrelid))
{$where}
UNION ALL
SELECT 'OPERATOR', po.oid, pn.nspname, NULL, po.oprname FROM pg_catalog.pg_operator po, pg_catalog.pg_namespace pn
WHERE po.oprnamespace=pn.oid AND oprname ILIKE {$term} {$where}
UNION ALL
SELECT 'CONVERSION', pc.oid, pn.nspname, NULL, pc.conname FROM pg_catalog.pg_conversion pc,
pg_catalog.pg_namespace pn WHERE pc.connamespace=pn.oid AND conname ILIKE {$term} {$where}
UNION ALL
SELECT 'LANGUAGE', pl.oid, NULL, NULL, pl.lanname FROM pg_catalog.pg_language pl
WHERE lanname ILIKE {$term} {$lan_where}
UNION ALL
SELECT DISTINCT ON (p.proname) 'AGGREGATE', p.oid, pn.nspname, NULL, p.proname FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace pn ON p.pronamespace=pn.oid
WHERE p.proisagg AND p.proname ILIKE {$term} {$where}
UNION ALL
SELECT DISTINCT ON (po.opcname) 'OPCLASS', po.oid, pn.nspname, NULL, po.opcname FROM pg_catalog.pg_opclass po,
pg_catalog.pg_namespace pn WHERE po.opcnamespace=pn.oid
AND po.opcname ILIKE {$term} {$where}
";
}
// 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
WHERE pt.typnamespace=pn.oid AND pt.typtype='d' AND typname ILIKE {$term}
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}%' ";
}
$sql .= "ORDER BY type, schemaname, relname, name";
return $this->selectSet($sql);
}
// Capabilities
}
?>

View File

@ -0,0 +1,30 @@
<?php
/**
* A class that implements the plugin system
*
* $Id: Plugin.php,v 1.2 2005/06/16 14:40:12 chriskl Exp $
*/
class Plugin {
var $tabname = null;
var $config = null;
var $name = null;
/**
* Constructor
*/
function Plugin($name) {
$this->name = $name;
// Read in configuration
if ($this->config !== null) {
global $conf;
include('./conf/' . $name . '.inc.php');
}
}
}
?>

View File

@ -0,0 +1,910 @@
<?php
/**
* A class that implements the Slony 1.0.x support plugin
*
* $Id: Slony.php,v 1.15 2007/10/02 21:36:35 ioguix Exp $
*/
include_once('./classes/plugins/Plugin.php');
class Slony extends Plugin {
var $slony_version;
var $slony_schema;
var $slony_cluster;
var $slony_owner;
var $slony_comment;
var $enabled = null;
/**
* Constructor
*/
function Slony() {
$this->Plugin('slony');
$this->isEnabled();
}
/**
* Determines whether or not Slony is installed in the current
* database.
* @post Will populate version and schema fields, etc.
* @return True if Slony is installed, false otherwise.
*/
function isEnabled() {
// Access cache
if ($this->enabled !== null) return $this->enabled;
else $this->enabled = false;
global $data;
// Check for the slonyversion() function and find the schema
// it's in. We put an order by and limit 1 in here to guarantee
// only finding the first one, even if there are somehow two
// Slony schemas.
$sql = "SELECT pn.nspname AS schema, pu.usename AS owner,
SUBSTRING(pn.nspname FROM 2) AS cluster,
pg_catalog.obj_description(pn.oid, 'pg_namespace') AS
nspcomment
FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pn,
pg_catalog.pg_user pu
WHERE pp.pronamespace=pn.oid
AND pn.nspowner = pu.usesysid
AND pp.proname='slonyversion'
AND pn.nspname LIKE '@_%' ESCAPE '@'
ORDER BY pn.nspname LIMIT 1";
$rs = $data->selectSet($sql);
if ($rs->recordCount() == 1) {
$schema = $rs->fields['schema'];
$this->slony_schema = $schema;
$this->slony_owner = $rs->fields['owner'];
$this->slony_comment = $rs->fields['nspcomment'];
// Cluster name is schema minus "_" prefix.
$this->slony_cluster = $rs->fields['cluster'];
$data->fieldClean($schema);
$sql = "SELECT \"{$schema}\".slonyversion() AS version";
$version = $data->selectField($sql, 'version');
if ($version === -1) return false;
else {
$this->slony_version = $version;
$this->enabled = true;
return true;
}
}
else return false;
}
// CLUSTERS
/**
* Gets the clusters in this database
*/
function getClusters() {
include_once('./classes/ArrayRecordSet.php');
if ($this->isEnabled()) {
$clusters = array(array('cluster' => $this->slony_cluster, 'comment' => $this->slony_comment));
}
else
$clusters = array();
return new ArrayRecordSet($clusters);
}
/**
* Gets a single cluster
*/
function getCluster() {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$sql = "SELECT no_id, no_comment, \"{$schema}\".slonyversion() AS version
FROM \"{$schema}\".sl_local_node_id, \"{$schema}\".sl_node
WHERE no_id=last_value";
return $data->selectSet($sql);
}
/**
* Drops an entire cluster.
*/
function dropCluster() {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$sql = "SELECT \"{$schema}\".uninstallnode(); DROP SCHEMA \"{$schema}\" CASCADE";
$status = $data->execute($sql);
if ($status == 0) {
$this->enabled = null;
$enabled = $this->isEnabled();
}
return $status;
}
/**
* Helper function to get a file into a string and replace
* variables.
* @return The file contents, or FALSE on error.
*/
function _getFile($file, $cluster) {
global $data,$misc;
$schema = '_' . $cluster;
$data->fieldClean($cluster);
$server_info = $misc->getServerInfo();
$path = $server_info['slony_sql'] . '/' . $file;
// Check that we can access the file
if (!file_exists($path) || !is_readable($path)) return false;
$buffer = null;
$handle = fopen($path, 'r');
if ($handle === false) return false;
while (!feof($handle)) {
$temp = fgets($handle, 4096);
$temp = str_replace('@CLUSTERNAME@', $cluster, $temp);
$temp = str_replace('@NAMESPACE@', $schema, $temp);
$buffer .= $temp;
}
fclose($handle);
return $buffer;
}
/**
* Initializes a new cluster
*/
function initCluster($name, $no_id, $no_comment) {
global $data, $misc;
// Prevent timeouts since cluster initialization can be slow
if (!ini_get('safe_mode')) set_time_limit(0);
$server_info = $misc->getServerInfo();
if (!$data->isSuperUser($server_info['username'])) {
return -10;
}
// Determine Slony compatibility version.
if ($data->major_version == 7.3)
$ver = '73';
elseif ($data->major_version >= 7.4)
$ver = '74';
else {
return -11;
}
$status = $data->beginTransaction();
if ($status != 0) return -1;
// Create the schema
$status = $data->createSchema('_' . $name);
if ($status != 0) {
$data->rollbackTransaction();
return -2;
}
$sql = $this->_getFile("xxid.v{$ver}.sql", $name);
if ($sql === false) {
$data->rollbackTransaction();
return -6;
}
$status = $data->execute($sql);
if ($status != 0) {
$data->rollbackTransaction();
return -3;
}
$sql = $this->_getFile('slony1_base.sql', $name);
if ($sql === false) {
$data->rollbackTransaction();
return -6;
}
$status = $data->execute($sql);
if ($status != 0) {
$data->rollbackTransaction();
return -3;
}
/* THIS FILE IS EMPTY AND JUST CAUSES ERRORS
$sql = $this->_getFile('slony1_base.v74.sql', $name);
$status = $data->execute($sql);
if ($status != 0) {
$data->rollbackTransaction();
return -3;
}
*/
$sql = $this->_getFile('slony1_funcs.sql', $name);
if ($sql === false) {
$data->rollbackTransaction();
return -6;
}
$status = $data->execute($sql);
if ($status != 0) {
$data->rollbackTransaction();
return -3;
}
$sql = $this->_getFile("slony1_funcs.v{$ver}.sql", $name);
if ($sql === false) {
$data->rollbackTransaction();
return -6;
}
$status = $data->execute($sql);
if ($status != 0) {
$data->rollbackTransaction();
return -3;
}
$this->enabled = null;
$enabled = $this->isEnabled();
if (!$enabled) {
$data->rollbackTransaction();
return -4;
}
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$data->clean($no_comment);
$sql = "SELECT \"{$schema}\".initializelocalnode('{$no_id}', '{$no_comment}'); SELECT \"{$schema}\".enablenode('{$no_id}')";
$status = $data->execute($sql);
if ($status != 0) {
$data->rollbackTransaction();
return -5;
}
return $data->endTransaction();
}
// NODES
/**
* Gets the nodes in this database
*/
function getNodes() {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
// We use 10 seconds as the default check time since that is the
// the default in Slony, and it gives no mechanism to look it up
$sql = "SELECT no_id, no_active, no_comment, no_spool, ".
"CASE WHEN st_lag_time > '10 seconds'::interval ".
"THEN 'outofsync' ELSE 'insync' END AS no_status ".
"FROM \"{$schema}\".sl_node ".
"LEFT JOIN \"{$schema}\".sl_status ON (no_id =st_received) ".
"ORDER BY no_comment";
return $data->selectSet($sql);
}
/**
* Gets a single node
*/
function getNode($no_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$sql = "SELECT * FROM \"{$schema}\".sl_node WHERE no_id='{$no_id}'";
return $data->selectSet($sql);
}
/**
* Creates a node
*/
function createNode($no_id, $no_comment) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_comment);
$data->clean($no_id);
if ($no_id != '')
$sql = "SELECT \"{$schema}\".storenode('{$no_id}', '{$no_comment}')";
else
$sql = "SELECT \"{$schema}\".storenode((SELECT COALESCE(MAX(no_id), 0) + 1 FROM \"{$schema}\".sl_node), '{$no_comment}')";
return $data->execute($sql);
}
/**
* Drops a node
*/
function dropNode($no_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$sql = "SELECT \"{$schema}\".dropnode('{$no_id}')";
return $data->execute($sql);
}
// REPLICATION SETS
/**
* Gets the replication sets in this database
*/
function getReplicationSets() {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$sql = "SELECT *, set_locked IS NOT NULL AS is_locked FROM \"{$schema}\".sl_set ORDER BY set_id";
return $data->selectSet($sql);
}
/**
* Gets a particular replication set
*/
function getReplicationSet($set_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$sql = "SELECT *, (SELECT COUNT(*) FROM \"{$schema}\".sl_subscribe ssub WHERE ssub.sub_set=ss.set_id) AS subscriptions,
set_locked IS NOT NULL AS is_locked
FROM \"{$schema}\".sl_set ss, \"{$schema}\".sl_node sn
WHERE ss.set_origin=sn.no_id
AND set_id='{$set_id}'";
return $data->selectSet($sql);
}
/**
* Creates a set
*/
function createReplicationSet($set_id, $set_comment) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_comment);
$data->clean($set_id);
if ($set_id != '')
$sql = "SELECT \"{$schema}\".storeset('{$set_id}', '{$set_comment}')";
else
$sql = "SELECT \"{$schema}\".storeset((SELECT COALESCE(MAX(set_id), 0) + 1 FROM \"{$schema}\".sl_set), '{$set_comment}')";
return $data->execute($sql);
}
/**
* Drops a set
*/
function dropReplicationSet($set_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$sql = "SELECT \"{$schema}\".dropset('{$set_id}')";
return $data->execute($sql);
}
/**
* Locks or unlocks a set
* @param boolean $lock True to lock, false to unlock
*/
function lockReplicationSet($set_id, $lock) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
if ($lock)
$sql = "SELECT \"{$schema}\".lockset('{$set_id}')";
else
$sql = "SELECT \"{$schema}\".unlockset('{$set_id}')";
return $data->execute($sql);
}
/**
* Merges two sets
*/
function mergeReplicationSet($set_id, $target) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$data->clean($target);
$sql = "SELECT \"{$schema}\".mergeset('{$target}', '{$set_id}')";
return $data->execute($sql);
}
/**
* Moves a set to a new origin
*/
function moveReplicationSet($set_id, $new_origin) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$data->clean($new_origin);
$sql = "SELECT \"{$schema}\".moveset('{$set_id}', '{$new_origin}')";
return $data->execute($sql);
}
/**
* Executes schema changing DDL set on nodes
*/
function executeReplicationSet($set_id, $script) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$data->clean($script);
$sql = "SELECT \"{$schema}\".ddlscript('{$set_id}', '{$script}')";
return $data->execute($sql);
}
// TABLES
/**
* Return all tables in a replication set
* @param $set_id The ID of the replication set
* @return Tables in the replication set, sorted alphabetically
*/
function getTables($set_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$sql = "SELECT st.tab_id, c.relname, n.nspname, n.nspname||'.'||c.relname AS qualname,
pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
reltuples::bigint";
// Tablespace
if ($data->hasTablespaces()) {
$sql .= ", (SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=c.reltablespace) AS tablespace";
}
$sql .= " FROM pg_catalog.pg_class c, \"{$schema}\".sl_table st, pg_catalog.pg_namespace n
WHERE c.oid=st.tab_reloid
AND c.relnamespace=n.oid
AND st.tab_set='{$set_id}'
ORDER BY n.nspname, c.relname";
return $data->selectSet($sql);
}
/**
* Adds a table to a replication set
*/
function addTable($set_id, $tab_id, $nspname, $relname, $idxname, $comment, $storedtriggers) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$data->clean($tab_id);
$fqname = $nspname . '.' . $relname;
$data->clean($fqname);
$data->clean($nspname);
$data->clean($relname);
$data->clean($idxname);
$data->clean($comment);
$hastriggers = (sizeof($storedtriggers) > 0);
if ($hastriggers) {
// Begin a transaction
$status = $data->beginTransaction();
if ($status != 0) return -1;
}
if ($tab_id != '')
$sql = "SELECT \"{$schema}\".setaddtable('{$set_id}', '{$tab_id}', '{$fqname}', '{$idxname}', '{$comment}')";
else {
$sql = "SELECT \"{$schema}\".setaddtable('{$set_id}', (SELECT COALESCE(MAX(tab_id), 0) + 1 FROM \"{$schema}\".sl_table), '{$fqname}', '{$idxname}', '{$comment}')";
}
$status = $data->execute($sql);
if ($status != 0) {
if ($hastriggers) $data->rollbackTransaction();
return -3;
}
// If we are storing triggers, we need to know the tab_id that was assigned to the table
if ($tab_id == '' && $hastriggers) {
$sql = "SELECT tab_id
FROM \"{$schema}\".sl_table
WHERE tab_set='{$set_id}'
AND tab_reloid=(SELECT pc.oid FROM pg_catalog.pg_class pc, pg_namespace pn
WHERE pc.relnamespace=pn.oid AND pc.relname='{$relname}'
AND pn.nspname='{$nspname}')";
$tab_id = $data->selectField($sql, 'tab_id');
if ($tab_id === -1) {
$data->rollbackTransaction();
return -4;
}
}
// Store requested triggers
if ($hastriggers) {
foreach ($storedtriggers as $tgname) {
$data->clean($tgname);
$sql = "SELECT \"{$schema}\".storetrigger('{$tab_id}', '{$tgname}')";
$status = $data->execute($sql);
if ($status != 0) {
$data->rollbackTransaction();
return -5;
}
}
}
if ($hastriggers)
return $data->endTransaction();
else
return $status;
}
/**
* Drops a table from a replication set
*/
function dropTable($tab_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($tab_id);
$sql = "SELECT \"{$schema}\".setdroptable('{$tab_id}')";
return $data->execute($sql);
}
/**
* Moves a table to another replication set
*/
function moveTable($tab_id, $new_set_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($tab_id);
$data->clean($new_set_id);
$sql = "SELECT \"{$schema}\".setmovetable('{$tab_id}', '{$new_set_id}')";
return $data->execute($sql);
}
/**
* Return all tables we are not current in a replication set
*/
function getNonRepTables()
{
global $data;
/*
* we cannot just query pg_tables as we want the OID of the table
* for the subquery against the slony table. We could match on
* on schema name and table name, but the slony info isn't updated
* if the user renames a table which is in a replication set
*/
$sql = "SELECT c.relname, n.nspname, n.nspname||'.'||c.relname AS qualname,
pg_get_userbyid(c.relowner) AS relowner
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r' AND n.nspname NOT IN ('pg_catalog',
'information_schema', 'pg_toast') AND
NOT(n.nspname = '_{$this->slony_cluster}' AND
relname LIKE 'sl_%') AND
NOT EXISTS(SELECT 1 FROM _{$this->slony_cluster}.sl_table s
WHERE s.tab_reloid = c.oid)
ORDER BY n.nspname, c.relname";
return $data->selectSet($sql);
}
// SEQUENCES
/**
* Return all sequences in a replication set
* @param $set_id The ID of the replication set
* @return Sequences in the replication set, sorted alphabetically
*/
function getSequences($set_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$sql = "SELECT ss.seq_id, c.relname AS seqname, n.nspname, n.nspname||'.'||c.relname AS qualname,
pg_catalog.obj_description(c.oid, 'pg_class') AS seqcomment,
pg_catalog.pg_get_userbyid(c.relowner) AS seqowner
FROM pg_catalog.pg_class c, \"{$schema}\".sl_sequence ss, pg_catalog.pg_namespace n
WHERE c.oid=ss.seq_reloid
AND c.relnamespace=n.oid
AND ss.seq_set='{$set_id}'
ORDER BY n.nspname, c.relname";
return $data->selectSet($sql);
}
/**
* Adds a sequence to a replication set
*/
function addSequence($set_id, $seq_id, $fqname, $comment) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$data->clean($seq_id);
$data->clean($fqname);
$data->clean($comment);
if ($seq_id != '')
$sql = "SELECT \"{$schema}\".setaddsequence('{$set_id}', '{$seq_id}', '{$fqname}', '{$comment}')";
else
$sql = "SELECT \"{$schema}\".setaddsequence('{$set_id}', (SELECT COALESCE(MAX(seq_id), 0) + 1 FROM \"{$schema}\".sl_sequence), '{$fqname}', '{$comment}')";
return $data->execute($sql); }
/**
* Drops a sequence from a replication set
*/
function dropSequence($seq_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($seq_id);
$sql = "SELECT \"{$schema}\".setdropsequence('{$seq_id}')";
return $data->execute($sql);
}
/**
* Moves a sequence to another replication set
*/
function moveSequence($seq_id, $new_set_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($seq_id);
$data->clean($new_set_id);
$sql = "SELECT \"{$schema}\".setmovesequence('{$seq_id}', '{$new_set_id}')";
return $data->execute($sql);
}
// SUBSCRIPTIONS
/**
* Gets all nodes subscribing to a set
* @param $set_id The ID of the replication set
* @return Nodes subscribing to this set
*/
function getSubscribedNodes($set_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$sql = "SELECT sn.*, ss.sub_set
FROM \"{$schema}\".sl_subscribe ss, \"{$schema}\".sl_node sn
WHERE ss.sub_set='{$set_id}'
AND ss.sub_receiver = sn.no_id
ORDER BY sn.no_comment";
return $data->selectSet($sql);
}
/**
* Gets all nodes subscribing to a set
* @param $set_id The ID of the replication set
* @return Nodes subscribing to this set
*/
function getSubscription($set_id, $no_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($set_id);
$data->clean($no_id);
$sql = "SELECT ss.*, sn.no_comment AS receiver, sn2.no_comment AS provider
FROM \"{$schema}\".sl_subscribe ss, \"{$schema}\".sl_node sn, \"{$schema}\".sl_node sn2
WHERE ss.sub_set='{$set_id}'
AND ss.sub_receiver = sn.no_id
AND ss.sub_provider = sn2.no_id
AND sn.no_id='{$no_id}'";
return $data->selectSet($sql);
}
// NODES
/**
* Gets node paths
*/
function getPaths($no_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$sql = "SELECT * FROM \"{$schema}\".sl_path sp, \"{$schema}\".sl_node sn
WHERE sp.pa_server=sn.no_id
AND sp.pa_client='{$no_id}'
ORDER BY sn.no_comment";
return $data->selectSet($sql);
}
/**
* Gets node path details
*/
function getPath($no_id, $path_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$data->clean($path_id);
$sql = "SELECT * FROM \"{$schema}\".sl_path sp, \"{$schema}\".sl_node sn
WHERE sp.pa_server=sn.no_id
AND sp.pa_client='{$no_id}'
AND sn.no_id='{$path_id}'";
return $data->selectSet($sql);
}
/**
* Creates a path
*/
function createPath($no_id, $server, $conn, $retry) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$data->clean($server);
$data->clean($conn);
$data->clean($retry);
$sql = "SELECT \"{$schema}\".storepath('{$server}', '{$no_id}', '{$conn}', '{$retry}')";
return $data->execute($sql);
}
/**
* Drops a path
*/
function dropPath($no_id, $path_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$data->clean($path_id);
$sql = "SELECT \"{$schema}\".droppath('{$path_id}', '{$no_id}')";
return $data->execute($sql);
}
// LISTENS
/**
* Gets node listens
*/
function getListens($no_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$sql = "SELECT * FROM \"{$schema}\".sl_listen sl, \"{$schema}\".sl_node sn
WHERE sl.li_provider=sn.no_id
AND sl.li_receiver='{$no_id}'
ORDER BY sn.no_comment";
return $data->selectSet($sql);
}
/**
* Gets node listen details
*/
function getListen($no_id, $listen_id) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$data->clean($listen_id);
$sql = "SELECT sl.*, sn.*, sn2.no_comment AS origin FROM \"{$schema}\".sl_listen sl, \"{$schema}\".sl_node sn, \"{$schema}\".sl_node sn2
WHERE sl.li_provider=sn.no_id
AND sl.li_receiver='{$no_id}'
AND sn.no_id='{$listen_id}'
AND sn2.no_id=sl.li_origin";
return $data->selectSet($sql);
}
/**
* Creates a listen
*/
function createListen($no_id, $origin, $provider) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$data->clean($origin);
$data->clean($provider);
$sql = "SELECT \"{$schema}\".storelisten('{$origin}', '{$provider}', '{$no_id}')";
return $data->execute($sql);
}
/**
* Drops a listen
*/
function dropListen($no_id, $origin, $provider) {
global $data;
$schema = $this->slony_schema;
$data->fieldClean($schema);
$data->clean($no_id);
$data->clean($origin);
$data->clean($provider);
$sql = "SELECT \"{$schema}\".droplisten('{$origin}', '{$provider}', '{$no_id}')";
return $data->execute($sql);
}
// ACTIONS
}
?>

View File

@ -0,0 +1,292 @@
<?php
/**
* List Columns properties in tables
*
* $Id: colproperties.php
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (isset($_REQUEST['table']))
$tableName =& $_REQUEST['table'];
elseif (isset($_REQUEST['view']))
$tableName =& $_REQUEST['view'];
else
die($lang['strnotableprovided']);
/**
* Displays a screen where they can alter a column
*/
function doAlter($msg = '') {
global $data, $misc, $_reload_browser;
global $lang;
if (!isset($_REQUEST['stage'])) $_REQUEST['stage'] = 1;
switch ($_REQUEST['stage']) {
case 1:
$misc->printTrail('column');
$misc->printTitle($lang['stralter'], 'pg.column.alter');
$misc->printMsg($msg);
echo "<script src=\"tables.js\" type=\"text/javascript\"></script>";
echo "<form action=\"colproperties.php\" method=\"post\">\n";
// Output table header
echo "<table>\n";
echo "<tr><th class=\"data required\">{$lang['strname']}</th>\n";
if ($data->hasAlterColumnType()) {
echo "<th class=\"data required\" colspan=\"2\">{$lang['strtype']}</th>\n";
echo "<th class=\"data\">{$lang['strlength']}</th>\n";
}
else {
echo "<th class=\"data required\">{$lang['strtype']}</th>\n";
}
echo "<th class=\"data\">{$lang['strnotnull']}</th>\n<th class=\"data\">{$lang['strdefault']}</th>\n<th class=\"data\">{$lang['strcomment']}</th></tr>\n";
$column = $data->getTableAttributes($_REQUEST['table'], $_REQUEST['column']);
$column->fields['attnotnull'] = $data->phpBool($column->fields['attnotnull']);
// Upon first drawing the screen, load the existing column information
// from the database.
if (!isset($_REQUEST['default'])) {
$_REQUEST['field'] = $column->fields['attname'];
$_REQUEST['type'] = $column->fields['base_type'];
// Check to see if its' an array type...
// XXX: HACKY
if (substr($column->fields['base_type'], strlen($column->fields['base_type']) - 2) == '[]') {
$_REQUEST['type'] = substr($column->fields['base_type'], 0, strlen($column->fields['base_type']) - 2);
$_REQUEST['array'] = '[]';
}
else {
$_REQUEST['type'] = $column->fields['base_type'];
$_REQUEST['array'] = '';
}
// To figure out the length, look in the brackets :(
// XXX: HACKY
if ($column->fields['type'] != $column->fields['base_type'] && preg_match('/\\(([0-9, ]*)\\)/', $column->fields['type'], $bits)) {
$_REQUEST['length'] = $bits[1];
}
else
$_REQUEST['length'] = '';
$_REQUEST['default'] = $_REQUEST['olddefault'] = $column->fields['adsrc'];
if ($column->fields['attnotnull']) $_REQUEST['notnull'] = 'YES';
$_REQUEST['comment'] = $column->fields['comment'];
}
// Column name
echo "<tr><td><input name=\"field\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_REQUEST['field']), "\" /></td>\n";
// Column type
$escaped_predef_types = array(); // the JS escaped array elements
if ($data->hasAlterColumnType()) {
// Fetch all available types
$types = $data->getTypes(true, false, true);
$types_for_js = array();
echo "<td><select name=\"type\" id=\"type\" onchange=\"checkLengths(document.getElementById('type').value,'');\">\n";
while (!$types->EOF) {
$typname = $types->fields['typname'];
$types_for_js[] = $typname;
echo "\t<option value=\"", htmlspecialchars($typname), "\"", ($typname == $_REQUEST['type']) ? ' selected="selected"' : '', ">",
$misc->printVal($typname), "</option>\n";
$types->moveNext();
}
echo "</select></td>\n";
// Output array type selector
echo "<td><select name=\"array\">\n";
echo "\t<option value=\"\"", ($_REQUEST['array'] == '') ? ' selected="selected"' : '', "></option>\n";
echo "\t<option value=\"[]\"", ($_REQUEST['array'] == '[]') ? ' selected="selected"' : '', ">[ ]</option>\n";
echo "</select></td>\n";
$predefined_size_types = array_intersect($data->predefined_size_types, $types_for_js);
foreach($predefined_size_types as $value) {
$escaped_predef_types[] = "'{$value}'";
}
echo "<td><input name=\"length\" id=\"lengths\" size=\"8\" value=\"",
htmlspecialchars($_REQUEST['length']), "\" /></td>\n";
} else {
// Otherwise draw the read-only type name
echo "<td>", $misc->printVal($data->formatType($column->fields['type'], $column->fields['atttypmod'])), "</td>\n";
}
echo "<td><input type=\"checkbox\" name=\"notnull\"", (isset($_REQUEST['notnull'])) ? ' checked="checked"' : '', " /></td>\n";
echo "<td><input name=\"default\" size=\"20\" value=\"",
htmlspecialchars($_REQUEST['default']), "\" /></td>\n";
echo "<td><input name=\"comment\" size=\"40\" value=\"",
htmlspecialchars($_REQUEST['comment']), "\" /></td></tr>\n";
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"properties\" />\n";
echo "<input type=\"hidden\" name=\"stage\" value=\"2\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo "<input type=\"hidden\" name=\"column\" value=\"", htmlspecialchars($_REQUEST['column']), "\" />\n";
echo "<input type=\"hidden\" name=\"olddefault\" value=\"", htmlspecialchars($_REQUEST['olddefault']), "\" />\n";
if ($column->fields['attnotnull']) echo "<input type=\"hidden\" name=\"oldnotnull\" value=\"on\" />\n";
echo "<input type=\"hidden\" name=\"oldtype\" value=\"", htmlspecialchars($data->formatType($column->fields['type'], $column->fields['atttypmod'])), "\" />\n";
// Add hidden variables to suppress error notices if we don't support altering column type
if (!$data->hasAlterColumnType()) {
echo "<input type=\"hidden\" name=\"type\" value=\"", htmlspecialchars($_REQUEST['type']), "\" />\n";
echo "<input type=\"hidden\" name=\"length\" value=\"", htmlspecialchars($_REQUEST['length']), "\" />\n";
echo "<input type=\"hidden\" name=\"array\" value=\"", htmlspecialchars($_REQUEST['array']), "\" />\n";
}
echo "<input type=\"submit\" value=\"{$lang['stralter']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
echo "<script type=\"text/javascript\">predefined_lengths = new Array(". implode(",",$escaped_predef_types) .");checkLengths(document.getElementById('type').value,'');</script>\n";
break;
case 2:
// Check inputs
if (trim($_REQUEST['field']) == '') {
$_REQUEST['stage'] = 1;
doAlter($lang['strcolneedsname']);
return;
}
if (!isset($_REQUEST['length'])) $_REQUEST['length'] = '';
$status = $data->alterColumn($_REQUEST['table'], $_REQUEST['column'], $_REQUEST['field'],
isset($_REQUEST['notnull']), isset($_REQUEST['oldnotnull']),
$_REQUEST['default'], $_REQUEST['olddefault'],
$_REQUEST['type'], $_REQUEST['length'], $_REQUEST['array'], $_REQUEST['oldtype'],
$_REQUEST['comment']);
if ($status == 0) {
if ($_REQUEST['column'] != $_REQUEST['field']) {
$_REQUEST['column'] = $_REQUEST['field'];
$_reload_browser = true;
}
doDefault($lang['strcolumnaltered']);
}
else {
$_REQUEST['stage'] = 1;
doAlter($lang['strcolumnalteredbad']);
return;
}
break;
default:
echo "<p>{$lang['strinvalidparam']}</p>\n";
}
}
/**
* Show default list of columns in the table
*/
function doDefault($msg = '', $isTable = true) {
global $data, $conf, $misc, $tableName;
global $lang;
function attPre(&$rowdata) {
global $data;
$rowdata->fields['+type'] = $data->formatType($rowdata->fields['type'], $rowdata->fields['atttypmod']);
}
if (empty($_REQUEST['column']))
$msg.= "<br/>{$lang['strnoobjects']}";
$misc->printTrail('column');
//$misc->printTitle($lang['strcolprop']);
$misc->printTabs('column','properties');
$misc->printMsg($msg);
if (! empty($_REQUEST['column'])) {
// Get table
$tdata = $data->getTable($tableName);
// Get columns
$attrs = $data->getTableAttributes($tableName, $_REQUEST['column']);
// Show comment if any
if ($attrs->fields['comment'] !== null)
echo "<p class=\"comment\">", $misc->printVal($attrs->fields['comment']), "</p>\n";
$column = array(
'column' => array(
'title' => $lang['strcolumn'],
'field' => field('attname'),
),
'type' => array(
'title' => $lang['strtype'],
'field' => field('+type'),
)
);
if ($isTable) {
$column['notnull'] = array(
'title' => $lang['strnotnull'],
'field' => field('attnotnull'),
'type' => 'bool',
'params'=> array('true' => 'NOT NULL', 'false' => '')
);
$column['default'] = array(
'title' => $lang['strdefault'],
'field' => field('adsrc'),
);
}
$actions=array();
$misc->printTable($attrs, $column, $actions, null, 'attPre');
echo "<br />\n";
echo "<ul class=\"navlink\">\n";
$f_attname = $_REQUEST['column'];
$f_table = $tableName;
$f_schema = $data->_schema;
$data->fieldClean($f_attname);
$data->fieldClean($f_table);
$data->fieldClean($f_schema);
$query_url = urlencode("SELECT \"{$f_attname}\", count(*) AS \"count\" FROM \"{$f_schema}\".\"{$f_table}\" GROUP BY \"{$f_attname}\" ORDER BY \"{$f_attname}\"") ;
if ($isTable) {
$return_url = urlencode("colproperties.php?{$misc->href}&amp;table=". urlencode($tableName)
."&amp;column=". urlencode($_REQUEST['column']));
/* Browse link */
/* FIXME browsing a col should somehow be a action so we don't
* send an ugly SQL in the URL */
echo "\t<li><a href=\"display.php?{$misc->href}&amp;subject=column&amp;table=",
urlencode($_REQUEST['table']),
"&amp;column=", urlencode($_REQUEST['column']),
"&amp;return_url={$return_url}&amp;return_desc=", urlencode($lang['strback']),
"&amp;query={$query_url}\">{$lang['strbrowse']}</a></li>\n";
/* Edit link */
echo "\t<li><a href=\"colproperties.php?action=properties&amp;{$misc->href}&amp;table=", urlencode($tableName),
"&amp;column=", urlencode($_REQUEST['column']) . "\">{$lang['stralter']}</a></li>\n";
echo "\t<li><a href=\"tblproperties.php?action=confirm_drop&amp;{$misc->href}&amp;table=", urlencode($tableName),
"&amp;column=" . urlencode($_REQUEST['column']) . "\">{$lang['strdrop']}</a></li>\n";
} else {
$return_url = urlencode("colproperties.php?{$misc->href}&amp;view=". urlencode($tableName)
."&amp;column=". urlencode($_REQUEST['column']));
/* Browse link */
echo "\t<li><a href=\"display.php?{$misc->href}&amp;subject=column&amp;column=",
urlencode($_REQUEST['column']), "&amp;return_url={$return_url}&amp;return_desc=", urlencode($lang['strback']),
"&amp;query={$query_url}\">{$lang['strbrowse']}</a></li>\n";
}
echo "</ul>\n";
}
}
$misc->printHeader($lang['strtables'] . ' - ' . $tableName);
$misc->printBody();
if (isset($_REQUEST['view']))
doDefault(null, false);
else
switch ($action) {
case 'properties':
if (isset($_POST['cancel'])) doDefault();
else doAlter();
break;
default:
doDefault();
break;
}
$misc->printFooter();
?>

View File

@ -0,0 +1,165 @@
<?php
/**
* Central phpPgAdmin configuration. As a user you may modify the
* settings here for your particular configuration.
*
* $Id: config.inc.php-dist,v 1.55 2008/02/18 21:10:31 xzilla Exp $
*/
// An example server. Create as many of these as you wish,
// indexed from zero upwards.
// Display name for the server on the login screen
$conf['servers'][0]['desc'] = 'beethoven';
// Hostname or IP address for server. Use '' for UNIX domain socket.
// use 'localhost' for TCP/IP connection on this computer
$conf['servers'][0]['host'] = 'localhost';
// Database port on server (5432 is the PostgreSQL default)
$conf['servers'][0]['port'] = 5432;
// Database SSL mode
// Possible options: disable, allow, prefer, require
// To require SSL on older servers use option: legacy
// To ignore the SSL mode, use option: unspecified
$conf['servers'][0]['sslmode'] = 'allow';
// Change the default database only if you cannot connect to template1.
// For a PostgreSQL 8.1+ server, you can set this to 'postgres'.
$conf['servers'][0]['defaultdb'] = 'template1';
// Specify the path to the database dump utilities for this server.
// You can set these to '' if no dumper is available.
$conf['servers'][0]['pg_dump_path'] = '/usr/bin/pg_dump';
$conf['servers'][0]['pg_dumpall_path'] = '/usr/bin/pg_dumpall';
// Slony (www.slony.info) support?
$conf['servers'][0]['slony_support'] = false;
// Specify the path to the Slony SQL scripts (where slony1_base.sql is located, etc.)
// No trailing slash.
$conf['servers'][0]['slony_sql'] = '/usr/share/pgsql';
// Example for a second server (PostgreSQL for Windows)
//$conf['servers'][1]['desc'] = 'Test Server';
//$conf['servers'][1]['host'] = '127.0.0.1';
//$conf['servers'][1]['port'] = 5432;
//$conf['servers'][1]['sslmode'] = 'allow';
//$conf['servers'][1]['defaultdb'] = 'template1';
//$conf['servers'][1]['pg_dump_path'] = 'C:\\Program Files\\PostgreSQL\\8.0\\bin\\pg_dump.exe';
//$conf['servers'][1]['pg_dumpall_path'] = 'C:\\Program Files\\PostgreSQL\\8.0\\bin\\pg_dumpall.exe';
//$conf['servers'][1]['slony_support'] = false;
//$conf['servers'][1]['slony_sql'] = 'C:\\Program Files\\PostgreSQL\\8.0\\share';
//$conf['servers'][1]['desc'] = 'localhost';
//$conf['servers'][1]['host'] = '127.0.0.1';
//$conf['servers'][1]['port'] = 5432;
//$conf['servers'][1]['sslmode'] = 'allow';
//$conf['servers'][1]['defaultdb'] = 'beatheaven_db';
// Example of groups definition.
// Groups allow administrators to logicaly group servers together under group nodes in the left browser tree
//
// The group '0' description
//$conf['srv_groups'][0]['desc'] = 'group one';
//
// Add here servers indexes belonging to the group '0' seperated by comma
//$conf['srv_groups'][0]['servers'] = '0,1,2';
//
// A server can belong to multi groups
//$conf['srv_groups'][1]['desc'] = 'group two';
//$conf['srv_groups'][1]['servers'] = '3,1';
// Default language. E.g.: 'english', 'polish', etc. See lang/ directory
// for all possibilities. If you specify 'auto' (the default) it will use
// your browser preference.
$conf['default_lang'] = 'auto';
// AutoComplete uses AJAX interaction to list foreign key values
// on insert fields. It currently only works on single column
// foreign keys. You can choose one of the following values:
// 'default on' enables AutoComplete and turns it on by default.
// 'default off' enables AutoComplete but turns it off by default.
// 'disable' disables AutoComplete.
$conf['autocomplete'] = 'default on';
// If extra login security is true, then logins via phpPgAdmin with no
// password or certain usernames (pgsql, postgres, root, administrator)
// will be denied. Only set this false once you have read the FAQ and
// understand how to change PostgreSQL's pg_hba.conf to enable
// passworded local connections.
$conf['extra_login_security'] = false;
// Only show owned databases?
// Note: This will simply hide other databases in the list - this does
// not in any way prevent your users from seeing other database by
// other means. (e.g. Run 'SELECT * FROM pg_database' in the SQL area.)
$conf['owned_only'] = false;
// Display comments on objects? Comments are a good way of documenting
// a database, but they do take up space in the interface.
$conf['show_comments'] = true;
// Display "advanced" objects? Setting this to true will show
// aggregates, types, operators, operator classes, conversions,
// languages and casts in phpPgAdmin. These objects are rarely
// administered and can clutter the interface.
$conf['show_advanced'] = false;
// Display "system" objects?
$conf['show_system'] = false;
// Display reports feature? For this feature to work, you must
// install the reports database as explained in the INSTALL file.
$conf['show_reports'] = true;
// Database and table for reports
$conf['reports_db'] = 'phppgadmin';
$conf['reports_schema'] = 'public';
$conf['reports_table'] = 'ppa_reports';
// Only show owned reports?
// Note: This does not prevent people from accessing other reports by
// other means.
$conf['owned_reports_only'] = false;
// Minimum length users can set their password to.
$conf['min_password_length'] = 1;
// Width of the left frame in pixels (object browser)
$conf['left_width'] = 200;
// Which look & feel theme to use
$conf['theme'] = 'default';
// Show OIDs when browsing tables?
$conf['show_oids'] = false;
// Max rows to show on a page when browsing record sets
$conf['max_rows'] = 30;
// Max chars of each field to display by default in browse mode
$conf['max_chars'] = 50;
// Send XHTML strict headers?
$conf['use_xhtml_strict'] = false;
// Base URL for PostgreSQL documentation.
// '%s', if present, will be replaced with the PostgreSQL version
// (e.g. 8.4 )
$conf['help_base'] = 'http://www.postgresql.org/docs/%s/interactive/';
// Configuration for ajax scripts
// Time in seconds. If set to 0, refreshing data using ajax will be disabled (locks and activity pages)
$conf['ajax_refresh'] = 3;
/*****************************************
* Don't modify anything below this line *
*****************************************/
$conf['version'] = 19;
?>

View File

@ -0,0 +1,159 @@
<?php
/**
* Central phpPgAdmin configuration. As a user you may modify the
* settings here for your particular configuration.
*
* $Id: config.inc.php-dist,v 1.55 2008/02/18 21:10:31 xzilla Exp $
*/
// An example server. Create as many of these as you wish,
// indexed from zero upwards.
// Display name for the server on the login screen
$conf['servers'][0]['desc'] = 'PostgreSQL';
// Hostname or IP address for server. Use '' for UNIX domain socket.
// use 'localhost' for TCP/IP connection on this computer
$conf['servers'][0]['host'] = '';
// Database port on server (5432 is the PostgreSQL default)
$conf['servers'][0]['port'] = 5432;
// Database SSL mode
// Possible options: disable, allow, prefer, require
// To require SSL on older servers use option: legacy
// To ignore the SSL mode, use option: unspecified
$conf['servers'][0]['sslmode'] = 'allow';
// Change the default database only if you cannot connect to template1.
// For a PostgreSQL 8.1+ server, you can set this to 'postgres'.
$conf['servers'][0]['defaultdb'] = 'template1';
// Specify the path to the database dump utilities for this server.
// You can set these to '' if no dumper is available.
$conf['servers'][0]['pg_dump_path'] = '/usr/bin/pg_dump';
$conf['servers'][0]['pg_dumpall_path'] = '/usr/bin/pg_dumpall';
// Slony (www.slony.info) support?
$conf['servers'][0]['slony_support'] = false;
// Specify the path to the Slony SQL scripts (where slony1_base.sql is located, etc.)
// No trailing slash.
$conf['servers'][0]['slony_sql'] = '/usr/share/pgsql';
// Example for a second server (PostgreSQL for Windows)
//$conf['servers'][1]['desc'] = 'Test Server';
//$conf['servers'][1]['host'] = '127.0.0.1';
//$conf['servers'][1]['port'] = 5432;
//$conf['servers'][1]['sslmode'] = 'allow';
//$conf['servers'][1]['defaultdb'] = 'template1';
//$conf['servers'][1]['pg_dump_path'] = 'C:\\Program Files\\PostgreSQL\\8.0\\bin\\pg_dump.exe';
//$conf['servers'][1]['pg_dumpall_path'] = 'C:\\Program Files\\PostgreSQL\\8.0\\bin\\pg_dumpall.exe';
//$conf['servers'][1]['slony_support'] = false;
//$conf['servers'][1]['slony_sql'] = 'C:\\Program Files\\PostgreSQL\\8.0\\share';
// Example of groups definition.
// Groups allow administrators to logicaly group servers together under group nodes in the left browser tree
//
// The group '0' description
//$conf['srv_groups'][0]['desc'] = 'group one';
//
// Add here servers indexes belonging to the group '0' seperated by comma
//$conf['srv_groups'][0]['servers'] = '0,1,2';
//
// A server can belong to multi groups
//$conf['srv_groups'][1]['desc'] = 'group two';
//$conf['srv_groups'][1]['servers'] = '3,1';
// Default language. E.g.: 'english', 'polish', etc. See lang/ directory
// for all possibilities. If you specify 'auto' (the default) it will use
// your browser preference.
$conf['default_lang'] = 'auto';
// AutoComplete uses AJAX interaction to list foreign key values
// on insert fields. It currently only works on single column
// foreign keys. You can choose one of the following values:
// 'default on' enables AutoComplete and turns it on by default.
// 'default off' enables AutoComplete but turns it off by default.
// 'disable' disables AutoComplete.
$conf['autocomplete'] = 'default on';
// If extra login security is true, then logins via phpPgAdmin with no
// password or certain usernames (pgsql, postgres, root, administrator)
// will be denied. Only set this false once you have read the FAQ and
// understand how to change PostgreSQL's pg_hba.conf to enable
// passworded local connections.
$conf['extra_login_security'] = true;
// Only show owned databases?
// Note: This will simply hide other databases in the list - this does
// not in any way prevent your users from seeing other database by
// other means. (e.g. Run 'SELECT * FROM pg_database' in the SQL area.)
$conf['owned_only'] = false;
// Display comments on objects? Comments are a good way of documenting
// a database, but they do take up space in the interface.
$conf['show_comments'] = true;
// Display "advanced" objects? Setting this to true will show
// aggregates, types, operators, operator classes, conversions,
// languages and casts in phpPgAdmin. These objects are rarely
// administered and can clutter the interface.
$conf['show_advanced'] = false;
// Display "system" objects?
$conf['show_system'] = false;
// Display reports feature? For this feature to work, you must
// install the reports database as explained in the INSTALL file.
$conf['show_reports'] = true;
// Database and table for reports
$conf['reports_db'] = 'phppgadmin';
$conf['reports_schema'] = 'public';
$conf['reports_table'] = 'ppa_reports';
// Only show owned reports?
// Note: This does not prevent people from accessing other reports by
// other means.
$conf['owned_reports_only'] = false;
// Minimum length users can set their password to.
$conf['min_password_length'] = 1;
// Width of the left frame in pixels (object browser)
$conf['left_width'] = 200;
// Which look & feel theme to use
$conf['theme'] = 'default';
// Show OIDs when browsing tables?
$conf['show_oids'] = false;
// Max rows to show on a page when browsing record sets
$conf['max_rows'] = 30;
// Max chars of each field to display by default in browse mode
$conf['max_chars'] = 50;
// Send XHTML strict headers?
$conf['use_xhtml_strict'] = false;
// Base URL for PostgreSQL documentation.
// '%s', if present, will be replaced with the PostgreSQL version
// (e.g. 8.4 )
$conf['help_base'] = 'http://www.postgresql.org/docs/%s/interactive/';
// Configuration for ajax scripts
// Time in seconds. If set to 0, refreshing data using ajax will be disabled (locks and activity pages)
$conf['ajax_refresh'] = 3;
/*****************************************
* Don't modify anything below this line *
*****************************************/
$conf['version'] = 19;
?>

576
php/pgadmin/constraints.php Normal file
View File

@ -0,0 +1,576 @@
<?php
/**
* List constraints on a table
*
* $Id: constraints.php,v 1.56 2007/12/31 16:46:07 xzilla Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
include_once('./classes/class.select.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
/**
* Confirm and then actually add a FOREIGN KEY constraint
*/
function addForeignKey($stage, $msg = '') {
global $data, $misc;
global $lang;
if (!isset($_POST['name'])) $_POST['name'] = '';
if (!isset($_POST['target'])) $_POST['target'] = '';
switch ($stage) {
case 2:
// Check that they've given at least one source column
if (!isset($_REQUEST['SourceColumnList']) && (!isset($_POST['IndexColumnList']) || !is_array($_POST['IndexColumnList']) || sizeof($_POST['IndexColumnList']) == 0))
addForeignKey(1, $lang['strfkneedscols']);
else {
// Copy the IndexColumnList variable from stage 1
if (isset($_REQUEST['IndexColumnList']) && !isset($_REQUEST['SourceColumnList']))
$_REQUEST['SourceColumnList'] = serialize($_REQUEST['IndexColumnList']);
// Initialise variables
if (!isset($_POST['upd_action'])) $_POST['upd_action'] = null;
if (!isset($_POST['del_action'])) $_POST['del_action'] = null;
if (!isset($_POST['match'])) $_POST['match'] = null;
if (!isset($_POST['deferrable'])) $_POST['deferrable'] = null;
if (!isset($_POST['initially'])) $_POST['initially'] = null;
$_REQUEST['target'] = unserialize($_REQUEST['target']);
$misc->printTrail('table');
$misc->printTitle($lang['straddfk'],'pg.constraint.foreign_key');
$misc->printMsg($msg);
// Unserialize target and fetch appropriate table. This is a bit messy
// because the table could be in another schema.
$data->setSchema($_REQUEST['target']['schemaname']);
$attrs = $data->getTableAttributes($_REQUEST['target']['tablename']);
$data->setSchema($_REQUEST['schema']);
$selColumns = new XHTML_select('TableColumnList', true, 10);
$selColumns->set_style('width: 15em;');
if ($attrs->recordCount() > 0) {
while (!$attrs->EOF) {
$selColumns->add(new XHTML_Option($attrs->fields['attname']));
$attrs->moveNext();
}
}
$selIndex = new XHTML_select('IndexColumnList[]', true, 10);
$selIndex->set_style('width: 15em;');
$selIndex->set_attribute('id', 'IndexColumnList');
$buttonAdd = new XHTML_Button('add', '>>');
$buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
$buttonAdd->set_attribute('type', 'button');
$buttonRemove = new XHTML_Button('remove', '<<');
$buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
$buttonRemove->set_attribute('type', 'button');
echo "<form onsubmit=\"doSelectAll();\" name=\"formIndex\" action=\"constraints.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data\" colspan=\"3\">{$lang['strfktarget']}</th></tr>";
echo "<tr><th class=\"data\">{$lang['strtablecolumnlist']}</th><th class=\"data\">&nbsp;</th><th class=data>{$lang['strfkcolumnlist']}</th></tr>\n";
echo "<tr><td class=\"data1\">" . $selColumns->fetch() . "</td>\n";
echo "<td class=\"data1\" style=\"text-align: center\">" . $buttonRemove->fetch() . $buttonAdd->fetch() . "</td>";
echo "<td class=\"data1\">" . $selIndex->fetch() . "</td></tr>\n";
echo "<tr><th class=\"data\" colspan=\"3\">{$lang['stractions']}</th></tr>";
echo "<tr>";
echo "<td class=\"data1\" colspan=\"3\">\n";
// ON SELECT actions
echo "{$lang['stronupdate']} <select name=\"upd_action\">";
foreach ($data->fkactions as $v)
echo "<option value=\"{$v}\"", ($_POST['upd_action'] == $v) ? ' selected="selected"' : '', ">{$v}</option>\n";
echo "</select><br />\n";
// ON DELETE actions
echo "{$lang['strondelete']} <select name=\"del_action\">";
foreach ($data->fkactions as $v)
echo "<option value=\"{$v}\"", ($_POST['del_action'] == $v) ? ' selected="selected"' : '', ">{$v}</option>\n";
echo "</select><br />\n";
// MATCH options
echo "<select name=\"match\">";
foreach ($data->fkmatches as $v)
echo "<option value=\"{$v}\"", ($_POST['match'] == $v) ? ' selected="selected"' : '', ">{$v}</option>\n";
echo "</select><br />\n";
// DEFERRABLE options
echo "<select name=\"deferrable\">";
foreach ($data->fkdeferrable as $v)
echo "<option value=\"{$v}\"", ($_POST['deferrable'] == $v) ? ' selected="selected"' : '', ">{$v}</option>\n";
echo "</select><br />\n";
// INITIALLY options
echo "<select name=\"initially\">";
foreach ($data->fkinitial as $v)
echo "<option value=\"{$v}\"", ($_POST['initially'] == $v) ? ' selected="selected"' : '', ">{$v}</option>\n";
echo "</select>\n";
echo "</td></tr>\n";
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_add_foreign_key\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo "<input type=\"hidden\" name=\"name\" value=\"", htmlspecialchars($_REQUEST['name']), "\" />\n";
echo "<input type=\"hidden\" name=\"target\" value=\"", htmlspecialchars(serialize($_REQUEST['target'])), "\" />\n";
echo "<input type=\"hidden\" name=\"SourceColumnList\" value=\"", htmlspecialchars($_REQUEST['SourceColumnList']), "\" />\n";
echo "<input type=\"hidden\" name=\"stage\" value=\"3\" />\n";
echo "<input type=\"submit\" value=\"{$lang['stradd']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
break;
case 3:
// Unserialize target
$_POST['target'] = unserialize($_POST['target']);
// Check that they've given at least one column
if (isset($_POST['SourceColumnList'])) $temp = unserialize($_POST['SourceColumnList']);
if (!isset($_POST['IndexColumnList']) || !is_array($_POST['IndexColumnList'])
|| sizeof($_POST['IndexColumnList']) == 0 || !isset($temp)
|| !is_array($temp) || sizeof($temp) == 0) addForeignKey(2, $lang['strfkneedscols']);
else {
$status = $data->addForeignKey($_POST['table'], $_POST['target']['schemaname'], $_POST['target']['tablename'],
unserialize($_POST['SourceColumnList']), $_POST['IndexColumnList'], $_POST['upd_action'], $_POST['del_action'],
$_POST['match'], $_POST['deferrable'], $_POST['initially'], $_POST['name']);
if ($status == 0)
doDefault($lang['strfkadded']);
else
addForeignKey(2, $lang['strfkaddedbad']);
}
break;
default:
$misc->printTrail('table');
$misc->printTitle($lang['straddfk'],'pg.constraint.foreign_key');
$misc->printMsg($msg);
$attrs = $data->getTableAttributes($_REQUEST['table']);
$tables = $data->getTables(true);
$selColumns = new XHTML_select('TableColumnList', true, 10);
$selColumns->set_style('width: 15em;');
if ($attrs->recordCount() > 0) {
while (!$attrs->EOF) {
$selColumns->add(new XHTML_Option($attrs->fields['attname']));
$attrs->moveNext();
}
}
$selIndex = new XHTML_select('IndexColumnList[]', true, 10);
$selIndex->set_style('width: 15em;');
$selIndex->set_attribute('id', 'IndexColumnList');
$buttonAdd = new XHTML_Button('add', '>>');
$buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
$buttonAdd->set_attribute('type', 'button');
$buttonRemove = new XHTML_Button('remove', '<<');
$buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
$buttonRemove->set_attribute('type', 'button');
echo "<form onsubmit=\"doSelectAll();\" name=\"formIndex\" action=\"constraints.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data\" colspan=\"3\">{$lang['strname']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"3\"><input type=\"text\" name=\"name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" /></td></tr>\n";
echo "<tr><th class=\"data\">{$lang['strtablecolumnlist']}</th><th class=\"data\">&nbsp;</th><th class=\"data required\">{$lang['strfkcolumnlist']}</th></tr>\n";
echo "<tr><td class=\"data1\">" . $selColumns->fetch() . "</td>\n";
echo "<td class=\"data1\" style=\"text-align: center\">" . $buttonRemove->fetch() . $buttonAdd->fetch() . "</td>\n";
echo "<td class=data1>" . $selIndex->fetch() . "</td></tr>\n";
echo "<tr><th class=\"data\" colspan=\"3\">{$lang['strfktarget']}</th></tr>";
echo "<tr>";
echo "<td class=\"data1\" colspan=\"3\"><select name=\"target\">";
while (!$tables->EOF) {
$key = array('schemaname' => $tables->fields['nspname'], 'tablename' => $tables->fields['relname']);
$key = serialize($key);
echo "<option value=\"", htmlspecialchars($key), "\">";
if ($tables->fields['nspname'] != $_REQUEST['schema']) {
echo htmlspecialchars($tables->fields['nspname']), '.';
}
echo htmlspecialchars($tables->fields['relname']), "</option>\n";
$tables->moveNext();
}
echo "</select>\n";
echo "</td></tr>";
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_add_foreign_key\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo "<input type=\"hidden\" name=\"stage\" value=\"2\" />\n";
echo "<input type=\"submit\" value=\"{$lang['stradd']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
break;
}
}
/**
* Confirm and then actually add a PRIMARY KEY or UNIQUE constraint
*/
function addPrimaryOrUniqueKey($type, $confirm, $msg = '') {
global $data, $misc;
global $lang;
if (!isset($_POST['name'])) $_POST['name'] = '';
if ($confirm) {
if (!isset($_POST['name'])) $_POST['name'] = '';
if (!isset($_POST['tablespace'])) $_POST['tablespace'] = '';
$misc->printTrail('table');
switch ($type) {
case 'primary':
$misc->printTitle($lang['straddpk'],'pg.constraint.primary_key');
break;
case 'unique':
$misc->printTitle($lang['stradduniq'],'pg.constraint.unique_key');
break;
default:
doDefault($lang['strinvalidparam']);
return;
}
$misc->printMsg($msg);
$attrs = $data->getTableAttributes($_REQUEST['table']);
// Fetch all tablespaces from the database
if ($data->hasTablespaces()) $tablespaces = $data->getTablespaces();
$selColumns = new XHTML_select('TableColumnList', true, 10);
$selColumns->set_style('width: 15em;');
if ($attrs->recordCount() > 0) {
while (!$attrs->EOF) {
$selColumns->add(new XHTML_Option($attrs->fields['attname']));
$attrs->moveNext();
}
}
$selIndex = new XHTML_select('IndexColumnList[]', true, 10);
$selIndex->set_style('width: 15em;');
$selIndex->set_attribute('id', 'IndexColumnList');
$buttonAdd = new XHTML_Button('add', '>>');
$buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
$buttonAdd->set_attribute('type', 'button');
$buttonRemove = new XHTML_Button('remove', '<<');
$buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
$buttonRemove->set_attribute('type', 'button');
echo "<form onsubmit=\"doSelectAll();\" name=\"formIndex\" action=\"constraints.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data\" colspan=\"3\">{$lang['strname']}</th></tr>";
echo "<tr>";
echo "<td class=\"data1\" colspan=\"3\"><input type=\"text\" name=\"name\" value=\"", htmlspecialchars($_POST['name']),
"\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" /></td></tr>";
echo "<tr><th class=\"data\">{$lang['strtablecolumnlist']}</th><th class=\"data\">&nbsp;</th><th class=\"data required\">{$lang['strindexcolumnlist']}</th></tr>\n";
echo "<tr><td class=\"data1\">" . $selColumns->fetch() . "</td>\n";
echo "<td class=\"data1\" style=\"text-align: center\">" . $buttonRemove->fetch() . $buttonAdd->fetch() . "</td>";
echo "<td class=data1>" . $selIndex->fetch() . "</td></tr>\n";
// Tablespace (if there are any)
if ($data->hasTablespaces() && $tablespaces->recordCount() > 0) {
echo "<tr><th class=\"data\" colspan=\"3\">{$lang['strtablespace']}</th></tr>";
echo "<tr><td class=\"data1\" colspan=\"3\"><select name=\"tablespace\">\n";
// Always offer the default (empty) option
echo "\t\t\t\t<option value=\"\"",
($_POST['tablespace'] == '') ? ' selected="selected"' : '', "></option>\n";
// Display all other tablespaces
while (!$tablespaces->EOF) {
$spcname = htmlspecialchars($tablespaces->fields['spcname']);
echo "\t\t\t\t<option value=\"{$spcname}\"",
($spcname == $_POST['tablespace']) ? ' selected="selected"' : '', ">{$spcname}</option>\n";
$tablespaces->moveNext();
}
echo "</select></td></tr>\n";
}
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_add_primary_key\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo "<input type=\"hidden\" name=\"type\" value=\"", htmlspecialchars($type), "\" />\n";
echo "<input type=\"submit\" value=\"{$lang['stradd']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
else {
// Default tablespace to empty if it isn't set
if (!isset($_POST['tablespace'])) $_POST['tablespace'] = '';
if ($_POST['type'] == 'primary') {
// Check that they've given at least one column
if (!isset($_POST['IndexColumnList']) || !is_array($_POST['IndexColumnList'])
|| sizeof($_POST['IndexColumnList']) == 0) addPrimaryOrUniqueKey($_POST['type'], true, $lang['strpkneedscols']);
else {
$status = $data->addPrimaryKey($_POST['table'], $_POST['IndexColumnList'], $_POST['name'], $_POST['tablespace']);
if ($status == 0)
doDefault($lang['strpkadded']);
else
addPrimaryOrUniqueKey($_POST['type'], true, $lang['strpkaddedbad']);
}
}
elseif ($_POST['type'] == 'unique') {
// Check that they've given at least one column
if (!isset($_POST['IndexColumnList']) || !is_array($_POST['IndexColumnList'])
|| sizeof($_POST['IndexColumnList']) == 0) addPrimaryOrUniqueKey($_POST['type'], true, $lang['struniqneedscols']);
else {
$status = $data->addUniqueKey($_POST['table'], $_POST['IndexColumnList'], $_POST['name'], $_POST['tablespace']);
if ($status == 0)
doDefault($lang['struniqadded']);
else
addPrimaryOrUniqueKey($_POST['type'], true, $lang['struniqaddedbad']);
}
}
else doDefault($lang['strinvalidparam']);
}
}
/**
* Confirm and then actually add a CHECK constraint
*/
function addCheck($confirm, $msg = '') {
global $data, $misc;
global $lang;
if (!isset($_POST['name'])) $_POST['name'] = '';
if (!isset($_POST['definition'])) $_POST['definition'] = '';
if ($confirm) {
$misc->printTrail('table');
$misc->printTitle($lang['straddcheck'],'pg.constraint.check');
$misc->printMsg($msg);
echo "<form action=\"constraints.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data\">{$lang['strname']}</th>\n";
echo "<th class=\"data required\">{$lang['strdefinition']}</th></tr>\n";
echo "<tr><td class=\"data1\"><input name=\"name\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_POST['name']), "\" /></td>\n";
echo "<td class=\"data1\">(<input name=\"definition\" size=\"32\" value=\"",
htmlspecialchars($_POST['definition']), "\" />)</td></tr>\n";
echo "</table>\n";
echo "<input type=\"hidden\" name=\"action\" value=\"save_add_check\" />\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo $misc->form;
echo "<p><input type=\"submit\" name=\"ok\" value=\"{$lang['stradd']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
else {
if (trim($_POST['definition']) == '')
addCheck(true, $lang['strcheckneedsdefinition']);
else {
$status = $data->addCheckConstraint($_POST['table'],
$_POST['definition'], $_POST['name']);
if ($status == 0)
doDefault($lang['strcheckadded']);
else
addCheck(true, $lang['strcheckaddedbad']);
}
}
}
/**
* Show confirmation of drop and perform actual drop
*/
function doDrop($confirm) {
global $data, $misc;
global $lang;
if ($confirm) {
$misc->printTrail('constraint');
$misc->printTitle($lang['strdrop'],'pg.constraint.drop');
echo "<p>", sprintf($lang['strconfdropconstraint'], $misc->printVal($_REQUEST['constraint']),
$misc->printVal($_REQUEST['table'])), "</p>\n";
echo "<form action=\"constraints.php\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo "<input type=\"hidden\" name=\"constraint\" value=\"", htmlspecialchars($_REQUEST['constraint']), "\" />\n";
echo "<input type=\"hidden\" name=\"type\" value=\"", htmlspecialchars($_REQUEST['type']), "\" />\n";
echo $misc->form;
echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
}
else {
$status = $data->dropConstraint($_POST['constraint'], $_POST['table'], $_POST['type'], isset($_POST['cascade']));
if ($status == 0)
doDefault($lang['strconstraintdropped']);
else
doDefault($lang['strconstraintdroppedbad']);
}
}
/**
* List all the constraints on the table
*/
function doDefault($msg = '') {
global $data, $misc, $lang;
function cnPre(&$rowdata) {
global $data;
if (is_null($rowdata->fields['consrc'])) {
$atts = $data->getAttributeNames($_REQUEST['table'], explode(' ', $rowdata->fields['indkey']));
$rowdata->fields['+definition'] = ($rowdata->fields['contype'] == 'u' ? "UNIQUE (" : "PRIMARY KEY (") . join(',', $atts) . ')';
} else {
$rowdata->fields['+definition'] = $rowdata->fields['consrc'];
}
}
$misc->printTrail('table');
$misc->printTabs('table','constraints');
$misc->printMsg($msg);
$constraints = $data->getConstraints($_REQUEST['table']);
$columns = array(
'constraint' => array(
'title' => $lang['strname'],
'field' => field('conname'),
),
'definition' => array(
'title' => $lang['strdefinition'],
'field' => field('+definition'),
'type' => 'pre',
),
'actions' => array(
'title' => $lang['stractions'],
),
'comment' => array(
'title' => $lang['strcomment'],
'field' => field('constcomment'),
),
);
$actions = array(
'drop' => array(
'title' => $lang['strdrop'],
'url' => "constraints.php?action=confirm_drop&amp;{$misc->href}&amp;table=".urlencode($_REQUEST['table'])."&amp;",
'vars' => array('constraint' => 'conname', 'type' => 'contype'),
),
);
$misc->printTable($constraints, $columns, $actions, $lang['strnoconstraints'], 'cnPre');
echo "<ul class=\"navlink\">\n\t<li><a href=\"constraints.php?action=add_check&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),
"\">{$lang['straddcheck']}</a></li>\n";
echo "\t<li><a href=\"constraints.php?action=add_unique_key&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),
"\">{$lang['stradduniq']}</a></li>\n";
echo "\t<li><a href=\"constraints.php?action=add_primary_key&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),
"\">{$lang['straddpk']}</a></li>\n";
echo "\t<li><a href=\"constraints.php?action=add_foreign_key&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),
"\">{$lang['straddfk']}</a></li>\n</ul>\n";
}
function doTree() {
global $misc, $data;
$constraints = $data->getConstraints($_REQUEST['table']);
$reqvars = $misc->getRequestVars('schema');
function getIcon($f) {
switch($f['contype']) {
case 'u':
return 'UniqueConstraint';
case 'c':
return 'CheckConstraint';
case 'f':
return 'ForeignKey';
case 'p':
return 'PrimaryKey';
}
}
$attrs = array(
'text' => field('conname'),
'icon' => callback('getIcon'),
);
$misc->printTreeXML($constraints, $attrs);
exit;
}
if ($action == 'tree') doTree();
$misc->printHeader($lang['strtables'] . ' - ' . $_REQUEST['table'] . ' - ' . $lang['strconstraints'],
"<script src=\"indexes.js\" type=\"text/javascript\"></script>");
if ($action == 'add_unique_key' || $action == 'save_add_unique_key'
|| $action == 'add_primary_key' || $action == 'save_add_primary_key'
|| $action == 'add_foreign_key' || $action == 'save_add_foreign_key')
echo "<body onload=\"init();\">";
else
$misc->printBody();
switch ($action) {
case 'add_foreign_key':
addForeignKey(1);
break;
case 'save_add_foreign_key':
if (isset($_POST['cancel'])) doDefault();
else addForeignKey($_REQUEST['stage']);
break;
case 'add_unique_key':
addPrimaryOrUniqueKey('unique', true);
break;
case 'save_add_unique_key':
if (isset($_POST['cancel'])) doDefault();
else addPrimaryOrUniqueKey('unique', false);
break;
case 'add_primary_key':
addPrimaryOrUniqueKey('primary', true);
break;
case 'save_add_primary_key':
if (isset($_POST['cancel'])) doDefault();
else addPrimaryOrUniqueKey('primary', false);
break;
case 'add_check':
addCheck(true);
break;
case 'save_add_check':
if (isset($_POST['cancel'])) doDefault();
else addCheck(false);
break;
case 'save_create':
doSaveCreate();
break;
case 'create':
doCreate();
break;
case 'drop':
if (isset($_POST['drop'])) doDrop(false);
else doDefault();
break;
case 'confirm_drop':
doDrop(true);
break;
default:
doDefault();
break;
}
$misc->printFooter();
?>

View File

@ -0,0 +1,88 @@
<?php
/**
* Manage conversions in a database
*
* $Id: conversions.php,v 1.15 2007/08/31 18:30:10 ioguix Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (!isset($msg)) $msg = '';
/**
* Show default list of conversions in the database
*/
function doDefault($msg = '') {
global $data, $conf, $misc, $database;
global $lang;
$misc->printTrail('schema');
$misc->printTabs('schema', 'conversions');
$misc->printMsg($msg);
$conversions = $data->getconversions();
$columns = array(
'conversion' => array(
'title' => $lang['strname'],
'field' => field('conname'),
),
'source_encoding' => array(
'title' => $lang['strsourceencoding'],
'field' => field('conforencoding'),
),
'target_encoding' => array(
'title' => $lang['strtargetencoding'],
'field' => field('contoencoding'),
),
'default' => array(
'title' => $lang['strdefault'],
'field' => field('condefault'),
'type' => 'yesno',
),
'comment' => array(
'title' => $lang['strcomment'],
'field' => field('concomment'),
),
);
$actions = array();
$misc->printTable($conversions, $columns, $actions, $lang['strnoconversions']);
}
/**
* Generate XML for the browser tree.
*/
function doTree() {
global $misc, $data;
$conversions = $data->getconversions();
$attrs = array(
'text' => field('conname'),
'icon' => 'Conversion',
'toolTip'=> field('concomment')
);
$misc->printTreeXML($conversions, $attrs);
exit;
}
if ($action == 'tree') doTree();
$misc->printHeader($lang['strconversions']);
$misc->printBody();
switch ($action) {
default:
doDefault();
break;
}
$misc->printFooter();
?>

676
php/pgadmin/database.php Normal file
View File

@ -0,0 +1,676 @@
<?php
/**
* Manage schemas within a database
*
* $Id: database.php,v 1.104 2007/11/30 06:04:43 xzilla Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (!isset($msg)) $msg = '';
$scripts = '';
function _highlight($string, $term) {
return str_replace($term, "<b>{$term}</b>", $string);
}
/**
* Sends a signal to a process
*/
function doSignal() {
global $data, $lang;
$status = $data->sendSignal($_REQUEST['procpid'], $_REQUEST['signal']);
if ($status == 0)
doProcesses($lang['strsignalsent']);
else
doProcesses($lang['strsignalsentbad']);
}
/**
* Searches for a named database object
*/
function doFind($confirm = true, $msg = '') {
global $data, $misc;
global $lang, $conf;
if (!isset($_REQUEST['term'])) $_REQUEST['term'] = '';
if (!isset($_REQUEST['filter'])) $_REQUEST['filter'] = '';
$misc->printTrail('database');
$misc->printTabs('database','find');
$misc->printMsg($msg);
echo "<form action=\"database.php\" method=\"post\">\n";
echo "<p><input name=\"term\" value=\"", htmlspecialchars($_REQUEST['term']),
"\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" />\n";
// Output list of filters. This is complex due to all the 'has' and 'conf' feature possibilities
echo "<select name=\"filter\">\n";
echo "\t<option value=\"\"", ($_REQUEST['filter'] == '') ? ' selected="selected"' : '', ">{$lang['strallobjects']}</option>\n";
echo "\t<option value=\"SCHEMA\"", ($_REQUEST['filter'] == 'SCHEMA') ? ' selected="selected"' : '', ">{$lang['strschemas']}</option>\n";
echo "\t<option value=\"TABLE\"", ($_REQUEST['filter'] == 'TABLE') ? ' selected="selected"' : '', ">{$lang['strtables']}</option>\n";
echo "\t<option value=\"VIEW\"", ($_REQUEST['filter'] == 'VIEW') ? ' selected="selected"' : '', ">{$lang['strviews']}</option>\n";
echo "\t<option value=\"SEQUENCE\"", ($_REQUEST['filter'] == 'SEQUENCE') ? ' selected="selected"' : '', ">{$lang['strsequences']}</option>\n";
echo "\t<option value=\"COLUMN\"", ($_REQUEST['filter'] == 'COLUMN') ? ' selected="selected"' : '', ">{$lang['strcolumns']}</option>\n";
echo "\t<option value=\"RULE\"", ($_REQUEST['filter'] == 'RULE') ? ' selected="selected"' : '', ">{$lang['strrules']}</option>\n";
echo "\t<option value=\"INDEX\"", ($_REQUEST['filter'] == 'INDEX') ? ' selected="selected"' : '', ">{$lang['strindexes']}</option>\n";
echo "\t<option value=\"TRIGGER\"", ($_REQUEST['filter'] == 'TRIGGER') ? ' selected="selected"' : '', ">{$lang['strtriggers']}</option>\n";
echo "\t<option value=\"CONSTRAINT\"", ($_REQUEST['filter'] == 'CONSTRAINT') ? ' selected="selected"' : '', ">{$lang['strconstraints']}</option>\n";
echo "\t<option value=\"FUNCTION\"", ($_REQUEST['filter'] == 'FUNCTION') ? ' selected="selected"' : '', ">{$lang['strfunctions']}</option>\n";
echo "\t<option value=\"DOMAIN\"", ($_REQUEST['filter'] == 'DOMAIN') ? ' selected="selected"' : '', ">{$lang['strdomains']}</option>\n";
if ($conf['show_advanced']) {
echo "\t<option value=\"AGGREGATE\"", ($_REQUEST['filter'] == 'AGGREGATE') ? ' selected="selected"' : '', ">{$lang['straggregates']}</option>\n";
echo "\t<option value=\"TYPE\"", ($_REQUEST['filter'] == 'TYPE') ? ' selected="selected"' : '', ">{$lang['strtypes']}</option>\n";
echo "\t<option value=\"OPERATOR\"", ($_REQUEST['filter'] == 'OPERATOR') ? ' selected="selected"' : '', ">{$lang['stroperators']}</option>\n";
echo "\t<option value=\"OPCLASS\"", ($_REQUEST['filter'] == 'OPCLASS') ? ' selected="selected"' : '', ">{$lang['stropclasses']}</option>\n";
echo "\t<option value=\"CONVERSION\"", ($_REQUEST['filter'] == 'CONVERSION') ? ' selected="selected"' : '', ">{$lang['strconversions']}</option>\n";
echo "\t<option value=\"LANGUAGE\"", ($_REQUEST['filter'] == 'LANGUAGE') ? ' selected="selected"' : '', ">{$lang['strlanguages']}</option>\n";
}
echo "</select>\n";
echo "<input type=\"submit\" value=\"{$lang['strfind']}\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"find\" /></p>\n";
echo "</form>\n";
// Default focus
$misc->setFocus('forms[0].term');
// If a search term has been specified, then perform the search
// and display the results, grouped by object type
if ($_REQUEST['term'] != '') {
$rs = $data->findObject($_REQUEST['term'], $_REQUEST['filter']);
if ($rs->recordCount() > 0) {
$curr = '';
while (!$rs->EOF) {
// Output a new header if the current type has changed, but not if it's just changed the rule type
if ($rs->fields['type'] != $curr) {
// Short-circuit in the case of changing from table rules to view rules; table cols to view cols;
// table constraints to domain constraints
if ($rs->fields['type'] == 'RULEVIEW' && $curr == 'RULETABLE') {
$curr = $rs->fields['type'];
}
elseif ($rs->fields['type'] == 'COLUMNVIEW' && $curr == 'COLUMNTABLE') {
$curr = $rs->fields['type'];
}
elseif ($rs->fields['type'] == 'CONSTRAINTTABLE' && $curr == 'CONSTRAINTDOMAIN') {
$curr = $rs->fields['type'];
}
else {
if ($curr != '') echo "</ul>\n";
$curr = $rs->fields['type'];
echo "<h3>";
switch ($curr) {
case 'SCHEMA':
echo $lang['strschemas'];
break;
case 'TABLE':
echo $lang['strtables'];
break;
case 'VIEW':
echo $lang['strviews'];
break;
case 'SEQUENCE':
echo $lang['strsequences'];
break;
case 'COLUMNTABLE':
case 'COLUMNVIEW':
echo $lang['strcolumns'];
break;
case 'INDEX':
echo $lang['strindexes'];
break;
case 'CONSTRAINTTABLE':
case 'CONSTRAINTDOMAIN':
echo $lang['strconstraints'];
break;
case 'TRIGGER':
echo $lang['strtriggers'];
break;
case 'RULETABLE':
case 'RULEVIEW':
echo $lang['strrules'];
break;
case 'FUNCTION':
echo $lang['strfunctions'];
break;
case 'TYPE':
echo $lang['strtypes'];
break;
case 'DOMAIN':
echo $lang['strdomains'];
break;
case 'OPERATOR':
echo $lang['stroperators'];
break;
case 'CONVERSION':
echo $lang['strconversions'];
break;
case 'LANGUAGE':
echo $lang['strlanguages'];
break;
case 'AGGREGATE':
echo $lang['straggregates'];
break;
case 'OPCLASS':
echo $lang['stropclasses'];
break;
}
echo "</h3>";
echo "<ul>\n";
}
}
switch ($curr) {
case 'SCHEMA':
echo "<li><a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", $misc->printVal($rs->fields['name']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'TABLE':
echo "<li>";
echo "<a href=\"tables.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"redirect.php?subject=table&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;table=",
urlencode($rs->fields['name']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'VIEW':
echo "<li>";
echo "<a href=\"views.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"redirect.php?subject=view&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;view=",
urlencode($rs->fields['name']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'SEQUENCE':
echo "<li>";
echo "<a href=\"sequences.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"sequences.php?subject=sequence&amp;action=properties&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']),
"&amp;sequence=", urlencode($rs->fields['name']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'COLUMNTABLE':
echo "<li>";
echo "<a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"tblproperties.php?subject=table&amp;{$misc->href}&amp;table=", urlencode($rs->fields['relname']), "&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['relname']), "</a>.";
echo "<a href=\"colproperties.php?{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;table=",
urlencode($rs->fields['relname']), "&amp;column=", urlencode($rs->fields['name']), "\">",
_highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'COLUMNVIEW':
echo "<li>";
echo "<a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"viewproperties.php?subject=view&amp;{$misc->href}&amp;view=", urlencode($rs->fields['relname']), "&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['relname']), "</a>.";
echo "<a href=\"colproperties.php?{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;view=",
urlencode($rs->fields['relname']), "&amp;column=", urlencode($rs->fields['name']), "\">",
_highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'INDEX':
echo "<li>";
echo "<a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"redirect.php?subject=table&amp;{$misc->href}&amp;table=", urlencode($rs->fields['relname']), "&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['relname']), "</a>.";
echo "<a href=\"indexes.php?{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;table=", urlencode($rs->fields['relname']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'CONSTRAINTTABLE':
echo "<li>";
echo "<a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"redirect.php?subject=table&amp;{$misc->href}&amp;table=", urlencode($rs->fields['relname']), "&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['relname']), "</a>.";
echo "<a href=\"constraints.php?{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;table=",
urlencode($rs->fields['relname']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'CONSTRAINTDOMAIN':
echo "<li>";
echo "<a href=\"domains.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"domains.php?action=properties&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;domain=", urlencode($rs->fields['relname']), "\">",
$misc->printVal($rs->fields['relname']), '.', _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'TRIGGER':
echo "<li>";
echo "<a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"redirect.php?subject=table&amp;{$misc->href}&amp;table=", urlencode($rs->fields['relname']), "&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['relname']), "</a>.";
echo "<a href=\"triggers.php?{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;table=", urlencode($rs->fields['relname']), "\">",
_highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'RULETABLE':
echo "<li>";
echo "<a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"redirect.php?subject=table&amp;{$misc->href}&amp;table=", urlencode($rs->fields['relname']), "&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['relname']), "</a>.";
echo "<a href=\"rules.php?subject=table&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;reltype=table&amp;table=",
urlencode($rs->fields['relname']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'RULEVIEW':
echo "<li>";
echo "<a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"redirect.php?subject=view&amp;{$misc->href}&amp;view=", urlencode($rs->fields['relname']), "&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['relname']), "</a>.";
echo "<a href=\"rules.php?subject=view&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;reltype=view&amp;view=",
urlencode($rs->fields['relname']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'FUNCTION':
echo "<li>";
echo "<a href=\"functions.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"functions.php?action=properties&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;function=",
urlencode($rs->fields['name']), "&amp;function_oid=", urlencode($rs->fields['oid']), "\">",
_highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'TYPE':
echo "<li>";
echo "<a href=\"types.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"types.php?action=properties&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;type=",
urlencode($rs->fields['name']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'DOMAIN':
echo "<li>";
echo "<a href=\"domains.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"domains.php?action=properties&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;domain=",
urlencode($rs->fields['name']), "\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'OPERATOR':
echo "<li>";
echo "<a href=\"operators.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"operators.php?action=properties&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "&amp;operator=",
urlencode($rs->fields['name']), "&amp;operator_oid=", urlencode($rs->fields['oid']) ,"\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'CONVERSION':
echo "<li>";
echo "<a href=\"conversions.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"conversions.php?{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']),
"\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'LANGUAGE':
echo "<li><a href=\"languages.php?{$misc->href}\">", _highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'AGGREGATE':
echo "<li>";
echo "<a href=\"aggregates.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"aggregates.php?{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">",
_highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
case 'OPCLASS':
echo "<li>";
echo "<a href=\"redirect.php?subject=schema&amp;{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">", $misc->printVal($rs->fields['schemaname']), "</a>.";
echo "<a href=\"opclasses.php?{$misc->href}&amp;schema=", urlencode($rs->fields['schemaname']), "\">",
_highlight($misc->printVal($rs->fields['name']), $_REQUEST['term']), "</a></li>\n";
break;
}
$rs->moveNext();
}
echo "</ul>\n";
echo "<p>", $rs->recordCount(), " ", $lang['strobjects'], "</p>\n";
}
else echo "<p>{$lang['strnoobjects']}</p>\n";
}
}
/**
* Displays options for database download
*/
function doExport($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('database');
$misc->printTabs('database','export');
$misc->printMsg($msg);
echo "<form action=\"dbexport.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data\">{$lang['strformat']}</th><th class=\"data\" colspan=\"2\">{$lang['stroptions']}</th></tr>\n";
// Data only
echo "<tr><th class=\"data left\" rowspan=\"2\">";
echo "<input type=\"radio\" id=\"what1\" name=\"what\" value=\"dataonly\" checked=\"checked\" /><label for=\"what1\">{$lang['strdataonly']}</label></th>\n";
echo "<td>{$lang['strformat']}</td>\n";
echo "<td><select name=\"d_format\">\n";
echo "<option value=\"copy\">COPY</option>\n";
echo "<option value=\"sql\">SQL</option>\n";
echo "</select>\n</td>\n</tr>\n";
echo "<tr><td><label for=\"d_oids\">{$lang['stroids']}</label></td><td><input type=\"checkbox\" id=\"d_oids\" name=\"d_oids\" /></td>\n</tr>\n";
// Structure only
echo "<tr><th class=\"data left\"><input type=\"radio\" id=\"what2\" name=\"what\" value=\"structureonly\" /><label for=\"what2\">{$lang['strstructureonly']}</label></th>\n";
echo "<td><label for=\"s_clean\">{$lang['strdrop']}</label></td><td><input type=\"checkbox\" id=\"s_clean\" name=\"s_clean\" /></td>\n</tr>\n";
// Structure and data
echo "<tr><th class=\"data left\" rowspan=\"3\">";
echo "<input type=\"radio\" id=\"what3\" name=\"what\" value=\"structureanddata\" /><label for=\"what3\">{$lang['strstructureanddata']}</label></th>\n";
echo "<td>{$lang['strformat']}</td>\n";
echo "<td><select name=\"sd_format\">\n";
echo "<option value=\"copy\">COPY</option>\n";
echo "<option value=\"sql\">SQL</option>\n";
echo "</select>\n</td>\n</tr>\n";
echo "<tr><td><label for=\"sd_clean\">{$lang['strdrop']}</label></td><td><input type=\"checkbox\" id=\"sd_clean\" name=\"sd_clean\" /></td>\n</tr>\n";
echo "<tr><td><label for=\"sd_oids\">{$lang['stroids']}</label></td><td><input type=\"checkbox\" id=\"sd_oids\" name=\"sd_oids\" /></td>\n</tr>\n";
echo "</table>\n";
echo "<h3>{$lang['stroptions']}</h3>\n";
echo "<p><input type=\"radio\" id=\"output1\" name=\"output\" value=\"show\" checked=\"checked\" /><label for=\"output1\">{$lang['strshow']}</label>\n";
echo "<br/><input type=\"radio\" id=\"output2\" name=\"output\" value=\"download\" /><label for=\"output2\">{$lang['strdownload']}</label>\n";
// MSIE cannot download gzip in SSL mode - it's just broken
if (!(strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS']))) {
echo "<br /><input type=\"radio\" id=\"output3\" name=\"output\" value=\"gzipped\" /><label for=\"output3\">{$lang['strdownloadgzipped']}</label>\n";
}
echo "</p>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
echo "<input type=\"hidden\" name=\"subject\" value=\"database\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
echo "</form>\n";
}
/**
* Show the current status of all database variables
*/
function doVariables() {
global $data, $misc;
global $lang;
// Fetch the variables from the database
$variables = $data->getVariables();
$misc->printTrail('database');
$misc->printTabs('database','variables');
$columns = array(
'variable' => array(
'title' => $lang['strname'],
'field' => field('name'),
),
'value' => array(
'title' => $lang['strsetting'],
'field' => field('setting'),
),
);
$actions = array();
$misc->printTable($variables, $columns, $actions, $lang['strnodata']);
}
/**
* Show all current database connections and any queries they
* are running.
*/
function doProcesses($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('database');
$misc->printTabs('database','processes');
$misc->printMsg($msg);
if (strlen($msg) === 0) {
echo "<br /><a id=\"control\" href=\"\"><img src=\"".$misc->icon('Refresh')."\" alt=\"{$lang['strrefresh']}\" title=\"{$lang['strrefresh']}\"/>&nbsp;{$lang['strrefresh']}</a>";
}
echo "<div id=\"data_block\">";
currentProcesses();
echo "</div>";
}
function currentProcesses($isAjax = false) {
global $data, $misc, $lang;
// Display prepared transactions
if($data->hasPreparedXacts()) {
echo "<h3>{$lang['strpreparedxacts']}</h3>\n";
$prep_xacts = $data->getPreparedXacts($_REQUEST['database']);
$columns = array(
'transaction' => array(
'title' => $lang['strxactid'],
'field' => field('transaction'),
),
'gid' => array(
'title' => $lang['strgid'],
'field' => field('gid'),
),
'prepared' => array(
'title' => $lang['strstarttime'],
'field' => field('prepared'),
),
'owner' => array(
'title' => $lang['strowner'],
'field' => field('owner'),
),
);
$actions = array();
$misc->printTable($prep_xacts, $columns, $actions, $lang['strnodata']);
}
// Fetch the processes from the database
echo "<h3>{$lang['strprocesses']}</h3>\n";
$processes = $data->getProcesses($_REQUEST['database']);
$columns = array(
'user' => array(
'title' => $lang['strusername'],
'field' => field('usename'),
),
'process' => array(
'title' => $lang['strprocess'],
'field' => field('procpid'),
),
'query' => array(
'title' => $lang['strsql'],
'field' => field('current_query'),
),
'start_time' => array(
'title' => $lang['strstarttime'],
'field' => field('query_start'),
),
);
// Build possible actions for our process list
$columns['actions'] = array('title' => $lang['stractions']);
$actions = array(
'cancel' => array(
'title' => $lang['strcancel'],
'url' => "database.php?action=signal&amp;signal=CANCEL&amp;{$misc->href}&amp;",
'vars' => array('procpid' => 'procpid')
),
'kill' => array(
'title' => $lang['strkill'],
'url' => "database.php?action=signal&amp;signal=KILL&amp;{$misc->href}&amp;",
'vars' => array('procpid' => 'procpid')
)
);
// Remove actions where not supported
if (!$data->hasQueryKill()) unset($actions['kill']);
if (!$data->hasQueryCancel()) unset($actions['cancel']);
if (count($actions) == 0) unset($columns['actions']);
// Remove query start time for <7.4
if (!isset($processes->fields['query_start'])) unset($columns['start_time']);
$misc->printTable($processes, $columns, $actions, $lang['strnodata']);
if ($isAjax) exit;
}
function currentLocks($isAjax = false) {
global $data, $misc, $lang;
// Get the info from the pg_locks view
$variables = $data->getLocks();
$columns = array(
'namespace' => array(
'title' => $lang['strschema'],
'field' => field('nspname'),
),
'tablename' => array(
'title' => $lang['strtablename'],
'field' => field('tablename'),
),
'vxid' => array(
'title' => $lang['strvirtualtransaction'],
'field' => field('virtualtransaction'),
),
'transactionid' => array(
'title' => $lang['strtransaction'],
'field' => field('transaction'),
),
'processid' => array(
'title' => $lang['strprocessid'],
'field' => field('pid'),
),
'mode' => array(
'title' => $lang['strmode'],
'field' => field('mode'),
),
'granted' => array(
'title' => $lang['strislockheld'],
'field' => field('granted'),
'type' => 'yesno',
),
);
if (!$data->hasVirtualTransactionId()) unset($columns['vxid']);
$actions = array();
$misc->printTable($variables, $columns, $actions, $lang['strnodata']);
if ($isAjax) exit;
}
/**
* Show the existing table locks in the current database
*/
function doLocks() {
global $data, $misc;
global $lang;
$misc->printTrail('database');
$misc->printTabs('database','locks');
echo "<br /><a id=\"control\" href=\"\"><img src=\"".$misc->icon('Refresh')."\" alt=\"{$lang['strrefresh']}\" title=\"{$lang['strrefresh']}\"/>&nbsp;{$lang['strrefresh']}</a>";
echo "<div id=\"data_block\">";
currentLocks();
echo "</div>";
}
/**
* Allow execution of arbitrary SQL statements on a database
*/
function doSQL() {
global $data, $misc;
global $lang;
if ((!isset($_SESSION['sqlquery'])) || isset($_REQUEST['new'])) $_SESSION['sqlquery'] = '';
$misc->printTrail('database');
$misc->printTabs('database','sql');
echo "<p>{$lang['strentersql']}</p>\n";
echo "<form action=\"sql.php\" method=\"post\" enctype=\"multipart/form-data\">\n";
echo "<p>{$lang['strsql']}<br />\n";
echo "<textarea style=\"width:100%;\" rows=\"20\" cols=\"50\" name=\"query\">",
htmlspecialchars($_SESSION['sqlquery']), "</textarea></p>\n";
// Check that file uploads are enabled
if (ini_get('file_uploads')) {
// Don't show upload option if max size of uploads is zero
$max_size = $misc->inisizeToBytes(ini_get('upload_max_filesize'));
if (is_double($max_size) && $max_size > 0) {
echo "<p><input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"{$max_size}\" />\n";
echo "<label for=\"script\">{$lang['struploadscript']}</label> <input id=\"script\" name=\"script\" type=\"file\" /></p>\n";
}
}
echo "<p><input type=\"checkbox\" id=\"paginate\" name=\"paginate\"", (isset($_REQUEST['paginate']) ? ' checked="checked"' : ''), " /><label for=\"paginate\">{$lang['strpaginate']}</label></p>\n";
echo "<p><input type=\"submit\" value=\"{$lang['strexecute']}\" />\n";
echo $misc->form;
echo "<input type=\"reset\" value=\"{$lang['strreset']}\" /></p>\n";
echo "</form>\n";
// Default focus
$misc->setFocus('forms[0].query');
}
function doTree() {
global $misc, $data, $lang, $slony;
$reqvars = $misc->getRequestVars('database');
$tabs = $misc->getNavTabs('database');
$items = $misc->adjustTabsForTree($tabs);
$attrs = array(
'text' => noEscape(field('title')),
'icon' => field('icon'),
'action' => url(field('url'),
$reqvars,
field('urlvars', array())
),
'branch' => url(field('url'),
$reqvars,
field('urlvars'),
array('action' => 'tree')
),
);
$misc->printTreeXML($items, $attrs);
exit;
}
require('./admin.php');
/* shortcuts: these functions exit the script */
if ($action == 'tree') doTree();
if ($action == 'refresh_locks') currentLocks(true);
if ($action == 'refresh_processes') currentProcesses(true);
/* normal flow */
if ($action == 'locks' or $action == 'processes') {
$scripts = "<script src=\"libraries/js/jquery.js\" type=\"text/javascript\"></script>\n";
$scripts .= "<script src=\"js/database.js\" type=\"text/javascript\"></script>";
$refreshTime = $conf['ajax_refresh'] * 1000;
$scripts .= "<script type=\"text/javascript\">\n";
$scripts .= "var Database = {\n";
$scripts .= "ajax_time_refresh: {$refreshTime},\n";
$scripts .= "str_start: {text:'{$lang['strstart']}',icon: '". $misc->icon('Execute') ."'},\n";
$scripts .= "str_stop: {text:'{$lang['strstop']}',icon: '". $misc->icon('Stop') ."'},\n";
$scripts .= "load_icon: '". $misc->icon('Loading') ."',\n";
$scripts .= "server:'{$_REQUEST['server']}',\n";
$scripts .= "dbname:'{$_REQUEST['database']}',\n";
$scripts .= "action:'refresh_{$action}',\n";
$scripts .= "errmsg: '". str_replace("'", "\'", $lang['strconnectionfail']) ."'\n";
$scripts .= "};\n";
$scripts .= "</script>\n";
}
$misc->printHeader($lang['strdatabase'], $scripts);
$misc->printBody();
switch ($action) {
case 'find':
if (isset($_REQUEST['term'])) doFind(false);
else doFind(true);
break;
case 'sql':
doSQL();
break;
case 'variables':
doVariables();
break;
case 'processes':
doProcesses();
break;
case 'locks':
doLocks();
break;
case 'export':
doExport();
break;
case 'signal':
doSignal();
break;
default:
if (adminActions($action, 'database') === false) doSQL();
break;
}
$misc->printFooter();
?>

345
php/pgadmin/dataexport.php Normal file
View File

@ -0,0 +1,345 @@
<?php
/**
* Does an export to the screen or as a download. This checks to
* see if they have pg_dump set up, and will use it if possible.
*
* $Id: dataexport.php,v 1.26 2007/07/12 19:26:22 xzilla Exp $
*/
$extensions = array(
'sql' => 'sql',
'copy' => 'sql',
'csv' => 'csv',
'tab' => 'txt',
'html' => 'html',
'xml' => 'xml'
);
// Prevent timeouts on large exports (non-safe mode only)
if (!ini_get('safe_mode')) set_time_limit(0);
// if (!isset($_REQUEST['table']) && !isset($_REQUEST['query']))
// What must we do in this case? Maybe redirect to the homepage?
// If format is set, then perform the export
if (isset($_REQUEST['what'])) {
// Include application functions
$_no_output = true;
include_once('./libraries/lib.inc.php');
switch ($_REQUEST['what']) {
case 'dataonly':
// Check to see if they have pg_dump set up and if they do, use that
// instead of custom dump code
if ($misc->isDumpEnabled()
&& ($_REQUEST['d_format'] == 'copy' || $_REQUEST['d_format'] == 'sql')) {
include('./dbexport.php');
exit;
}
else {
$format = $_REQUEST['d_format'];
$oids = isset($_REQUEST['d_oids']);
}
break;
case 'structureonly':
// Check to see if they have pg_dump set up and if they do, use that
// instead of custom dump code
if ($misc->isDumpEnabled()) {
include('./dbexport.php');
exit;
}
else $clean = isset($_REQUEST['s_clean']);
break;
case 'structureanddata':
// Check to see if they have pg_dump set up and if they do, use that
// instead of custom dump code
if ($misc->isDumpEnabled()) {
include('./dbexport.php');
exit;
}
else {
$format = $_REQUEST['sd_format'];
$clean = isset($_REQUEST['sd_clean']);
$oids = isset($_REQUEST['sd_oids']);
}
break;
}
// Make it do a download, if necessary
if ($_REQUEST['output'] == 'download') {
// Set headers. MSIE is totally broken for SSL downloading, so
// we need to have it download in-place as plain text
if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS'])) {
header('Content-Type: text/plain');
}
else {
header('Content-Type: application/download');
if (isset($extensions[$format]))
$ext = $extensions[$format];
else
$ext = 'txt';
header('Content-Disposition: attachment; filename=dump.' . $ext);
}
}
else {
header('Content-Type: text/plain');
}
if (isset($_REQUEST['query'])) $_REQUEST['query'] = trim(urldecode($_REQUEST['query']));
// Set the schema search path
if (isset($_REQUEST['search_path'])) {
$data->setSearchPath(array_map('trim',explode(',',$_REQUEST['search_path'])));
}
// Set up the dump transaction
$status = $data->beginDump();
// If the dump is not dataonly then dump the structure prefix
if ($_REQUEST['what'] != 'dataonly')
echo $data->getTableDefPrefix($_REQUEST['table'], $clean);
// If the dump is not structureonly then dump the actual data
if ($_REQUEST['what'] != 'structureonly') {
// Get database encoding
$dbEncoding = $data->getDatabaseEncoding();
// Set fetch mode to NUM so that duplicate field names are properly returned
$data->conn->setFetchMode(ADODB_FETCH_NUM);
// Execute the query, if set, otherwise grab all rows from the table
if (isset($_REQUEST['table']))
$rs = $data->dumpRelation($_REQUEST['table'], $oids);
else
$rs = $data->conn->Execute($_REQUEST['query']);
if ($format == 'copy') {
$data->fieldClean($_REQUEST['table']);
echo "COPY \"{$_REQUEST['table']}\"";
if ($oids) echo " WITH OIDS";
echo " FROM stdin;\n";
while (!$rs->EOF) {
$first = true;
while(list($k, $v) = each($rs->fields)) {
// Escape value
$v = $data->escapeBytea($v);
// We add an extra escaping slash onto octal encoded characters
$v = preg_replace('/\\\\([0-7]{3})/', '\\\\\1', $v);
if ($first) {
echo (is_null($v)) ? '\\N' : $v;
$first = false;
}
else echo "\t", (is_null($v)) ? '\\N' : $v;
}
echo "\n";
$rs->moveNext();
}
echo "\\.\n";
}
elseif ($format == 'html') {
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n";
echo "<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n";
echo "<head>\r\n";
echo "\t<title></title>\r\n";
echo "\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset={$data->codemap[$dbEncoding]}\" />\r\n";
echo "</head>\r\n";
echo "<body>\r\n";
echo "<table class=\"phppgadmin\">\r\n";
echo "\t<tr>\r\n";
if (!$rs->EOF) {
// Output header row
$j = 0;
foreach ($rs->fields as $k => $v) {
$finfo = $rs->fetchField($j++);
if ($finfo->name == $data->id && !$oids) continue;
echo "\t\t<th>", $misc->printVal($finfo->name, true), "</th>\r\n";
}
}
echo "\t</tr>\r\n";
while (!$rs->EOF) {
echo "\t<tr>\r\n";
$j = 0;
foreach ($rs->fields as $k => $v) {
$finfo = $rs->fetchField($j++);
if ($finfo->name == $data->id && !$oids) continue;
echo "\t\t<td>", $misc->printVal($v, true, $finfo->type), "</td>\r\n";
}
echo "\t</tr>\r\n";
$rs->moveNext();
}
echo "</table>\r\n";
echo "</body>\r\n";
echo "</html>\r\n";
}
elseif ($format == 'xml') {
echo "<?xml version=\"1.0\"";
if (isset($data->codemap[$dbEncoding]))
echo " encoding=\"{$data->codemap[$dbEncoding]}\"";
echo " ?>\n";
echo "<data>\n";
if (!$rs->EOF) {
// Output header row
$j = 0;
echo "\t<header>\n";
foreach ($rs->fields as $k => $v) {
$finfo = $rs->fetchField($j++);
$name = htmlspecialchars($finfo->name);
$type = htmlspecialchars($finfo->type);
echo "\t\t<column name=\"{$name}\" type=\"{$type}\" />\n";
}
echo "\t</header>\n";
}
echo "\t<records>\n";
while (!$rs->EOF) {
$j = 0;
echo "\t\t<row>\n";
foreach ($rs->fields as $k => $v) {
$finfo = $rs->fetchField($j++);
$name = htmlspecialchars($finfo->name);
if (!is_null($v)) $v = htmlspecialchars($v);
echo "\t\t\t<column name=\"{$name}\"", (is_null($v) ? ' null="null"' : ''), ">{$v}</column>\n";
}
echo "\t\t</row>\n";
$rs->moveNext();
}
echo "\t</records>\n";
echo "</data>\n";
}
elseif ($format == 'sql') {
$data->fieldClean($_REQUEST['table']);
while (!$rs->EOF) {
echo "INSERT INTO \"{$_REQUEST['table']}\" (";
$first = true;
$j = 0;
foreach ($rs->fields as $k => $v) {
$finfo = $rs->fetchField($j++);
$k = $finfo->name;
// SQL (INSERT) format cannot handle oids
// if ($k == $data->id) continue;
// Output field
$data->fieldClean($k);
if ($first) echo "\"{$k}\"";
else echo ", \"{$k}\"";
if (!is_null($v)) {
// Output value
// addCSlashes converts all weird ASCII characters to octal representation,
// EXCEPT the 'special' ones like \r \n \t, etc.
$v = addCSlashes($v, "\0..\37\177..\377");
// We add an extra escaping slash onto octal encoded characters
$v = preg_replace('/\\\\([0-7]{3})/', '\\\1', $v);
// Finally, escape all apostrophes
$v = str_replace("'", "''", $v);
}
if ($first) {
$values = (is_null($v) ? 'NULL' : "'{$v}'");
$first = false;
}
else $values .= ', ' . ((is_null($v) ? 'NULL' : "'{$v}'"));
}
echo ") VALUES ({$values});\n";
$rs->moveNext();
}
}
else {
switch ($format) {
case 'tab':
$sep = "\t";
break;
case 'csv':
default:
$sep = ',';
break;
}
if (!$rs->EOF) {
// Output header row
$first = true;
foreach ($rs->fields as $k => $v) {
$finfo = $rs->fetchField($k);
$v = $finfo->name;
if (!is_null($v)) $v = str_replace('"', '""', $v);
if ($first) {
echo "\"{$v}\"";
$first = false;
}
else echo "{$sep}\"{$v}\"";
}
echo "\r\n";
}
while (!$rs->EOF) {
$first = true;
foreach ($rs->fields as $k => $v) {
if (!is_null($v)) $v = str_replace('"', '""', $v);
if ($first) {
echo (is_null($v)) ? "\"\\N\"" : "\"{$v}\"";
$first = false;
}
else echo is_null($v) ? "{$sep}\"\\N\"" : "{$sep}\"{$v}\"";
}
echo "\r\n";
$rs->moveNext();
}
}
}
// If the dump is not dataonly then dump the structure suffix
if ($_REQUEST['what'] != 'dataonly') {
// Set fetch mode back to ASSOC for the table suffix to work
$data->conn->setFetchMode(ADODB_FETCH_ASSOC);
echo $data->getTableDefSuffix($_REQUEST['table']);
}
// Finish the dump transaction
$status = $data->endDump();
}
else {
// Include application functions
include_once('./libraries/lib.inc.php');
$misc->printHeader($lang['strexport']);
$misc->printBody();
$misc->printTrail(isset($_REQUEST['subject']) ? $_REQUEST['subject'] : 'database');
$misc->printTitle($lang['strexport']);
if (isset($msg)) $misc->printMsg($msg);
echo "<form action=\"dataexport.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data\">{$lang['strformat']}:</th><td><select name=\"d_format\">\n";
// COPY and SQL require a table
if (isset($_REQUEST['table'])) {
echo "<option value=\"copy\">COPY</option>\n";
echo "<option value=\"sql\">SQL</option>\n";
}
echo "<option value=\"csv\">CSV</option>\n";
echo "<option value=\"tab\">{$lang['strtabbed']}</option>\n";
echo "<option value=\"html\">XHTML</option>\n";
echo "<option value=\"xml\">XML</option>\n";
echo "</select></td></tr>";
echo "</table>\n";
echo "<h3>{$lang['stroptions']}</h3>\n";
echo "<p><input type=\"radio\" id=\"output1\" name=\"output\" value=\"show\" checked=\"checked\" /><label for=\"output1\">{$lang['strshow']}</label>\n";
echo "<br/><input type=\"radio\" id=\"output2\" name=\"output\" value=\"download\" /><label for=\"output2\">{$lang['strdownload']}</label></p>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
echo "<input type=\"hidden\" name=\"what\" value=\"dataonly\" />\n";
if (isset($_REQUEST['table'])) {
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
}
echo "<input type=\"hidden\" name=\"query\" value=\"", htmlspecialchars(urlencode($_REQUEST['query'])), "\" />\n";
if (isset($_REQUEST['search_path'])) {
echo "<input type=\"hidden\" name=\"search_path\" value=\"", htmlspecialchars($_REQUEST['search_path']), "\" />\n";
}
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
echo "</form>\n";
$misc->printFooter();
}
?>

298
php/pgadmin/dataimport.php Normal file
View File

@ -0,0 +1,298 @@
<?php
/**
* Does an import to a particular table from a text file
*
* $Id: dataimport.php,v 1.11 2007/01/22 16:33:01 soranzo Exp $
*/
// Prevent timeouts on large exports (non-safe mode only)
if (!ini_get('safe_mode')) set_time_limit(0);
// Include application functions
include_once('./libraries/lib.inc.php');
// Default state for XML parser
$state = 'XML';
$curr_col_name = null;
$curr_col_val = null;
$curr_col_null = false;
$curr_row = array();
/**
* Open tag handler for XML import feature
*/
function _startElement($parser, $name, $attrs) {
global $data, $misc, $lang;
global $state, $curr_row, $curr_col_name, $curr_col_val, $curr_col_null;
switch ($name) {
case 'DATA':
if ($state != 'XML') {
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror']);
exit;
}
$state = 'DATA';
break;
case 'HEADER':
if ($state != 'DATA') {
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror']);
exit;
}
$state = 'HEADER';
break;
case 'RECORDS':
if ($state != 'READ_HEADER') {
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror']);
exit;
}
$state = 'RECORDS';
break;
case 'ROW':
if ($state != 'RECORDS') {
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror']);
exit;
}
$state = 'ROW';
$curr_row = array();
break;
case 'COLUMN':
// We handle columns in rows
if ($state == 'ROW') {
$state = 'COLUMN';
$curr_col_name = $attrs['NAME'];
$curr_col_null = isset($attrs['NULL']);
}
// And we ignore columns in headers and fail in any other context
elseif ($state != 'HEADER') {
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror']);
exit;
}
break;
default:
// An unrecognised tag means failure
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror']);
exit;
}
}
/**
* Close tag handler for XML import feature
*/
function _endElement($parser, $name) {
global $data, $misc, $lang;
global $state, $curr_row, $curr_col_name, $curr_col_val, $curr_col_null;
switch ($name) {
case 'DATA':
$state = 'READ_DATA';
break;
case 'HEADER':
$state = 'READ_HEADER';
break;
case 'RECORDS':
$state = 'READ_RECORDS';
break;
case 'ROW':
// Build value map in order to insert row into table
$fields = array();
$vars = array();
$nulls = array();
$format = array();
$types = array();
$i = 0;
foreach ($curr_row as $k => $v) {
$fields[$i] = $k;
// Check for nulls
if ($v === null) $nulls[$i] = 'on';
// Add to value array
$vars[$i] = $v;
// Format is always VALUE
$format[$i] = 'VALUE';
// Type is always text
$types[$i] = 'text';
$i++;
}
$status = $data->insertRow($_REQUEST['table'], $fields, $vars, $nulls, $format, $types);
if ($status != 0) {
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror']);
exit;
}
$curr_row = array();
$state = 'RECORDS';
break;
case 'COLUMN':
$curr_row[$curr_col_name] = ($curr_col_null ? null : $curr_col_val);
$curr_col_name = null;
$curr_col_val = null;
$curr_col_null = false;
$state = 'ROW';
break;
default:
// An unrecognised tag means failure
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror']);
exit;
}
}
/**
* Character data handler for XML import feature
*/
function _charHandler($parser, $cdata) {
global $data, $misc, $lang;
global $state, $curr_col_val;
if ($state == 'COLUMN') {
$curr_col_val .= $cdata;
}
}
function loadNULLArray() {
$array = array();
if (isset($_POST['allowednulls'])) {
foreach ($_POST['allowednulls'] as $null_char)
$array[] = $null_char;
}
return $array;
}
function determineNull($field, $null_array) {
return in_array($field, $null_array);
}
$misc->printHeader($lang['strimport']);
$misc->printTrail('table');
$misc->printTabs('table','import');
// Check that file is specified and is an uploaded file
if (isset($_FILES['source']) && is_uploaded_file($_FILES['source']['tmp_name']) && is_readable($_FILES['source']['tmp_name'])) {
$fd = fopen($_FILES['source']['tmp_name'], 'r');
// Check that file was opened successfully
if ($fd !== false) {
$null_array = loadNULLArray();
$status = $data->beginTransaction();
if ($status != 0) {
$misc->printMsg($lang['strimporterror']);
exit;
}
// If format is set to 'auto', then determine format automatically from file name
if ($_REQUEST['format'] == 'auto') {
$extension = substr(strrchr($_FILES['source']['name'], '.'), 1);
switch ($extension) {
case 'csv':
$_REQUEST['format'] = 'csv';
break;
case 'txt':
$_REQUEST['format'] = 'tab';
break;
case 'xml':
$_REQUEST['format'] = 'xml';
break;
default:
$data->rollbackTransaction();
$misc->printMsg($lang['strimporterror-fileformat']);
exit;
}
}
// Do different import technique depending on file format
switch ($_REQUEST['format']) {
case 'csv':
case 'tab':
// XXX: Length of CSV lines limited to 100k
$csv_max_line = 100000;
// Set delimiter to tabs or commas
if ($_REQUEST['format'] == 'csv') $csv_delimiter = ',';
else $csv_delimiter = "\t";
// Get first line of field names
$fields = fgetcsv($fd, $csv_max_line, $csv_delimiter);
$row = 2; //We start on the line AFTER the field names
while ($line = fgetcsv($fd, $csv_max_line, $csv_delimiter)) {
// Build value map
$t_fields = array();
$vars = array();
$nulls = array();
$format = array();
$types = array();
$i = 0;
foreach ($fields as $f) {
// Check that there is a column
if (!isset($line[$i])) {
$misc->printMsg(sprintf($lang['strimporterrorline-badcolumnnum'], $row));
exit;
}
$t_fields[$i] = $f;
// Check for nulls
if (determineNull($line[$i], $null_array)) {
$nulls[$i] = 'on';
}
// Add to value array
$vars[$i] = $line[$i];
// Format is always VALUE
$format[$i] = 'VALUE';
// Type is always text
$types[$i] = 'text';
$i++;
}
$status = $data->insertRow($_REQUEST['table'], $t_fields, $vars, $nulls, $format, $types);
if ($status != 0) {
$data->rollbackTransaction();
$misc->printMsg(sprintf($lang['strimporterrorline'], $row));
exit;
}
$row++;
}
break;
case 'xml':
$parser = xml_parser_create();
xml_set_element_handler($parser, '_startElement', '_endElement');
xml_set_character_data_handler($parser, '_charHandler');
while (!feof($fd)) {
$line = fgets($fd, 4096);
xml_parse($parser, $line);
}
xml_parser_free($parser);
break;
default:
// Unknown type
$data->rollbackTransaction();
$misc->printMsg($lang['strinvalidparam']);
exit;
}
$status = $data->endTransaction();
if ($status != 0) {
$misc->printMsg($lang['strimporterror']);
exit;
}
fclose($fd);
$misc->printMsg($lang['strfileimported']);
}
else {
// File could not be opened
$misc->printMsg($lang['strimporterror']);
}
}
else {
// Upload went wrong
$misc->printMsg($lang['strimporterror-uploadedfile']);
}
$misc->printFooter();
?>

139
php/pgadmin/dbexport.php Normal file
View File

@ -0,0 +1,139 @@
<?php
/**
* Does an export of a database, schema, or table (via pg_dump)
* to the screen or as a download.
*
* $Id: dbexport.php,v 1.22 2007/03/25 03:15:09 xzilla Exp $
*/
// Prevent timeouts on large exports (non-safe mode only)
if (!ini_get('safe_mode')) set_time_limit(0);
// Include application functions
$_no_output = true;
$f_schema = $f_object = '';
include_once('./libraries/lib.inc.php');
// Are we doing a cluster-wide dump or just a per-database dump
$dumpall = ($_REQUEST['subject'] == 'server');
// Check that database dumps are enabled.
if ($misc->isDumpEnabled($dumpall)) {
$server_info = $misc->getServerInfo();
// Get the path of the pg_dump/pg_dumpall executable
$exe = $misc->escapeShellCmd($server_info[$dumpall ? 'pg_dumpall_path' : 'pg_dump_path']);
// Obtain the pg_dump version number and check if the path is good
$version = array();
preg_match("/(\d+(?:\.\d+)?)(?:\.\d+)?.*$/", exec($exe . " --version"), $version);
if (empty($version)) {
if ($dumpall)
printf($lang['strbadpgdumpallpath'], $server_info['pg_dumpall_path']);
else
printf($lang['strbadpgdumppath'], $server_info['pg_dump_path']);
exit;
}
// Make it do a download, if necessary
switch($_REQUEST['output']){
case 'show':
header('Content-Type: text/plain');
break;
case 'download':
// Set headers. MSIE is totally broken for SSL downloading, so
// we need to have it download in-place as plain text
if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS'])) {
header('Content-Type: text/plain');
}
else {
header('Content-Type: application/download');
header('Content-Disposition: attachment; filename=dump.sql');
}
break;
case 'gzipped':
// MSIE in SSL mode cannot do this - it should never get to this point
header('Content-Type: application/download');
header('Content-Disposition: attachment; filename=dump.sql.gz');
break;
}
// Set environmental variables that pg_dump uses
putenv('PGPASSWORD=' . $server_info['password']);
putenv('PGUSER=' . $server_info['username']);
$hostname = $server_info['host'];
if ($hostname !== null && $hostname != '') {
putenv('PGHOST=' . $hostname);
}
$port = $server_info['port'];
if ($port !== null && $port != '') {
putenv('PGPORT=' . $port);
}
// Build command for executing pg_dump. '-i' means ignore version differences.
$cmd = $exe . " -i";
// we are PG 7.4+, so we always have a schema
if (isset($_REQUEST['schema'])) {
$f_schema = $_REQUEST['schema'];
$data->fieldClean($f_schema);
}
// Check for a specified table/view
switch ($_REQUEST['subject']) {
case 'schema':
// This currently works for 8.2+ (due to the orthoganl -t -n issue introduced then)
$cmd .= " -n " . $misc->escapeShellArg("\"{$f_schema}\"");
break;
case 'table':
case 'view':
$f_object = $_REQUEST[$_REQUEST['subject']];
$data->fieldClean($f_object);
// Starting in 8.2, -n and -t are orthagonal, so we now schema qualify
// the table name in the -t argument and quote both identifiers
if ( ((float) $version[1]) >= 8.2 ) {
$cmd .= " -t " . $misc->escapeShellArg("\"{$f_schema}\".\"{$f_object}\"");
}
else {
// If we are 7.4 or higher, assume they are using 7.4 pg_dump and
// set dump schema as well. Also, mixed case dumping has been fixed
// then..
$cmd .= " -t " . $misc->escapeShellArg($f_object)
. " -n " . $misc->escapeShellArg($f_schema);
}
}
// Check for GZIP compression specified
if ($_REQUEST['output'] == 'gzipped' && !$dumpall) {
$cmd .= " -Z 9";
}
switch ($_REQUEST['what']) {
case 'dataonly':
$cmd .= ' -a';
if ($_REQUEST['d_format'] == 'sql') $cmd .= ' --inserts';
elseif (isset($_REQUEST['d_oids'])) $cmd .= ' -o';
break;
case 'structureonly':
$cmd .= ' -s';
if (isset($_REQUEST['s_clean'])) $cmd .= ' -c';
break;
case 'structureanddata':
if ($_REQUEST['sd_format'] == 'sql') $cmd .= ' --inserts';
elseif (isset($_REQUEST['sd_oids'])) $cmd .= ' -o';
if (isset($_REQUEST['sd_clean'])) $cmd .= ' -c';
break;
}
if (!$dumpall) {
putenv('PGDATABASE=' . $_REQUEST['database']);
}
// Execute command and return the output to the screen
passthru($cmd);
}
?>

663
php/pgadmin/display.php Normal file
View File

@ -0,0 +1,663 @@
<?php
/**
* Common relation browsing function that can be used for views,
* tables, reports, arbitrary queries, etc. to avoid code duplication.
* @param $query The SQL SELECT string to execute
* @param $count The same SQL query, but only retrieves the count of the rows (AS total)
* @param $return_url The return URL
* @param $return_desc The return link name
* @param $page The current page
*
* $Id: display.php,v 1.68 2008/04/14 12:44:27 ioguix Exp $
*/
// Prevent timeouts on large exports (non-safe mode only)
if (!ini_get('safe_mode')) set_time_limit(0);
// Include application functions
include_once('./libraries/lib.inc.php');
global $conf, $lang;
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
/**
* Show confirmation of edit and perform actual update
*/
function doEditRow($confirm, $msg = '') {
global $data, $misc, $conf;
global $lang;
if (is_array($_REQUEST['key']))
$key = $_REQUEST['key'];
else
$key = unserialize($_REQUEST['key']);
if ($confirm) {
$misc->printTrail($_REQUEST['subject']);
$misc->printTitle($lang['streditrow']);
$misc->printMsg($msg);
$attrs = $data->getTableAttributes($_REQUEST['table']);
$rs = $data->browseRow($_REQUEST['table'], $key);
if (($conf['autocomplete'] != 'disable')) {
$fksprops = $misc->getAutocompleteFKProperties($_REQUEST['table']);
if ($fksprops !== false)
echo $fksprops['code'];
}
else $fksprops = false;
echo "<form action=\"display.php\" method=\"post\" id=\"ac_form\">\n";
$elements = 0;
$error = true;
if ($rs->recordCount() == 1 && $attrs->recordCount() > 0) {
echo "<table>\n";
// Output table header
echo "<tr><th class=\"data\">{$lang['strcolumn']}</th><th class=\"data\">{$lang['strtype']}</th>";
echo "<th class=\"data\">{$lang['strformat']}</th>\n";
echo "<th class=\"data\">{$lang['strnull']}</th><th class=\"data\">{$lang['strvalue']}</th></tr>";
$i = 0;
while (!$attrs->EOF) {
$attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
$id = (($i % 2) == 0 ? '1' : '2');
// Initialise variables
if (!isset($_REQUEST['format'][$attrs->fields['attname']]))
$_REQUEST['format'][$attrs->fields['attname']] = 'VALUE';
echo "<tr class=\"data{$id}\">\n";
echo "<td style=\"white-space:nowrap;\">", $misc->printVal($attrs->fields['attname']), "</td>";
echo "<td style=\"white-space:nowrap;\">\n";
echo $misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod']));
echo "<input type=\"hidden\" name=\"types[", htmlspecialchars($attrs->fields['attname']), "]\" value=\"",
htmlspecialchars($attrs->fields['type']), "\" /></td>";
$elements++;
echo "<td style=\"white-space:nowrap;\">\n";
echo "<select name=\"format[", htmlspecialchars($attrs->fields['attname']), "]\">\n";
echo "<option value=\"VALUE\"", ($_REQUEST['format'][$attrs->fields['attname']] == 'VALUE') ? ' selected="selected"' : '', ">{$lang['strvalue']}</option>\n";
echo "<option value=\"EXPRESSION\"", ($_REQUEST['format'][$attrs->fields['attname']] == 'EXPRESSION') ? ' selected="selected"' : '', ">{$lang['strexpression']}</option>\n";
echo "</select>\n</td>\n";
$elements++;
echo "<td style=\"white-space:nowrap;\">";
// Output null box if the column allows nulls (doesn't look at CHECKs or ASSERTIONS)
if (!$attrs->fields['attnotnull']) {
// Set initial null values
if ($_REQUEST['action'] == 'confeditrow' && $rs->fields[$attrs->fields['attname']] === null) {
$_REQUEST['nulls'][$attrs->fields['attname']] = 'on';
}
echo "<input type=\"checkbox\" name=\"nulls[{$attrs->fields['attname']}]\"",
isset($_REQUEST['nulls'][$attrs->fields['attname']]) ? ' checked="checked"' : '', " /></td>\n";
$elements++;
}
else
echo "&nbsp;</td>";
echo "<td id=\"row_att_{$attrs->fields['attnum']}\" style=\"white-space:nowrap;\">";
$extras = array();
// If the column allows nulls, then we put a JavaScript action on the data field to unset the
// NULL checkbox as soon as anything is entered in the field. We use the $elements variable to
// keep track of which element offset we're up to. We can't refer to the null checkbox by name
// as it contains '[' and ']' characters.
if (!$attrs->fields['attnotnull']) {
$extras['onChange'] = 'elements[' . ($elements - 1) . '].checked = false;';
}
if (($fksprops !== false) && isset($fksprops['byfield'][$attrs->fields['attnum']])) {
$extras['id'] = "attr_{$attrs->fields['attnum']}";
$extras['autocomplete'] = 'off';
}
echo $data->printField("values[{$attrs->fields['attname']}]", $rs->fields[$attrs->fields['attname']], $attrs->fields['type'], $extras);
echo "</td>";
$elements++;
echo "</tr>\n";
$i++;
$attrs->moveNext();
}
echo "</table>\n";
$error = false;
}
elseif ($rs->recordCount() != 1) {
echo "<p>{$lang['strrownotunique']}</p>\n";
}
else {
echo "<p>{$lang['strinvalidparam']}</p>\n";
}
echo "<input type=\"hidden\" name=\"action\" value=\"editrow\" />\n";
echo $misc->form;
if (isset($_REQUEST['table']))
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
if (isset($_REQUEST['subject']))
echo "<input type=\"hidden\" name=\"subject\" value=\"", htmlspecialchars($_REQUEST['subject']), "\" />\n";
if (isset($_REQUEST['query']))
echo "<input type=\"hidden\" name=\"query\" value=\"", htmlspecialchars($_REQUEST['query']), "\" />\n";
if (isset($_REQUEST['count']))
echo "<input type=\"hidden\" name=\"count\" value=\"", htmlspecialchars($_REQUEST['count']), "\" />\n";
if (isset($_REQUEST['return_url']))
echo "<input type=\"hidden\" name=\"return_url\" value=\"", htmlspecialchars($_REQUEST['return_url']), "\" />\n";
if (isset($_REQUEST['return_desc']))
echo "<input type=\"hidden\" name=\"return_desc\" value=\"", htmlspecialchars($_REQUEST['return_desc']), "\" />\n";
echo "<input type=\"hidden\" name=\"page\" value=\"", htmlspecialchars($_REQUEST['page']), "\" />\n";
echo "<input type=\"hidden\" name=\"sortkey\" value=\"", htmlspecialchars($_REQUEST['sortkey']), "\" />\n";
echo "<input type=\"hidden\" name=\"sortdir\" value=\"", htmlspecialchars($_REQUEST['sortdir']), "\" />\n";
echo "<input type=\"hidden\" name=\"strings\" value=\"", htmlspecialchars($_REQUEST['strings']), "\" />\n";
echo "<input type=\"hidden\" name=\"key\" value=\"", htmlspecialchars(serialize($key)), "\" />\n";
echo "<p>";
if (!$error) echo "<input type=\"submit\" name=\"save\" value=\"{$lang['strsave']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
if($fksprops !== false) {
if ($conf['autocomplete'] != 'default off')
echo "<input type=\"checkbox\" id=\"no_ac\" value=\"1\" checked=\"checked\" /><label for=\"no_ac\">{$lang['strac']}</label>\n";
else
echo "<input type=\"checkbox\" id=\"no_ac\" value=\"0\" /><label for=\"no_ac\">{$lang['strac']}</label>\n";
}
echo "</p>\n";
echo "</form>\n";
}
else {
if (!isset($_POST['values'])) $_POST['values'] = array();
if (!isset($_POST['nulls'])) $_POST['nulls'] = array();
$status = $data->editRow($_POST['table'], $_POST['values'], $_POST['nulls'],
$_POST['format'], $_POST['types'], unserialize($_POST['key']));
if ($status == 0)
doBrowse($lang['strrowupdated']);
elseif ($status == -2)
doEditRow(true, $lang['strrownotunique']);
else
doEditRow(true, $lang['strrowupdatedbad']);
}
}
/**
* Show confirmation of drop and perform actual drop
*/
function doDelRow($confirm) {
global $data, $misc;
global $lang;
if ($confirm) {
$misc->printTrail($_REQUEST['subject']);
$misc->printTitle($lang['strdeleterow']);
echo "<p>{$lang['strconfdeleterow']}</p>\n";
echo "<form action=\"display.php\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"delrow\" />\n";
echo $misc->form;
if (isset($_REQUEST['table']))
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
if (isset($_REQUEST['subject']))
echo "<input type=\"hidden\" name=\"subject\" value=\"", htmlspecialchars($_REQUEST['subject']), "\" />\n";
if (isset($_REQUEST['query']))
echo "<input type=\"hidden\" name=\"query\" value=\"", htmlspecialchars($_REQUEST['query']), "\" />\n";
if (isset($_REQUEST['count']))
echo "<input type=\"hidden\" name=\"count\" value=\"", htmlspecialchars($_REQUEST['count']), "\" />\n";
if (isset($_REQUEST['return_url']))
echo "<input type=\"hidden\" name=\"return_url\" value=\"", htmlspecialchars($_REQUEST['return_url']), "\" />\n";
if (isset($_REQUEST['return_desc']))
echo "<input type=\"hidden\" name=\"return_desc\" value=\"", htmlspecialchars($_REQUEST['return_desc']), "\" />\n";
echo "<input type=\"hidden\" name=\"page\" value=\"", htmlspecialchars($_REQUEST['page']), "\" />\n";
echo "<input type=\"hidden\" name=\"sortkey\" value=\"", htmlspecialchars($_REQUEST['sortkey']), "\" />\n";
echo "<input type=\"hidden\" name=\"sortdir\" value=\"", htmlspecialchars($_REQUEST['sortdir']), "\" />\n";
echo "<input type=\"hidden\" name=\"strings\" value=\"", htmlspecialchars($_REQUEST['strings']), "\" />\n";
echo "<input type=\"hidden\" name=\"key\" value=\"", htmlspecialchars(serialize($_REQUEST['key'])), "\" />\n";
echo "<input type=\"submit\" name=\"yes\" value=\"{$lang['stryes']}\" />\n";
echo "<input type=\"submit\" name=\"no\" value=\"{$lang['strno']}\" />\n";
echo "</form>\n";
}
else {
$status = $data->deleteRow($_POST['table'], unserialize($_POST['key']));
if ($status == 0)
doBrowse($lang['strrowdeleted']);
elseif ($status == -2)
doBrowse($lang['strrownotunique']);
else
doBrowse($lang['strrowdeletedbad']);
}
}
/* build & return the FK information data structure
* used when deciding if a field should have a FK link or not*/
function &getFKInfo() {
global $data, $misc, $lang;
// Get the foreign key(s) information from the current table
$fkey_information = array('byconstr' => array(), 'byfield' => array());
if (isset($_REQUEST['table'])) {
$constraints = $data->getConstraintsWithFields($_REQUEST['table']);
if ($constraints->recordCount() > 0) {
/* build the common parts of the url for the FK */
$fk_return_url = "{$misc->href}&amp;subject=table&amp;table=". urlencode($_REQUEST['table']);
if (isset($_REQUEST['page'])) $fk_return_url .= "&amp;page=" . urlencode($_REQUEST['page']);
if (isset($_REQUEST['query'])) $fk_return_url .= "&amp;query=" . urlencode($_REQUEST['query']);
if (isset($_REQUEST['search_path'])) $fk_return_url .= "&amp;search_path=" . urlencode($_REQUEST['search_path']);
/* yes, we double urlencode fk_return_url so parameters here don't
* overwrite real one when included in the final url */
$fkey_information['common_url'] = $misc->getHREF('schema') .'&amp;subject=table&amp;return_url=display.php?'
. urlencode($fk_return_url) .'&amp;return_desc='. urlencode($lang['strback']);
/* build the FK constraints data structure */
while (!$constraints->EOF) {
$constr =& $constraints->fields;
if ($constr['contype'] == 'f') {
if (!isset($fkey_information['byconstr'][$constr['conid']])) {
$fkey_information['byconstr'][$constr['conid']] = array (
'url_data' => 'table='. urlencode($constr['f_table']) .'&amp;schema='. urlencode($constr['f_schema']),
'fkeys' => array(),
'consrc' => $constr['consrc']
);
}
$fkey_information['byconstr'][$constr['conid']]['fkeys'][$constr['p_field']] = $constr['f_field'];
if (!isset($fkey_information['byfield'][$constr['p_field']]))
$fkey_information['byfield'][$constr['p_field']] = array();
$fkey_information['byfield'][$constr['p_field']][] = $constr['conid'];
}
$constraints->moveNext();
}
}
}
return $fkey_information;
}
/* Print table header cells
* @param $sortLink must be urlencoded already
* */
function printTableHeaderCells(&$rs, $sortLink, $withOid) {
global $misc, $data, $conf;
$j = 0;
foreach ($rs->fields as $k => $v) {
if (($k === $data->id) && ( !($withOid && $conf['show_oids']) )) {
$j++;
continue;
}
$finfo = $rs->fetchField($j);
if ($sortLink === false) {
echo "<th class=\"data\">", $misc->printVal($finfo->name), "</th>\n";
}
else {
echo "<th class=\"data\"><a href=\"display.php?{$sortLink}&amp;sortkey=", ($j + 1), "&amp;sortdir=";
// Sort direction opposite to current direction, unless it's currently ''
echo ($_REQUEST['sortdir'] == 'asc' && $_REQUEST['sortkey'] == ($j + 1)) ? 'desc' : 'asc';
echo "&amp;strings=", urlencode($_REQUEST['strings']),
"&amp;page=" . urlencode($_REQUEST['page']), "\">",
$misc->printVal($finfo->name), "</a></th>\n";
}
$j++;
}
reset($rs->fields);
}
/* Print data-row cells */
function printTableRowCells(&$rs, &$fkey_information, $withOid) {
global $data, $misc, $conf;
$j = 0;
if (!isset($_REQUEST['strings'])) $_REQUEST['strings'] = 'collapsed';
foreach ($rs->fields as $k => $v) {
$finfo = $rs->fetchField($j++);
if (($k === $data->id) && ( !($withOid && $conf['show_oids']) )) continue;
elseif ($v !== null && $v == '') echo "<td>&nbsp;</td>";
else {
echo "<td style=\"white-space:nowrap;\">";
if (($v !== null) && isset($fkey_information['byfield'][$k])) {
foreach ($fkey_information['byfield'][$k] as $conid) {
$query_params = $fkey_information['byconstr'][$conid]['url_data'];
foreach ($fkey_information['byconstr'][$conid]['fkeys'] as $p_field => $f_field) {
$query_params .= '&amp;'. urlencode("fkey[{$f_field}]") .'='. urlencode($rs->fields[$p_field]);
}
/* $fkey_information['common_url'] is already urlencoded */
$query_params .= '&amp;'. $fkey_information['common_url'];
echo "<div style=\"display:inline-block;\">";
echo "<a class=\"fk fk_". htmlentities($conid) ."\" href=\"display.php?{$query_params}\">";
echo "<img src=\"".$misc->icon('ForeignKey')."\" style=\"vertical-align:middle;\" alt=\"[fk]\" title=\""
. htmlentities($fkey_information['byconstr'][$conid]['consrc'])
."\" />";
echo "</a>";
echo "</div>";
}
echo $misc->printVal($v, $finfo->type, array('null' => true, 'clip' => ($_REQUEST['strings']=='collapsed'), 'class' => 'fk_value'));
} else {
echo $misc->printVal($v, $finfo->type, array('null' => true, 'clip' => ($_REQUEST['strings']=='collapsed')));
}
echo "</td>";
}
}
}
/* Print the FK row, used in ajax requests */
function doBrowseFK() {
global $data, $misc, $lang;
$ops = array();
foreach($_REQUEST['fkey'] as $x => $y) {
$ops[$x] = '=';
}
$query = $data->getSelectSQL($_REQUEST['table'], array(), $_REQUEST['fkey'], $ops);
$_REQUEST['query'] = $query;
$fkinfo =& getFKInfo();
$max_pages = 1;
// Retrieve page from query. $max_pages is returned by reference.
$rs = $data->browseQuery('SELECT', $_REQUEST['table'], $_REQUEST['query'],
null, null, 1, 1, $max_pages);
echo "<a href=\"\" style=\"display:table-cell;\" class=\"fk_delete\"><img alt=\"[delete]\" src=\"". $misc->icon('Delete') ."\" /></a>\n";
echo "<div style=\"display:table-cell;\">";
if (is_object($rs) && $rs->recordCount() > 0) {
/* we are browsing a referenced table here
* we should show OID if show_oids is true
* so we give true to withOid in functions bellow
* as 3rd paramter */
echo "<table><tr>";
printTableHeaderCells($rs, false, true);
echo "</tr>";
echo "<tr class=\"data1\">\n";
printTableRowCells($rs, $fkinfo, true);
echo "</tr>\n";
echo "</table>\n";
}
else
echo $lang['strnodata'];
echo "</div>";
exit;
}
/**
* Displays requested data
*/
function doBrowse($msg = '') {
global $data, $conf, $misc, $lang;
$save_history = false;
// If current page is not set, default to first page
if (!isset($_REQUEST['page']))
$_REQUEST['page'] = 1;
if (!isset($_REQUEST['nohistory']))
$save_history = true;
if (isset($_REQUEST['subject'])) {
$subject = $_REQUEST['subject'];
if (isset($_REQUEST[$subject])) $object = $_REQUEST[$subject];
}
else {
$subject = '';
}
$misc->printTrail(isset($subject) ? $subject : 'database');
/* This code is used when browsing FK in pure-xHTML (without js) */
if (isset($_REQUEST['fkey'])) {
$ops = array();
foreach($_REQUEST['fkey'] as $x => $y) {
$ops[$x] = '=';
}
$query = $data->getSelectSQL($_REQUEST['table'], array(), $_REQUEST['fkey'], $ops);
$_REQUEST['query'] = $query;
}
if (isset($object)) {
if (isset($_REQUEST['query'])) {
$_SESSION['sqlquery'] = $_REQUEST['query'];
$misc->printTitle($lang['strselect']);
$type = 'SELECT';
} else {
$misc->printTitle($lang['strbrowse']);
$type = 'TABLE';
}
} else {
$misc->printTitle($lang['strqueryresults']);
$type = 'QUERY';
}
$misc->printMsg($msg);
// If 'sortkey' is not set, default to ''
if (!isset($_REQUEST['sortkey'])) $_REQUEST['sortkey'] = '';
// If 'sortdir' is not set, default to ''
if (!isset($_REQUEST['sortdir'])) $_REQUEST['sortdir'] = '';
// If 'strings' is not set, default to collapsed
if (!isset($_REQUEST['strings'])) $_REQUEST['strings'] = 'collapsed';
// Fetch unique row identifier, if this is a table browse request.
if (isset($object))
$key = $data->getRowIdentifier($object);
else
$key = array();
// Set the schema search path
if (isset($_REQUEST['search_path'])) {
if ($data->setSearchPath(array_map('trim',explode(',',$_REQUEST['search_path']))) != 0) {
return;
}
}
// Retrieve page from query. $max_pages is returned by reference.
$rs = $data->browseQuery($type,
isset($object) ? $object : null,
isset($_REQUEST['query']) ? $_REQUEST['query'] : null,
$_REQUEST['sortkey'], $_REQUEST['sortdir'], $_REQUEST['page'],
$conf['max_rows'], $max_pages);
$fkey_information =& getFKInfo();
// Build strings for GETs
$gets = $misc->href;
if (isset($object)) $gets .= "&amp;" . urlencode($subject) . '=' . urlencode($object);
if (isset($subject)) $gets .= "&amp;subject=" . urlencode($subject);
if (isset($_REQUEST['query'])) $gets .= "&amp;query=" . urlencode($_REQUEST['query']);
if (isset($_REQUEST['count'])) $gets .= "&amp;count=" . urlencode($_REQUEST['count']);
if (isset($_REQUEST['return_url'])) $gets .= "&amp;return_url=" . urlencode($_REQUEST['return_url']);
if (isset($_REQUEST['return_desc'])) $gets .= "&amp;return_desc=" . urlencode($_REQUEST['return_desc']);
if (isset($_REQUEST['search_path'])) $gets .= "&amp;search_path=" . urlencode($_REQUEST['search_path']);
if (isset($_REQUEST['table'])) $gets .= "&amp;table=" . urlencode($_REQUEST['table']);
// This string just contains sort info
$getsort = "sortkey=" . urlencode($_REQUEST['sortkey']) .
"&amp;sortdir=" . urlencode($_REQUEST['sortdir']);
if ($save_history && is_object($rs) && ($type == 'QUERY')) //{
$misc->saveScriptHistory($_REQUEST['query']);
if (is_object($rs) && $rs->recordCount() > 0) {
// Show page navigation
$misc->printPages($_REQUEST['page'], $max_pages, "display.php?page=%s&amp;{$gets}&amp;{$getsort}&amp;nohistory=t&amp;strings=" . urlencode($_REQUEST['strings']));
echo "<table id=\"data\">\n<tr>";
// Check that the key is actually in the result set. This can occur for select
// operations where the key fields aren't part of the select. XXX: We should
// be able to support this, somehow.
foreach ($key as $v) {
// If a key column is not found in the record set, then we
// can't use the key.
if (!in_array($v, array_keys($rs->fields))) {
$key = array();
break;
}
}
// Display edit and delete actions if we have a key
if (sizeof($key) > 0)
echo "<th colspan=\"2\" class=\"data\">{$lang['stractions']}</th>\n";
/* we show OIDs only if we are in TABLE or SELECT type browsing */
printTableHeaderCells($rs, $gets, isset($object));
echo "</tr>\n";
$i = 0;
reset($rs->fields);
while (!$rs->EOF) {
$id = (($i % 2) == 0 ? '1' : '2');
echo "<tr class=\"data{$id}\">\n";
// Display edit and delete links if we have a key
if (sizeof($key) > 0) {
$key_str = '';
$has_nulls = false;
foreach ($key as $v) {
if ($rs->fields[$v] === null) {
$has_nulls = true;
break;
}
if ($key_str != '') $key_str .= '&amp;';
$key_str .= urlencode("key[{$v}]") . '=' . urlencode($rs->fields[$v]);
}
if ($has_nulls) {
echo "<td colspan=\"2\">&nbsp;</td>\n";
} else {
echo "<td class=\"opbutton{$id}\"><a href=\"display.php?action=confeditrow&amp;strings=",
urlencode($_REQUEST['strings']), "&amp;page=",
urlencode($_REQUEST['page']), "&amp;{$key_str}&amp;{$gets}&amp;{$getsort}\">{$lang['stredit']}</a></td>\n";
echo "<td class=\"opbutton{$id}\"><a href=\"display.php?action=confdelrow&amp;strings=",
urlencode($_REQUEST['strings']), "&amp;page=",
urlencode($_REQUEST['page']), "&amp;{$key_str}&amp;{$gets}&amp;{$getsort}\">{$lang['strdelete']}</a></td>\n";
}
}
print printTableRowCells($rs, $fkey_information, isset($object));
echo "</tr>\n";
$rs->moveNext();
$i++;
}
echo "</table>\n";
echo "<p>", $rs->recordCount(), " {$lang['strrows']}</p>\n";
// Show page navigation
$misc->printPages($_REQUEST['page'], $max_pages, "display.php?page=%s&amp;{$gets}&amp;{$getsort}&amp;strings=" . urlencode($_REQUEST['strings']));
}
else echo "<p>{$lang['strnodata']}</p>\n";
// Navigation links
echo "<ul class=\"navlink\">\n";
// Return
if (isset($_REQUEST['return_url']) && isset($_REQUEST['return_desc']))
echo "\t<li><a href=\"{$_REQUEST['return_url']}\">{$_REQUEST['return_desc']}</a></li>\n";
// Edit SQL link
if (isset($_REQUEST['query']))
echo "\t<li><a href=\"database.php?{$misc->href}&amp;action=sql&amp;paginate=on&amp;query=",
urlencode($_REQUEST['query']), "\">{$lang['streditsql']}</a></li>\n";
// Expand/Collapse
if ($_REQUEST['strings'] == 'expanded')
echo "\t<li><a href=\"display.php?{$gets}&amp;{$getsort}&amp;strings=collapsed&amp;page=",
urlencode($_REQUEST['page']), "\">{$lang['strcollapse']}</a></li>\n";
else
echo "\t<li><a href=\"display.php?{$gets}&amp;{$getsort}&amp;strings=expanded&amp;page=",
urlencode($_REQUEST['page']), "\">{$lang['strexpand']}</a></li>\n";
// Create report
if (isset($_REQUEST['query']) && ($subject !== 'report') && $conf['show_reports'] && isset($rs) && is_object($rs) && $rs->recordCount() > 0)
echo "\t<li><a href=\"reports.php?{$misc->href}&amp;action=create&amp;report_sql=",
urlencode($_REQUEST['query']), "&amp;paginate=", (isset($_REQUEST['paginate'])? urlencode($_REQUEST['paginate']):'f'), "\">{$lang['strcreatereport']}</a></li>\n";
// Create view and download
if (isset($_REQUEST['query']) && isset($rs) && is_object($rs) && $rs->recordCount() > 0) {
// Report views don't set a schema, so we need to disable create view in that case
if (isset($_REQUEST['schema']))
echo "\t<li><a href=\"views.php?action=create&amp;formDefinition=",
urlencode($_REQUEST['query']), "&amp;{$misc->href}\">{$lang['strcreateview']}</a></li>\n";
echo "\t<li><a href=\"dataexport.php?query=", urlencode($_REQUEST['query']);
if (isset($_REQUEST['search_path']))
echo "&amp;search_path=", urlencode($_REQUEST['search_path']);
echo "&amp;{$misc->href}\">{$lang['strdownload']}</a></li>\n";
}
// Insert
if (isset($object) && (isset($subject) && $subject == 'table'))
echo "\t<li><a href=\"tables.php?action=confinsertrow&amp;table=",
urlencode($object), "&amp;{$misc->href}\">{$lang['strinsert']}</a></li>\n";
// Refresh
echo "\t<li><a href=\"display.php?{$gets}&amp;{$getsort}&amp;strings=", urlencode($_REQUEST['strings']),
"&amp;page=" . urlencode($_REQUEST['page']),
"\">{$lang['strrefresh']}</a></li>\n";
echo "</ul>\n";
}
/* shortcuts: this function exit the script for ajax purpose */
if ($action == 'dobrowsefk') {
doBrowseFK();
}
$scripts = "<script src=\"libraries/js/jquery.js\" type=\"text/javascript\"></script>\n";
$scripts .= "<script src=\"js/display.js\" type=\"text/javascript\"></script>";
$scripts .= "<script type=\"text/javascript\">\n";
$scripts .= "var Display = {\n";
$scripts .= "errmsg: '". str_replace("'", "\'", $lang['strconnectionfail']) ."'\n";
$scripts .= "};\n";
$scripts .= "</script>\n";
// If a table is specified, then set the title differently
if (isset($_REQUEST['subject']) && isset($_REQUEST[$_REQUEST['subject']]))
$misc->printHeader($lang['strtables'], $scripts);
else
$misc->printHeader($lang['strqueryresults']);
$misc->printBody();
switch ($action) {
case 'editrow':
if (isset($_POST['save'])) doEditRow(false);
else doBrowse();
break;
case 'confeditrow':
doEditRow(true);
break;
case 'delrow':
if (isset($_POST['yes'])) doDelRow(false);
else doBrowse();
break;
case 'confdelrow':
doDelRow(true);
break;
default:
doBrowse();
break;
}
$misc->printFooter();
?>

503
php/pgadmin/domains.php Normal file
View File

@ -0,0 +1,503 @@
<?php
/**
* Manage domains in a database
*
* $Id: domains.php,v 1.34 2007/09/13 13:41:01 ioguix Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (!isset($msg)) $msg = '';
/**
* Function to save after altering a domain
*/
function doSaveAlter() {
global $data, $lang;
$status = $data->alterDomain($_POST['domain'], $_POST['domdefault'],
isset($_POST['domnotnull']), $_POST['domowner']);
if ($status == 0)
doProperties($lang['strdomainaltered']);
else
doAlter($lang['strdomainalteredbad']);
}
/**
* Allow altering a domain
*/
function doAlter($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('domain');
$misc->printTitle($lang['stralter'],'pg.domain.alter');
$misc->printMsg($msg);
// Fetch domain info
$domaindata = $data->getDomain($_REQUEST['domain']);
// Fetch all users
$users = $data->getUsers();
if ($domaindata->recordCount() > 0) {
if (!isset($_POST['domname'])) {
$_POST['domtype'] = $domaindata->fields['domtype'];
$_POST['domdefault'] = $domaindata->fields['domdef'];
$domaindata->fields['domnotnull'] = $data->phpBool($domaindata->fields['domnotnull']);
if ($domaindata->fields['domnotnull']) $_POST['domnotnull'] = 'on';
$_POST['domowner'] = $domaindata->fields['domowner'];
}
// Display domain info
echo "<form action=\"domains.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data left required\" style=\"width: 70px\">{$lang['strname']}</th>\n";
echo "<td class=\"data1\">", $misc->printVal($domaindata->fields['domname']), "</td></tr>\n";
echo "<tr><th class=\"data left required\">{$lang['strtype']}</th>\n";
echo "<td class=\"data1\">", $misc->printVal($domaindata->fields['domtype']), "</td></tr>\n";
echo "<tr><th class=\"data left\"><label for=\"domnotnull\">{$lang['strnotnull']}</label></th>\n";
echo "<td class=\"data1\"><input type=\"checkbox\" id=\"domnotnull\" name=\"domnotnull\"", (isset($_POST['domnotnull']) ? ' checked="checked"' : ''), " /></td></tr>\n";
echo "<tr><th class=\"data left\">{$lang['strdefault']}</th>\n";
echo "<td class=\"data1\"><input name=\"domdefault\" size=\"32\" value=\"",
htmlspecialchars($_POST['domdefault']), "\" /></td></tr>\n";
echo "<tr><th class=\"data left required\">{$lang['strowner']}</th>\n";
echo "<td class=\"data1\"><select name=\"domowner\">";
while (!$users->EOF) {
$uname = $users->fields['usename'];
echo "<option value=\"", htmlspecialchars($uname), "\"",
($uname == $_POST['domowner']) ? ' selected="selected"' : '', ">", htmlspecialchars($uname), "</option>\n";
$users->moveNext();
}
echo "</select></td></tr>\n";
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_alter\" />\n";
echo "<input type=\"hidden\" name=\"domain\" value=\"", htmlspecialchars($_REQUEST['domain']), "\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"alter\" value=\"{$lang['stralter']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
else echo "<p>{$lang['strnodata']}</p>\n";
}
/**
* Confirm and then actually add a CHECK constraint
*/
function addCheck($confirm, $msg = '') {
global $data, $misc;
global $lang;
if (!isset($_POST['name'])) $_POST['name'] = '';
if (!isset($_POST['definition'])) $_POST['definition'] = '';
if ($confirm) {
$misc->printTrail('domain');
$misc->printTitle($lang['straddcheck'],'pg.constraint.check');
$misc->printMsg($msg);
echo "<form action=\"domains.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data\">{$lang['strname']}</th>\n";
echo "<th class=\"data required\">{$lang['strdefinition']}</th></tr>\n";
echo "<tr><td class=\"data1\"><input name=\"name\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_POST['name']), "\" /></td>\n";
echo "<td class=\"data1\">(<input name=\"definition\" size=\"32\" value=\"",
htmlspecialchars($_POST['definition']), "\" />)</td></tr>\n";
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_add_check\" />\n";
echo "<input type=\"hidden\" name=\"domain\" value=\"", htmlspecialchars($_REQUEST['domain']), "\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"add\" value=\"{$lang['stradd']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
else {
if (trim($_POST['definition']) == '')
addCheck(true, $lang['strcheckneedsdefinition']);
else {
$status = $data->addDomainCheckConstraint($_POST['domain'],
$_POST['definition'], $_POST['name']);
if ($status == 0)
doProperties($lang['strcheckadded']);
else
addCheck(true, $lang['strcheckaddedbad']);
}
}
}
/**
* Show confirmation of drop constraint and perform actual drop
*/
function doDropConstraint($confirm, $msg = '') {
global $data, $misc;
global $lang;
if ($confirm) {
$misc->printTrail('domain');
$misc->printTitle($lang['strdrop'],'pg.constraint.drop');
$misc->printMsg($msg);
echo "<p>", sprintf($lang['strconfdropconstraint'], $misc->printVal($_REQUEST['constraint']),
$misc->printVal($_REQUEST['domain'])), "</p>\n";
echo "<form action=\"domains.php\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"drop_con\" />\n";
echo "<input type=\"hidden\" name=\"domain\" value=\"", htmlspecialchars($_REQUEST['domain']), "\" />\n";
echo "<input type=\"hidden\" name=\"constraint\" value=\"", htmlspecialchars($_REQUEST['constraint']), "\" />\n";
echo $misc->form;
echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
}
else {
$status = $data->dropDomainConstraint($_POST['domain'], $_POST['constraint'], isset($_POST['cascade']));
if ($status == 0)
doProperties($lang['strconstraintdropped']);
else
doDropConstraint(true, $lang['strconstraintdroppedbad']);
}
}
/**
* Show properties for a domain. Allow manipulating constraints as well.
*/
function doProperties($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('domain');
$misc->printTitle($lang['strproperties'],'pg.domain');
$misc->printMsg($msg);
$domaindata = $data->getDomain($_REQUEST['domain']);
if ($domaindata->recordCount() > 0) {
// Show comment if any
if ($domaindata->fields['domcomment'] !== null)
echo "<p class=\"comment\">", $misc->printVal($domaindata->fields['domcomment']), "</p>\n";
// Display domain info
$domaindata->fields['domnotnull'] = $data->phpBool($domaindata->fields['domnotnull']);
echo "<table>\n";
echo "<tr><th class=\"data left\" style=\"width: 70px\">{$lang['strname']}</th>\n";
echo "<td class=\"data1\">", $misc->printVal($domaindata->fields['domname']), "</td></tr>\n";
echo "<tr><th class=\"data left\">{$lang['strtype']}</th>\n";
echo "<td class=\"data1\">", $misc->printVal($domaindata->fields['domtype']), "</td></tr>\n";
echo "<tr><th class=\"data left\">{$lang['strnotnull']}</th>\n";
echo "<td class=\"data1\">", ($domaindata->fields['domnotnull'] ? 'NOT NULL' : ''), "</td></tr>\n";
echo "<tr><th class=\"data left\">{$lang['strdefault']}</th>\n";
echo "<td class=\"data1\">", $misc->printVal($domaindata->fields['domdef']), "</td></tr>\n";
echo "<tr><th class=\"data left\">{$lang['strowner']}</th>\n";
echo "<td class=\"data1\">", $misc->printVal($domaindata->fields['domowner']), "</td></tr>\n";
echo "</table>\n";
// Display domain constraints
if ($data->hasDomainConstraints()) {
$domaincons = $data->getDomainConstraints($_REQUEST['domain']);
if ($domaincons->recordCount() > 0) {
echo "<h3>{$lang['strconstraints']}</h3>\n";
echo "<table>\n";
echo "<tr><th class=\"data\">{$lang['strname']}</th><th class=\"data\">{$lang['strdefinition']}</th><th class=\"data\">{$lang['stractions']}</th>\n";
$i = 0;
while (!$domaincons->EOF) {
$id = (($i % 2 ) == 0 ? '1' : '2');
echo "<tr class=\"data{$id}\"><td>", $misc->printVal($domaincons->fields['conname']), "</td>";
echo "<td>";
echo $misc->printVal($domaincons->fields['consrc']);
echo "</td>";
echo "<td class=\"opbutton{$id}\">";
echo "<a href=\"domains.php?action=confirm_drop_con&amp;{$misc->href}&amp;constraint=", urlencode($domaincons->fields['conname']),
"&amp;domain=", urlencode($_REQUEST['domain']), "&amp;type=", urlencode($domaincons->fields['contype']), "\">{$lang['strdrop']}</a></td></tr>\n";
$domaincons->moveNext();
$i++;
}
echo "</table>\n";
}
}
}
else echo "<p>{$lang['strnodata']}</p>\n";
echo "<ul class=\"navlink\">\n\t<li><a href=\"domains.php?action=confirm_drop&amp;{$misc->href}&amp;domain=", urlencode($_REQUEST['domain']),"\">{$lang['strdrop']}</a></li>\n";
if ($data->hasAlterDomains()) {
echo "\t<li><a href=\"domains.php?action=add_check&amp;{$misc->href}&amp;domain=", urlencode($_REQUEST['domain']),
"\">{$lang['straddcheck']}</a></li>\n";
echo "\t<li><a href=\"domains.php?action=alter&amp;{$misc->href}&amp;domain=",
urlencode($_REQUEST['domain']), "\">{$lang['stralter']}</a></li>\n";
}
echo "</ul>\n";
}
/**
* Show confirmation of drop and perform actual drop
*/
function doDrop($confirm) {
global $data, $misc;
global $lang;
if ($confirm) {
$misc->printTrail('domain');
$misc->printTitle($lang['strdrop'],'pg.domain.drop');
echo "<p>", sprintf($lang['strconfdropdomain'], $misc->printVal($_REQUEST['domain'])), "</p>\n";
echo "<form action=\"domains.php\" method=\"post\">\n";
echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /><label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"domain\" value=\"", htmlspecialchars($_REQUEST['domain']), "\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
else {
$status = $data->dropDomain($_POST['domain'], isset($_POST['cascade']));
if ($status == 0)
doDefault($lang['strdomaindropped']);
else
doDefault($lang['strdomaindroppedbad']);
}
}
/**
* Displays a screen where they can enter a new domain
*/
function doCreate($msg = '') {
global $data, $misc;
global $lang;
if (!isset($_POST['domname'])) $_POST['domname'] = '';
if (!isset($_POST['domtype'])) $_POST['domtype'] = '';
if (!isset($_POST['domlength'])) $_POST['domlength'] = '';
if (!isset($_POST['domarray'])) $_POST['domarray'] = '';
if (!isset($_POST['domdefault'])) $_POST['domdefault'] = '';
if (!isset($_POST['domcheck'])) $_POST['domcheck'] = '';
$types = $data->getTypes(true);
$misc->printTrail('schema');
$misc->printTitle($lang['strcreatedomain'],'pg.domain.create');
$misc->printMsg($msg);
echo "<form action=\"domains.php\" method=\"post\">\n";
echo "<table>\n";
echo "<tr><th class=\"data left required\" style=\"width: 70px\">{$lang['strname']}</th>\n";
echo "<td class=\"data1\"><input name=\"domname\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_POST['domname']), "\" /></td></tr>\n";
echo "<tr><th class=\"data left required\">{$lang['strtype']}</th>\n";
echo "<td class=\"data1\">\n";
// Output return type list
echo "<select name=\"domtype\">\n";
while (!$types->EOF) {
echo "<option value=\"", htmlspecialchars($types->fields['typname']), "\"",
($types->fields['typname'] == $_POST['domtype']) ? ' selected="selected"' : '', ">",
$misc->printVal($types->fields['typname']), "</option>\n";
$types->moveNext();
}
echo "</select>\n";
// Type length
echo "<input type=\"text\" size=\"4\" name=\"domlength\" value=\"", htmlspecialchars($_POST['domlength']), "\" />";
// Output array type selector
echo "<select name=\"domarray\">\n";
echo "<option value=\"\"", ($_POST['domarray'] == '') ? ' selected="selected"' : '', "></option>\n";
echo "<option value=\"[]\"", ($_POST['domarray'] == '[]') ? ' selected="selected"' : '', ">[ ]</option>\n";
echo "</select></td></tr>\n";
echo "<tr><th class=\"data left\"><label for=\"domnotnull\">{$lang['strnotnull']}</label></th>\n";
echo "<td class=\"data1\"><input type=\"checkbox\" id=\"domnotnull\" name=\"domnotnull\"",
(isset($_POST['domnotnull']) ? ' checked="checked"' : ''), " /></td></tr>\n";
echo "<tr><th class=\"data left\">{$lang['strdefault']}</th>\n";
echo "<td class=\"data1\"><input name=\"domdefault\" size=\"32\" value=\"",
htmlspecialchars($_POST['domdefault']), "\" /></td></tr>\n";
if ($data->hasDomainConstraints()) {
echo "<tr><th class=\"data left\">{$lang['strconstraints']}</th>\n";
echo "<td class=\"data1\">CHECK (<input name=\"domcheck\" size=\"32\" value=\"",
htmlspecialchars($_POST['domcheck']), "\" />)</td></tr>\n";
}
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
/**
* Actually creates the new domain in the database
*/
function doSaveCreate() {
global $data, $lang;
if (!isset($_POST['domcheck'])) $_POST['domcheck'] = '';
// Check that they've given a name and a definition
if ($_POST['domname'] == '') doCreate($lang['strdomainneedsname']);
else {
$status = $data->createDomain($_POST['domname'], $_POST['domtype'], $_POST['domlength'], $_POST['domarray'] != '',
isset($_POST['domnotnull']), $_POST['domdefault'], $_POST['domcheck']);
if ($status == 0)
doDefault($lang['strdomaincreated']);
else
doCreate($lang['strdomaincreatedbad']);
}
}
/**
* Show default list of domains in the database
*/
function doDefault($msg = '') {
global $data, $conf, $misc;
global $lang;
$misc->printTrail('schema');
$misc->printTabs('schema','domains');
$misc->printMsg($msg);
$domains = $data->getDomains();
$columns = array(
'domain' => array(
'title' => $lang['strdomain'],
'field' => field('domname'),
'url' => "domains.php?action=properties&amp;{$misc->href}&amp;",
'vars' => array('domain' => 'domname'),
),
'type' => array(
'title' => $lang['strtype'],
'field' => field('domtype'),
),
'notnull' => array(
'title' => $lang['strnotnull'],
'field' => field('domnotnull'),
'type' => 'bool',
'params'=> array('true' => 'NOT NULL', 'false' => ''),
),
'default' => array(
'title' => $lang['strdefault'],
'field' => field('domdef'),
),
'owner' => array(
'title' => $lang['strowner'],
'field' => field('domowner'),
),
'actions' => array(
'title' => $lang['stractions'],
),
'comment' => array(
'title' => $lang['strcomment'],
'field' => field('domcomment'),
),
);
$actions = array(
'alter' => array(
'title' => $lang['stralter'],
'url' => "domains.php?action=alter&amp;{$misc->href}&amp;",
'vars' => array('domain' => 'domname'),
),
'drop' => array(
'title' => $lang['strdrop'],
'url' => "domains.php?action=confirm_drop&amp;{$misc->href}&amp;",
'vars' => array('domain' => 'domname'),
),
);
if (!$data->hasAlterDomains()) unset($actions['alter']);
$misc->printTable($domains, $columns, $actions, $lang['strnodomains']);
echo "<p><a class=\"navlink\" href=\"domains.php?action=create&amp;{$misc->href}\">{$lang['strcreatedomain']}</a></p>\n";
}
/**
* Generate XML for the browser tree.
*/
function doTree() {
global $misc, $data;
$domains = $data->getDomains();
$reqvars = $misc->getRequestVars('domain');
$attrs = array(
'text' => field('domname'),
'icon' => 'Domain',
'toolTip'=> field('domcomment'),
'action' => url('domains.php',
$reqvars,
array(
'action' => 'properties',
'domain' => field('domname')
)
)
);
$misc->printTreeXML($domains, $attrs);
exit;
}
if ($action == 'tree') doTree();
$misc->printHeader($lang['strdomains']);
$misc->printBody();
switch ($action) {
case 'add_check':
addCheck(true);
break;
case 'save_add_check':
if (isset($_POST['cancel'])) doProperties();
else addCheck(false);
break;
case 'drop_con':
if (isset($_POST['drop'])) doDropConstraint(false);
else doProperties();
break;
case 'confirm_drop_con':
doDropConstraint(true);
break;
case 'save_create':
if (isset($_POST['cancel'])) doDefault();
else doSaveCreate();
break;
case 'create':
doCreate();
break;
case 'drop':
if (isset($_POST['drop'])) doDrop(false);
else doDefault();
break;
case 'confirm_drop':
doDrop(true);
break;
case 'save_alter':
if (isset($_POST['alter'])) doSaveAlter();
else doProperties();
break;
case 'alter':
doAlter();
break;
case 'properties':
doProperties();
break;
default:
doDefault();
break;
}
$misc->printFooter();
?>

1035
php/pgadmin/fulltext.php Normal file

File diff suppressed because it is too large Load Diff

204
php/pgadmin/functions.js Normal file
View File

@ -0,0 +1,204 @@
var g_args = 0;
var g_no_args = new Boolean(false);
/*
function for adding arguments
*/
function addArg() {
var baseTR = baseArgTR();
if(document.getElementById("args_table").insertBefore(baseTR,document.getElementById("parent_add_tr"))) {
g_args++;
return baseTR;
}
}
function buildArgImages(orig_td) {
var table = document.createElement("table");
var tbody = document.createElement("tbody");
var tr = document.createElement("tr");
var td = document.createElement("td");
var img = document.createElement("img");
img.src="images/themes/default/RaiseArgument.png";
td.onmouseover=function() { this.style.cursor='pointer';this.title=g_lang_strargraise; }
td.onclick=function() { swapArgTR(this.parentNode.parentNode.parentNode.parentNode.parentNode.previousSibling,this.parentNode.parentNode.parentNode.parentNode.parentNode); }
img.className='arg_icon';
td.appendChild(img);
td.className="data1";
tr.appendChild(td);
var img = document.createElement("img");
var td = document.createElement("td");
img.src="images/themes/default/LowerArgument.png";
img.className='arg_icon';
td.appendChild(img);
td.className="data1";
td.onmouseover=function() { this.style.cursor='pointer';this.title=g_lang_strarglower; }
td.onclick=function() { swapArgTR(this.parentNode.parentNode.parentNode.parentNode.parentNode,this.parentNode.parentNode.parentNode.parentNode.parentNode.nextSibling); }
tr.appendChild(td);
var img = document.createElement("img");
var td = document.createElement("td");
img.src="images/themes/default/RemoveArgument.png";
img.title=g_lang_strargremove;
img.className='arg_icon';
td.appendChild(img);
td.className="data1";
td.onmouseover=function() { this.style.cursor='pointer';this.title='Remove'; }
td.onclick=function() { if(g_args>1) { if(confirm(g_lang_strargremoveconfirm)) document.getElementById("args_table").removeChild(this.parentNode.parentNode.parentNode.parentNode.parentNode);g_args--; } else {
if(g_no_args==false) {
disableArgTR(this.parentNode.parentNode.parentNode.parentNode.parentNode);
this.childNodes[0].src='images/themes/default/EnableArgument.png';
this.childNodes[0].title=g_lang_strargenableargs;
this.childNodes[0].id="1st_arg_iag";
alert(g_lang_strargnoargs);
g_no_args = true;
g_args--;
} else {
enableArgTR(this.parentNode.parentNode.parentNode.parentNode.parentNode);
this.childNodes[0].src='images/themes/default/RemoveArgument.png';
this.childNodes[0].title=g_lang_strargremove;
g_args++;
g_no_args = false;
}
}
}
td.onmouseout=function() { }
if(g_args==0) {
td.id="1st_arg_td";
}
tr.className='arg_tr_pc';
tr.appendChild(td);
tbody.appendChild(tr);
table.appendChild(tbody);
orig_td.appendChild(table);
return orig_td;
}
function noArgsRebuild(tr) {
disableArgTR(tr);
var td = document.getElementById("1st_arg_td");
td.childNodes[0].src='images/themes/default/EnableArgument.png';
td.childNodes[0].title=g_lang_strargenableargs;
td.childNodes[0].id="1st_arg_iag";
g_no_args = true;
g_args--;
}
function swapArgTR(first,second) {
var tmp = null;
tmp = second;
second = first;
first = tmp;
if(first.className=='arg_tr_pc' && second.className=='arg_tr_pc') {
document.getElementById("args_table").insertBefore(first,second);
} else if(first.className=='arg_tr_pc' && second.className!='arg_tr_pc') {
alert(g_lang_strargnorowabove);
} else if(first.className!='arg_tr_pc' && second.className=='arg_tr_pc') {
alert(g_lang_strargnorowbelow);
}
}
function disableArgTR(tr) {
var children = (tr.childNodes);
for(i in children) {
var secondary_children = children[i].childNodes;
for(i2 in secondary_children) {
secondary_children[i2].disabled=true;
}
}
}
function enableArgTR(tr) {
var children = (tr.childNodes);
for(i in children) {
var secondary_children = children[i].childNodes;
for(i2 in secondary_children) {
secondary_children[i2].disabled=false;
}
}
}
function RebuildArgTR(mode,arg_name,arg_type,arg_array) {
var tr = document.createElement("tr");
var td = document.createElement("td");
var modes_select = buildSelect("formArgModes[]",g_main_modes,mode);
modes_select.style.width='100%';
td.appendChild(modes_select);
tr.appendChild(td);
var arg_txt = document.createElement("input");
arg_txt.type='text';
arg_txt.name='formArgName[]';
arg_txt.style.width='100%';
arg_txt.value=arg_name;
var td = document.createElement("td");
td.appendChild(arg_txt);
tr.appendChild(td);
var td = document.createElement("td");
td.appendChild(buildSelect("formArgType[]",g_main_types,arg_type));
if(arg_array==true) {
var szArr = "[]";
} else {
var szArr = "";
}
td.appendChild(buildSelect("formArgArray[]",new Array("","[]"),szArr));
tr.appendChild(td);
var td = document.createElement("td");
td = buildArgImages(td);
td.className="data3";
tr.className='arg_tr_pc';
tr.appendChild(td);
if(document.getElementById("args_table").insertBefore(tr,document.getElementById("parent_add_tr"))) {
g_args++;
}
}
function buildSelect(name,options,selected) {
var s = document.createElement('select');
for(i=0;i<options.length;i++) {
var o = document.createElement('option');
o.value=options[i];
o.text=options[i];
if(options[i].toLowerCase()==selected.toLowerCase()) {
o.selected="selected";
}
s.appendChild(o);
}
s.name=name;
return s;
}
function baseArgTR() {
if(g_no_args==false) {
var tr = document.createElement("tr");
var td = document.createElement("td");
var txt = document.createElement("input");
tr.className='arg_tr_pc';
td.className='data3';
td.innerHTML = g_modes_select;
tr.appendChild(td);
txt.type='text';
txt.name='formArgName[]';
txt.style.width='100%';
txt.value=g_name;
var td = document.createElement("td");
td.className='data3';
td.appendChild(txt);
tr.appendChild(td);
var td = document.createElement("td");
td.className='data3';
td.innerHTML = g_types_select;
tr.appendChild(td);
var td = document.createElement("td");
td = buildArgImages(td);
td.className="data3";
tr.appendChild(td);
if(g_args==0) {
tr.id="1st_arg_tr";
}
return tr;
} else {
var p_tr = document.getElementById("1st_arg_tr");
enableArgTR(p_tr.childNodes[4]);
document.getElementById("1st_arg_iag").src='images/themes/default/RemoveArgument.png';
g_args++;
g_no_args = false;
}
}

900
php/pgadmin/functions.php Normal file
View File

@ -0,0 +1,900 @@
<?php
/**
* Manage functions in a database
*
* $Id: functions.php,v 1.78 2008/01/08 22:50:29 xzilla Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (!isset($msg)) $msg = '';
/**
* Function to save after editing a function
*/
function doSaveEdit() {
global $data, $lang, $misc, $_reload_browser;
$fnlang = strtolower($_POST['original_lang']);
if ($fnlang == 'c') {
$def = array($_POST['formObjectFile'], $_POST['formLinkSymbol']);
} else if ($fnlang == 'internal'){
$def = $_POST['formLinkSymbol'];
} else {
$def = $_POST['formDefinition'];
}
if(!$data->hasFunctionAlterSchema()) $_POST['formFuncSchema'] = '';
$status = $data->setFunction($_POST['function_oid'], $_POST['original_function'], $_POST['formFunction'],
$_POST['original_arguments'], $_POST['original_returns'], $def,
$_POST['original_lang'], $_POST['formProperties'], isset($_POST['original_setof']),
$_POST['original_owner'], $_POST['formFuncOwn'], $_POST['original_schema'],
$_POST['formFuncSchema'], isset($_POST['formCost']) ? $_POST['formCost'] : null,
isset($_POST['formRows']) ? $_POST['formRows'] : 0, $_POST['formComment']);
if ($status == 0) {
// If function has had schema altered, need to change to the new schema
// and reload the browser frame.
if (!empty($_POST['formFuncSchema']) && ($_POST['formFuncSchema'] != $_POST['original_schema'])) {
// Jump them to the new function schema
$_REQUEST['schema'] = $_POST['formFuncSchema'];
$misc->href = "server={$_REQUEST['server']}&amp;database={$_REQUEST['database']}&amp;schema={$_REQUEST['schema']}";
// Force a browser reload
$_reload_browser = true;
}
doProperties($lang['strfunctionupdated']);
} else {
doEdit($lang['strfunctionupdatedbad']);
}
}
/**
* Function to allow editing of a Function
*/
function doEdit($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('function');
$misc->printTitle($lang['stralter'],'pg.function.alter');
$misc->printMsg($msg);
$fndata = $data->getFunction($_REQUEST['function_oid']);
if ($fndata->recordCount() > 0) {
$fndata->fields['proretset'] = $data->phpBool($fndata->fields['proretset']);
// Initialise variables
if (!isset($_POST['formDefinition'])) $_POST['formDefinition'] = $fndata->fields['prosrc'];
if (!isset($_POST['formProperties'])) $_POST['formProperties'] = $data->getFunctionProperties($fndata->fields);
if (!isset($_POST['formFunction'])) $_POST['formFunction'] = $fndata->fields['proname'];
if (!isset($_POST['formComment'])) $_POST['formComment'] = $fndata->fields['procomment'];
if (!isset($_POST['formObjectFile'])) $_POST['formObjectFile'] = $fndata->fields['probin'];
if (!isset($_POST['formLinkSymbol'])) $_POST['formLinkSymbol'] = $fndata->fields['prosrc'];
if (!isset($_POST['formFuncOwn'])) $_POST['formFuncOwn'] = $fndata->fields['proowner'];
if (!isset($_POST['formFuncSchema'])) $_POST['formFuncSchema'] = $fndata->fields['proschema'];
if ($data->hasFunctionCosting()) {
if (!isset($_POST['formCost'])) $_POST['formCost'] = $fndata->fields['procost'];
if (!isset($_POST['formRows'])) $_POST['formRows'] = $fndata->fields['prorows'];
}
// Deal with named parameters
if ($data->hasNamedParams()) {
$args_arr = explode(', ', $fndata->fields['proarguments']);
$names_arr = $data->phpArray($fndata->fields['proargnames']);
$args = '';
$i = 0;
for ($i = 0; $i < sizeof($args_arr); $i++) {
if ($i != 0) $args .= ', ';
if (isset($names_arr[$i]) && $names_arr[$i] != '') {
$data->fieldClean($names_arr[$i]);
$args .= '"' . $names_arr[$i] . '" ';
}
$args .= $args_arr[$i];
}
}
else {
$args = $fndata->fields['proarguments'];
}
$func_full = $fndata->fields['proname'] . "(". $fndata->fields['proarguments'] .")";
echo "<form action=\"functions.php\" method=\"post\">\n";
echo "<table style=\"width: 90%\">\n";
echo "<tr>\n";
echo "<th class=\"data required\">{$lang['strschema']}</th>\n";
echo "<th class=\"data required\">{$lang['strfunction']}</th>\n";
echo "<th class=\"data\">{$lang['strarguments']}</th>\n";
echo "<th class=\"data required\">{$lang['strreturns']}</th>\n";
echo "<th class=\"data required\">{$lang['strproglanguage']}</th>\n";
echo "</tr>\n";
echo "<tr>\n";
echo "<td class=\"data1\">";
echo "<input type=\"hidden\" name=\"original_schema\" value=\"", htmlspecialchars($fndata->fields['proschema']),"\" />\n";
if ($data->hasFunctionAlterSchema()) {
$schemas = $data->getSchemas();
echo "<select name=\"formFuncSchema\">";
while (!$schemas->EOF) {
$schema = $schemas->fields['nspname'];
echo "<option value=\"", htmlspecialchars($schema), "\"",
($schema == $_POST['formFuncSchema']) ? ' selected="selected"' : '', ">", htmlspecialchars($schema), "</option>\n";
$schemas->moveNext();
}
echo "</select>\n";
}
else echo $fndata->fields['proschema'];
echo "</td>\n";
echo "<td class=\"data1\">";
echo "<input type=\"hidden\" name=\"original_function\" value=\"", htmlspecialchars($fndata->fields['proname']),"\" />\n";
echo "<input name=\"formFunction\" style=\"width: 100%\" maxlength=\"{$data->_maxNameLen}\" value=\"", htmlspecialchars($_POST['formFunction']), "\" />";
echo "</td>\n";
echo "<td class=\"data1\">", $misc->printVal($args), "\n";
echo "<input type=\"hidden\" name=\"original_arguments\" value=\"",htmlspecialchars($args),"\" />\n";
echo "</td>\n";
echo "<td class=\"data1\">";
if ($fndata->fields['proretset']) echo "setof ";
echo $misc->printVal($fndata->fields['proresult']), "\n";
echo "<input type=\"hidden\" name=\"original_returns\" value=\"", htmlspecialchars($fndata->fields['proresult']), "\" />\n";
if ($fndata->fields['proretset'])
echo "<input type=\"hidden\" name=\"original_setof\" value=\"yes\" />\n";
echo "</td>\n";
echo "<td class=\"data1\">", $misc->printVal($fndata->fields['prolanguage']), "\n";
echo "<input type=\"hidden\" name=\"original_lang\" value=\"", htmlspecialchars($fndata->fields['prolanguage']), "\" />\n";
echo "</td>\n";
echo "</tr>\n";
$fnlang = strtolower($fndata->fields['prolanguage']);
if ($fnlang == 'c') {
echo "<tr><th class=\"data required\" colspan=\"2\">{$lang['strobjectfile']}</th>\n";
echo "<th class=\"data\" colspan=\"2\">{$lang['strlinksymbol']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"2\"><input type=\"text\" name=\"formObjectFile\" style=\"width:100%\" value=\"",
htmlspecialchars($_POST['formObjectFile']), "\" /></td>\n";
echo "<td class=\"data1\" colspan=\"2\"><input type=\"text\" name=\"formLinkSymbol\" style=\"width:100%\" value=\"",
htmlspecialchars($_POST['formLinkSymbol']), "\" /></td></tr>\n";
} else if ($fnlang == 'internal') {
echo "<tr><th class=\"data\" colspan=\"5\">{$lang['strlinksymbol']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"5\"><input type=\"text\" name=\"formLinkSymbol\" style=\"width:100%\" value=\"",
htmlspecialchars($_POST['formLinkSymbol']), "\" /></td></tr>\n";
} else {
echo "<tr><th class=\"data required\" colspan=\"5\">{$lang['strdefinition']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"5\"><textarea style=\"width:100%;\" rows=\"20\" cols=\"50\" name=\"formDefinition\">",
htmlspecialchars($_POST['formDefinition']), "</textarea></td></tr>\n";
}
// Display function comment
echo "<tr><th class=\"data\" colspan=\"5\">{$lang['strcomment']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"5\"><textarea style=\"width:100%;\" name=\"formComment\" rows=\"3\" cols=\"50\">",
htmlspecialchars($_POST['formComment']), "</textarea></td></tr>\n";
// Display function cost options
if ($data->hasFunctionCosting()) {
echo "<tr><th class=\"data required\" colspan=\"5\">{$lang['strfunctioncosting']}</th></tr>\n";
echo "<td class=\"data1\" colspan=\"2\">{$lang['strexecutioncost']}: <input name=\"formCost\" size=\"16\" value=\"".
htmlspecialchars($_POST['formCost']) ."\" /></td>";
echo "<td class=\"data1\" colspan=\"2\">{$lang['strresultrows']}: <input name=\"formRows\" size=\"16\" value=\"",
htmlspecialchars($_POST['formRows']) ,"\"", (!$fndata->fields['proretset']) ? 'disabled' : '', "/></td>";
}
// Display function properties
if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
echo "<tr><th class=\"data\" colspan=\"5\">{$lang['strproperties']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"5\">\n";
$i = 0;
foreach ($data->funcprops as $k => $v) {
echo "<select name=\"formProperties[{$i}]\">\n";
foreach ($v as $p) {
echo "<option value=\"", htmlspecialchars($p), "\"",
($p == $_POST['formProperties'][$i]) ? ' selected="selected"' : '',
">", $misc->printVal($p), "</option>\n";
}
echo "</select><br />\n";
$i++;
}
echo "</td></tr>\n";
}
// function owner
if ($data->hasFunctionAlterOwner()) {
$users = $data->getUsers();
echo "<tr><td class=\"data1\" colspan=\"5\">{$lang['strowner']}: <select name=\"formFuncOwn\">";
while (!$users->EOF) {
$uname = $users->fields['usename'];
echo "<option value=\"", htmlspecialchars($uname), "\"",
($uname == $_POST['formFuncOwn']) ? ' selected="selected"' : '', ">", htmlspecialchars($uname), "</option>\n";
$users->moveNext();
}
echo "</select>\n";
echo "<input type=\"hidden\" name=\"original_owner\" value=\"", htmlspecialchars($fndata->fields['proowner']),"\" />\n";
echo "</td></tr>\n";
}
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_edit\" />\n";
echo "<input type=\"hidden\" name=\"function\" value=\"", htmlspecialchars($_REQUEST['function']), "\" />\n";
echo "<input type=\"hidden\" name=\"function_oid\" value=\"", htmlspecialchars($_REQUEST['function_oid']), "\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['stralter']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
else echo "<p>{$lang['strnodata']}</p>\n";
}
/**
* Show read only properties of a function
*/
function doProperties($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('function');
$misc->printTitle($lang['strproperties'],'pg.function');
$misc->printMsg($msg);
$funcdata = $data->getFunction($_REQUEST['function_oid']);
if ($funcdata->recordCount() > 0) {
// Deal with named parameters
if ($data->hasNamedParams()) {
$args_arr = explode(', ', $funcdata->fields['proarguments']);
$names_arr = $data->phpArray($funcdata->fields['proargnames']);
$args = '';
$i = 0;
for ($i = 0; $i < sizeof($args_arr); $i++) {
if ($i != 0) $args .= ', ';
if (isset($names_arr[$i]) && $names_arr[$i] != '') {
$data->fieldClean($names_arr[$i]);
$args .= '"' . $names_arr[$i] . '" ';
}
$args .= $args_arr[$i];
}
}
else {
$args = $funcdata->fields['proarguments'];
}
// Show comment if any
if ($funcdata->fields['procomment'] !== null)
echo "<p class=\"comment\">", $misc->printVal($funcdata->fields['procomment']), "</p>\n";
$funcdata->fields['proretset'] = $data->phpBool($funcdata->fields['proretset']);
$func_full = $funcdata->fields['proname'] . "(". $funcdata->fields['proarguments'] .")";
echo "<table style=\"width: 90%\">\n";
echo "<tr><th class=\"data\">{$lang['strfunction']}</th>\n";
echo "<th class=\"data\">{$lang['strarguments']}</th>\n";
echo "<th class=\"data\">{$lang['strreturns']}</th>\n";
echo "<th class=\"data\">{$lang['strproglanguage']}</th></tr>\n";
echo "<tr><td class=\"data1\">", $misc->printVal($funcdata->fields['proname']), "</td>\n";
echo "<td class=\"data1\">", $misc->printVal($args), "</td>\n";
echo "<td class=\"data1\">";
if ($funcdata->fields['proretset']) echo "setof ";
echo $misc->printVal($funcdata->fields['proresult']), "</td>\n";
echo "<td class=\"data1\">", $misc->printVal($funcdata->fields['prolanguage']), "</td></tr>\n";
$fnlang = strtolower($funcdata->fields['prolanguage']);
if ($fnlang == 'c') {
echo "<tr><th class=\"data\" colspan=\"2\">{$lang['strobjectfile']}</th>\n";
echo "<th class=\"data\" colspan=\"2\">{$lang['strlinksymbol']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"2\">", $misc->printVal($funcdata->fields['probin']), "</td>\n";
echo "<td class=\"data1\" colspan=\"2\">", $misc->printVal($funcdata->fields['prosrc']), "</td></tr>\n";
} else if ($fnlang == 'internal') {
echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strlinksymbol']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"4\">", $misc->printVal($funcdata->fields['prosrc']), "</td></tr>\n";
} else {
include_once('./libraries/highlight.php');
echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strdefinition']}</th></tr>\n";
// Check to see if we have syntax highlighting for this language
if (isset($data->langmap[$funcdata->fields['prolanguage']])) {
$temp = syntax_highlight(htmlspecialchars($funcdata->fields['prosrc']), $data->langmap[$funcdata->fields['prolanguage']]);
$tag = 'prenoescape';
}
else {
$temp = $funcdata->fields['prosrc'];
$tag = 'pre';
}
echo "<tr><td class=\"data1\" colspan=\"4\">", $misc->printVal($temp, $tag, array('lineno' => true, 'class' => 'data1')), "</td></tr>\n";
}
// Display function cost options
if ($data->hasFunctionCosting()) {
echo "<tr><th class=\"data required\" colspan=\"4\">{$lang['strfunctioncosting']}</th></tr>\n";
echo "<td class=\"data1\" colspan=\"2\">{$lang['strexecutioncost']}: ", $misc->printVal($funcdata->fields['procost']), " </td>";
echo "<td class=\"data1\" colspan=\"2\">{$lang['strresultrows']}: ", $misc->printVal($funcdata->fields['prorows']), " </td>";
}
// Show flags
if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
// Fetch an array of the function properties
$funcprops = $data->getFunctionProperties($funcdata->fields);
echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strproperties']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"4\">\n";
foreach ($funcprops as $v) {
echo $misc->printVal($v), "<br />\n";
}
echo "</td></tr>\n";
}
echo "<tr><td class=\"data1\" colspan=\"5\">{$lang['strowner']}: ", htmlspecialchars($funcdata->fields['proowner']),"\n";
echo "</td></tr>\n";
echo "</table>\n";
}
else echo "<p>{$lang['strnodata']}</p>\n";
echo "<ul class=\"navlink\">\n\t<li><a href=\"functions.php?{$misc->href}\">{$lang['strshowallfunctions']}</a></li>\n";
echo "\t<li><a href=\"functions.php?action=edit&amp;{$misc->href}&amp;function=",
urlencode($_REQUEST['function']), "&amp;function_oid=", urlencode($_REQUEST['function_oid']), "\">{$lang['stralter']}</a></li>\n";
echo "\t<li><a href=\"functions.php?action=confirm_drop&amp;{$misc->href}&amp;function=",
urlencode($func_full), "&amp;function_oid=", $_REQUEST['function_oid'], "\">{$lang['strdrop']}</a></li>\n</ul>";
}
/**
* Show confirmation of drop and perform actual drop
*/
function doDrop($confirm) {
global $data, $misc;
global $lang, $_reload_browser;
if (empty($_REQUEST['function']) && empty($_REQUEST['ma'])) {
doDefault($lang['strspecifyfunctiontodrop']);
exit();
}
if ($confirm) {
$misc->printTrail('schema');
$misc->printTitle($lang['strdrop'],'pg.function.drop');
echo "<form action=\"functions.php\" method=\"post\">\n";
//If multi drop
if (isset($_REQUEST['ma'])) {
foreach($_REQUEST['ma'] as $v) {
$a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
echo "<p>", sprintf($lang['strconfdropfunction'], $misc->printVal($a['function'])), "</p>\n";
echo '<input type="hidden" name="function[]" value="', htmlspecialchars($a['function']), "\" />\n";
echo "<input type=\"hidden\" name=\"function_oid[]\" value=\"", htmlspecialchars($a['function_oid']), "\" />\n";
}
}
else {
echo "<p>", sprintf($lang['strconfdropfunction'], $misc->printVal($_REQUEST['function'])), "</p>\n";
echo "<input type=\"hidden\" name=\"function\" value=\"", htmlspecialchars($_REQUEST['function']), "\" />\n";
echo "<input type=\"hidden\" name=\"function_oid\" value=\"", htmlspecialchars($_REQUEST['function_oid']), "\" />\n";
}
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo $misc->form;
echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /><label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
}
else {
if (is_array($_POST['function_oid'])) {
$msg='';
$status = $data->beginTransaction();
if ($status == 0) {
foreach($_POST['function_oid'] as $k => $s) {
$status = $data->dropFunction($s, isset($_POST['cascade']));
if ($status == 0)
$msg.= sprintf('%s: %s<br />', htmlentities($_POST['function'][$k]), $lang['strfunctiondropped']);
else {
$data->endTransaction();
doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($_POST['function'][$k]), $lang['strfunctiondroppedbad']));
return;
}
}
}
if($data->endTransaction() == 0) {
// Everything went fine, back to the Default page....
$_reload_browser = true;
doDefault($msg);
}
else doDefault($lang['strfunctiondroppedbad']);
}
else{
$status = $data->dropFunction($_POST['function_oid'], isset($_POST['cascade']));
if ($status == 0) {
$_reload_browser = true;
doDefault($lang['strfunctiondropped']);
}
else {
doDefault($lang['strfunctiondroppedbad']);
}
}
}
}
/**
* Displays a screen where they can enter a new function
*/
function doCreate($msg = '',$szJS="") {
global $data, $misc;
global $lang;
$misc->printTrail('schema');
if (!isset($_POST['formFunction'])) $_POST['formFunction'] = '';
if (!isset($_POST['formArguments'])) $_POST['formArguments'] = '';
if (!isset($_POST['formReturns'])) $_POST['formReturns'] = '';
if (!isset($_POST['formLanguage'])) $_POST['formLanguage'] = isset($_REQUEST['language']) ? $_REQUEST['language'] : 'sql';
if (!isset($_POST['formDefinition'])) $_POST['formDefinition'] = '';
if (!isset($_POST['formObjectFile'])) $_POST['formObjectFile'] = '';
if (!isset($_POST['formLinkSymbol'])) $_POST['formLinkSymbol'] = '';
if (!isset($_POST['formProperties'])) $_POST['formProperties'] = $data->defaultprops;
if (!isset($_POST['formSetOf'])) $_POST['formSetOf'] = '';
if (!isset($_POST['formArray'])) $_POST['formArray'] = '';
if (!isset($_POST['formCost'])) $_POST['formCost'] = '';
if (!isset($_POST['formRows'])) $_POST['formRows'] = '';
if (!isset($_POST['formComment'])) $_POST['formComment'] = '';
$types = $data->getTypes(true, true, true);
$langs = $data->getLanguages(true);
$fnlang = strtolower($_POST['formLanguage']);
switch ($fnlang) {
case 'c':
$misc->printTitle($lang['strcreatecfunction'],'pg.function.create.c');
break;
case 'internal':
$misc->printTitle($lang['strcreateinternalfunction'],'pg.function.create.internal');
break;
default:
$misc->printTitle($lang['strcreateplfunction'],'pg.function.create.pl');
break;
}
$misc->printMsg($msg);
// Create string for return type list
$szTypes = "";
while (!$types->EOF) {
$szSelected = "";
if($types->fields['typname'] == $_POST['formReturns']) {
$szSelected = " selected=\"selected\"";
}
/* this variable is include in the JS code bellow, so we need to ENT_QUOTES */
$szTypes .= "<option value=\"". htmlspecialchars($types->fields['typname'], ENT_QUOTES) ."\"{$szSelected}>";
$szTypes .= htmlspecialchars($types->fields['typname'], ENT_QUOTES) ."</option>";
$types->moveNext();
}
$szFunctionName = "<td class=\"data1\"><input name=\"formFunction\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"".
htmlspecialchars($_POST['formFunction']) ."\" /></td>";
$szArguments = "<td class=\"data1\"><input name=\"formArguments\" style=\"width:100%;\" size=\"16\" value=\"".
htmlspecialchars($_POST['formArguments']) ."\" /></td>";
$szSetOfSelected = "";
$szNotSetOfSelected = "";
if($_POST['formSetOf'] == '') {
$szNotSetOfSelected = " selected=\"selected\"";
} else if($_POST['formSetOf'] == 'SETOF') {
$szSetOfSelected = " selected=\"selected\"";
}
$szReturns = "<td class=\"data1\" colspan=\"2\">";
$szReturns .= "<select name=\"formSetOf\">";
$szReturns .= "<option value=\"\"{$szNotSetOfSelected}></option>";
$szReturns .= "<option value=\"SETOF\"{$szSetOfSelected}>SETOF</option>";
$szReturns .= "</select>";
$szReturns .= "<select name=\"formReturns\">".$szTypes."</select>";
// Create string array type selector
$szArraySelected = "";
$szNotArraySelected = "";
if($_POST['formArray'] == '') {
$szNotArraySelected = " selected=\"selected\"";
} else if($_POST['formArray'] == '[]') {
$szArraySelected = " selected=\"selected\"";
}
$szReturns .= "<select name=\"formArray\">";
$szReturns .= "<option value=\"\"{$szNotArraySelected}></option>";
$szReturns .= "<option value=\"[]\"{$szArraySelected}>[ ]</option>";
$szReturns .= "</select>\n</td>";
// Create string for language
$szLanguage = "<td class=\"data1\">";
if ($fnlang == 'c' || $fnlang == 'internal') {
$szLanguage .= $_POST['formLanguage'] . "\n";
$szLanguage .= "<input type=\"hidden\" name=\"formLanguage\" value=\"{$_POST['formLanguage']}\" />\n";
}
else {
$szLanguage .= "<select name=\"formLanguage\">\n";
while (!$langs->EOF) {
$szSelected = '';
if($langs->fields['lanname'] == $_POST['formLanguage']) {
$szSelected = ' selected="selected"';
}
if (strtolower($langs->fields['lanname']) != 'c' && strtolower($langs->fields['lanname']) != 'internal')
$szLanguage .= "<option value=\"". htmlspecialchars($langs->fields['lanname']). "\"{$szSelected}>\n".
$misc->printVal($langs->fields['lanname']) ."</option>";
$langs->moveNext();
}
$szLanguage .= "</select>\n";
}
$szLanguage .= "</td>";
$szJSArguments = "<tr><th class=\"data\" colspan=\"7\">{$lang['strarguments']}</th></tr>";
$arrayModes = array("IN","OUT","INOUT");
$szModes = "<select name=\"formArgModes[]\" style=\"width:100%;\">";
foreach($arrayModes as $pV) {
$szModes .= "<option value=\"{$pV}\">{$pV}</option>";
}
$szModes .= "</select>";
$szArgReturns = "<select name=\"formArgArray[]\">";
$szArgReturns .= "<option value=\"\"></option>";
$szArgReturns .= "<option value=\"[]\">[]</option>";
$szArgReturns .= "</select>";
if(!empty($conf['theme'])) {
$szImgPath = "images/themes/{$conf['theme']}";
} else {
$szImgPath = "images/themes/default";
}
if(empty($msg)) {
$szJSTRArg = "<script type=\"text/javascript\" >addArg();</script>\n";
} else {
$szJSTRArg = "";
}
$szJSAddTR = "<tr id=\"parent_add_tr\" onclick=\"addArg();\" onmouseover=\"this.style.cursor='pointer'\">\n<td style=\"text-align: right\" colspan=\"6\" class=\"data3\"><table><tr><td class=\"data3\"><img src=\"{$szImgPath}/AddArguments.png\" alt=\"Add Argument\" /></td><td class=\"data3\"><span style=\"font-size: 8pt\">{$lang['strargadd']}</span></td></tr></table></td>\n</tr>\n";
echo "<script src=\"functions.js\" type=\"text/javascript\"></script>
<script type=\"text/javascript\">
//<![CDATA[
var g_types_select = '<select name=\"formArgType[]\">{$szTypes}</select>{$szArgReturns}';
var g_modes_select = '{$szModes}';
var g_name = '';
var g_lang_strargremove = '", htmlspecialchars($lang["strargremove"], ENT_QUOTES) ,"';
var g_lang_strargnoargs = '", htmlspecialchars($lang["strargnoargs"], ENT_QUOTES) ,"';
var g_lang_strargenableargs = '", htmlspecialchars($lang["strargenableargs"], ENT_QUOTES) ,"';
var g_lang_strargnorowabove = '", htmlspecialchars($lang["strargnorowabove"], ENT_QUOTES) ,"';
var g_lang_strargnorowbelow = '", htmlspecialchars($lang["strargnorowbelow"], ENT_QUOTES) ,"';
var g_lang_strargremoveconfirm = '", htmlspecialchars($lang["strargremoveconfirm"], ENT_QUOTES) ,"';
var g_lang_strargraise = '", htmlspecialchars($lang["strargraise"], ENT_QUOTES) ,"';
var g_lang_strarglower = '", htmlspecialchars($lang["strarglower"], ENT_QUOTES) ,"';
//]]>
</script>
";
echo "<form action=\"functions.php\" method=\"post\">\n";
echo "<table><tbody id=\"args_table\">\n";
echo "<tr><th class=\"data required\">{$lang['strname']}</th>\n";
echo "<th class=\"data required\" colspan=\"2\">{$lang['strreturns']}</th>\n";
echo "<th class=\"data required\">{$lang['strproglanguage']}</th></tr>\n";
echo "<tr>\n";
echo "{$szFunctionName}\n";
echo "{$szReturns}\n";
echo "{$szLanguage}\n";
echo "</tr>\n";
echo "{$szJSArguments}\n";
echo "<tr>\n";
echo "<th class=\"data required\">{$lang['strargmode']}</th>\n";
echo "<th class=\"data required\">{$lang['strname']}</th>\n";
echo "<th class=\"data required\" colspan=\"2\">{$lang['strargtype']}</th>\n";
echo "</tr>\n";
echo "{$szJSAddTR}\n";
if ($fnlang == 'c') {
echo "<tr><th class=\"data required\" colspan=\"2\">{$lang['strobjectfile']}</th>\n";
echo "<th class=\"data\" colspan=\"2\">{$lang['strlinksymbol']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"2\"><input type=\"text\" name=\"formObjectFile\" style=\"width:100%\" value=\"",
htmlspecialchars($_POST['formObjectFile']), "\" /></td>\n";
echo "<td class=\"data1\" colspan=\"2\"><input type=\"text\" name=\"formLinkSymbol\" style=\"width:100%\" value=\"",
htmlspecialchars($_POST['formLinkSymbol']), "\" /></td></tr>\n";
} else if ($fnlang == 'internal') {
echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strlinksymbol']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"4\"><input type=\"text\" name=\"formLinkSymbol\" style=\"width:100%\" value=\"",
htmlspecialchars($_POST['formLinkSymbol']), "\" /></td></tr>\n";
} else {
echo "<tr><th class=\"data required\" colspan=\"4\">{$lang['strdefinition']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"4\"><textarea style=\"width:100%;\" rows=\"20\" cols=\"50\" name=\"formDefinition\">",
htmlspecialchars($_POST['formDefinition']), "</textarea></td></tr>\n";
}
// Display function comment
echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strcomment']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"4\"><textarea style=\"width:100%;\" name=\"formComment\" rows=\"3\" cols=\"50\">",
htmlspecialchars($_POST['formComment']), "</textarea></td></tr>\n";
// Display function cost options
if ($data->hasFunctionCosting()) {
echo "<tr><th class=\"data required\" colspan=\"4\">{$lang['strfunctioncosting']}</th></tr>\n";
echo "<td class=\"data1\" colspan=\"2\">{$lang['strexecutioncost']}: <input name=\"formCost\" size=\"16\" value=\"".
htmlspecialchars($_POST['formCost']) ."\" /></td>";
echo "<td class=\"data1\" colspan=\"2\">{$lang['strresultrows']}: <input name=\"formRows\" size=\"16\" value=\"".
htmlspecialchars($_POST['formRows']) ."\" /></td>";
}
// Display function properties
if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
echo "<tr><th class=\"data required\" colspan=\"4\">{$lang['strproperties']}</th></tr>\n";
echo "<tr><td class=\"data1\" colspan=\"4\">\n";
$i = 0;
foreach ($data->funcprops as $k => $v) {
echo "<select name=\"formProperties[{$i}]\">\n";
foreach ($v as $p) {
echo "<option value=\"", htmlspecialchars($p), "\"",
($p == $_POST['formProperties'][$i]) ? ' selected="selected"' : '',
">", $misc->printVal($p), "</option>\n";
}
echo "</select><br />\n";
$i++;
}
echo "</td></tr>\n";
}
echo "</tbody></table>\n";
echo $szJSTRArg;
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
echo $szJS;
}
/**
* Actually creates the new function in the database
*/
function doSaveCreate() {
global $data, $lang;
$fnlang = strtolower($_POST['formLanguage']);
if ($fnlang == 'c') {
$def = array($_POST['formObjectFile'], $_POST['formLinkSymbol']);
} else if ($fnlang == 'internal'){
$def = $_POST['formLinkSymbol'];
} else {
$def = $_POST['formDefinition'];
}
$szJS = '';
echo "<script src=\"functions.js\" type=\"text/javascript\"></script>";
echo "<script type=\"text/javascript\">". buildJSData() .'</script>';
if(!empty($_POST['formArgName'])) {
$szJS = buildJSRows(buildFunctionArguments($_POST));
} else {
$szJS = "<script type=\"text/javascript\" src=\"functions.js\">noArgsRebuild(addArg());</script>";
}
$cost = (isset($_POST['formCost'])) ? $_POST['formCost'] : null;
if ($cost == '' || !is_numeric($cost) || $cost != (int)$cost || $cost < 0) {
$cost = null;
}
$rows = (isset($_POST['formRows'])) ? $_POST['formRows'] : null;
if ($rows == '' || !is_numeric($rows) || $rows != (int)$rows ) {
$rows = null;
}
// Check that they've given a name and a definition
if ($_POST['formFunction'] == '') doCreate($lang['strfunctionneedsname'],$szJS);
elseif ($fnlang != 'internal' && !$def) doCreate($lang['strfunctionneedsdef'],$szJS);
else {
// Append array symbol to type if chosen
$status = $data->createFunction($_POST['formFunction'], empty($_POST['nojs'])? buildFunctionArguments($_POST) : $_POST['formArguments'],
$_POST['formReturns'] . $_POST['formArray'] , $def , $_POST['formLanguage'],
$_POST['formProperties'], $_POST['formSetOf'] == 'SETOF',
$cost, $rows, $_POST['formComment'], false);
if ($status == 0)
doDefault($lang['strfunctioncreated']);
else {
doCreate($lang['strfunctioncreatedbad'],$szJS);
}
}
}
/**
* Build out the function arguments string
*/
function buildFunctionArguments($arrayVars) {
if(isset($_POST['formArgName'])) {
$arrayArgs = array();
foreach($arrayVars['formArgName'] as $pK => $pV) {
$arrayArgs[] = $arrayVars['formArgModes'][$pK] .' '. trim($pV) .' '. trim($arrayVars['formArgType'][$pK]) . $arrayVars['formArgArray'][$pK];
}
return implode(",", $arrayArgs);
}
return '';
}
/**
* Build out JS to re-create table rows for arguments
*/
function buildJSRows($szArgs) {
$arrayModes = array('IN','OUT','INOUT');
$arrayArgs = explode(',',$szArgs);
$arrayProperArgs = array();
$nC = 0;
$szReturn = '';
foreach($arrayArgs as $pV) {
$arrayWords = explode(' ',$pV);
if(in_array($arrayWords[0],$arrayModes)===true) {
$szMode = $arrayWords[0];
array_shift($arrayWords);
}
$szArgName = array_shift($arrayWords);
if(strpos($arrayWords[count($arrayWords)-1],'[]')===false) {
$szArgType = implode(" ",$arrayWords);
$bArgIsArray = "false";
} else {
$szArgType = str_replace('[]','',implode(' ',$arrayWords));
$bArgIsArray = "true";
}
$arrayProperArgs[] = array($szMode,$szArgName,$szArgType,$bArgIsArray);
$szReturn .= "<script type=\"text/javascript\">RebuildArgTR('{$szMode}','{$szArgName}','{$szArgType}',new Boolean({$bArgIsArray}));</script>";
$nC++;
}
return $szReturn;
}
function buildJSData() {
global $data;
$arrayModes = array('IN','OUT','INOUT');
$arrayTypes = $data->getTypes(true, true, true);
$arrayPTypes = array();
$arrayPModes = array();
$szTypes = '';
while (!$arrayTypes->EOF) {
$arrayPTypes[] = "'". $arrayTypes->fields['typname'] ."'";
$arrayTypes->moveNext();
}
foreach($arrayModes as $pV) {
$arrayPModes[] = "'{$pV}'";
}
$szTypes = 'g_main_types = new Array('. implode(',', $arrayPTypes) .');';
$szModes = 'g_main_modes = new Array('. implode(',', $arrayPModes) .');';
return $szTypes . $szModes;
}
/**
* Show default list of functions in the database
*/
function doDefault($msg = '') {
global $data, $conf, $misc, $func;
global $lang;
$misc->printTrail('schema');
$misc->printTabs('schema','functions');
$misc->printMsg($msg);
$funcs = $data->getFunctions();
$columns = array(
'function' => array(
'title' => $lang['strfunction'],
'field' => field('proproto'),
'type' => 'verbatim',
'url' => "redirect.php?subject=function&amp;action=properties&amp;{$misc->href}&amp;",
'vars' => array('function' => 'proproto', 'function_oid' => 'prooid'),
),
'returns' => array(
'title' => $lang['strreturns'],
'field' => field('proreturns'),
'type' => 'verbatim',
),
'owner' => array(
'title' => $lang['strowner'],
'field' => field('proowner'),
),
'proglanguage' => array(
'title' => $lang['strproglanguage'],
'field' => field('prolanguage'),
),
'actions' => array(
'title' => $lang['stractions'],
),
'comment' => array(
'title' => $lang['strcomment'],
'field' => field('procomment'),
),
);
$actions = array(
'multiactions' => array(
'keycols' => array('function' => 'proproto', 'function_oid' => 'prooid'),
'url' => 'functions.php',
),
'alter' => array(
'title' => $lang['stralter'],
'url' => "functions.php?action=edit&amp;{$misc->href}&amp;",
'vars' => array('function' => 'proproto', 'function_oid' => 'prooid'),
),
'drop' => array(
'title' => $lang['strdrop'],
'url' => "functions.php?action=confirm_drop&amp;{$misc->href}&amp;",
'vars' => array('function' => 'proproto', 'function_oid' => 'prooid'),
'multiaction' => 'confirm_drop',
),
'privileges' => array(
'title' => $lang['strprivileges'],
'url' => "privileges.php?{$misc->href}&amp;subject=function&amp;",
'vars' => array('function' => 'proproto', 'function_oid' => 'prooid'),
),
);
$misc->printTable($funcs, $columns, $actions, $lang['strnofunctions']);
echo "<ul class=\"navlink\">\n\t<li><a href=\"functions.php?action=create&amp;{$misc->href}\">{$lang['strcreateplfunction']}</a></li>\n";
echo "\t<li><a href=\"functions.php?action=create&amp;language=internal&amp;{$misc->href}\">{$lang['strcreateinternalfunction']}</a></li>\n";
echo "\t<li><a href=\"functions.php?action=create&amp;language=C&amp;{$misc->href}\">{$lang['strcreatecfunction']}</a></li>\n</ul>\n";
}
/**
* Generate XML for the browser tree.
*/
function doTree() {
global $misc, $data;
$funcs = $data->getFunctions();
$proto = concat(field('proname'),' (',field('proarguments'),')');
$reqvars = $misc->getRequestVars('function');
$attrs = array(
'text' => $proto,
'icon' => 'Function',
'toolTip' => field('procomment'),
'action' => url('redirect.php',
$reqvars,
array(
'action' => 'properties',
'function' => $proto,
'function_oid' => field('prooid')
)
)
);
$misc->printTreeXML($funcs, $attrs);
exit;
}
if ($action == 'tree') doTree();
$misc->printHeader($lang['strfunctions']);
$misc->printBody();
switch ($action) {
case 'save_create':
if (isset($_POST['cancel'])) doDefault();
else doSaveCreate();
break;
case 'create':
doCreate();
break;
case 'drop':
if (isset($_POST['drop'])) doDrop(false);
else doDefault();
break;
case 'confirm_drop':
doDrop(true);
break;
case 'save_edit':
if (isset($_POST['cancel'])) doDefault();
else doSaveEdit();
break;
case 'edit':
doEdit();
break;
case 'properties':
doProperties();
break;
default:
doDefault();
break;
}
$misc->printFooter();
?>

288
php/pgadmin/groups.php Normal file
View File

@ -0,0 +1,288 @@
<?php
/**
* Manage groups in a database cluster
*
* $Id: groups.php,v 1.27 2007/08/31 18:30:11 ioguix Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
if (!isset($msg)) $msg = '';
/**
* Add user to a group
*/
function doAddMember() {
global $data, $misc;
global $lang;
$status = $data->addGroupMember($_REQUEST['group'], $_REQUEST['user']);
if ($status == 0)
doProperties($lang['strmemberadded']);
else
doProperties($lang['strmemberaddedbad']);
}
/**
* Show confirmation of drop user from group and perform actual drop
*/
function doDropMember($confirm) {
global $data, $misc;
global $lang;
if ($confirm) {
$misc->printTrail('group');
$misc->printTitle($lang['strdropmember'],'pg.group.alter');
echo "<p>", sprintf($lang['strconfdropmember'], $misc->printVal($_REQUEST['user']), $misc->printVal($_REQUEST['group'])), "</p>\n";
echo "<form action=\"groups.php\" method=\"post\">\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"drop_member\" />\n";
echo "<input type=\"hidden\" name=\"group\" value=\"", htmlspecialchars($_REQUEST['group']), "\" />\n";
echo "<input type=\"hidden\" name=\"user\" value=\"", htmlspecialchars($_REQUEST['user']), "\" />\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
}
else {
$status = $data->dropGroupMember($_REQUEST['group'], $_REQUEST['user']);
if ($status == 0)
doProperties($lang['strmemberdropped']);
else
doDropMember(true, $lang['strmemberdroppedbad']);
}
}
/**
* Show read only properties for a group
*/
function doProperties($msg = '') {
global $data, $misc;
global $lang;
if (!isset($_POST['user'])) $_POST['user'] = '';
$misc->printTrail('group');
$misc->printTitle($lang['strproperties'],'pg.group');
$misc->printMsg($msg);
$groupdata = $data->getGroup($_REQUEST['group']);
$users = $data->getUsers();
if ($groupdata->recordCount() > 0) {
echo "<table>\n";
echo "<tr><th class=\"data\">{$lang['strmembers']}</th><th class=\"data\">{$lang['stractions']}</th></tr>\n";
$i = 0;
while (!$groupdata->EOF) {
$id = (($i % 2) == 0 ? '1' : '2');
echo "<tr class=\"data{$id}\"><td>", $misc->printVal($groupdata->fields['usename']), "</td>\n";
echo "<td class=\"opbutton{$id}\"><a href=\"groups.php?action=confirm_drop_member&{$misc->href}&group=",
urlencode($_REQUEST['group']), "&user=", urlencode($groupdata->fields['usename']), "\">{$lang['strdrop']}</a></td>\n";
echo "</tr>\n";
$groupdata->moveNext();
}
echo "</table>\n";
}
else echo "<p>{$lang['strnousers']}</p>\n";
// Display form for adding a user to the group
echo "<form action=\"groups.php\" method=\"post\">\n";
echo "<select name=\"user\">";
while (!$users->EOF) {
$uname = $misc->printVal($users->fields['usename']);
echo "<option value=\"{$uname}\"",
($uname == $_POST['user']) ? ' selected="selected"' : '', ">{$uname}</option>\n";
$users->moveNext();
}
echo "</select>\n";
echo "<input type=\"submit\" value=\"{$lang['straddmember']}\" />\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"group\" value=\"", htmlspecialchars($_REQUEST['group']), "\" />\n";
echo "<input type=\"hidden\" name=\"action\" value=\"add_member\" />\n";
echo "</form>\n";
echo "<p><a class=\"navlink\" href=\"groups.php?{$misc->href}\">{$lang['strshowallgroups']}</a></p>\n";
}
/**
* Show confirmation of drop and perform actual drop
*/
function doDrop($confirm) {
global $data, $misc;
global $lang;
if ($confirm) {
$misc->printTrail('group');
$misc->printTitle($lang['strdrop'],'pg.group.drop');
echo "<p>", sprintf($lang['strconfdropgroup'], $misc->printVal($_REQUEST['group'])), "</p>\n";
echo "<form action=\"groups.php\" method=\"post\">\n";
echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"group\" value=\"", htmlspecialchars($_REQUEST['group']), "\" />\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
}
else {
$status = $data->dropGroup($_REQUEST['group']);
if ($status == 0)
doDefault($lang['strgroupdropped']);
else
doDefault($lang['strgroupdroppedbad']);
}
}
/**
* Displays a screen where they can enter a new group
*/
function doCreate($msg = '') {
global $data, $misc;
global $lang;
if (!isset($_POST['name'])) $_POST['name'] = '';
if (!isset($_POST['members'])) $_POST['members'] = array();
// Fetch a list of all users in the cluster
$users = $data->getUsers();
$misc->printTrail('server');
$misc->printTitle($lang['strcreategroup'],'pg.group.create');
$misc->printMsg($msg);
echo "<form action=\"\" method=\"post\">\n";
echo $misc->form;
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
echo "\t\t<td class=\"data\"><input size=\"32\" maxlength=\"{$data->_maxNameLen}\" name=\"name\" value=\"", htmlspecialchars($_POST['name']), "\" /></td>\n\t</tr>\n";
if ($users->recordCount() > 0) {
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strmembers']}</th>\n";
echo "\t\t<td class=\"data\">\n";
echo "\t\t\t<select name=\"members[]\" multiple=\"multiple\" size=\"", min(40, $users->recordCount()), "\">\n";
while (!$users->EOF) {
$username = $users->fields['usename'];
echo "\t\t\t\t<option value=\"{$username}\"",
(in_array($username, $_POST['members']) ? ' selected="selected"' : ''), ">", $misc->printVal($username), "</option>\n";
$users->moveNext();
}
echo "\t\t\t</select>\n";
echo "\t\t</td>\n\t</tr>\n";
}
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
}
/**
* Actually creates the new group in the database
*/
function doSaveCreate() {
global $data;
global $lang;
if (!isset($_POST['members'])) $_POST['members'] = array();
// Check form vars
if (trim($_POST['name']) == '')
doCreate($lang['strgroupneedsname']);
else {
$status = $data->createGroup($_POST['name'], $_POST['members']);
if ($status == 0)
doDefault($lang['strgroupcreated']);
else
doCreate($lang['strgroupcreatedbad']);
}
}
/**
* Show default list of groups in the database
*/
function doDefault($msg = '') {
global $data, $misc;
global $lang;
$misc->printTrail('server');
$misc->printTabs('server','groups');
$misc->printMsg($msg);
$groups = $data->getGroups();
$columns = array(
'group' => array(
'title' => $lang['strgroup'],
'field' => field('groname'),
'url' => "groups.php?action=properties&amp;{$misc->href}&amp;",
'vars' => array('group' => 'groname'),
),
'actions' => array(
'title' => $lang['stractions'],
),
);
$actions = array(
'drop' => array(
'title' => $lang['strdrop'],
'url' => "groups.php?action=confirm_drop&amp;{$misc->href}&amp;",
'vars' => array('group' => 'groname'),
),
);
$misc->printTable($groups, $columns, $actions, $lang['strnogroups']);
echo "<p><a class=\"navlink\" href=\"groups.php?action=create&amp;{$misc->href}\">{$lang['strcreategroup']}</a></p>\n";
}
$misc->printHeader($lang['strgroups']);
$misc->printBody();
switch ($action) {
case 'add_member':
doAddMember();
break;
case 'drop_member':
if (isset($_REQUEST['drop'])) doDropMember(false);
else doProperties();
break;
case 'confirm_drop_member':
doDropMember(true);
break;
case 'save_create':
if (isset($_REQUEST['cancel'])) doDefault();
else doSaveCreate();
break;
case 'create':
doCreate();
break;
case 'drop':
if (isset($_REQUEST['drop'])) doDrop(false);
else doDefault();
break;
case 'confirm_drop':
doDrop(true);
break;
case 'save_edit':
doSaveEdit();
break;
case 'edit':
doEdit();
break;
case 'properties':
doProperties();
break;
default:
doDefault();
break;
}
$misc->printFooter();
?>

88
php/pgadmin/help.php Normal file
View File

@ -0,0 +1,88 @@
<?php
/**
* Help page redirection/browsing.
*
* $Id: help.php,v 1.3 2006/12/31 16:21:26 soranzo Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
function doDefault() {
global $data, $lang;
if (isset($_REQUEST['help'])) {
$url = $data->getHelp($_REQUEST['help']);
if (is_array($url)) {
doChoosePage($url);
return;
}
if ($url) {
header("Location: $url");
exit;
}
}
doBrowse($lang['strinvalidhelppage']);
}
function doBrowse($msg = '') {
global $misc, $data, $lang;
$misc->printHeader($lang['strhelppagebrowser']);
$misc->printBody();
$misc->printTitle($lang['strselecthelppage']);
echo $misc->printMsg($msg);
echo "<dl>\n";
$pages = $data->getHelpPages();
foreach ($pages as $page => $dummy) {
echo "<dt>{$page}</dt>\n";
$urls = $data->getHelp($page);
if (!is_array($urls)) $urls = array($urls);
foreach ($urls as $url) {
echo "<dd><a href=\"{$url}\">{$url}</a></dd>\n";
}
}
echo "</dl>\n";
$misc->printFooter();
}
function doChoosePage($urls) {
global $misc, $lang;
$misc->printHeader($lang['strhelppagebrowser']);
$misc->printBody();
$misc->printTitle($lang['strselecthelppage']);
echo "<ul>\n";
foreach($urls as $url) {
echo "<li><a href=\"{$url}\">{$url}</a></li>\n";
}
echo "</ul>\n";
$misc->printFooter();
}
switch ($action) {
case 'browse':
doBrowse();
break;
default:
doDefault();
break;
}
?>

View File

@ -0,0 +1,160 @@
<?php
/**
* Help links for PostgreSQL 7.4 documentation
*/
$this->help_base = sprintf($GLOBALS['conf']['help_base'], '7.4');
# TODO: Check and fix links
$this->help_page = array(
'pg.database' => 'managing-databases.html',
'pg.database.create' => array('sql-createdatabase.html', 'manage-ag-createdb.html'),
'pg.database.alter' => 'sql-alterdatabase.html',
'pg.database.drop' => array('sql-dropdatabase.html', 'manage-ag-dropdb.html'),
'pg.admin.analyze' => 'sql-analyze.html',
'pg.admin.vacuum' => 'sql-vacuum.html',
'pg.cast' => array('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' => array('ddl-alter.html#AEN2115', 'sql-altertable.html'),
'pg.column.alter' => array('ddl-alter.html','sql-altertable.html'),
'pg.column.drop' => array('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' => array('xfunc.html', 'functions.html', 'sql-expressions.html#AEN1599'),
'pg.function.alter' => 'sql-alterfunction.html',
'pg.function.create' => 'sql-createfunction.html',
'pg.function.create.c' => array('xfunc-c.html','sql-createfunction.html'),
'pg.function.create.internal' => array('xfunc-internal.html','sql-createfunction.html'),
'pg.function.create.pl' => array('xfunc-sql.html','xfunc-pl.html','sql-createfunction.html'),
'pg.function.drop' => 'sql-dropfunction.html',
'pg.group' => 'groups.html',
'pg.group.alter' => array('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' => array('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' => array('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' => array( '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' => array('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' => array('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' => array('sql-alteruser.html','user-attributes.html'),
'pg.user.create' => array('sql-createuser.html','user-manag.html#DATABASE-USERS'),
'pg.user.drop' => array('sql-dropuser.html','user-manag.html#DATABASE-USERS'),
'pg.variable' => 'runtime-config.html',
'pg.view' => 'tutorial-views.html',
'pg.view.alter' => array('sql-createview.html','sql-altertable.html'),
'pg.view.create' => 'sql-createview.html',
'pg.view.drop' => 'sql-dropview.html',
'pg.aggregate' => array('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'
);
?>

View File

@ -0,0 +1,28 @@
<?php
/**
* Help links for PostgreSQL 8.0 documentation
*
* $Id: PostgresDoc80.php,v 1.5 2005/02/16 10:27:44 jollytoad Exp $
*/
include('./help/PostgresDoc74.php');
$this->help_base = sprintf($GLOBALS['conf']['help_base'], '8.0');
$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.domain'] = 'extend-type-system.html#AEN27940';
$this->help_page['pg.function'][2] = 'sql-expressions.html#AEN1652';
$this->help_page['pg.operator'][2] = 'sql-expressions.html#AEN1623';
?>

View File

@ -0,0 +1,18 @@
<?php
/**
* Help links for PostgreSQL 8.1 documentation
*
* $Id: PostgresDoc81.php,v 1.3 2006/12/28 04:26:55 xzilla Exp $
*/
include('./help/PostgresDoc80.php');
$this->help_base = sprintf($GLOBALS['conf']['help_base'], '8.1');
$this->help_page['pg.role'] = 'user-manag.html';
$this->help_page['pg.role.create'] = array('sql-createrole.html','user-manag.html#DATABASE-ROLES');
$this->help_page['pg.role.alter'] = array('sql-alterrole.html','role-attributes.html');
$this->help_page['pg.role.drop'] = array('sql-droprole.html','user-manag.html#DATABASE-ROLES');
?>

View File

@ -0,0 +1,13 @@
<?php
/**
* Help links for PostgreSQL 8.2 documentation
*
* $Id: PostgresDoc82.php,v 1.3 2007/11/30 15:27:26 soranzo Exp $
*/
include('./help/PostgresDoc81.php');
$this->help_base = sprintf($GLOBALS['conf']['help_base'], '8.2');
?>

View File

@ -0,0 +1,27 @@
<?php
/**
* Help links for PostgreSQL 8.3 documentation
*
* $Id: PostgresDoc83.php,v 1.3 2008/03/17 21:35:48 ioguix Exp $
*/
include('./help/PostgresDoc82.php');
$this->help_base = sprintf($GLOBALS['conf']['help_base'], '8.3');
$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.ftsdict'] = 'textsearch-dictionaries.html';
$this->help_page['pg.ftsdict.drop'] = 'sql-droptsdictionary.html';
$this->help_page['pg.ftsdict.create'] = array('sql-createtsdictionary.html', 'sql-createtstemplate.html');
$this->help_page['pg.ftsdict.alter'] = 'sql-altertsdictionary.html';
$this->help_page['pg.ftsparser'] = 'textsearch-parsers.html';
?>

View File

@ -0,0 +1,13 @@
<?php
/**
* Help links for PostgreSQL 8.4 documentation
*
* $Id: PostgresDoc84.php,v 1.3 2008/11/18 21:35:48 ioguix Exp $
*/
include('./help/PostgresDoc83.php');
$this->help_base = sprintf($GLOBALS['conf']['help_base'], '8.4');
?>

View File

@ -0,0 +1,13 @@
<?php
/**
* Help links for PostgreSQL 9.0 documentation
*
* $Id: PostgresDoc84.php,v 1.3 2008/11/18 21:35:48 ioguix Exp $
*/
include('./help/PostgresDoc84.php');
$this->help_base = sprintf($GLOBALS['conf']['help_base'], '9.0');
?>

150
php/pgadmin/history.php Normal file
View File

@ -0,0 +1,150 @@
<?php
/**
* Alternative SQL editing window
*
* $Id: history.php,v 1.3 2008/01/10 19:37:07 xzilla Exp $
*/
// Include application functions
include_once('./libraries/lib.inc.php');
$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
function doDefault() {
global $misc, $lang;
$onchange = "onchange=\"location.href='history.php?server=' + encodeURI(server.options[server.selectedIndex].value) + '&amp;database=' + encodeURI(database.options[database.selectedIndex].value) + '&amp;'\"";
$misc->printHeader($lang['strhistory']);
// Bring to the front always
echo "<body onload=\"window.focus();\">\n";
echo "<form action=\"history.php\" method=\"post\">\n";
$misc->printConnection($onchange);
echo "</form><br />";
if (!isset($_REQUEST['database'])) {
echo "<p>{$lang['strnodatabaseselected']}</p>\n";
return;
}
if (isset($_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']])) {
include_once('classes/ArrayRecordSet.php');
$history = new ArrayRecordSet($_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']]);
$columns = array(
'query' => array(
'title' => $lang['strsql'],
'field' => field('query'),
),
'paginate' => array(
'title' => $lang['strpaginate'],
'field' => field('paginate'),
'type' => 'yesno',
),
'actions' => array(
'title' => $lang['stractions'],
),
);
$actions = array(
'run' => array(
'title' => $lang['strexecute'],
'url' => "sql.php?{$misc->href}&amp;nohistory=t&amp;",
'vars' => array('query' => 'query', 'paginate' => 'paginate'),
'target' => 'detail',
),
'remove' => array(
'title' => $lang['strdelete'],
'url' => "history.php?{$misc->href}&amp;action=confdelhistory&amp;",
'vars' => array('queryid' => 'queryid'),
),
);
$misc->printTable($history, $columns, $actions, $lang['strnohistory']);
}
else echo "<p>{$lang['strnohistory']}</p>\n";
echo "<ul class=\"navlink\">\n";
if (isset($_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']])
&& count($_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']]))
echo "\t<li><a href=\"history.php?action=confclearhistory&amp;{$misc->href}\">{$lang['strclearhistory']}</a></li>\n";
echo "\t<li><a href=\"history.php?action=history&amp;{$misc->href}\">{$lang['strrefresh']}</a></li>\n</ul>\n";
}
function doDelHistory($qid, $confirm) {
global $misc, $lang;
if ($confirm) {
$misc->printHeader($lang['strhistory']);
// Bring to the front always
echo "<body onload=\"window.focus();\">\n";
echo "<h3>{$lang['strdelhistory']}</h3>\n";
echo "<p>{$lang['strconfdelhistory']}</p>\n";
echo "<pre>", htmlentities($_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']][$qid]['query']), "</pre>";
echo "<form action=\"history.php\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"delhistory\" />\n";
echo "<input type=\"hidden\" name=\"queryid\" value=\"$qid\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"yes\" value=\"{$lang['stryes']}\" />\n";
echo "<input type=\"submit\" name=\"no\" value=\"{$lang['strno']}\" />\n";
echo "</form>\n";
}
else
unset($_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']][$qid]);
}
function doClearHistory($confirm) {
global $misc, $lang;
if ($confirm) {
$misc->printHeader($lang['strhistory']);
// Bring to the front always
echo "<body onload=\"window.focus();\">\n";
echo "<h3>{$lang['strclearhistory']}</h3>\n";
echo "<p>{$lang['strconfclearhistory']}</p>\n";
echo "<form action=\"history.php\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"clearhistory\" />\n";
echo $misc->form;
echo "<input type=\"submit\" name=\"yes\" value=\"{$lang['stryes']}\" />\n";
echo "<input type=\"submit\" name=\"no\" value=\"{$lang['strno']}\" />\n";
echo "</form>\n";
}
else
unset($_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']]);
}
switch ($action) {
case 'confdelhistory':
doDelHistory($_REQUEST['queryid'], true);
break;
case 'delhistory':
if (isset($_POST['yes'])) doDelHistory($_REQUEST['queryid'], false);
doDefault();
break;
case 'confclearhistory':
doClearHistory(true);
break;
case 'clearhistory':
if (isset($_POST['yes'])) doClearHistory(false);
doDefault();
break;
default:
doDefault();
}
// Set the name of the window
$misc->setWindowName('history');
$misc->printFooter();
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Some files were not shown because too many files have changed in this diff Show More