package com.tesora.dve.queryplan; /* * #%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.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import com.tesora.dve.common.catalog.ConstraintType; import com.tesora.dve.common.catalog.IndexType; import com.tesora.dve.common.catalog.Key; import com.tesora.dve.common.catalog.KeyColumn; import com.tesora.dve.common.catalog.UserColumn; import com.tesora.dve.common.catalog.UserTable; import com.tesora.dve.sql.util.ListSet; // hints for the temp table declaration - info we can't figure out // in the engine alone. public class TempTableDeclHints extends TableHints { // each tuple of index columns becomes an index // use a set container to prevent insertion of duplicate keys. ListSet<List<String>> indexColumns; ListSet<List<String>> uniqueColumns; Map<String,TempTableColumnHints> columnHints; // overriding declaration for columns, by column name Map<String,UserColumn> overrideDecls; public TempTableDeclHints() { indexColumns = new ListSet<List<String>>(); uniqueColumns = new ListSet<List<String>>(); columnHints = new HashMap<String,TempTableColumnHints>(); overrideDecls = new HashMap<String,UserColumn>(); } public TempTableColumnHints getHint(String columnName) { TempTableColumnHints h = columnHints.get(columnName); if (h == null) { h = new TempTableColumnHints(); columnHints.put(columnName, h); } return h; } public boolean addIndex(final String[] cols) { return indexColumns.add(Arrays.asList(cols)); } public boolean addIndex(final String col) { return indexColumns.add(Collections.singletonList(col)); } public boolean addUniqueKey(final String[] cols) { return uniqueColumns.add(Arrays.asList(cols)); } public boolean addUniqueKey(final String col) { return uniqueColumns.add(Collections.singletonList(col)); } public void addOverrideDecl(String columnName, UserColumn def) { overrideDecls.put(columnName, def); } public void addZeroFilled(String col) { getHint(col).setZeroFilled(); } public void addCollation(String column, String collation) { getHint(column).setCollation(collation); } public void addCharset(String column, String charset) { getHint(column).setCharset(charset); } public List<List<String>> getIndexes() { return indexColumns; } public List<List<String>> getUniqueKeys() { return uniqueColumns; } @Override public void modify(UserTable ut) { addKeysOn(ut, indexColumns, null); addKeysOn(ut, uniqueColumns, ConstraintType.UNIQUE); for(Map.Entry<String, TempTableColumnHints> me : columnHints.entrySet()) { String cn = me.getKey(); TempTableColumnHints ttch = me.getValue(); UserColumn uc = ut.getUserColumn(cn); uc.setZerofill(ttch.isZeroFilled()); if (ttch.getCharset() != null) { uc.setCharset(ttch.getCharset()); } if (ttch.getCollation() != null) { uc.setCollation(ttch.getCollation()); } } if (!overrideDecls.isEmpty()) { for(Map.Entry<String, UserColumn> me : overrideDecls.entrySet()) { UserColumn uc = ut.getUserColumn(me.getKey()); UserColumn dd = me.getValue(); uc.copyFrom(dd); } } } private void addKeysOn(final UserTable ut, final List<List<String>> keyDefs, final ConstraintType constraint) { if (!keyDefs.isEmpty()) { final StringBuilder keyName = new StringBuilder(ut.getName()); if (constraint != null) { keyName.append(constraint.getSQL()); } keyName.append("pekey"); for (int i = 0; i < keyDefs.size(); ++i) { final List<String> keyColumnNames = keyDefs.get(i); final int keyLength = keyColumnNames.size(); final List<KeyColumn> keyColumns = new ArrayList<KeyColumn>(keyLength); for (int j = 0; j < keyLength; ++j) { final UserColumn uc = ut.getUserColumn(keyColumnNames.get(j)); final KeyColumn kc = new KeyColumn(uc, null, j + 1,-1L); keyColumns.add(kc); } final int offset = i + 1; final Key k = new Key(keyName.append(offset).toString(), IndexType.BTREE, ut, keyColumns, offset); k.setConstraint(constraint); ut.addKey(k); } } } protected static class TempTableColumnHints { protected boolean zeroFilled; protected String collation; protected String charset; public TempTableColumnHints() { this.zeroFilled = false; this.collation = null; this.charset = null; } public void setZeroFilled() { zeroFilled = true; } public void setCollation(String c) { this.collation = c; } public void setCharset(String charset) { this.charset = charset; } public boolean isZeroFilled() { return zeroFilled; } public String getCollation() { return collation; } public String getCharset() { return charset; } } }