Example #1
0
 function applyTables()
 {
     if (empty($this->schema['TABLE'])) {
         return;
     }
     foreach ($this->schema['TABLE'] as $table => $columns) {
         if (empty($table)) {
             continue;
         }
         if (!DB_TableExists($table)) {
             $sql = "CREATE TABLE \"{$table}\" ()";
             $this->applyOrEchoOnce($sql, $stmt = __METHOD__ . $table);
         }
         foreach ($columns as $column => $modification) {
             if ($this->currSchema['TABLE'][$table][$column]['ADD'] != $modification['ADD']) {
                 $rename = "";
                 if (DB_ColExists($table, $column)) {
                     /* The column exists, but it looks different!
                        Solution: Delete the column! */
                     $rename = $column . '_old';
                     $sql = "ALTER TABLE \"{$table}\" RENAME COLUMN \"{$column}\" TO \"{$rename}\"";
                     $this->applyOrEchoOnce($sql);
                 }
                 $sql = $modification['ADD'];
                 if ($this->debug) {
                     print "{$sql}\n";
                 } else {
                     // Add the new column which sets the default value
                     $this->dbman->queryOnce($sql);
                 }
                 if (!empty($rename)) {
                     /* copy over the old data */
                     $this->applyOrEchoOnce($sql = "UPDATE \"{$table}\" SET \"{$column}\" = \"{$rename}\"");
                     $this->applyOrEchoOnce($sql = "ALTER TABLE \"{$table}\" DROP COLUMN \"{$rename}\"");
                 }
             }
             if ($this->currSchema['TABLE'][$table][$column]['ALTER'] != $modification['ALTER'] && isset($modification['ALTER'])) {
                 $sql = $modification['ALTER'];
                 if ($this->debug) {
                     print "{$sql}\n";
                 } else {
                     if (!empty($sql)) {
                         $this->dbman->queryOnce($sql);
                     }
                 }
             }
             if ($this->currSchema['TABLE'][$table][$column]['DESC'] != $modification['DESC']) {
                 $sql = empty($modification['DESC']) ? "COMMENT ON COLUMN \"{$table}\".\"{$column}\" IS ''" : $modification['DESC'];
                 $this->applyOrEchoOnce($sql, $stmt = __METHOD__ . "{$table}.{$column}.comment");
             }
         }
     }
 }
Example #2
0
/**
 * @brief Make schema match $Filename.  This is a single transaction.
 * @param $Filename Schema file written by schema-export.php
 * @param $Debug Turn on debugging (echo sql as it is being executed)
 * @param $Catalog Optional database name
 * @return false=success, on error return string with error message.
 **/
function ApplySchema($Filename = NULL, $Debug = false, $Catalog = 'fossology')
{
    global $PG_CONN;
    if (!file_exists($Filename)) {
        $ErrMsg = $Filename . " does not exist.";
        return $ErrMsg;
    }
    require_once $Filename;
    /* this will DIE if the file does not exist. */
    /* Very basic sanity check (so we don't delete everything!) */
    if (count($Schema['TABLE']) < 5 || count($Schema['SEQUENCE']) < 5 || count($Schema['INDEX']) < 5 || count($Schema['CONSTRAINT']) < 5) {
        $ErrMsg = "Schema from '{$Filename}' appears invalid.";
        return $ErrMsg;
    }
    /* get the current statement timeout */
    $SQL = "show statement_timeout";
    $result = pg_query($PG_CONN, $SQL);
    DBCheckResult($result, $SQL, __FILE__, __LINE__);
    $Results = pg_fetch_all($result);
    $Statement_Timeout = $Results[0]['statement_timeout'];
    pg_free_result($result);
    pg_query($PG_CONN, "SET statement_timeout = 0;");
    /* turn off DB timeouts */
    pg_query($PG_CONN, "BEGIN;");
    $Curr = GetSchema();
    /* The gameplan: Make $Curr look like $Schema. */
    // print "<pre>"; print_r($Schema); print "</pre>";
    /* turn off E_NOTICE so this stops reporting undefined index */
    $errlev = error_reporting(E_ERROR | E_WARNING | E_PARSE);
    /************************************/
    /* Add sequences */
    /************************************/
    if (!empty($Schema['SEQUENCE'])) {
        foreach ($Schema['SEQUENCE'] as $Name => $SQL) {
            if (empty($Name)) {
                echo "warning empty sequence in .dat\n";
                continue;
            }
            if ($Curr['SEQUENCE'][$Name] == $SQL) {
                continue;
            }
            if ($Debug) {
                print "{$SQL}\n";
            } else {
                $result = pg_query($PG_CONN, $SQL);
                DBCheckResult($result, $SQL, __FILE__, __LINE__);
            }
        }
    }
    /************************************/
    /* Add tables/columns (dependent on sequences for default values) */
    /************************************/
    if (!empty($Schema['TABLE'])) {
        foreach ($Schema['TABLE'] as $Table => $Columns) {
            if (empty($Table)) {
                continue;
            }
            if (!DB_TableExists($Table)) {
                $SQL = "CREATE TABLE \"{$Table}\" ();";
                if ($Debug) {
                    print "{$SQL}\n";
                } else {
                    $result = pg_query($PG_CONN, $SQL);
                    DBCheckResult($result, $SQL, __FILE__, __LINE__);
                }
            }
            foreach ($Columns as $Column => $Val) {
                if ($Curr['TABLE'][$Table][$Column]['ADD'] != $Val['ADD']) {
                    $Rename = "";
                    if (DB_ColExists($Table, $Column)) {
                        /* The column exists, but it looks different!
                           Solution: Delete the column! */
                        $Rename = $Column . "_old";
                        $SQL = "ALTER TABLE \"{$Table}\" RENAME COLUMN \"{$Column}\" TO \"{$Rename}\";";
                        if ($Debug) {
                            print "{$SQL}\n";
                        } else {
                            $result = pg_query($PG_CONN, $SQL);
                            DBCheckResult($result, $SQL, __FILE__, __LINE__);
                        }
                    }
                    $SQL = $Val['ADD'];
                    if ($Debug) {
                        print "{$SQL}\n";
                    } else {
                        // Add the new column, then set the default value with update
                        $result = pg_query($PG_CONN, $SQL);
                        DBCheckResult($result, $SQL, __FILE__, __LINE__);
                        if (!empty($Val['UPDATE'])) {
                            $SQL = $Val['UPDATE'];
                            $result = pg_query($PG_CONN, $SQL);
                            DBCheckResult($result, $SQL, __FILE__, __LINE__);
                        }
                    }
                    if (!empty($Rename)) {
                        /* copy over the old data */
                        $SQL = "UPDATE \"{$Table}\" SET \"{$Column}\" = \"{$Rename}\";";
                        if ($Debug) {
                            print "{$SQL}\n";
                        } else {
                            $result = pg_query($PG_CONN, $SQL);
                            DBCheckResult($result, $SQL, __FILE__, __LINE__);
                        }
                        $SQL = "ALTER TABLE \"{$Table}\" DROP COLUMN \"{$Rename}\";";
                        if ($Debug) {
                            print "{$SQL}\n";
                        } else {
                            $result = pg_query($PG_CONN, $SQL);
                            DBCheckResult($result, $SQL, __FILE__, __LINE__);
                        }
                    }
                }
                // if
                if ($Curr['TABLE'][$Table][$Column]['ALTER'] != $Val['ALTER']) {
                    if ($Debug) {
                        print $Val['ALTER'] . "\n";
                    } else {
                        $SQL = $Val['ALTER'];
                        $result = pg_query($PG_CONN, $SQL);
                        DBCheckResult($result, $SQL, __FILE__, __LINE__);
                        $SQL = $Val['UPDATE'];
                        if (!empty($Val['UPDATE'])) {
                            $SQL = $Val['UPDATE'];
                            $result = pg_query($PG_CONN, $SQL);
                            DBCheckResult($result, $SQL, __FILE__, __LINE__);
                        }
                    }
                }
                if ($Curr['TABLE'][$Table][$Column]['DESC'] != $Val['DESC']) {
                    if (empty($Val['DESC'])) {
                        $SQL = "COMMENT ON COLUMN \"{$Table}\".\"{$Column}\" IS '';";
                    } else {
                        $SQL = $Val['DESC'];
                    }
                    if ($Debug) {
                        print "{$SQL}\n";
                    } else {
                        $result = pg_query($PG_CONN, $SQL);
                        DBCheckResult($result, $SQL, __FILE__, __LINE__);
                    }
                }
            }
        }
    }
    /************************************/
    /* Add views (dependent on columns) */
    /************************************/
    if (!empty($Schema['VIEW'])) {
        foreach ($Schema['VIEW'] as $Name => $SQL) {
            if (empty($Name)) {
                continue;
            }
            if ($Curr['VIEW'][$Name] == $SQL) {
                continue;
            }
            if (!empty($Curr['VIEW'][$Name])) {
                /* Delete it if it exists and looks different */
                $SQL1 = "DROP VIEW {$Name};";
                if ($Debug) {
                    print "{$SQL1}\n";
                } else {
                    $result = pg_query($PG_CONN, $SQL1);
                    DBCheckResult($result, $SQL1, __FILE__, __LINE__);
                }
            }
            /* Create the view */
            if ($Debug) {
                print "{$SQL}\n";
            } else {
                $result = pg_query($PG_CONN, $SQL);
                DBCheckResult($result, $SQL, __FILE__, __LINE__);
            }
        }
    }
    /************************************/
    /* Delete constraints */
    /* Delete now, so they won't interfere with migrations. */
    /************************************/
    if (!empty($Curr['CONSTRAINT'])) {
        foreach ($Curr['CONSTRAINT'] as $Name => $SQL) {
            if (empty($Name)) {
                continue;
            }
            /* Only process tables that I know about */
            $Table = preg_replace("/^ALTER TABLE \"(.*)\" ADD CONSTRAINT.*/", '${1}', $SQL);
            $TableFk = preg_replace("/^.*FOREIGN KEY .* REFERENCES \"(.*)\" \\(.*/", '${1}', $SQL);
            if ($TableFk == $SQL) {
                $TableFk = $Table;
            }
            /* If I don't know the primary or foreign table... */
            if (empty($Schema['TABLE'][$Table]) && empty($Schema['TABLE'][$TableFk])) {
                continue;
            }
            /* If it is already set correctly, then skip it. */
            if ($Schema['CONSTRAINT'][$Name] == $SQL) {
                continue;
            }
            $SQL = "ALTER TABLE \"{$Table}\" DROP CONSTRAINT \"{$Name}\" CASCADE;";
            if ($Debug) {
                print "{$SQL}\n";
            } else {
                $result = @pg_query($PG_CONN, $SQL);
                DBCheckResult($result, $SQL, __FILE__, __LINE__);
            }
        }
    }
    /* Reload current since the CASCADE may have changed things */
    /************************************/
    /* Delete indexes */
    /************************************/
    $Curr = GetSchema();
    /* constraints and indexes are linked, recheck */
    if (!empty($Curr['INDEX'])) {
        foreach ($Curr['INDEX'] as $Table => $IndexInfo) {
            if (empty($Table)) {
                continue;
            }
            /* Only delete indexes on known tables */
            if (empty($Schema['TABLE'][$Table])) {
                continue;
            }
            foreach ($IndexInfo as $Name => $SQL) {
                if (empty($Name)) {
                    continue;
                }
                /* Only delete indexes that are different */
                if ($Schema['INDEX'][$Table][$Name] == $SQL) {
                    continue;
                }
                $SQL = "DROP INDEX \"{$Name}\";";
                if ($Debug) {
                    print "{$SQL}\n";
                } else {
                    $result = pg_query($PG_CONN, $SQL);
                    DBCheckResult($result, $SQL, __FILE__, __LINE__);
                }
            }
        }
    }
    /************************************/
    /* Add indexes (dependent on columns) */
    /************************************/
    if (!empty($Schema['INDEX'])) {
        foreach ($Schema['INDEX'] as $Table => $IndexInfo) {
            if (empty($Table)) {
                continue;
            }
            // bobg
            if (!array_key_exists($Table, $Schema["TABLE"])) {
                echo "skipping orphan table: {$Table}\n";
                continue;
            }
            foreach ($IndexInfo as $Name => $SQL) {
                if (empty($Name)) {
                    continue;
                }
                if ($Curr['INDEX'][$Table][$Name] == $SQL) {
                    continue;
                }
                if ($Debug) {
                    print "{$SQL}\n";
                } else {
                    $result = pg_query($PG_CONN, $SQL);
                    DBCheckResult($result, $SQL, __FILE__, __LINE__);
                }
                $SQL = "REINDEX INDEX \"{$Name}\";";
                if ($Debug) {
                    print "{$SQL}\n";
                } else {
                    $result = pg_query($PG_CONN, $SQL);
                    DBCheckResult($result, $SQL, __FILE__, __LINE__);
                }
            }
        }
    }
    /************************************/
    /* Add constraints (dependent on columns, views, and indexes) */
    /************************************/
    $Curr = GetSchema();
    /* constraints and indexes are linked, recheck */
    if (!empty($Schema['CONSTRAINT'])) {
        /* Constraints must be added in the correct order! */
        /* CONSTRAINT: PRIMARY KEY */
        foreach ($Schema['CONSTRAINT'] as $Name => $SQL) {
            if (empty($Name)) {
                continue;
            }
            if ($Curr['CONSTRAINT'][$Name] == $SQL) {
                continue;
            }
            if (!preg_match("/PRIMARY KEY/", $SQL)) {
                continue;
            }
            if ($Debug) {
                print "{$SQL}\n";
            } else {
                $result = pg_query($PG_CONN, $SQL);
                DBCheckResult($result, $SQL, __FILE__, __LINE__);
            }
        }
        /* CONSTRAINT: UNIQUE */
        foreach ($Schema['CONSTRAINT'] as $Name => $SQL) {
            if (empty($Name)) {
                continue;
            }
            if ($Curr['CONSTRAINT'][$Name] == $SQL) {
                continue;
            }
            if (!preg_match("/UNIQUE/", $SQL)) {
                continue;
            }
            if ($Debug) {
                print "{$SQL}\n";
            } else {
                $result = pg_query($PG_CONN, $SQL);
                DBCheckResult($result, $SQL, __FILE__, __LINE__);
            }
        }
        /* CONSTRAINT: FOREIGN KEY */
        foreach ($Schema['CONSTRAINT'] as $Name => $SQL) {
            if (empty($Name)) {
                continue;
            }
            if ($Curr['CONSTRAINT'][$Name] == $SQL) {
                continue;
            }
            if (!preg_match("/FOREIGN KEY/", $SQL)) {
                continue;
            }
            if ($Debug) {
                print "{$SQL}\n";
            } else {
                $result = pg_query($PG_CONN, $SQL);
                DBCheckResult($result, $SQL, __FILE__, __LINE__);
            }
        }
        /* All other constraints */
        foreach ($Schema['CONSTRAINT'] as $Name => $SQL) {
            if (empty($Name)) {
                continue;
            }
            if ($Curr['CONSTRAINT'][$Name] == $SQL) {
                continue;
            }
            if (preg_match("/PRIMARY KEY/", $SQL)) {
                continue;
            }
            if (preg_match("/UNIQUE/", $SQL)) {
                continue;
            }
            if (preg_match("/FOREIGN KEY/", $SQL)) {
                continue;
            }
            if ($Debug) {
                print "{$SQL}\n";
            } else {
                $result = pg_query($PG_CONN, $SQL);
                DBCheckResult($result, $SQL, __FILE__, __LINE__);
            }
        }
    }
    /* Add constraints */
    error_reporting($errlev);
    /* return to previous error reporting level */
    /************************************/
    /* CREATE FUNCTIONS */
    /************************************/
    MakeFunctions($Debug);
    /* Reload current since CASCADE during migration may have changed things */
    $Curr = GetSchema();
    /************************************/
    /* Delete views */
    /************************************/
    print "  Removing obsolete views\n";
    flush();
    /* Get current tables and columns used by all views */
    /* Delete if: uses table I know and column I do not know. */
    /* Without this delete, we won't be able to drop columns. */
    $SQL = "SELECT view_name,table_name,column_name\n  FROM information_schema.view_column_usage\n  WHERE table_catalog='{$Catalog}'\n  ORDER BY view_name,table_name,column_name;";
    $result = pg_query($PG_CONN, $SQL);
    DBCheckResult($result, $SQL, __FILE__, __LINE__);
    $Results = pg_fetch_all($result);
    for ($i = 0; !empty($Results[$i]['view_name']); $i++) {
        $View = $Results[$i]['view_name'];
        $Table = $Results[$i]['table_name'];
        if (empty($Schema['TABLE'][$Table])) {
            continue;
        }
        $Column = $Results[$i]['column_name'];
        if (empty($Schema['TABLE'][$Table][$Column])) {
            $SQL = "DROP VIEW \"{$View}\";";
            if ($Debug) {
                print "{$SQL}\n";
            } else {
                $results = pg_query($PG_CONN, $SQL);
                DBCheckResult($results, $SQL, __FILE__, __LINE__);
            }
        }
    }
    /************************************/
    /* Delete columns/tables */
    /************************************/
    print "  Removing obsolete columns\n";
    flush();
    if (!empty($Curr['TABLE'])) {
        foreach ($Curr['TABLE'] as $Table => $Columns) {
            if (empty($Table)) {
                continue;
            }
            /* only delete from tables I know */
            if (empty($Schema['TABLE'][$Table])) {
                continue;
            }
            foreach ($Columns as $Column => $Val) {
                if (empty($Column)) {
                    continue;
                }
                if (empty($Schema['TABLE'][$Table][$Column])) {
                    $SQL = "ALTER TABLE \"{$Table}\" DROP COLUMN \"{$Column}\";";
                    if ($Debug) {
                        print "{$SQL}\n";
                    } else {
                        $results = pg_query($PG_CONN, $SQL);
                        DBCheckResult($results, $SQL, __FILE__, __LINE__);
                    }
                }
            }
        }
    }
    /************************************/
    /* Commit changes */
    /************************************/
    $results = pg_query($PG_CONN, "COMMIT;");
    DBCheckResult($results, $SQL, __FILE__, __LINE__);
    /************************************/
    /* Flush any cached data. */
    /************************************/
    ReportCachePurgeAll();
    /* restore DB timeouts */
    pg_query($PG_CONN, "SET statement_timeout = {$Statement_Timeout};");
    return false;
}