PostgreSQL: Support functions

This commit is contained in:
Jakub Vrana 2018-01-30 15:18:26 +01:00
parent 6c3e1e2768
commit e81334ef87
7 changed files with 51 additions and 33 deletions

View file

@ -1,8 +1,8 @@
<?php <?php
$PROCEDURE = $_GET["call"]; $PROCEDURE = ($_GET["name"] ? $_GET["name"] : $_GET["call"]);
page_header(lang('Call') . ": " . h($PROCEDURE), $error); page_header(lang('Call') . ": " . h($PROCEDURE), $error);
$routine = routine($PROCEDURE, (isset($_GET["callf"]) ? "FUNCTION" : "PROCEDURE")); $routine = routine($_GET["call"], (isset($_GET["callf"]) ? "FUNCTION" : "PROCEDURE"));
$in = array(); $in = array();
$out = array(); $out = array();
foreach ($routine["fields"] as $i => $field) { foreach ($routine["fields"] as $i => $field) {

View file

@ -159,11 +159,12 @@ if ($adminer->homepage()) {
echo '<thead><tr><th>' . lang('Name') . '<td>' . lang('Type') . '<td>' . lang('Return type') . "<td>&nbsp;</thead>\n"; echo '<thead><tr><th>' . lang('Name') . '<td>' . lang('Type') . '<td>' . lang('Return type') . "<td>&nbsp;</thead>\n";
odd(''); odd('');
foreach ($routines as $row) { foreach ($routines as $row) {
$name = ($row["SPECIFIC_NAME"] == $row["ROUTINE_NAME"] ? "" : "&name=" . urlencode($row["ROUTINE_NAME"])); // not computed on the pages to be able to print the header first
echo '<tr' . odd() . '>'; echo '<tr' . odd() . '>';
echo '<th><a href="' . h(ME) . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'callf=' : 'call=') . urlencode($row["ROUTINE_NAME"]) . '">' . h($row["ROUTINE_NAME"]) . '</a>'; echo '<th><a href="' . h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'callf=' : 'call=') . urlencode($row["SPECIFIC_NAME"]) . $name) . '">' . h($row["ROUTINE_NAME"]) . '</a>';
echo '<td>' . h($row["ROUTINE_TYPE"]); echo '<td>' . h($row["ROUTINE_TYPE"]);
echo '<td>' . h($row["DTD_IDENTIFIER"]); echo '<td>' . h($row["DTD_IDENTIFIER"]);
echo '<td><a href="' . h(ME) . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'function=' : 'procedure=') . urlencode($row["ROUTINE_NAME"]) . '">' . lang('Alter') . "</a>"; echo '<td><a href="' . h(ME . ($row["ROUTINE_TYPE"] != "PROCEDURE" ? 'function=' : 'procedure=') . urlencode($row["SPECIFIC_NAME"]) . $name) . '">' . lang('Alter') . "</a>";
} }
echo "</table>\n"; echo "</table>\n";
} }

View file

@ -840,10 +840,10 @@ if (!defined("DRIVER")) {
} }
/** Get list of routines /** Get list of routines
* @return array ("ROUTINE_TYPE" => , "ROUTINE_NAME" => , "DTD_IDENTIFIER" => ) * @return array ("SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => )
*/ */
function routines() { function routines() {
return get_rows("SELECT ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB)); return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB));
} }
/** Get list of available routine languages /** Get list of available routine languages
@ -853,6 +853,15 @@ if (!defined("DRIVER")) {
return array(); // "SQL" not required return array(); // "SQL" not required
} }
/** Get routine signature
* @param string
* @param array result of routine()
* @return string
*/
function routine_id($name, $row) {
return idf_escape($name);
}
/** Get last auto increment ID /** Get last auto increment ID
* @return string * @return string
*/ */

View file

@ -541,30 +541,36 @@ ORDER BY conkey, conname") as $row) {
); );
} }
/*
function routine($name, $type) { function routine($name, $type) {
//! there can be more functions with the same name differing only in parameters, it must be also passed to DROP FUNCTION $rows = get_rows('SELECT routine_definition AS definition, LOWER(external_language) AS language, *
//! no procedures, only functions FROM information_schema.routines
//! different syntax of CREATE FUNCTION WHERE routine_schema = current_schema() AND specific_name = ' . q($name));
$rows = get_rows('SELECT pg_catalog.format_type(p.prorettype, NULL) AS "returns", p.prosrc AS "definition" $return = $rows[0];
FROM pg_catalog.pg_namespace n $return["returns"] = array("type" => $return["type_udt_name"]);
JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid $return["fields"] = get_rows('SELECT parameter_name AS field, data_type AS type, character_maximum_length AS length, parameter_mode AS inout
WHERE n.nspname = current_schema() AND p.proname = ' . q($name)); FROM information_schema.parameters
$rows[0]["fields"] = array(); //! WHERE specific_schema = current_schema() AND specific_name = ' . q($name) . '
return $rows[0]; ORDER BY ordinal_position');
return $return;
} }
*/
function routines() { function routines() {
return get_rows('SELECT p.proname AS "ROUTINE_NAME", p.proargtypes AS "ROUTINE_TYPE", pg_catalog.format_type(p.prorettype, NULL) AS "DTD_IDENTIFIER" return get_rows('SELECT specific_name AS "SPECIFIC_NAME", routine_type AS "ROUTINE_TYPE", routine_name AS "ROUTINE_NAME", type_udt_name AS "DTD_IDENTIFIER"
FROM pg_catalog.pg_namespace n FROM information_schema.routines
JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid WHERE routine_schema = current_schema()
WHERE n.nspname = current_schema() ORDER BY SPECIFIC_NAME');
ORDER BY p.proname');
} }
function routine_languages() { function routine_languages() {
return get_vals("SELECT langname FROM pg_catalog.pg_language"); return get_vals("SELECT LOWER(lanname) FROM pg_catalog.pg_language");
}
function routine_id($name, $row) {
$return = array();
foreach ($row["fields"] as $field) {
$return[] = $field["type"];
}
return idf_escape($name) . "(" . implode(", ", $return) . ")";
} }
function last_id() { function last_id() {
@ -727,7 +733,7 @@ AND typelem = 0"
} }
function support($feature) { function support($feature) {
return preg_match('~^(database|table|columns|sql|indexes|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|processlist|sequence|trigger|type|variables|drop_col|kill|dump)$~', $feature); //! routine| return preg_match('~^(database|table|columns|sql|indexes|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|routine|processlist|sequence|trigger|type|variables|drop_col|kill|dump)$~', $feature);
} }
function kill_process($val) { function kill_process($val) {

View file

@ -413,7 +413,7 @@ function create_trigger($on, $row) {
* @return string * @return string
*/ */
function create_routine($routine, $row) { function create_routine($routine, $row) {
global $inout; global $inout, $jush;
$set = array(); $set = array();
$fields = (array) $row["fields"]; $fields = (array) $row["fields"];
ksort($fields); // enforce fields order ksort($fields); // enforce fields order
@ -422,13 +422,13 @@ function create_routine($routine, $row) {
$set[] = (preg_match("~^($inout)\$~", $field["inout"]) ? "$field[inout] " : "") . idf_escape($field["field"]) . process_type($field, "CHARACTER SET"); $set[] = (preg_match("~^($inout)\$~", $field["inout"]) ? "$field[inout] " : "") . idf_escape($field["field"]) . process_type($field, "CHARACTER SET");
} }
} }
$definition = rtrim("\n$row[definition]", ";");
return "CREATE $routine " return "CREATE $routine "
. idf_escape(trim($row["name"])) . idf_escape(trim($row["name"]))
. " (" . implode(", ", $set) . ")" . " (" . implode(", ", $set) . ")"
. (isset($_GET["function"]) ? " RETURNS" . process_type($row["returns"], "CHARACTER SET") : "") . (isset($_GET["function"]) ? " RETURNS" . process_type($row["returns"], "CHARACTER SET") : "")
. ($row["language"] ? " LANGUAGE $row[language]" : "") . ($row["language"] ? " LANGUAGE $row[language]" : "")
. rtrim("\n$row[definition]", ";") . ($jush == "pgsql" ? " AS " . q($definition) : "$definition;")
. ";"
; ;
} }

View file

@ -1,17 +1,18 @@
<?php <?php
$PROCEDURE = $_GET["procedure"]; $PROCEDURE = ($_GET["name"] ? $_GET["name"] : $_GET["procedure"]);
$routine = (isset($_GET["function"]) ? "FUNCTION" : "PROCEDURE"); $routine = (isset($_GET["function"]) ? "FUNCTION" : "PROCEDURE");
$row = $_POST; $row = $_POST;
$row["fields"] = (array) $row["fields"]; $row["fields"] = (array) $row["fields"];
if ($_POST && !process_fields($row["fields"]) && !$error) { if ($_POST && !process_fields($row["fields"]) && !$error) {
$orig = routine($_GET["procedure"], $routine);
$temp_name = "$row[name]_adminer_" . uniqid(); $temp_name = "$row[name]_adminer_" . uniqid();
drop_create( drop_create(
"DROP $routine " . idf_escape($PROCEDURE), "DROP $routine " . routine_id($PROCEDURE, $orig),
create_routine($routine, $row), create_routine($routine, $row),
"DROP $routine " . idf_escape($row["name"]), "DROP $routine " . routine_id($row["name"], $row),
create_routine($routine, array("name" => $temp_name) + $row), create_routine($routine, array("name" => $temp_name) + $row),
"DROP $routine " . idf_escape($temp_name), "DROP $routine " . routine_id($temp_name, $row),
substr(ME, 0, -1), substr(ME, 0, -1),
lang('Routine has been dropped.'), lang('Routine has been dropped.'),
lang('Routine has been altered.'), lang('Routine has been altered.'),
@ -24,7 +25,7 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
page_header(($PROCEDURE != "" ? (isset($_GET["function"]) ? lang('Alter function') : lang('Alter procedure')) . ": " . h($PROCEDURE) : (isset($_GET["function"]) ? lang('Create function') : lang('Create procedure'))), $error); page_header(($PROCEDURE != "" ? (isset($_GET["function"]) ? lang('Alter function') : lang('Alter procedure')) . ": " . h($PROCEDURE) : (isset($_GET["function"]) ? lang('Create function') : lang('Create procedure'))), $error);
if (!$_POST && $PROCEDURE != "") { if (!$_POST && $PROCEDURE != "") {
$row = routine($PROCEDURE, $routine); $row = routine($_GET["procedure"], $routine);
$row["name"] = $PROCEDURE; $row["name"] = $PROCEDURE;
} }
@ -35,7 +36,7 @@ $routine_languages = routine_languages();
<form action="" method="post" id="form"> <form action="" method="post" id="form">
<p><?php echo lang('Name'); ?>: <input name="name" value="<?php echo h($row["name"]); ?>" maxlength="64" autocapitalize="off"> <p><?php echo lang('Name'); ?>: <input name="name" value="<?php echo h($row["name"]); ?>" maxlength="64" autocapitalize="off">
<?php echo ($routine_languages ? lang('Language') . ": " . html_select("language", $routine_languages, $row["language"]) : ""); ?> <?php echo ($routine_languages ? lang('Language') . ": " . html_select("language", $routine_languages, $row["language"]) . "\n" : ""); ?>
<input type="submit" value="<?php echo lang('Save'); ?>"> <input type="submit" value="<?php echo lang('Save'); ?>">
<table cellspacing="0" class="nowrap"> <table cellspacing="0" class="nowrap">
<?php <?php

View file

@ -2,6 +2,7 @@ Adminer 4.5.1-dev:
Fix counting selected rows after going back to select page Fix counting selected rows after going back to select page
PHP <5.3 compatibility even with Elasticsearch enabled PHP <5.3 compatibility even with Elasticsearch enabled
MariaDB: Support JSON since MariaDB 10.2 MariaDB: Support JSON since MariaDB 10.2
PostgreSQL: Support functions
SimpleDB: Document that allow_url_fopen is required SimpleDB: Document that allow_url_fopen is required
Malay translation Malay translation