Package edu.brown.catalog

Source Code of edu.brown.catalog.CatalogCloner

package edu.brown.catalog;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;

import org.apache.log4j.Logger;
import org.voltdb.catalog.Catalog;
import org.voltdb.catalog.CatalogMap;
import org.voltdb.catalog.CatalogProxy;
import org.voltdb.catalog.CatalogType;
import org.voltdb.catalog.Cluster;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.ColumnRef;
import org.voltdb.catalog.ConflictPair;
import org.voltdb.catalog.ConflictSet;
import org.voltdb.catalog.Constraint;
import org.voltdb.catalog.ConstraintRef;
import org.voltdb.catalog.Database;
import org.voltdb.catalog.Index;
import org.voltdb.catalog.MaterializedViewInfo;
import org.voltdb.catalog.PlanFragment;
import org.voltdb.catalog.ProcParameter;
import org.voltdb.catalog.Procedure;
import org.voltdb.catalog.Site;
import org.voltdb.catalog.Statement;
import org.voltdb.catalog.StmtParameter;
import org.voltdb.catalog.Table;
import org.voltdb.catalog.TableRef;
import org.voltdb.types.ConstraintType;

import edu.brown.catalog.special.MultiColumn;
import edu.brown.catalog.special.MultiProcParameter;
import edu.brown.catalog.special.ReplicatedColumn;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.utils.AbstractTreeWalker;

public abstract class CatalogCloner {
    private static final Logger LOG = Logger.getLogger(CatalogCloner.class);
    private static final LoggerBoolean debug = new LoggerBoolean();
    private static final LoggerBoolean trace = new LoggerBoolean();
    static {
        LoggerUtil.attachObserver(LOG, debug, trace);
    }

    /**
     * Clone and return the given catalog
     *
     * @param catalog_db
     * @return
     * @throws Exception
     */
    public static Database cloneDatabase(Database catalog_db) throws Exception {
        assert (catalog_db != null);
        // Catalog clone_catalog = new Catalog();
        // clone_catalog.execute(catalog_db.getCatalog().serialize());
        // return (CatalogUtil.getDatabase(clone_catalog));

        final Catalog clone_catalog = CatalogCloner.cloneBaseCatalog(catalog_db.getCatalog(), new ArrayList<Class<? extends CatalogType>>());
        Database clone_db = CatalogUtil.getDatabase(clone_catalog);
        assert (!catalog_db.equals(clone_db));

        // Need to also clone the MultiColumn guys too!
        for (Table catalog_tbl : catalog_db.getTables()) {
            Table clone_tbl = clone_db.getTables().get(catalog_tbl.getName());
            for (Column catalog_col : catalog_tbl.getColumns()) {
                if (catalog_col instanceof MultiColumn) {
                    MultiColumn mc = (MultiColumn) catalog_col;
                    Column clone_cols[] = new Column[mc.size()];
                    for (int i = 0; i < clone_cols.length; i++) {
                        clone_cols[i] = clone_tbl.getColumns().get(mc.get(i).getName());
                    } // FOR

                    MultiColumn clone_mc = MultiColumn.get(clone_cols);
                    assert (clone_mc != null);
                }
            }
            assert (catalog_tbl.getColumns().size() == clone_tbl.getColumns().size()) : catalog_tbl.getColumns() + " != " + clone_tbl.getColumns();
        } // FOR

        // And don't forget MultiProcParameter!
        for (Procedure catalog_proc : catalog_db.getProcedures()) {
            Procedure clone_proc = clone_db.getProcedures().get(catalog_proc.getName());
            for (ProcParameter catalog_param : catalog_proc.getParameters()) {
                if (catalog_param instanceof MultiProcParameter) {
                    MultiProcParameter mpp = (MultiProcParameter) catalog_param;
                    ProcParameter clone_params[] = new ProcParameter[mpp.size()];
                    for (int i = 0; i < clone_params.length; i++) {
                        clone_params[i] = clone_proc.getParameters().get(mpp.get(i).getIndex());
                    } // FOR

                    // This will automatically add our guy into clone_tbl
                    MultiProcParameter clone_mpp = MultiProcParameter.get(clone_params);
                    assert (clone_mpp != null);
                }
            }
            assert (catalog_proc.getParameters().size() == clone_proc.getParameters().size()) : catalog_proc.getParameters() + " != " + clone_proc.getParameters();
        } // FOR

        return (clone_db);
    }

    /**
     * Clones the base components of a catalog. All underlying objects are recreated
     * @param catalog
     * @return
     */
    public static Catalog cloneBaseCatalog(Catalog catalog) {
        HashSet<Class<? extends CatalogType>> skip_types = new HashSet<Class<? extends CatalogType>>();
        skip_types.add(Table.class);
       
        // XXX: I don't remember why I did this instead of just re-executing Catalog.serialize()?
        return (CatalogCloner.cloneBaseCatalog(catalog, skip_types));
    }

    public static Catalog cloneBaseCatalog(Catalog catalog, Class<? extends CatalogType>... skip_types) {
        return (CatalogCloner.cloneBaseCatalog(catalog, Arrays.asList(skip_types)));
    }

    /**
     * @param catalog
     * @param skip_types
     * @return
     */
    public static Catalog cloneBaseCatalog(Catalog catalog, final Collection<Class<? extends CatalogType>> skip_types) {
        final Catalog new_catalog = new Catalog();

        new AbstractTreeWalker<CatalogType>() {
            protected void populate_children(AbstractTreeWalker.Children<CatalogType> children, CatalogType element) {
                if (element instanceof Catalog) {
                    children.addAfter(((Catalog) element).getClusters().values());
                } else if (element instanceof Cluster) {
                    children.addAfter(((Cluster) element).getDatabases().values());
                    children.addAfter(((Cluster) element).getHosts().values());
                    children.addAfter(((Cluster) element).getSites().values());
                } else if (element instanceof Site) {
                    children.addAfter(((Site) element).getPartitions().values());
                } else if (element instanceof Database) {
                    children.addAfter(((Database) element).getProcedures().values());
                    children.addAfter(((Database) element).getPrograms().values());
                    children.addAfter(((Database) element).getTables().values());
                } else if (element instanceof Procedure) {
                    for (ProcParameter param : ((Procedure) element).getParameters().values()) {
                        if (!(param instanceof MultiProcParameter))
                            children.addAfter(param);
                    } // FOR
                    children.addAfter(((Procedure) element).getStatements().values());
                } else if (element instanceof Statement) {
                    children.addAfter(((Statement) element).getParameters().values());
                    children.addAfter(((Statement) element).getFragments().values());
                    children.addAfter(((Statement) element).getMs_fragments().values());
                    children.addAfter(((Statement) element).getOutput_columns().values());
                } else if (element instanceof PlanFragment) {
                    // children.addAfter(((PlanFragment)element).getDependencyids().values());
                    // children.addAfter(((PlanFragment)element).getOutputdependencyids().values());
                }
            };

            @Override
            protected void callback(CatalogType element) {
                if (element != null && !skip_types.contains(element.getClass()))
                    CatalogCloner.clone(element, new_catalog);
            }
        }.traverse(catalog);
       
        Database orig_database = CatalogUtil.getDatabase(catalog);
        Database new_database = CatalogUtil.getDatabase(new_catalog);

        if (skip_types.contains(Table.class) == false && skip_types.contains(Column.class) == false) {
            // Clone constraints if they were not skipped
            if (skip_types.contains(Constraint.class) == false) {
                CatalogCloner.cloneConstraints(orig_database, new_database);
            }
           
            // Clone MaterializedViewes if they were not skipped
            // if (skip_types.contains(MaterializedViewInfo.class) == false) {
            // CatalogCloner.cloneViews(CatalogUtil.getDatabase(catalog),
            // CatalogUtil.getDatabase(new_catalog));
            // }
        }
           
        // Clone Procedure conflicts if they were not skipped
        if (skip_types.contains(Procedure.class) == false) {
            CatalogCloner.cloneConflicts(orig_database, new_database);
        }
           
        return (new_catalog);
    }

    /**
     * Add a single catalog element from one catalog into the destination
     * catalog Note that this will not copy constraints for tables, since that
     * needs to be done later to ensure that any foreign key references are
     * included properly
     *
     * @param <T>
     * @param src_item
     * @param dest_catalog
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends CatalogType> T clone(T src_item, Catalog dest_catalog) {
        StringBuilder buffer = new StringBuilder();
        if (src_item instanceof MultiProcParameter) {
            LOG.warn(src_item + ": ??????????");
            return (null);
        }
        CatalogProxy.writeCommands(src_item, buffer);
        dest_catalog.execute(buffer.toString());
        T clone = (T) dest_catalog.getItemForRef(src_item.getPath());

        // SPECIAL HANDLING

        // Table
        if (src_item instanceof Table) {
            Table src_tbl = (Table) src_item;
            Table dest_tbl = (Table) clone;

            // Columns
            for (Column src_col : src_tbl.getColumns()) {
                if (!(src_col instanceof MultiColumn))
                    CatalogCloner.clone(src_col, dest_catalog);
            } // FOR
            // Indexes
            for (Index src_idx : src_tbl.getIndexes()) {
                CatalogCloner.clone(src_idx, dest_catalog);
            } // FOR
            // MaterializedViews
            for (MaterializedViewInfo src_view : src_tbl.getViews()) {
                CatalogCloner.clone(src_view, dest_catalog);
            } // FOR

            // // Constraints
            // for (Constraint src_cons : ((Table)src).getConstraints()) {
            // CatalogUtil.clone(src_cons, dest_catalog);
            // } // FOR

            // Partitioning Column
            if (src_tbl.getPartitioncolumn() != null) {
                Column src_part_col = src_tbl.getPartitioncolumn();
                Column dest_part_col = null;

                // Special Case: Replicated Column Marker
                if (src_part_col instanceof ReplicatedColumn) {
                    dest_part_col = ReplicatedColumn.get(dest_tbl);
                // Special Case: MultiColumn
                } else if (src_part_col instanceof MultiColumn) {
                    MultiColumn mc = (MultiColumn) src_part_col;
                    Column dest_cols[] = new Column[mc.size()];
                    for (int i = 0; i < dest_cols.length; i++) {
                        dest_cols[i] = dest_tbl.getColumns().get(mc.get(i).getName());
                    } // FOR
                    dest_part_col = MultiColumn.get(dest_cols);

                } else {
                    dest_part_col = dest_tbl.getColumns().get(src_part_col.getName());
                }
                assert (dest_part_col != null) : "Missing partitioning column " + CatalogUtil.getDisplayName(src_part_col);
                dest_tbl.setPartitioncolumn(dest_part_col);
            }
        // MaterializedViewInfo
        } else if (src_item instanceof MaterializedViewInfo) {
            // ColumnRefs
            MaterializedViewInfo src_view = (MaterializedViewInfo) src_item;
            MaterializedViewInfo dest_view = (MaterializedViewInfo) clone;
            updateColumnsRefs((Table) src_view.getParent(), src_view.getGroupbycols(), (Table) dest_view.getParent(), dest_view.getGroupbycols());

        // Index
        } else if (src_item instanceof Index) {
            // ColumnRefs
            Index src_idx = (Index) src_item;
            Index dest_idx = (Index) clone;
            updateColumnsRefs((Table) src_idx.getParent(), src_idx.getColumns(), (Table) dest_idx.getParent(), dest_idx.getColumns());

        // Constraint
        } else if (src_item instanceof Constraint) {
            // ColumnRefs
            Constraint src_cons = (Constraint) src_item;
            Constraint dest_cons = (Constraint) clone;

            Table src_fkey_tbl = src_cons.getForeignkeytable();
            if (src_fkey_tbl != null) {
                Database dest_db = (Database) dest_cons.getParent().getParent();
                Table dest_fkey_tbl = dest_db.getTables().get(src_fkey_tbl.getName());
                if (dest_fkey_tbl != null) {
                    dest_cons.setForeignkeytable(dest_fkey_tbl);
                    for (ColumnRef src_cref : ((Constraint) src_item).getForeignkeycols()) {
                        CatalogCloner.clone(src_cref, dest_catalog);

                        // Correct what it's pointing to
                        ColumnRef dest_colref = dest_cons.getForeignkeycols().get(src_cref.getName());
                        assert (dest_colref != null);
                        dest_colref.setColumn(dest_fkey_tbl.getColumns().get(src_cref.getColumn().getName()));
                    } // FOR
                }
            }

            // Important: We have to add ConstraintRefs to Columns *after* we add the columns
            Table src_tbl = (Table) src_cons.getParent();
            Table dest_tbl = (Table) dest_cons.getParent();
            for (Column src_col : src_tbl.getColumns()) {
                Column dest_col = dest_tbl.getColumns().get(src_col.getName());
                assert (dest_col != null);
                for (ConstraintRef src_conref : src_col.getConstraints()) {
                    if (!src_conref.getConstraint().equals(src_cons))
                        continue;
                    CatalogCloner.clone(src_conref, dest_catalog);

                    // Correct what it's pointing to
                    ConstraintRef dest_conref = dest_col.getConstraints().get(src_conref.getName());
                    assert (dest_conref != null);
                    // System.out.println("dest_tbl: " + dest_tbl);
                    // System.out.println("dest_tbl.getConstraints(): " +
                    // CatalogUtil.debug(dest_tbl.getConstraints()));
                    // System.out.println("src_confref: " + src_conref);
                    // System.out.println("src_confref.getConstraint(): " +
                    // src_conref.getConstraint());
                    dest_conref.setConstraint(dest_tbl.getConstraints().get(src_conref.getConstraint().getName()));
                } // FOR
            } // FOR

            Index src_index = src_cons.getIndex();
            if (src_index != null) {
                Index dest_index = dest_tbl.getIndexes().get(src_index.getName());
                dest_cons.setIndex(dest_index);
            }

        // StmtParameter
        } else if (src_item instanceof StmtParameter) {
            // We need to fix the reference to the ProcParameter (if one exists)
            StmtParameter src_stmt_param = (StmtParameter) src_item;
            StmtParameter dest_stmt_param = (StmtParameter) clone;

            if (src_stmt_param.getProcparameter() != null) {
                Procedure dest_proc = (Procedure) dest_stmt_param.getParent().getParent();
                ProcParameter src_proc_param = src_stmt_param.getProcparameter();
                ProcParameter dest_proc_param = dest_proc.getParameters().get(src_proc_param.getName());
                if (dest_proc_param == null) {
                    LOG.warn("dest_proc:      " + dest_proc);
                    LOG.warn("dest_stmt:      " + dest_stmt_param.getParent());
                    LOG.warn("src_proc_param: " + src_proc_param);
                    LOG.warn("dest_proc.getParameters(): " + CatalogUtil.debug(dest_proc.getParameters()));
                    CatalogUtil.saveCatalog(dest_catalog, CatalogUtil.CATALOG_FILENAME);
                }

                assert (dest_proc_param != null);
                dest_stmt_param.setProcparameter(dest_proc_param);
            }
        }
        return (clone);
    }

    private static void updateColumnsRefs(Table src_tbl, CatalogMap<ColumnRef> src_refs, Table dest_tbl, CatalogMap<ColumnRef> dest_refs) {
        for (ColumnRef src_colref : src_refs) {
            // First clone it
            CatalogCloner.clone(src_colref, dest_tbl.getCatalog());

            // Correct what it's pointing to
            ColumnRef dest_colref = dest_refs.get(src_colref.getName());
            dest_colref.setColumn(dest_tbl.getColumns().get(src_colref.getColumn().getName()));
        } // FOR
    }
   
    /**
     * Clone Procedure conflicts
     * @param src_db
     * @param dest_db
     */
    public static void cloneConflicts(Database src_db, Database dest_db) {
        for (Procedure src_proc : src_db.getProcedures()) {
            Procedure dest_proc = dest_db.getProcedures().get(src_proc.getName());
            assert(dest_proc != null) : src_proc;
           
            for (ConflictSet src_conflicts : src_proc.getConflicts()) {
                Procedure dest_otherProc = dest_db.getProcedures().get(src_conflicts.getProcedure().getName());
                ConflictSet dest_conflicts = dest_proc.getConflicts().add(src_conflicts.getName());
                dest_conflicts.setProcedure(dest_otherProc);
               
                for (ConflictPair src_pair : src_conflicts.getReadwriteconflicts()) {
                    ConflictPair dest_pair = clone(src_pair, dest_db.getCatalog());
                    dest_pair.setStatement0(dest_proc.getStatements().get(src_pair.getStatement0().getName()));
                    dest_pair.setStatement1(dest_otherProc.getStatements().get(src_pair.getStatement1().getName()));
                    for (TableRef src_ref : src_pair.getTables()) {
                        TableRef dest_ref = dest_pair.getTables().add(src_ref.getName());
                        dest_ref.setTable(dest_db.getTables().get(src_ref.getTable().getName()));
                    } // FOR
                } // FOR
                for (ConflictPair src_pair : src_conflicts.getWritewriteconflicts()) {
                    ConflictPair dest_pair = clone(src_pair, dest_db.getCatalog());
                    dest_pair.setStatement0(dest_proc.getStatements().get(src_pair.getStatement0().getName()));
                    dest_pair.setStatement1(dest_otherProc.getStatements().get(src_pair.getStatement1().getName()));
                    for (TableRef src_ref : src_pair.getTables()) {
                        TableRef dest_ref = dest_pair.getTables().add(src_ref.getName());
                        dest_ref.setTable(dest_db.getTables().get(src_ref.getTable().getName()));
                    } // FOR
                } // FOR
            }
        } // FOR
    }

    /**
     * @param src_db
     * @param dest_db
     */
    public static void cloneConstraints(Database src_db, Database dest_db) {
        Catalog dest_catalog = dest_db.getCatalog();
        for (Table src_tbl : src_db.getTables()) {
            Table dest_tbl = dest_db.getTables().get(src_tbl.getName());
            if (dest_tbl != null) {
                for (Constraint src_cons : src_tbl.getConstraints()) {
                    // Only clone FKEY constraint if the other table is in the catalog
                    ConstraintType cons_type = ConstraintType.get(src_cons.getType());
                    if (cons_type != ConstraintType.FOREIGN_KEY || (cons_type == ConstraintType.FOREIGN_KEY && dest_db.getTables().get(src_cons.getForeignkeytable().getName()) != null)) {
                        Constraint dest_cons = clone(src_cons, dest_catalog);
                        assert (dest_cons != null);
                    }
                } // FOR
            }
        } // FOR
    }

}
TOP

Related Classes of edu.brown.catalog.CatalogCloner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.