mirror of https://github.com/apache/cassandra
408 lines
17 KiB
Java
408 lines
17 KiB
Java
/**
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package org.apache.cassandra.db;
|
|
|
|
import java.util.SortedSet;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.ArrayList;
|
|
import java.io.IOException;
|
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
import org.junit.Test;
|
|
|
|
import static junit.framework.Assert.*;
|
|
import org.apache.cassandra.CleanupHelper;
|
|
import org.apache.cassandra.io.SSTable;
|
|
|
|
public class TableTest extends CleanupHelper
|
|
{
|
|
private static final String KEY2 = "key2";
|
|
private static final String TEST_KEY = "key1";
|
|
private static final String TABLE_NAME = "Table1";
|
|
|
|
@Test
|
|
public void testOpen() throws Throwable {
|
|
Table table = Table.open("Mailbox");
|
|
Row row = table.get("35300190:1");
|
|
assertNotNull(row);
|
|
}
|
|
|
|
@Test
|
|
public void testGetRowSingleColumn() throws Throwable
|
|
{
|
|
Table table = Table.open(TABLE_NAME);
|
|
RowMutation rm = makeSimpleRowMutation();
|
|
rm.apply();
|
|
Row result = table.getRow(TEST_KEY, "Standard1:col1");
|
|
ColumnFamily cres = result.getColumnFamily("Standard1");
|
|
assertNotNull(cres);
|
|
assertEquals(1, cres.getColumnCount());
|
|
assertNotNull(cres.getColumn("col1"));
|
|
}
|
|
|
|
@Test
|
|
public void testGetRowOffsetCount() throws Throwable
|
|
{
|
|
Table table = Table.open(TABLE_NAME);
|
|
|
|
RowMutation rm = makeSimpleRowMutation(); //inserts col1, col2, col3
|
|
|
|
|
|
rm.apply();
|
|
Row result = table.getRow(TEST_KEY, "Standard1", 0, 2);
|
|
ColumnFamily cres = result.getColumnFamily("Standard1");
|
|
assertNotNull(cres);
|
|
assertEquals(cres.getColumnCount(), 2);
|
|
// should have col1 and col2
|
|
assertNotNull(cres.getColumn("col1"));
|
|
assertNotNull(cres.getColumn("col2"));
|
|
|
|
result = table.getRow(TEST_KEY, "Standard1", 1, 2);
|
|
cres = result.getColumnFamily("Standard1");
|
|
assertNotNull(cres);
|
|
assertEquals(2, cres.getColumnCount());
|
|
// offset is 1, so we should have col2 and col3
|
|
assertNotNull(cres.getColumn("col2"));
|
|
assertNotNull(cres.getColumn("col3"));
|
|
}
|
|
|
|
@Test
|
|
public void testGetRowOffsetCountFromDisk() throws Throwable
|
|
{
|
|
Table table = Table.open("Table1");
|
|
|
|
RowMutation rm = new RowMutation(TABLE_NAME,KEY2);
|
|
ColumnFamily cf = new ColumnFamily("Standard1","Standard");
|
|
// First write 5, 6
|
|
cf.addColumn(new Column("col5", "val5".getBytes(), 1L));
|
|
cf.addColumn(new Column("col6", "val6".getBytes(), 1L));
|
|
rm.add(cf);
|
|
|
|
rm.apply();
|
|
Row result = table.getRow(KEY2, "Standard1:col5");
|
|
ColumnFamily cres = result.getColumnFamily("Standard1");
|
|
assertNotNull(cres.getColumn("col5"));
|
|
|
|
table.getColumnFamilyStore("Standard1").forceBlockingFlush();
|
|
// Flushed memtable to disk, we're now inserting into a new memtable
|
|
|
|
rm = new RowMutation(TABLE_NAME, KEY2);
|
|
cf = new ColumnFamily("Standard1","Standard");
|
|
// now write 7, 8, 4 into new memtable
|
|
cf.addColumn(new Column("col7", "val7".getBytes(), 1L));
|
|
cf.addColumn(new Column("col8", "val8".getBytes(), 1L));
|
|
cf.addColumn(new Column("col4", "val4".getBytes(), 1L));
|
|
rm.add(cf);
|
|
rm.apply();
|
|
|
|
// Check col5 is still around
|
|
result = table.getRow(KEY2, "Standard1:col5");
|
|
cres = result.getColumnFamily("Standard1");
|
|
assertNotNull(cres.getColumn("col5"));
|
|
|
|
// Read back 3 cols from start -- should see 4,5,6 NOT 4,7,8
|
|
result = table.getRow(KEY2, "Standard1", 0, 3);
|
|
cres = result.getColumnFamily("Standard1");
|
|
assertNotNull(cres);
|
|
assertEquals(cres.getColumnCount(), 3);
|
|
|
|
// Should have col4, col5, and col6
|
|
assertNotNull(cres.getColumn("col4"));
|
|
assertNotNull(cres.getColumn("col5"));
|
|
assertNotNull(cres.getColumn("col6"));
|
|
// not 8
|
|
assertNull(cres.getColumn("col8"));
|
|
}
|
|
|
|
@Test
|
|
public void testGetRowSliceByRange() throws Throwable
|
|
{
|
|
String key = TEST_KEY+"slicerow";
|
|
Table table = Table.open(TABLE_NAME);
|
|
RowMutation rm = new RowMutation(TABLE_NAME,key);
|
|
ColumnFamily cf = new ColumnFamily("Standard1","Standard");
|
|
// First write "a", "b", "c"
|
|
cf.addColumn(new Column("a", "val1".getBytes(), 1L));
|
|
cf.addColumn(new Column("b", "val2".getBytes(), 1L));
|
|
cf.addColumn(new Column("c", "val3".getBytes(), 1L));
|
|
rm.add(cf);
|
|
rm.apply();
|
|
|
|
Row result = table.getRow(key, "Standard1", "b", "c",-1);
|
|
assertEquals(2, result.getColumnFamily("Standard1").getColumnCount());
|
|
|
|
result = table.getRow(key, "Standard1", "b", "b", 50);
|
|
assertEquals(1, result.getColumnFamily("Standard1").getColumnCount());
|
|
|
|
result = table.getRow(key, "Standard1", "b", "c",1);
|
|
assertEquals(1, result.getColumnFamily("Standard1").getColumnCount());
|
|
|
|
result = table.getRow(key, "Standard1", "c", "b",1);
|
|
assertEquals(0, result.getColumnFamily("Standard1").getColumnCount());
|
|
|
|
}
|
|
|
|
@Test
|
|
public void testGetRowSuperColumnOffsetCount() throws Throwable
|
|
{
|
|
Table table = Table.open(TABLE_NAME);
|
|
|
|
RowMutation rm = new RowMutation(TABLE_NAME,TEST_KEY);
|
|
ColumnFamily cf = new ColumnFamily("Super1","Super");
|
|
SuperColumn sc1 = new SuperColumn("sc1");
|
|
sc1.addColumn(new Column("col1","val1".getBytes(), 1L));
|
|
sc1.addColumn(new Column("col2","val2".getBytes(), 1L));
|
|
SuperColumn sc2 = new SuperColumn("sc2");
|
|
sc2.addColumn(new Column("col3","val3".getBytes(), 1L));
|
|
sc2.addColumn(new Column("col4","val4".getBytes(), 1L));
|
|
cf.addColumn(sc1);
|
|
cf.addColumn(sc2);
|
|
rm.add(cf);
|
|
|
|
rm.apply();
|
|
//Slicing top level columns of a supercolumn
|
|
Row result = table.getRow(TEST_KEY, "Super1", 0, 2);
|
|
ColumnFamily cres = result.getColumnFamily("Super1");
|
|
assertNotNull(cres);
|
|
assertEquals(cres.getAllColumns().size(), 2); //2 supercolumns
|
|
assertEquals(cres.getColumnCount(),2+4); //2 cols, 2 subcols each
|
|
// should have col1 ... col4
|
|
assertNotNull(cres.getColumn("sc1").getSubColumn("col1"));
|
|
assertNotNull(cres.getColumn("sc1").getSubColumn("col2"));
|
|
assertNotNull(cres.getColumn("sc2").getSubColumn("col3"));
|
|
assertNotNull(cres.getColumn("sc2").getSubColumn("col4"));
|
|
|
|
|
|
result = table.getRow(TEST_KEY, "Super1:sc1", 1, 2); //get at most 2, but only 1 column will be available
|
|
cres = result.getColumnFamily("Super1");
|
|
assertNotNull(cres);
|
|
assertEquals(cres.getAllColumns().size(), 1); //only 1 top level column. sc1 has only 2 subcolumns
|
|
assertEquals(cres.getColumnCount(), 2); //getObjectCount: 1 for the column, and 1 for subcolumn
|
|
|
|
assertNotNull(cres.getColumn("sc1").getSubColumn("col2"));
|
|
assertNull(cres.getColumn("sc2"));
|
|
}
|
|
|
|
private RowMutation makeSimpleRowMutation()
|
|
{
|
|
RowMutation rm = new RowMutation(TABLE_NAME,TEST_KEY);
|
|
ColumnFamily cf = new ColumnFamily("Standard1", "Standard");
|
|
cf.addColumn(new Column("col1","val1".getBytes(), 1L));
|
|
cf.addColumn(new Column("col2","val2".getBytes(), 1L));
|
|
cf.addColumn(new Column("col3","val3".getBytes(), 1L));
|
|
rm.add(cf);
|
|
return rm;
|
|
}
|
|
|
|
@Test
|
|
public void testGetSliceNoMatch() throws Throwable
|
|
{
|
|
Table table = Table.open(TABLE_NAME);
|
|
RowMutation rm = new RowMutation(TABLE_NAME, "row1000");
|
|
ColumnFamily cf = new ColumnFamily("Standard2", "Standard");
|
|
cf.addColumn(new Column("col1", "val1".getBytes(), 1));
|
|
rm.add(cf);
|
|
rm.apply();
|
|
|
|
validateGetSliceNoMatch(table);
|
|
table.getColumnFamilyStore("Standard2").forceBlockingFlush();
|
|
validateGetSliceNoMatch(table);
|
|
|
|
SortedSet<String> ssTables = table.getColumnFamilyStore("Standard2").getSSTableFilenames();
|
|
assertEquals(1, ssTables.size());
|
|
SSTable.forceBloomFilterFailures(ssTables.iterator().next());
|
|
validateGetSliceNoMatch(table);
|
|
}
|
|
|
|
private void validateGetSliceNoMatch(Table table) throws IOException
|
|
{
|
|
Row result;
|
|
ColumnFamily cf;
|
|
|
|
// key before the rows that exists
|
|
result = table.getSliceFrom("a", "Standard2", true, 0);
|
|
cf = result.getColumnFamily("Standard2");
|
|
assertColumns(cf);
|
|
|
|
// key after the rows that exist
|
|
result = table.getSliceFrom("z", "Standard2", true, 0);
|
|
cf = result.getColumnFamily("Standard2");
|
|
assertColumns(cf);
|
|
}
|
|
|
|
@Test
|
|
public void testGetSliceFromBasic() throws Throwable
|
|
{
|
|
// tests slicing against data from one row in a memtable and then flushed to an sstable
|
|
Table table = Table.open(TABLE_NAME);
|
|
String ROW = "row1";
|
|
RowMutation rm = new RowMutation(TABLE_NAME, ROW);
|
|
ColumnFamily cf = new ColumnFamily("Standard1", "Standard");
|
|
cf.addColumn(new Column("col1", "val1".getBytes(), 1L));
|
|
cf.addColumn(new Column("col3", "val3".getBytes(), 1L));
|
|
cf.addColumn(new Column("col4", "val4".getBytes(), 1L));
|
|
cf.addColumn(new Column("col5", "val5".getBytes(), 1L));
|
|
cf.addColumn(new Column("col7", "val7".getBytes(), 1L));
|
|
cf.addColumn(new Column("col9", "val9".getBytes(), 1L));
|
|
rm.add(cf);
|
|
rm.apply();
|
|
|
|
rm = new RowMutation(TABLE_NAME, ROW);
|
|
rm.delete("Standard1:col4", 2L);
|
|
rm.apply();
|
|
|
|
validateGetSliceFromBasic(table, ROW);
|
|
table.getColumnFamilyStore("Standard1").forceBlockingFlush();
|
|
validateGetSliceFromBasic(table, ROW);
|
|
}
|
|
|
|
@Test
|
|
public void testGetSliceFromAdvanced() throws Throwable
|
|
{
|
|
// tests slicing against data from one row spread across two sstables
|
|
Table table = Table.open(TABLE_NAME);
|
|
String ROW = "row2";
|
|
RowMutation rm = new RowMutation(TABLE_NAME, ROW);
|
|
ColumnFamily cf = new ColumnFamily("Standard1", "Standard");
|
|
cf.addColumn(new Column("col1", "val1".getBytes(), 1L));
|
|
cf.addColumn(new Column("col2", "val2".getBytes(), 1L));
|
|
cf.addColumn(new Column("col3", "val3".getBytes(), 1L));
|
|
cf.addColumn(new Column("col4", "val4".getBytes(), 1L));
|
|
cf.addColumn(new Column("col5", "val5".getBytes(), 1L));
|
|
cf.addColumn(new Column("col6", "val6".getBytes(), 1L));
|
|
rm.add(cf);
|
|
rm.apply();
|
|
table.getColumnFamilyStore("Standard1").forceBlockingFlush();
|
|
|
|
rm = new RowMutation(TABLE_NAME, ROW);
|
|
cf = new ColumnFamily("Standard1", "Standard");
|
|
cf.addColumn(new Column("col1", "valx".getBytes(), 2L));
|
|
cf.addColumn(new Column("col2", "valx".getBytes(), 2L));
|
|
cf.addColumn(new Column("col3", "valx".getBytes(), 2L));
|
|
rm.add(cf);
|
|
rm.apply();
|
|
|
|
validateGetSliceFromAdvanced(table, ROW);
|
|
table.getColumnFamilyStore("Standard1").forceBlockingFlush();
|
|
validateGetSliceFromAdvanced(table, ROW);
|
|
}
|
|
|
|
@Test
|
|
public void testGetSliceFromLarge() throws Throwable
|
|
{
|
|
// tests slicing against 1000 columns in an sstable
|
|
Table table = Table.open(TABLE_NAME);
|
|
String ROW = "row3";
|
|
RowMutation rm = new RowMutation(TABLE_NAME, ROW);
|
|
ColumnFamily cf = new ColumnFamily("Standard1", "Standard");
|
|
for (int i = 1000; i < 2000; i++)
|
|
cf.addColumn(new Column("col" + i, ("vvvvvvvvvvvvvvvv" + i).getBytes(), 1L));
|
|
rm.add(cf);
|
|
rm.apply();
|
|
table.getColumnFamilyStore("Standard1").forceBlockingFlush();
|
|
|
|
Row result;
|
|
ColumnFamily cfres;
|
|
result = table.getSliceFrom(ROW, "Standard1:col1000", true, 3);
|
|
cfres = result.getColumnFamily("Standard1");
|
|
assertColumns(cfres, "col1000", "col1001", "col1002");
|
|
assertEquals(new String(cfres.getColumn("col1000").value()), "vvvvvvvvvvvvvvvv1000");
|
|
assertEquals(new String(cfres.getColumn("col1001").value()), "vvvvvvvvvvvvvvvv1001");
|
|
assertEquals(new String(cfres.getColumn("col1002").value()), "vvvvvvvvvvvvvvvv1002");
|
|
|
|
result = table.getSliceFrom(ROW, "Standard1:col1195", true, 3);
|
|
cfres = result.getColumnFamily("Standard1");
|
|
assertColumns(cfres, "col1195", "col1196", "col1197");
|
|
assertEquals(new String(cfres.getColumn("col1195").value()), "vvvvvvvvvvvvvvvv1195");
|
|
assertEquals(new String(cfres.getColumn("col1196").value()), "vvvvvvvvvvvvvvvv1196");
|
|
assertEquals(new String(cfres.getColumn("col1197").value()), "vvvvvvvvvvvvvvvv1197");
|
|
|
|
result = table.getSliceFrom(ROW, "Standard1:col1196", false, 3);
|
|
cfres = result.getColumnFamily("Standard1");
|
|
assertColumns(cfres, "col1194", "col1195", "col1196");
|
|
assertEquals(new String(cfres.getColumn("col1194").value()), "vvvvvvvvvvvvvvvv1194");
|
|
assertEquals(new String(cfres.getColumn("col1195").value()), "vvvvvvvvvvvvvvvv1195");
|
|
assertEquals(new String(cfres.getColumn("col1196").value()), "vvvvvvvvvvvvvvvv1196");
|
|
|
|
result = table.getSliceFrom(ROW, "Standard1:col1990", true, 3);
|
|
cfres = result.getColumnFamily("Standard1");
|
|
assertColumns(cfres, "col1990", "col1991", "col1992");
|
|
assertEquals(new String(cfres.getColumn("col1990").value()), "vvvvvvvvvvvvvvvv1990");
|
|
assertEquals(new String(cfres.getColumn("col1991").value()), "vvvvvvvvvvvvvvvv1991");
|
|
assertEquals(new String(cfres.getColumn("col1992").value()), "vvvvvvvvvvvvvvvv1992");
|
|
}
|
|
|
|
private void assertColumns(ColumnFamily columnFamily, String... columnNames)
|
|
{
|
|
assertNotNull(columnFamily);
|
|
SortedSet<IColumn> columns = columnFamily.getAllColumns();
|
|
List<String> L = new ArrayList<String>();
|
|
for (IColumn column : columns)
|
|
{
|
|
L.add(column.name());
|
|
}
|
|
assert Arrays.equals(L.toArray(new String[columns.size()]), columnNames)
|
|
: "Columns [" + StringUtils.join(columns, ", ") + "] is not expected [" + StringUtils.join(columnNames, ", ") + "]";
|
|
}
|
|
|
|
private void validateGetSliceFromAdvanced(Table table, String row) throws Throwable
|
|
{
|
|
Row result;
|
|
ColumnFamily cfres;
|
|
|
|
result = table.getSliceFrom(row, "Standard1:col2", true, 3);
|
|
cfres = result.getColumnFamily("Standard1");
|
|
assertColumns(cfres, "col2", "col3", "col4");
|
|
assertEquals(new String(cfres.getColumn("col2").value()), "valx");
|
|
assertEquals(new String(cfres.getColumn("col3").value()), "valx");
|
|
assertEquals(new String(cfres.getColumn("col4").value()), "val4");
|
|
}
|
|
|
|
private void validateGetSliceFromBasic(Table table, String row) throws Throwable
|
|
{
|
|
Row result;
|
|
ColumnFamily cf;
|
|
|
|
result = table.getSliceFrom(row, "Standard1:col5", true, 2);
|
|
cf = result.getColumnFamily("Standard1");
|
|
assertColumns(cf, "col5", "col7");
|
|
|
|
result = table.getSliceFrom(row, "Standard1:col4", true, 2);
|
|
cf = result.getColumnFamily("Standard1");
|
|
assertColumns(cf, "col4", "col5", "col7");
|
|
|
|
result = table.getSliceFrom(row, "Standard1:col5", false, 2);
|
|
cf = result.getColumnFamily("Standard1");
|
|
assertColumns(cf, "col3", "col4", "col5");
|
|
|
|
result = table.getSliceFrom(row, "Standard1:col6", false, 2);
|
|
cf = result.getColumnFamily("Standard1");
|
|
assertColumns(cf, "col3", "col4", "col5");
|
|
|
|
result = table.getSliceFrom(row, "Standard1:col95", true, 2);
|
|
cf = result.getColumnFamily("Standard1");
|
|
assertColumns(cf);
|
|
|
|
result = table.getSliceFrom(row, "Standard1:col0", false, 2);
|
|
cf = result.getColumnFamily("Standard1");
|
|
assertColumns(cf);
|
|
}
|
|
}
|