]> git.joonet.de Git - adminer.git/commitdiff
PostgreSQL: Support functions
authorJakub Vrana <jakub@vrana.cz>
Tue, 30 Jan 2018 14:18:26 +0000 (15:18 +0100)
committerJakub Vrana <jakub@vrana.cz>
Tue, 30 Jan 2018 14:18:26 +0000 (15:18 +0100)
adminer/call.inc.php
adminer/db.inc.php
adminer/drivers/mysql.inc.php
adminer/drivers/pgsql.inc.php
adminer/include/editing.inc.php
adminer/procedure.inc.php
changes.txt

index cc64027a971a2257bf6a930a0efbdfc09ce205e6..9ceb398f35da1fe12fc24ac1248359d088e004a4 100644 (file)
@@ -1,8 +1,8 @@
 <?php
-$PROCEDURE = $_GET["call"];
+$PROCEDURE = ($_GET["name"] ? $_GET["name"] : $_GET["call"]);
 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();
 $out = array();
 foreach ($routine["fields"] as $i => $field) {
index 671c232f2f31670945fa0256de05de353775f0aa..9439a30b7ead8f8c8ac97ed71e92a4f0424ffdc9 100644 (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";
                                odd('');
                                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 '<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["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";
                        }
index 6504536cdbb0b4a4590edd6acca5440bbb7d9a19..5adbac8376b6ab9a657c944ac0f1c951821ff605 100644 (file)
@@ -840,10 +840,10 @@ if (!defined("DRIVER")) {
        }
 
        /** Get list of routines
-       * @return array ("ROUTINE_TYPE" => , "ROUTINE_NAME" => , "DTD_IDENTIFIER" => )
+       * @return array ("SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => )
        */
        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
@@ -853,6 +853,15 @@ if (!defined("DRIVER")) {
                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
        * @return string
        */
index 793a02ff1a5ed42de814c6028f0596d883fa13ee..cd24826fa8fa19a880742148f24b17547d0f90dd 100644 (file)
@@ -541,30 +541,36 @@ ORDER BY conkey, conname") as $row) {
                );
        }
 
-       /*
        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
-               //! no procedures, only functions
-               //! different syntax of CREATE FUNCTION
-               $rows = get_rows('SELECT pg_catalog.format_type(p.prorettype, NULL) AS "returns", p.prosrc AS "definition"
-FROM pg_catalog.pg_namespace n
-JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid
-WHERE n.nspname = current_schema() AND p.proname = ' . q($name));
-               $rows[0]["fields"] = array(); //!
-               return $rows[0];
-       }
-       */
+               $rows = get_rows('SELECT routine_definition AS definition, LOWER(external_language) AS language, *
+FROM information_schema.routines
+WHERE routine_schema = current_schema() AND specific_name = ' . q($name));
+               $return = $rows[0];
+               $return["returns"] = array("type" => $return["type_udt_name"]);
+               $return["fields"] = get_rows('SELECT parameter_name AS field, data_type AS type, character_maximum_length AS length, parameter_mode AS inout
+FROM information_schema.parameters
+WHERE specific_schema = current_schema() AND specific_name = ' . q($name) . '
+ORDER BY ordinal_position');
+               return $return;
+       }
 
        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"
-FROM pg_catalog.pg_namespace n
-JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid
-WHERE n.nspname = current_schema()
-ORDER BY p.proname');
+               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 information_schema.routines
+WHERE routine_schema = current_schema()
+ORDER BY SPECIFIC_NAME');
        }
 
        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() {
@@ -727,7 +733,7 @@ AND typelem = 0"
        }
 
        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) {
index 23a174d0951e310c1b86ebe45cf90c7584052533..983e6c0d4999bf2ec88edfd5abbaab7664cbe27b 100644 (file)
@@ -413,7 +413,7 @@ function create_trigger($on, $row) {
 * @return string
 */
 function create_routine($routine, $row) {
-       global $inout;
+       global $inout, $jush;
        $set = array();
        $fields = (array) $row["fields"];
        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");
                }
        }
+       $definition = rtrim("\n$row[definition]", ";");
        return "CREATE $routine "
                . idf_escape(trim($row["name"]))
                . " (" . implode(", ", $set) . ")"
                . (isset($_GET["function"]) ? " RETURNS" . process_type($row["returns"], "CHARACTER SET") : "")
                . ($row["language"] ? " LANGUAGE $row[language]" : "")
-               . rtrim("\n$row[definition]", ";")
-               . ";"
+               . ($jush == "pgsql" ? " AS " . q($definition) : "$definition;")
        ;
 }
 
index fede3e33b2f39f23541df8865074127c8a6d626c..942dd1897669002ea6c2753d278fe438b52e09b7 100644 (file)
@@ -1,17 +1,18 @@
 <?php
-$PROCEDURE = $_GET["procedure"];
+$PROCEDURE = ($_GET["name"] ? $_GET["name"] : $_GET["procedure"]);
 $routine = (isset($_GET["function"]) ? "FUNCTION" : "PROCEDURE");
 $row = $_POST;
 $row["fields"] = (array) $row["fields"];
 
 if ($_POST && !process_fields($row["fields"]) && !$error) {
+       $orig = routine($_GET["procedure"], $routine);
        $temp_name = "$row[name]_adminer_" . uniqid();
        drop_create(
-               "DROP $routine " . idf_escape($PROCEDURE),
+               "DROP $routine " . routine_id($PROCEDURE, $orig),
                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),
-               "DROP $routine " . idf_escape($temp_name),
+               "DROP $routine " . routine_id($temp_name, $row),
                substr(ME, 0, -1),
                lang('Routine has been dropped.'),
                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);
 
 if (!$_POST && $PROCEDURE != "") {
-       $row = routine($PROCEDURE, $routine);
+       $row = routine($_GET["procedure"], $routine);
        $row["name"] = $PROCEDURE;
 }
 
@@ -35,7 +36,7 @@ $routine_languages = routine_languages();
 
 <form action="" method="post" id="form">
 <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'); ?>">
 <table cellspacing="0" class="nowrap">
 <?php
index eb76513a8c7301a6f1612a8a51f86c36ac91450c..5315231cc3ee4a77a3c3ce37c82734032a2b7960 100644 (file)
@@ -2,6 +2,7 @@ Adminer 4.5.1-dev:
 Fix counting selected rows after going back to select page
 PHP <5.3 compatibility even with Elasticsearch enabled
 MariaDB: Support JSON since MariaDB 10.2
+PostgreSQL: Support functions
 SimpleDB: Document that allow_url_fopen is required
 Malay translation