com.tesora.dve.sql.util.PEDDL.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.sql.util.PEDDL.java

Source

package com.tesora.dve.sql.util;

/*
 * #%L
 * Tesora Inc.
 * Database Virtualization Engine
 * %%
 * Copyright (C) 2011 - 2014 Tesora Inc.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.tesora.dve.common.catalog.FKMode;
import com.tesora.dve.common.catalog.MultitenantMode;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.resultset.ResultColumn;
import com.tesora.dve.resultset.ResultRow;
import com.tesora.dve.sql.parser.ParserInvoker.LineTag;
import com.tesora.dve.sql.parser.ParserInvoker.TaggedLineInfo;

public class PEDDL extends ProjectDDL {

    private List<StorageGroupDDL> persGroups;
    private boolean tenant = false;
    private boolean throwDropRangeInUseException = true;
    private List<String> templateDeclarations = new ArrayList<String>();

    public PEDDL() {
        super();
        persGroups = new ArrayList<StorageGroupDDL>();
    }

    public PEDDL(PEDDL other) {
        super(other);
        persGroups = other.persGroups;
        this.templateDeclarations = new ArrayList<String>(other.templateDeclarations);
    }

    @Override
    public StorageGroupDDL getPersistentGroup() {
        return persGroups.get(0);
    }

    public PEDDL withStorageGroup(StorageGroupDDL sgddl) {
        persGroups.add(sgddl);
        return this;
    }

    @Override
    public List<String> getCreateStatements() throws Exception {
        ArrayList<String> buf = new ArrayList<String>();
        if (!tenant) {
            for (StorageGroupDDL sgddl : persGroups) {
                buf.addAll(sgddl.getCreateStatements());
            }
            buf.addAll(templateDeclarations);
            for (DatabaseDDL dbddl : getDatabases()) {
                buf.addAll(dbddl.getCreateStatements());
            }
            setCreated();
        }
        buf.add("use " + getDatabases().get(0).getDatabaseName());
        return buf;
    }

    // our destroy is now slightly more complicated - in addition to dropping the db
    // we also have to drop ranges, persistent groups
    @Override
    public void destroy(ConnectionResource mr) throws Throwable {
        if (mr == null)
            return;

        TaggedLineInfo tli = new TaggedLineInfo(-1, null, -1, LineTag.DDL);
        // drop all the dbs
        for (DatabaseDDL dbddl : getDatabases())
            mr.execute(tli, dbddl.getDropStatement());
        HashSet<String> pgnames = new HashSet<String>();
        for (StorageGroupDDL sgddl : persGroups)
            pgnames.add(sgddl.getName());
        ResourceResponse rr = mr.fetch("show containers");
        List<ResultRow> results = rr.getResults();
        for (ResultRow row : results) {
            ResultColumn rc = row.getResultColumn(1);
            String contName = (String) rc.getColumnValue();
            mr.execute(tli, "drop container " + contName);
        }
        // now we have to find ranges that use our persistent group
        rr = mr.fetch("show ranges");
        results = rr.getResults();
        for (ResultRow row : results) {
            ResultColumn rangeNameColumn = row.getResultColumn(1);
            ResultColumn storageGroupColumn = row.getResultColumn(2);
            String rangeName = rangeNameColumn.getColumnValue().getClass().isArray()
                    ? new String((byte[]) rangeNameColumn.getColumnValue())
                    : (String) rangeNameColumn.getColumnValue();
            String groupName = storageGroupColumn.getColumnValue().getClass().isArray()
                    ? new String((byte[]) storageGroupColumn.getColumnValue())
                    : (String) storageGroupColumn.getColumnValue();
            if (pgnames.contains(groupName.trim())) {
                try {
                    mr.execute(tli, "drop range " + rangeName + " persistent group " + groupName.trim());
                } catch (PEException e) {
                    if (!throwDropRangeInUseException
                            && (StringUtils.containsIgnoreCase(e.getMessage(), "Unable to drop range")
                                    && StringUtils.containsIgnoreCase(e.getMessage(), "because used by table"))) {
                        // eat the exception
                    } else {
                        throw e;
                    }
                }
            }
        }
        // now we can drop the persistent group, which apparently also drops the persistent sites
        for (StorageGroupDDL sgddl : persGroups) {
            sgddl.destroy(mr);
        }
    }

    @Override
    public List<String> getSetupDrops() {
        ArrayList<String> buf = new ArrayList<String>();
        ArrayList<String> nativeDrops = new ArrayList<String>();
        for (DatabaseDDL dbddl : getDatabases()) {
            buf.addAll(dbddl.getSetupDrops());
            for (StorageGroupDDL sgddl : persGroups) {
                nativeDrops.addAll(sgddl.getSetupDrops(dbddl.getDatabaseName()));
            }
        }
        buf.addAll(nativeDrops);
        return buf;
    }

    // for mt support - the database name of the tenant is different than the database name of the landlord
    @Override
    public PEDDL buildTenantDDL(String tenantName) {
        PEDDL copy = new PEDDL(this);
        if (getDatabases().size() > 1)
            throw new IllegalStateException("Cannot build tenant ddl: more than one database");
        getDatabases().get(0).dbn = tenantName;
        copy.created = true; // tenants never create
        copy.tenant = true;
        return copy;
    }

    @Override
    public List<String> getDestroyStatements() throws Exception {
        throw new IllegalStateException("PEDDL does not use destroy statements");
    }

    // these are all compatibility constructors and functions
    public PEDDL(String dbname, StorageGroupDDL persGroup, String dbtag) {
        this(dbname, persGroup, dbtag, null, null);
    }

    public PEDDL(String dbname, StorageGroupDDL persGroup, String dbtag, String charset, String collation) {
        super();
        persGroups = new ArrayList<StorageGroupDDL>();
        withStorageGroup(persGroup);
        withDatabase(new PEDatabaseDDL(dbname, dbtag, charset, collation).withStorageGroup(persGroup));
    }

    public PEDDL withTemplate(String temp, boolean strict) {
        getSinglePEDB().withTemplate(temp, strict);
        return this;
    }

    public PEDDL withMTMode(MultitenantMode mm) {
        getSinglePEDB().withMTMode(mm);
        return this;
    }

    public PEDDL withFKMode(FKMode fkm) {
        getSinglePEDB().withFKMode(fkm);
        return this;
    }

    public PEDDL withTemplateDeclarations(String... decls) {
        for (String s : decls) {
            templateDeclarations.add(s);
        }
        if (templateDeclarations.size() > 0) {
            for (DatabaseDDL db : getDatabases()) {
                PEDatabaseDDL pedb = (PEDatabaseDDL) db;
                pedb.withLoadTemplate(false);
            }
        }
        return this;
    }

    public MultitenantMode getMultitenantMode() {
        return getSinglePEDB().getMultitenantMode();
    }

    public FKMode getForeignKeyMode() {
        return getSinglePEDB().getForeignKeyMode();
    }

    protected PEDatabaseDDL getSinglePEDB() {
        return (PEDatabaseDDL) super.getSingleDB();
    }

    @Override
    public void clearCreated() {
        super.clearCreated();
        // also do the same on persistent groups
        for (StorageGroupDDL sgddl : persGroups)
            sgddl.clearCreated();
    }

    public PEDDL setThrowDropRangeInUseException(boolean value) {
        this.throwDropRangeInUseException = value;
        return this;
    }
}