]> git.joonet.de Git - adminer.git/commitdiff
PostgreSQL: Support UPDATE OF triggers (bug #789) and triggers with more events (OR)
authorJakub Vrana <jakub@vrana.cz>
Wed, 3 Mar 2021 10:07:44 +0000 (11:07 +0100)
committerJakub Vrana <jakub@vrana.cz>
Wed, 3 Mar 2021 10:07:58 +0000 (11:07 +0100)
adminer/drivers/pgsql.inc.php
adminer/include/editing.inc.php
adminer/static/editing.js
adminer/trigger.inc.php
changes.txt

index af6f2bfd429097de16e3da46d184584c1c6edcf2..296b8aa3e0d69ee111869a18244a7243dc81ee0a 100644 (file)
@@ -608,21 +608,34 @@ ORDER BY connamespace, conname") as $row) {
                return true;
        }
 
-       function trigger($name, $table = null) {
+       function trigger($name, $table) {
                if ($name == "") {
                        return array("Statement" => "EXECUTE PROCEDURE ()");
                }
-               if ($table === null) {
-                       $table = $_GET['trigger'];
+               $columns = array();
+               $where = "WHERE trigger_schema = current_schema() AND event_object_table = " . q($table) . " AND trigger_name = " . q($name);
+               foreach (get_rows("SELECT * FROM information_schema.triggered_update_columns $where") as $row) {
+                       $columns[] = $row["event_object_column"];
                }
-               $rows = get_rows('SELECT t.trigger_name AS "Trigger", t.action_timing AS "Timing", (SELECT STRING_AGG(event_manipulation, \' OR \') FROM information_schema.triggers WHERE event_object_table = t.event_object_table AND trigger_name = t.trigger_name ) AS "Events", t.event_manipulation AS "Event", \'FOR EACH \' || t.action_orientation AS "Type", t.action_statement AS "Statement" FROM information_schema.triggers t WHERE t.event_object_table = ' . q($table) . ' AND t.trigger_name = ' . q($name));
-               return reset($rows);
+               $return = array();
+               foreach (get_rows('SELECT trigger_name AS "Trigger", action_timing AS "Timing", event_manipulation AS "Event", \'FOR EACH \' || action_orientation AS "Type", action_statement AS "Statement" FROM information_schema.triggers ' . "$where ORDER BY event_manipulation DESC") as $row) {
+                       if ($columns && $row["Event"] == "UPDATE") {
+                               $row["Event"] .= " OF";
+                       }
+                       $row["Of"] = implode(", ", $columns);
+                       if ($return) {
+                               $row["Event"] .= " OR $return[Event]";
+                       }
+                       $return = $row;
+               }
+               return $return;
        }
 
        function triggers($table) {
                $return = array();
                foreach (get_rows("SELECT * FROM information_schema.triggers WHERE trigger_schema = current_schema() AND event_object_table = " . q($table)) as $row) {
-                       $return[$row["trigger_name"]] = array($row["action_timing"], $row["event_manipulation"]);
+                       $trigger = trigger($row["trigger_name"], $table);
+                       $return[$trigger["Trigger"]] = array($trigger["Timing"], $trigger["Event"]);
                }
                return $return;
        }
@@ -630,7 +643,7 @@ ORDER BY connamespace, conname") as $row) {
        function trigger_options() {
                return array(
                        "Timing" => array("BEFORE", "AFTER"),
-                       "Event" => array("INSERT", "UPDATE", "DELETE"),
+                       "Event" => array("INSERT", "UPDATE", "UPDATE OF", "DELETE", "INSERT OR UPDATE", "INSERT OR UPDATE OF", "DELETE OR INSERT", "DELETE OR UPDATE", "DELETE OR UPDATE OF", "DELETE OR INSERT OR UPDATE", "DELETE OR INSERT OR UPDATE OF"),
                        "Type" => array("FOR EACH ROW", "FOR EACH STATEMENT"),
                );
        }
@@ -831,7 +844,7 @@ AND typelem = 0"
                $return = "";
                foreach (triggers($table) as $trg_id => $trg) {
                        $trigger = trigger($trg_id, $status['Name']);
-                       $return .= "\nCREATE TRIGGER " . idf_escape($trigger['Trigger']) . " $trigger[Timing] $trigger[Events] ON " . idf_escape($status["nspname"]) . "." . idf_escape($status['Name']) . " $trigger[Type] $trigger[Statement];;\n";
+                       $return .= "\nCREATE TRIGGER " . idf_escape($trigger['Trigger']) . " $trigger[Timing] $trigger[Event] ON " . idf_escape($status["nspname"]) . "." . idf_escape($status['Name']) . " $trigger[Type] $trigger[Statement];;\n";
                }
                return $return;
        }
index 3cc2734eb04ab06708501d08629e91eacb8e6a20..88d66d4478dc4bd89b1865f651833730aef3984f 100644 (file)
@@ -430,7 +430,7 @@ function drop_create($drop, $create, $drop_created, $test, $drop_test, $location
 */
 function create_trigger($on, $row) {
        global $jush;
-       $timing_event = " $row[Timing] $row[Event]" . ($row["Event"] == "UPDATE OF" ? " " . idf_escape($row["Of"]) : "");
+       $timing_event = " $row[Timing] $row[Event]" . (preg_match('~ OF~', $row["Event"]) ? " $row[Of]" : ""); // SQL injection
        return "CREATE TRIGGER "
                . idf_escape($row["Trigger"])
                . ($jush == "mssql" ? $on . $timing_event : $timing_event . $on)
index 73643c6e2e7560103d600f69786215ec316c8fb5..04210c7258613838d48cba65a1c74d4c83f9a193 100644 (file)
@@ -658,7 +658,7 @@ function triggerChange(tableRe, table, form) {
        if (tableRe.test(form['Trigger'].value)) {
                form['Trigger'].value = table + '_' + (selectValue(form['Timing']).charAt(0) + formEvent.charAt(0)).toLowerCase();
        }
-       alterClass(form['Of'], 'hidden', formEvent != 'UPDATE OF');
+       alterClass(form['Of'], 'hidden', !/ OF/.test(formEvent));
 }
 
 
index 4864862ceed572a61e475e7a1336e1e06fba6fd2..4c780cb04bc07ff4ec207f0af2ec9879cf1e1c50 100644 (file)
@@ -2,7 +2,7 @@
 $TABLE = $_GET["trigger"];
 $name = $_GET["name"];
 $trigger_options = trigger_options();
-$row = (array) trigger($name) + array("Trigger" => $TABLE . "_bi");
+$row = (array) trigger($name, $TABLE) + array("Trigger" => $TABLE . "_bi");
 
 if ($_POST) {
        if (!$error && in_array($_POST["Timing"], $trigger_options["Timing"]) && in_array($_POST["Event"], $trigger_options["Event"]) && in_array($_POST["Type"], $trigger_options["Type"])) {
index ec4bbb6cc8099762f04da59d2e1ea2c3fcd84a49..0500f5cc30ebf53907c8dff305ef3a50158c0aa0 100644 (file)
@@ -2,6 +2,8 @@ Adminer 4.8.1-dev:
 Fix more PHP 8 warnings (bug #781)
 Avoid PHP warnings with PDO drivers (bug #786, regression from 4.7.8)
 MySQL: Allow moving views to other DB and renaming DB with views (bug #783)
+PostgreSQL: Support UPDATE OF triggers (bug #789)
+PostgreSQL: Support triggers with more events (OR)
 PostgreSQL < 10 PDO: Avoid displaying GENERATED ALWAYS BY IDENTITY everywhere (bug #785, regression from 4.7.9)
 SQLite: Fix displayed types (bug #784, regression from 4.8.0)