/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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/>. */ package com.foundationdb.ais.model; import com.foundationdb.ais.model.aisb2.AISBBasedBuilder; import com.foundationdb.server.types.mcompat.mtypes.MTypesTranslator; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; public final class HKeySegmentTest { @Test public void nonCascading() { AkibanInformationSchema ais = AISBBasedBuilder.create(SCHEMA, MTypesTranslator.INSTANCE) .table("c") .colInt("cid") .colString("name", 64) .pk("cid") .table("o") .colInt("oid") .colInt("c_id") .colString("date", 32) .pk("oid") .joinTo("c").on("c_id", "cid") .table("i") .colInt("iid") .colInt("o_id") .colInt("sku") .pk("iid") .joinTo("o").on("o_id", "oid") .ais(); checkHKeyColumn( ais, "c", expectedSegments(1).checkSegment(0).expectedCols(1).checkCol(0).expectAtIndex(0), c("c", "cid"), c("o", "c_id")); checkHKeyColumn( ais, "o", expectedSegments(2).checkSegment(0).expectedCols(1).checkCol(0).expectAtIndex(1), c("c", "cid"), c("o", "c_id")); checkHKeyColumn( ais, "o", expectedSegments(2).checkSegment(1).expectedCols(1).checkCol(0).expectAtIndex(0), c("o", "oid"), c("i", "o_id")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(0).expectedCols(1).checkCol(0).expectAtIndex(1), c("c", "cid"), c("o", "c_id")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(1).expectedCols(1).checkCol(0).expectAtIndex(1), c("o", "oid"), c("i", "o_id")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(2).expectedCols(1).checkCol(0).expectAtIndex(0), c("i", "iid")); } @Test public void cascading() { AkibanInformationSchema ais = AISBBasedBuilder.create(SCHEMA, MTypesTranslator.INSTANCE) .table("c") .colInt("cid") .colString("name", 64) .pk("cid") .table("o") .colInt("c_id") .colInt("oid") .colString("date", 32) .pk("c_id", "oid") .joinTo("c").on("c_id", "cid") .table("i") .colInt("c__id") .colInt("o_id") .colInt("iid") .colInt("sku") .pk("c__id", "o_id", "iid") .joinTo("o").on("c__id","c_id").and("o_id", "oid") .ais(); checkHKeyColumn( ais, "c", expectedSegments(1).checkSegment(0).expectedCols(1).checkCol(0).expectAtIndex(0), c("c", "cid"), c("o", "c_id"), c("i", "c__id")); checkHKeyColumn( ais, "o", expectedSegments(2).checkSegment(0).expectedCols(1).checkCol(0).expectAtIndex(1), c("c", "cid"), c("o", "c_id"), c("i", "c__id")); checkHKeyColumn( ais, "o", expectedSegments(2).checkSegment(1).expectedCols(1).checkCol(0).expectAtIndex(0), c("o", "oid"), c("i", "o_id")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(0).expectedCols(1).checkCol(0).expectAtIndex(2), c("c", "cid"), c("o", "c_id"), c("i", "c__id")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(1).expectedCols(1).checkCol(0).expectAtIndex(1), c("o", "oid"), c("i", "o_id")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(2).expectedCols(1).checkCol(0).expectAtIndex(0), c("i", "iid")); } @Test public void multiColumnPkNoCascade() { AkibanInformationSchema ais = AISBBasedBuilder.create(SCHEMA, MTypesTranslator.INSTANCE) .table("c") .colInt("cid1") .colInt("cid2") .colString("name", 64) .pk("cid1", "cid2") .table("o") .colInt("oid") .colInt("c_id1") .colInt("c_id2") .colString("date", 32) .pk("oid") .joinTo("c").on("c_id1", "cid1").and("c_id2", "cid2") .table("i") .colInt("iid") .colInt("o_id") .colInt("sku") .pk("iid") .joinTo("o").on("o_id", "oid") .ais(); checkHKeyColumn( ais, "c", expectedSegments(1).checkSegment(0).expectedCols(2).checkCol(0).expectAtIndex(0), c("c", "cid1"), c("o", "c_id1")); checkHKeyColumn( ais, "c", expectedSegments(1).checkSegment(0).expectedCols(2).checkCol(1).expectAtIndex(0), c("c", "cid2"), c("o", "c_id2")); checkHKeyColumn( ais, "o", expectedSegments(2).checkSegment(0).expectedCols(2).checkCol(0).expectAtIndex(1), c("c", "cid1"), c("o", "c_id1")); checkHKeyColumn( ais, "o", expectedSegments(2).checkSegment(0).expectedCols(2).checkCol(1).expectAtIndex(1), c("c", "cid2"), c("o", "c_id2")); checkHKeyColumn( ais, "o", expectedSegments(2).checkSegment(1).expectedCols(1).checkCol(0).expectAtIndex(0), c("o", "oid"), c("i", "o_id")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(0).expectedCols(2).checkCol(0).expectAtIndex(1), c("c", "cid1"), c("o", "c_id1")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(0).expectedCols(2).checkCol(1).expectAtIndex(1), c("c", "cid2"), c("o", "c_id2")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(1).expectedCols(1).checkCol(0).expectAtIndex(1), c("o", "oid"), c("i", "o_id")); checkHKeyColumn( ais, "i", expectedSegments(3).checkSegment(2).expectedCols(1).checkCol(0).expectAtIndex(0), c("i", "iid")); } private void checkHKeyColumn( AkibanInformationSchema ais, String tableName, SegmentCheckParameters segmentParameters, ColumnName... equivalentColumns) { List<HKeySegment> segments = ais.getTable(SCHEMA, tableName).hKey().segments(); assertEquals("segments size for " + segments, segmentParameters.expectedSegments, segments.size()); List<HKeyColumn> hKeyColumns = segments.get(segmentParameters.checkSegment).columns(); assertEquals("hKeyColumns size", segmentParameters.expectedColumns, hKeyColumns.size()); HKeyColumn hKeyColumn = hKeyColumns.get(segmentParameters.checkColumn); checkColumnName(hKeyColumn.column(), equivalentColumns[segmentParameters.mainColumnIndex]); checkEquivalentColumns(Arrays.asList(equivalentColumns), hKeyColumn.equivalentColumns()); } private void checkEquivalentColumns(List<ColumnName> expected, List<Column> actual) { List<ColumnName> actualNames = new ArrayList<>(); for (Column column : actual) { actualNames.add(new ColumnName(column)); } assertEquals("equivalent columns", expected, actualNames); } private static void checkColumnName(Column column, ColumnName expected) { ColumnName actual = new ColumnName(column); assertEquals("column name", expected, actual); } private static ColumnName c(String table, String column) { return new ColumnName(SCHEMA, table, column); } private static SegmentCheckParameters expectedSegments(int expectedSegments) { return new SegmentCheckParameters().expectedSegments(expectedSegments); } // consts private static final String SCHEMA = "hkeytest"; // nested classes private static class SegmentCheckParameters { /** * How many HKeySegments we expect in the HKey * @param expectedSegments expected size of {@link HKey#segments()} * @return this object (for chaining) */ SegmentCheckParameters expectedSegments(int expectedSegments) { this.expectedSegments = expectedSegments; return this; } /** * Which segment to check ( must be between 0 and expectedSegments ) * @param checkSegment the index of {@link HKey#segments()} to check * @return this object (for chaining) */ SegmentCheckParameters checkSegment(int checkSegment) { this.checkSegment = checkSegment; return this; } /** * How many columns we expect in this segment * @param expectedColumns the expected size of {@link HKeySegment#columns} * @return this object (for chaining) */ SegmentCheckParameters expectedCols(int expectedColumns) { this.expectedColumns = expectedColumns; return this; } /** * Which column to check * @param checkColumn the index of {@link HKeySegment#columns} to check * @return this object (for chaining) */ SegmentCheckParameters checkCol(int checkColumn) { this.checkColumn = checkColumn; return this; } /** * Where in the equivalent columns list we expect the "main" column to be. In other words, we'll check that * {@link HKeyColumn#column()} is the same as the entry of the given index in * {@link HKeyColumn#equivalentColumns()}. * @param mainColumnIndex the index within {@linkplain HKeyColumn#equivalentColumns()} to expect to find * {@link HKeyColumn#column()} * @return this object (for chaining) */ SegmentCheckParameters expectAtIndex(int mainColumnIndex) { this.mainColumnIndex = mainColumnIndex; return this; } private int expectedSegments = -1; private int checkSegment = -1; private int expectedColumns = -1; private int checkColumn = -1; private int mainColumnIndex = -1; } }