]> git.joonet.de Git - adminer.git/commitdiff
PostgreSQL: Export all FKs after all CREATE TABLE
authorIvan Masár <helix84@centrum.sk>
Fri, 19 Jul 2019 11:17:10 +0000 (13:17 +0200)
committerJakub Vrana <jakub@vrana.cz>
Sat, 6 Feb 2021 10:37:47 +0000 (11:37 +0100)
adminer/drivers/pgsql.inc.php
adminer/dump.inc.php
changes.txt

index 76c40d3d518acb41a8aa294a8d154b730884765f..5466ed21b2432a03aac14a5cf6b4f3ee23d175de 100644 (file)
@@ -436,6 +436,23 @@ ORDER BY conkey, conname") as $row) {
                return $return;
        }
 
+       function constraints($table) {
+               global $on_actions;
+               $return = array();
+               foreach (get_rows("SELECT conname, consrc
+FROM pg_catalog.pg_constraint
+INNER JOIN pg_catalog.pg_namespace ON pg_constraint.connamespace = pg_namespace.oid
+INNER JOIN pg_catalog.pg_class ON pg_constraint.conrelid = pg_class.oid AND pg_constraint.connamespace = pg_class.relnamespace
+WHERE pg_constraint.contype = 'c'
+AND conrelid != 0 -- handle only CONSTRAINTs here, not TYPES
+AND nspname = current_schema()
+AND relname = " . q($table) . "
+ORDER BY connamespace, conname") as $row) {
+                       $return[$row['conname']] = $row['consrc'];
+               }
+               return $return;
+       }
+
        function view($name) {
                global $connection;
                return array("select" => trim($connection->result("SELECT pg_get_viewdef(" . $connection->result("SELECT oid FROM pg_class WHERE relname = " . q($name)) . ")")));
@@ -704,6 +721,23 @@ AND typelem = 0"
                return $return;
        }
 
+       // create_sql() produces CREATE TABLE without FK CONSTRAINTs
+       // foreign_keys_sql() produces all FK CONSTRAINTs as ALTER TABLE ... ADD CONSTRAINT
+       // so that all FKs can be added after all tables have been created, avoiding any need to reorder CREATE TABLE statements in order of their FK dependencies
+       function foreign_keys_sql($table) {
+               $return = "";
+
+               $status = table_status($table);
+               $fkeys = foreign_keys($table);
+               ksort($fkeys);
+
+               foreach ($fkeys as $fkey_name => $fkey) {
+                       $return .= "ALTER TABLE ONLY " . idf_escape($status['nspname']) . "." . idf_escape($status['Name']) . " ADD CONSTRAINT " . idf_escape($fkey_name) . " $fkey[definition] " . ($fkey['deferrable'] ? 'DEFERRABLE' : 'NOT DEFERRABLE') . ";\n";
+               }
+
+               return ($return ? "$return\n" : $return);
+       }
+
        function create_sql($table, $auto_increment, $style) {
                global $connection;
                $return = '';
@@ -718,8 +752,7 @@ AND typelem = 0"
                $fields = fields($table);
                $indexes = indexes($table);
                ksort($indexes);
-               $fkeys = foreign_keys($table);
-               ksort($fkeys);
+               $constraints = constraints($table);
 
                if (!$status || empty($fields)) {
                        return false;
@@ -759,9 +792,8 @@ AND typelem = 0"
                        }
                }
 
-               // foreign keys
-               foreach ($fkeys as $fkey_name => $fkey) {
-                       $return_parts[] = "CONSTRAINT " . idf_escape($fkey_name) . " $fkey[definition] " . ($fkey['deferrable'] ? 'DEFERRABLE' : 'NOT DEFERRABLE');
+               foreach ($constraints as $conname => $consrc) {
+                       $return_parts[] = "CONSTRAINT " . idf_escape($conname) . " CHECK $consrc";
                }
 
                $return .= implode(",\n    ", $return_parts) . "\n) WITH (oids = " . ($status['Oid'] ? 'true' : 'false') . ");";
index e758f458f7aecbca8d36ba2622aa1a5dd3e552de..f6e9a48b13c17af8b49cbd520b3a27b8b326eb33 100644 (file)
@@ -105,6 +105,16 @@ SET foreign_key_checks = 0;
                                        }
                                }
 
+                               // add FKs after creating tables (except in MySQL which uses SET FOREIGN_KEY_CHECKS=0)
+                               if (function_exists('foreign_keys_sql')) {
+                                       foreach (table_status('', true) as $name => $table_status) {
+                                               $table = (DB == "" || in_array($name, (array) $_POST["tables"]));
+                                               if ($table && !is_view($table_status)) {
+                                                       echo foreign_keys_sql($name);
+                                               }
+                                       }
+                               }
+
                                foreach ($views as $view) {
                                        $adminer->dumpTable($view, $_POST["table_style"], 1);
                                }
index af1cfb5cb1c80ee2bb9b50f42e0ca85af3376efc..7fa7ad50d1e1ece45b8e010f7f4faa3e2b62ab7f 100644 (file)
@@ -1,5 +1,6 @@
 Adminer 4.7.9-dev:
 Elasticsearch, ClickHouse: Do not print response if HTTP code is not 200
+PostgreSQL: Export all FKs after all CREATE TABLE (PR #351)
 PostgreSQL: Fix dollar-quoted syntax highlighting (bug #738)
 Re-enable PHP warnings (regression from 4.7.8)