diff --git a/interface/cassandra.thrift b/interface/cassandra.thrift index 51d911878d..a256df8f92 100644 --- a/interface/cassandra.thrift +++ b/interface/cassandra.thrift @@ -107,7 +107,7 @@ service Cassandra { list get_slice_by_names(1:string tablename, 2:string key, 3:string columnParent, 4:list columnNames) throws (1: InvalidRequestException ire, 2: NotFoundException nfe), - list get_slice(1:string tablename, 2:string key, 3:string columnParent, 4:bool isAscending, 5:i32 count=100) + list get_slice(1:string tablename, 2:string key, 3:string columnParent, 4:bool isAscending, 5:i32 offset, 6:i32 count=100) throws (1: InvalidRequestException ire, 2: NotFoundException nfe), column_t get_column(1:string tablename, 2:string key, 3:string columnPath) @@ -128,7 +128,7 @@ service Cassandra { list get_columns_since(1:string tablename, 2:string key, 3:string columnParent, 4:i64 timeStamp) throws (1: InvalidRequestException ire, 2: NotFoundException nfe), - list get_slice_super(1:string tablename, 2:string key, 3:string columnFamily, 4:bool isAscending, 5:i32 count=100) + list get_slice_super(1:string tablename, 2:string key, 3:string columnFamily, 4:bool isAscending, 5:i32 offset, 6:i32 count=100) throws (1: InvalidRequestException ire), list get_slice_super_by_names(1:string tablename, 2:string key, 3:string columnFamily, 4:list superColumnNames) diff --git a/interface/gen-java/org/apache/cassandra/service/Cassandra.java b/interface/gen-java/org/apache/cassandra/service/Cassandra.java index d19dcfa03b..91e7663fc5 100644 --- a/interface/gen-java/org/apache/cassandra/service/Cassandra.java +++ b/interface/gen-java/org/apache/cassandra/service/Cassandra.java @@ -26,7 +26,7 @@ public class Cassandra { public List get_slice_by_names(String tablename, String key, String columnParent, List columnNames) throws InvalidRequestException, NotFoundException, TException; - public List get_slice(String tablename, String key, String columnParent, boolean isAscending, int count) throws InvalidRequestException, NotFoundException, TException; + public List get_slice(String tablename, String key, String columnParent, boolean isAscending, int offset, int count) throws InvalidRequestException, NotFoundException, TException; public column_t get_column(String tablename, String key, String columnPath) throws InvalidRequestException, NotFoundException, TException; @@ -40,7 +40,7 @@ public class Cassandra { public List get_columns_since(String tablename, String key, String columnParent, long timeStamp) throws InvalidRequestException, NotFoundException, TException; - public List get_slice_super(String tablename, String key, String columnFamily, boolean isAscending, int count) throws InvalidRequestException, TException; + public List get_slice_super(String tablename, String key, String columnFamily, boolean isAscending, int offset, int count) throws InvalidRequestException, TException; public List get_slice_super_by_names(String tablename, String key, String columnFamily, List superColumnNames) throws InvalidRequestException, TException; @@ -173,13 +173,13 @@ public class Cassandra { throw new TApplicationException(TApplicationException.MISSING_RESULT, "get_slice_by_names failed: unknown result"); } - public List get_slice(String tablename, String key, String columnParent, boolean isAscending, int count) throws InvalidRequestException, NotFoundException, TException + public List get_slice(String tablename, String key, String columnParent, boolean isAscending, int offset, int count) throws InvalidRequestException, NotFoundException, TException { - send_get_slice(tablename, key, columnParent, isAscending, count); + send_get_slice(tablename, key, columnParent, isAscending, offset, count); return recv_get_slice(); } - public void send_get_slice(String tablename, String key, String columnParent, boolean isAscending, int count) throws TException + public void send_get_slice(String tablename, String key, String columnParent, boolean isAscending, int offset, int count) throws TException { oprot_.writeMessageBegin(new TMessage("get_slice", TMessageType.CALL, seqid_)); get_slice_args args = new get_slice_args(); @@ -187,6 +187,7 @@ public class Cassandra { args.key = key; args.columnParent = columnParent; args.isAscending = isAscending; + args.offset = offset; args.count = count; args.write(oprot_); oprot_.writeMessageEnd(); @@ -455,13 +456,13 @@ public class Cassandra { throw new TApplicationException(TApplicationException.MISSING_RESULT, "get_columns_since failed: unknown result"); } - public List get_slice_super(String tablename, String key, String columnFamily, boolean isAscending, int count) throws InvalidRequestException, TException + public List get_slice_super(String tablename, String key, String columnFamily, boolean isAscending, int offset, int count) throws InvalidRequestException, TException { - send_get_slice_super(tablename, key, columnFamily, isAscending, count); + send_get_slice_super(tablename, key, columnFamily, isAscending, offset, count); return recv_get_slice_super(); } - public void send_get_slice_super(String tablename, String key, String columnFamily, boolean isAscending, int count) throws TException + public void send_get_slice_super(String tablename, String key, String columnFamily, boolean isAscending, int offset, int count) throws TException { oprot_.writeMessageBegin(new TMessage("get_slice_super", TMessageType.CALL, seqid_)); get_slice_super_args args = new get_slice_super_args(); @@ -469,6 +470,7 @@ public class Cassandra { args.key = key; args.columnFamily = columnFamily; args.isAscending = isAscending; + args.offset = offset; args.count = count; args.write(oprot_); oprot_.writeMessageEnd(); @@ -906,7 +908,7 @@ public class Cassandra { iprot.readMessageEnd(); get_slice_result result = new get_slice_result(); try { - result.success = iface_.get_slice(args.tablename, args.key, args.columnParent, args.isAscending, args.count); + result.success = iface_.get_slice(args.tablename, args.key, args.columnParent, args.isAscending, args.offset, args.count); } catch (InvalidRequestException ire) { result.ire = ire; } catch (NotFoundException nfe) { @@ -1115,7 +1117,7 @@ public class Cassandra { iprot.readMessageEnd(); get_slice_super_result result = new get_slice_super_result(); try { - result.success = iface_.get_slice_super(args.tablename, args.key, args.columnFamily, args.isAscending, args.count); + result.success = iface_.get_slice_super(args.tablename, args.key, args.columnFamily, args.isAscending, args.offset, args.count); } catch (InvalidRequestException ire) { result.ire = ire; } catch (Throwable th) { @@ -3136,7 +3138,8 @@ public class Cassandra { private static final TField KEY_FIELD_DESC = new TField("key", TType.STRING, (short)2); private static final TField COLUMN_PARENT_FIELD_DESC = new TField("columnParent", TType.STRING, (short)3); private static final TField IS_ASCENDING_FIELD_DESC = new TField("isAscending", TType.BOOL, (short)4); - private static final TField COUNT_FIELD_DESC = new TField("count", TType.I32, (short)5); + private static final TField OFFSET_FIELD_DESC = new TField("offset", TType.I32, (short)5); + private static final TField COUNT_FIELD_DESC = new TField("count", TType.I32, (short)6); public String tablename; public static final int TABLENAME = 1; @@ -3146,12 +3149,15 @@ public class Cassandra { public static final int COLUMNPARENT = 3; public boolean isAscending; public static final int ISASCENDING = 4; + public int offset; + public static final int OFFSET = 5; public int count; - public static final int COUNT = 5; + public static final int COUNT = 6; private final Isset __isset = new Isset(); private static final class Isset implements java.io.Serializable { public boolean isAscending = false; + public boolean offset = false; public boolean count = false; } @@ -3164,6 +3170,8 @@ public class Cassandra { new FieldValueMetaData(TType.STRING))); put(ISASCENDING, new FieldMetaData("isAscending", TFieldRequirementType.DEFAULT, new FieldValueMetaData(TType.BOOL))); + put(OFFSET, new FieldMetaData("offset", TFieldRequirementType.DEFAULT, + new FieldValueMetaData(TType.I32))); put(COUNT, new FieldMetaData("count", TFieldRequirementType.DEFAULT, new FieldValueMetaData(TType.I32))); }}); @@ -3182,6 +3190,7 @@ public class Cassandra { String key, String columnParent, boolean isAscending, + int offset, int count) { this(); @@ -3190,6 +3199,8 @@ public class Cassandra { this.columnParent = columnParent; this.isAscending = isAscending; this.__isset.isAscending = true; + this.offset = offset; + this.__isset.offset = true; this.count = count; this.__isset.count = true; } @@ -3209,6 +3220,8 @@ public class Cassandra { } __isset.isAscending = other.__isset.isAscending; this.isAscending = other.isAscending; + __isset.offset = other.__isset.offset; + this.offset = other.offset; __isset.count = other.__isset.count; this.count = other.count; } @@ -3309,6 +3322,28 @@ public class Cassandra { this.__isset.isAscending = value; } + public int getOffset() { + return this.offset; + } + + public void setOffset(int offset) { + this.offset = offset; + this.__isset.offset = true; + } + + public void unsetOffset() { + this.__isset.offset = false; + } + + // Returns true if field offset is set (has been asigned a value) and false otherwise + public boolean isSetOffset() { + return this.__isset.offset; + } + + public void setOffsetIsSet(boolean value) { + this.__isset.offset = value; + } + public int getCount() { return this.count; } @@ -3365,6 +3400,14 @@ public class Cassandra { } break; + case OFFSET: + if (value == null) { + unsetOffset(); + } else { + setOffset((Integer)value); + } + break; + case COUNT: if (value == null) { unsetCount(); @@ -3392,6 +3435,9 @@ public class Cassandra { case ISASCENDING: return new Boolean(isIsAscending()); + case OFFSET: + return new Integer(getOffset()); + case COUNT: return new Integer(getCount()); @@ -3411,6 +3457,8 @@ public class Cassandra { return isSetColumnParent(); case ISASCENDING: return isSetIsAscending(); + case OFFSET: + return isSetOffset(); case COUNT: return isSetCount(); default: @@ -3467,6 +3515,15 @@ public class Cassandra { return false; } + boolean this_present_offset = true; + boolean that_present_offset = true; + if (this_present_offset || that_present_offset) { + if (!(this_present_offset && that_present_offset)) + return false; + if (this.offset != that.offset) + return false; + } + boolean this_present_count = true; boolean that_present_count = true; if (this_present_count || that_present_count) { @@ -3524,6 +3581,14 @@ public class Cassandra { TProtocolUtil.skip(iprot, field.type); } break; + case OFFSET: + if (field.type == TType.I32) { + this.offset = iprot.readI32(); + this.__isset.offset = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; case COUNT: if (field.type == TType.I32) { this.count = iprot.readI32(); @@ -3567,6 +3632,9 @@ public class Cassandra { oprot.writeFieldBegin(IS_ASCENDING_FIELD_DESC); oprot.writeBool(this.isAscending); oprot.writeFieldEnd(); + oprot.writeFieldBegin(OFFSET_FIELD_DESC); + oprot.writeI32(this.offset); + oprot.writeFieldEnd(); oprot.writeFieldBegin(COUNT_FIELD_DESC); oprot.writeI32(this.count); oprot.writeFieldEnd(); @@ -3607,6 +3675,10 @@ public class Cassandra { sb.append(this.isAscending); first = false; if (!first) sb.append(", "); + sb.append("offset:"); + sb.append(this.offset); + first = false; + if (!first) sb.append(", "); sb.append("count:"); sb.append(this.count); first = false; @@ -8290,7 +8362,8 @@ public class Cassandra { private static final TField KEY_FIELD_DESC = new TField("key", TType.STRING, (short)2); private static final TField COLUMN_FAMILY_FIELD_DESC = new TField("columnFamily", TType.STRING, (short)3); private static final TField IS_ASCENDING_FIELD_DESC = new TField("isAscending", TType.BOOL, (short)4); - private static final TField COUNT_FIELD_DESC = new TField("count", TType.I32, (short)5); + private static final TField OFFSET_FIELD_DESC = new TField("offset", TType.I32, (short)5); + private static final TField COUNT_FIELD_DESC = new TField("count", TType.I32, (short)6); public String tablename; public static final int TABLENAME = 1; @@ -8300,12 +8373,15 @@ public class Cassandra { public static final int COLUMNFAMILY = 3; public boolean isAscending; public static final int ISASCENDING = 4; + public int offset; + public static final int OFFSET = 5; public int count; - public static final int COUNT = 5; + public static final int COUNT = 6; private final Isset __isset = new Isset(); private static final class Isset implements java.io.Serializable { public boolean isAscending = false; + public boolean offset = false; public boolean count = false; } @@ -8318,6 +8394,8 @@ public class Cassandra { new FieldValueMetaData(TType.STRING))); put(ISASCENDING, new FieldMetaData("isAscending", TFieldRequirementType.DEFAULT, new FieldValueMetaData(TType.BOOL))); + put(OFFSET, new FieldMetaData("offset", TFieldRequirementType.DEFAULT, + new FieldValueMetaData(TType.I32))); put(COUNT, new FieldMetaData("count", TFieldRequirementType.DEFAULT, new FieldValueMetaData(TType.I32))); }}); @@ -8336,6 +8414,7 @@ public class Cassandra { String key, String columnFamily, boolean isAscending, + int offset, int count) { this(); @@ -8344,6 +8423,8 @@ public class Cassandra { this.columnFamily = columnFamily; this.isAscending = isAscending; this.__isset.isAscending = true; + this.offset = offset; + this.__isset.offset = true; this.count = count; this.__isset.count = true; } @@ -8363,6 +8444,8 @@ public class Cassandra { } __isset.isAscending = other.__isset.isAscending; this.isAscending = other.isAscending; + __isset.offset = other.__isset.offset; + this.offset = other.offset; __isset.count = other.__isset.count; this.count = other.count; } @@ -8463,6 +8546,28 @@ public class Cassandra { this.__isset.isAscending = value; } + public int getOffset() { + return this.offset; + } + + public void setOffset(int offset) { + this.offset = offset; + this.__isset.offset = true; + } + + public void unsetOffset() { + this.__isset.offset = false; + } + + // Returns true if field offset is set (has been asigned a value) and false otherwise + public boolean isSetOffset() { + return this.__isset.offset; + } + + public void setOffsetIsSet(boolean value) { + this.__isset.offset = value; + } + public int getCount() { return this.count; } @@ -8519,6 +8624,14 @@ public class Cassandra { } break; + case OFFSET: + if (value == null) { + unsetOffset(); + } else { + setOffset((Integer)value); + } + break; + case COUNT: if (value == null) { unsetCount(); @@ -8546,6 +8659,9 @@ public class Cassandra { case ISASCENDING: return new Boolean(isIsAscending()); + case OFFSET: + return new Integer(getOffset()); + case COUNT: return new Integer(getCount()); @@ -8565,6 +8681,8 @@ public class Cassandra { return isSetColumnFamily(); case ISASCENDING: return isSetIsAscending(); + case OFFSET: + return isSetOffset(); case COUNT: return isSetCount(); default: @@ -8621,6 +8739,15 @@ public class Cassandra { return false; } + boolean this_present_offset = true; + boolean that_present_offset = true; + if (this_present_offset || that_present_offset) { + if (!(this_present_offset && that_present_offset)) + return false; + if (this.offset != that.offset) + return false; + } + boolean this_present_count = true; boolean that_present_count = true; if (this_present_count || that_present_count) { @@ -8678,6 +8805,14 @@ public class Cassandra { TProtocolUtil.skip(iprot, field.type); } break; + case OFFSET: + if (field.type == TType.I32) { + this.offset = iprot.readI32(); + this.__isset.offset = true; + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; case COUNT: if (field.type == TType.I32) { this.count = iprot.readI32(); @@ -8721,6 +8856,9 @@ public class Cassandra { oprot.writeFieldBegin(IS_ASCENDING_FIELD_DESC); oprot.writeBool(this.isAscending); oprot.writeFieldEnd(); + oprot.writeFieldBegin(OFFSET_FIELD_DESC); + oprot.writeI32(this.offset); + oprot.writeFieldEnd(); oprot.writeFieldBegin(COUNT_FIELD_DESC); oprot.writeI32(this.count); oprot.writeFieldEnd(); @@ -8761,6 +8899,10 @@ public class Cassandra { sb.append(this.isAscending); first = false; if (!first) sb.append(", "); + sb.append("offset:"); + sb.append(this.offset); + first = false; + if (!first) sb.append(", "); sb.append("count:"); sb.append(this.count); first = false; diff --git a/src/java/org/apache/cassandra/cli/CliClient.java b/src/java/org/apache/cassandra/cli/CliClient.java index fffc055db7..6a35df00dc 100644 --- a/src/java/org/apache/cassandra/cli/CliClient.java +++ b/src/java/org/apache/cassandra/cli/CliClient.java @@ -135,7 +135,7 @@ public class CliClient { // table.cf['key'] List columns = new ArrayList(); - columns = thriftClient_.get_slice(tableName, key, columnFamily, true, 1000000); + columns = thriftClient_.get_slice(tableName, key, columnFamily, true, 0, 1000000); int size = columns.size(); for (Iterator colIter = columns.iterator(); colIter.hasNext(); ) { diff --git a/src/java/org/apache/cassandra/cql/common/ColumnRangeQueryRSD.java b/src/java/org/apache/cassandra/cql/common/ColumnRangeQueryRSD.java index 12abebcaa2..ca0e7e662d 100644 --- a/src/java/org/apache/cassandra/cql/common/ColumnRangeQueryRSD.java +++ b/src/java/org/apache/cassandra/cql/common/ColumnRangeQueryRSD.java @@ -97,7 +97,7 @@ public class ColumnRangeQueryRSD extends RowSourceDef try { String key = (String)(rowKey_.get()); - ReadCommand readCommand = new SliceFromReadCommand(cfMetaData_.tableName, key, columnFamily_column, true, limit_); + ReadCommand readCommand = new SliceFromReadCommand(cfMetaData_.tableName, key, columnFamily_column, true, offset_, limit_); row = StorageProxy.readProtocol(readCommand, StorageService.ConsistencyLevel.WEAK); } catch (Exception e) diff --git a/src/java/org/apache/cassandra/cql/common/SuperColumnRangeQueryRSD.java b/src/java/org/apache/cassandra/cql/common/SuperColumnRangeQueryRSD.java index 377f39d8be..4acc40b264 100644 --- a/src/java/org/apache/cassandra/cql/common/SuperColumnRangeQueryRSD.java +++ b/src/java/org/apache/cassandra/cql/common/SuperColumnRangeQueryRSD.java @@ -66,7 +66,7 @@ public class SuperColumnRangeQueryRSD extends RowSourceDef try { String key = (String)(rowKey_.get()); - ReadCommand readCommand = new SliceFromReadCommand(cfMetaData_.tableName, key, cfMetaData_.cfName, true, limit_); + ReadCommand readCommand = new SliceFromReadCommand(cfMetaData_.tableName, key, cfMetaData_.cfName, true, offset_, limit_); row = StorageProxy.readProtocol(readCommand, StorageService.ConsistencyLevel.WEAK); } catch (Exception e) diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java index 8ee08c53eb..0bb9a93a8a 100644 --- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java +++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java @@ -1535,7 +1535,7 @@ public final class ColumnFamilyStore implements ColumnFamilyStoreMBean * get a list of columns starting from a given column, in a specified order * only the latest version of a column is returned */ - public ColumnFamily getSliceFrom(String key, String cfName, String startColumn, boolean isAscending, int count) + public ColumnFamily getSliceFrom(String key, String cfName, String startColumn, boolean isAscending, int offset, int count) throws IOException, ExecutionException, InterruptedException { lock_.readLock().lock(); @@ -1620,16 +1620,18 @@ public final class ColumnFamilyStore implements ColumnFamilyStoreMBean // add unique columns to the CF container int liveColumns = 0; + int limit = offset + count; for (IColumn column : reduced) { - if (liveColumns >= count) + if (liveColumns >= limit) { break; } if (!column.isMarkedForDelete()) liveColumns++; - returnCF.addColumn(column); + if (liveColumns > offset) + returnCF.addColumn(column); } return removeDeleted(returnCF); diff --git a/src/java/org/apache/cassandra/db/SliceFromReadCommand.java b/src/java/org/apache/cassandra/db/SliceFromReadCommand.java index 935cbba6be..8c04203f4e 100644 --- a/src/java/org/apache/cassandra/db/SliceFromReadCommand.java +++ b/src/java/org/apache/cassandra/db/SliceFromReadCommand.java @@ -25,13 +25,15 @@ public class SliceFromReadCommand extends ReadCommand { public final String columnFamilyColumn; public final boolean isAscending; + public final int limit; public final int count; - public SliceFromReadCommand(String table, String key, String columnFamilyColumn, boolean isAscending, int count) + public SliceFromReadCommand(String table, String key, String columnFamilyColumn, boolean isAscending, int limit, int count) { super(table, key, CMD_TYPE_GET_SLICE_FROM); this.columnFamilyColumn = columnFamilyColumn; this.isAscending = isAscending; + this.limit = limit; this.count = count; } @@ -44,7 +46,7 @@ public class SliceFromReadCommand extends ReadCommand @Override public ReadCommand copy() { - ReadCommand readCommand = new SliceFromReadCommand(table, key, columnFamilyColumn, isAscending, count); + ReadCommand readCommand = new SliceFromReadCommand(table, key, columnFamilyColumn, isAscending, limit, count); readCommand.setDigestQuery(isDigestQuery()); return readCommand; } @@ -52,7 +54,7 @@ public class SliceFromReadCommand extends ReadCommand @Override public Row getRow(Table table) throws IOException { - return table.getSliceFrom(key, columnFamilyColumn, isAscending, count); + return table.getSliceFrom(key, columnFamilyColumn, isAscending, limit, count); } @Override @@ -63,6 +65,7 @@ public class SliceFromReadCommand extends ReadCommand ", key='" + key + '\'' + ", columnFamily='" + columnFamilyColumn + '\'' + ", isAscending='" + isAscending + '\'' + + ", limit='" + limit + '\'' + ", count='" + count + '\'' + ')'; } @@ -79,6 +82,7 @@ class SliceFromReadCommandSerializer extends ReadCommandSerializer dos.writeUTF(realRM.key); dos.writeUTF(realRM.columnFamilyColumn); dos.writeBoolean(realRM.isAscending); + dos.writeInt(realRM.limit); dos.writeInt(realRM.count); } @@ -90,9 +94,10 @@ class SliceFromReadCommandSerializer extends ReadCommandSerializer String key = dis.readUTF(); String columnFamily = dis.readUTF(); boolean isAscending = dis.readBoolean(); + int limit = dis.readInt(); int count = dis.readInt(); - SliceFromReadCommand rm = new SliceFromReadCommand(table, key, columnFamily, isAscending, count); + SliceFromReadCommand rm = new SliceFromReadCommand(table, key, columnFamily, isAscending, limit, count); rm.setDigestQuery(isDigest); return rm; } diff --git a/src/java/org/apache/cassandra/db/Table.java b/src/java/org/apache/cassandra/db/Table.java index 3f547322ed..5f16d4068b 100644 --- a/src/java/org/apache/cassandra/db/Table.java +++ b/src/java/org/apache/cassandra/db/Table.java @@ -605,7 +605,7 @@ public class Table /** * Selects a list of columns in a column family from a given column for the specified key. */ - public Row getSliceFrom(String key, String cf, boolean isAscending, int count) throws IOException + public Row getSliceFrom(String key, String cf, boolean isAscending, int limit, int count) throws IOException { Row row = new Row(table_, key); String[] values = cf.split(":", -1); @@ -615,7 +615,7 @@ public class Table long start1 = System.currentTimeMillis(); try { - ColumnFamily columnFamily = cfStore.getSliceFrom(key, cfName, startWith, isAscending, count); + ColumnFamily columnFamily = cfStore.getSliceFrom(key, cfName, startWith, isAscending, limit, count); if (columnFamily != null) row.addColumnFamily(columnFamily); long timeTaken = System.currentTimeMillis() - start1; diff --git a/src/java/org/apache/cassandra/service/CassandraServer.java b/src/java/org/apache/cassandra/service/CassandraServer.java index 4b7c647913..cf3c3ad70c 100644 --- a/src/java/org/apache/cassandra/service/CassandraServer.java +++ b/src/java/org/apache/cassandra/service/CassandraServer.java @@ -167,7 +167,7 @@ public class CassandraServer implements Cassandra.Iface } } - public List get_slice(String tablename, String key, String columnParent, boolean isAscending, int count) throws InvalidRequestException + public List get_slice(String tablename, String key, String columnParent, boolean isAscending, int offset, int count) throws InvalidRequestException { logger.debug("get_slice_from"); String[] values = columnParent.split(":", -1); // allow empty column specifier @@ -178,7 +178,7 @@ public class CassandraServer implements Cassandra.Iface if ("Name".compareTo(DatabaseDescriptor.getCFMetaData(tablename, values[0]).indexProperty_) != 0) throw new InvalidRequestException("get_slice_from requires CF indexed by name"); - ColumnFamily cfamily = readColumnFamily(new SliceFromReadCommand(tablename, key, columnParent, isAscending, count)); + ColumnFamily cfamily = readColumnFamily(new SliceFromReadCommand(tablename, key, columnParent, isAscending, offset, count)); if (cfamily == null) { return EMPTY_COLUMNS; @@ -232,7 +232,7 @@ public class CassandraServer implements Cassandra.Iface ColumnFamily cfamily; if (DatabaseDescriptor.isNameSortingEnabled(tablename, values[0])) { - cfamily = readColumnFamily(new SliceFromReadCommand(tablename, key, columnParent + ":", true, Integer.MAX_VALUE)); + cfamily = readColumnFamily(new SliceFromReadCommand(tablename, key, columnParent + ":", true, 0, Integer.MAX_VALUE)); } else { @@ -341,7 +341,7 @@ public class CassandraServer implements Cassandra.Iface return thriftSuperColumns; } - public List get_slice_super(String tablename, String key, String columnFamily, boolean isAscending, int count) throws InvalidRequestException + public List get_slice_super(String tablename, String key, String columnFamily, boolean isAscending, int offset, int count) throws InvalidRequestException { logger.debug("get_slice_super"); String[] values = columnFamily.split(":", -1); @@ -350,7 +350,7 @@ public class CassandraServer implements Cassandra.Iface if (count <= 0) throw new InvalidRequestException("get_slice_super requires positive count"); - ColumnFamily cfamily = readColumnFamily(new SliceFromReadCommand(tablename, key, columnFamily, isAscending, count)); + ColumnFamily cfamily = readColumnFamily(new SliceFromReadCommand(tablename, key, columnFamily, isAscending, offset, count)); if (cfamily == null) { return EMPTY_SUPERCOLUMNS; diff --git a/test/system/test_server.py b/test/system/test_server.py index ade6378a8b..640781b950 100644 --- a/test/system/test_server.py +++ b/test/system/test_server.py @@ -43,13 +43,13 @@ def _insert_batch(block): def _verify_batch(): _verify_simple() - L = client.get_slice('Table1', 'key1', 'Standard2:', True, 1000) + L = client.get_slice('Table1', 'key1', 'Standard2:', True, 0, 1000) assert L == _SIMPLE_COLUMNS, L def _verify_simple(): assert client.get_column('Table1', 'key1', 'Standard1:c1') == \ column_t(columnName='c1', value='value1', timestamp=0) - L = client.get_slice('Table1', 'key1', 'Standard1:', True, 1000) + L = client.get_slice('Table1', 'key1', 'Standard1:', True, 0, 1000) assert L == _SIMPLE_COLUMNS, L def _insert_super(): @@ -80,7 +80,7 @@ def _verify_range(): def _verify_super(supercolumn='Super1'): assert client.get_column('Table1', 'key1', supercolumn + ':sc1:c4') == \ column_t(columnName='c4', value='value4', timestamp=0) - slice = client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) + slice = client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) assert slice == _SUPER_COLUMNS, slice def _expect_exception(fn, type_): @@ -101,10 +101,10 @@ class TestMutations(CassandraTester): _verify_simple() def test_empty_slice(self): - assert client.get_slice('Table1', 'key1', 'Standard2:', True, 1000) == [] + assert client.get_slice('Table1', 'key1', 'Standard2:', True, 0, 1000) == [] def test_empty_slice_super(self): - assert client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) == [] + assert client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) == [] def test_missing_super(self): _expect_missing(lambda: client.get_column('Table1', 'key1', 'Super1:sc1:c1')) @@ -160,24 +160,24 @@ class TestMutations(CassandraTester): _expect_missing(lambda: client.get_column('Table1', 'key1', 'Standard1:c1')) assert client.get_column('Table1', 'key1', 'Standard1:c2') == \ column_t(columnName='c2', value='value2', timestamp=0) - assert client.get_slice('Table1', 'key1', 'Standard1:', True, 1000) == \ + assert client.get_slice('Table1', 'key1', 'Standard1:', True, 0, 1000) == \ [column_t(columnName='c2', value='value2', timestamp=0)] # New insert, make sure it shows up post-remove: client.insert('Table1', 'key1', 'Standard1:c3', 'value3', 0, True) - assert client.get_slice('Table1', 'key1', 'Standard1:', True, 1000) == \ + assert client.get_slice('Table1', 'key1', 'Standard1:', True, 0, 1000) == \ [column_t(columnName='c2', value='value2', timestamp=0), column_t(columnName='c3', value='value3', timestamp=0)] # Test resurrection. First, re-insert the value w/ older timestamp, # and make sure it stays removed: client.insert('Table1', 'key1', 'Standard1:c1', 'value1', 0, True) - assert client.get_slice('Table1', 'key1', 'Standard1:', True, 1000) == \ + assert client.get_slice('Table1', 'key1', 'Standard1:', True, 0, 1000) == \ [column_t(columnName='c2', value='value2', timestamp=0), column_t(columnName='c3', value='value3', timestamp=0)] # Next, w/ a newer timestamp; it should come back: client.insert('Table1', 'key1', 'Standard1:c1', 'value1', 2, True) - assert client.get_slice('Table1', 'key1', 'Standard1:', True, 1000) == \ + assert client.get_slice('Table1', 'key1', 'Standard1:', True, 0, 1000) == \ [column_t(columnName='c1', value='value1', timestamp=2), column_t(columnName='c2', value='value2', timestamp=0), column_t(columnName='c3', value='value3', timestamp=0)] @@ -189,16 +189,16 @@ class TestMutations(CassandraTester): # Remove the key1:Standard1 cf: client.remove('Table1', 'key1', 'Standard1', 3, True) - assert client.get_slice('Table1', 'key1', 'Standard1:', True, 1000) == [] + assert client.get_slice('Table1', 'key1', 'Standard1:', True, 0, 1000) == [] _verify_super() # Test resurrection. First, re-insert a value w/ older timestamp, # and make sure it stays removed: client.insert('Table1', 'key1', 'Standard1:c1', 'value1', 0, True) - assert client.get_slice('Table1', 'key1', 'Standard1:', True, 1000) == [] + assert client.get_slice('Table1', 'key1', 'Standard1:', True, 0, 1000) == [] # Next, w/ a newer timestamp; it should come back: client.insert('Table1', 'key1', 'Standard1:c1', 'value1', 4, True) - assert client.get_slice('Table1', 'key1', 'Standard1:', True, 1000) == \ + assert client.get_slice('Table1', 'key1', 'Standard1:', True, 0, 1000) == \ [column_t(columnName='c1', value='value1', timestamp=4)] @@ -209,7 +209,7 @@ class TestMutations(CassandraTester): # Make sure remove clears out what it's supposed to, and _only_ that: client.remove('Table1', 'key1', 'Super1:sc2:c5', 5, True) _expect_missing(lambda: client.get_column('Table1', 'key1', 'Super1:sc2:c5')) - assert client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) == \ + assert client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) == \ [superColumn_t(name='sc1', columns=[column_t(columnName='c4', value='value4', timestamp=0)]), superColumn_t(name='sc2', @@ -224,17 +224,17 @@ class TestMutations(CassandraTester): columns=[column_t(columnName='c6', value='value6', timestamp=0), column_t(columnName='c7', value='value7', timestamp=0)])] - assert client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) == scs + assert client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) == scs # Test resurrection. First, re-insert the value w/ older timestamp, # and make sure it stays removed: client.insert('Table1', 'key1', 'Super1:sc2:c5', 'value5', 0, True) - actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) + actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) assert actual == scs, actual # Next, w/ a newer timestamp; it should come back client.insert('Table1', 'key1', 'Super1:sc2:c5', 'value5', 6, True) - actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) + actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) assert actual == \ [superColumn_t(name='sc1', columns=[column_t(columnName='c4', value='value4', timestamp=0)]), @@ -254,19 +254,19 @@ class TestMutations(CassandraTester): assert actual == [], actual scs = [superColumn_t(name='sc1', columns=[column_t(columnName='c4', value='value4', timestamp=0)])] - actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) + actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) assert actual == scs, actual _verify_simple() # Test resurrection. First, re-insert the value w/ older timestamp, # and make sure it stays removed: client.insert('Table1', 'key1', 'Super1:sc2:c5', 'value5', 0, True) - actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) + actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) assert actual == scs, actual # Next, w/ a newer timestamp; it should come back client.insert('Table1', 'key1', 'Super1:sc2:c5', 'value5', 6, True) - actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 1000) + actual = client.get_slice_super('Table1', 'key1', 'Super1:', True, 0, 1000) assert actual == \ [superColumn_t(name='sc1', columns=[column_t(columnName='c4', value='value4', timestamp=0)]), diff --git a/test/unit/org/apache/cassandra/db/ReadMessageTest.java b/test/unit/org/apache/cassandra/db/ReadMessageTest.java index 2801faf65d..0ce0cbe2c1 100644 --- a/test/unit/org/apache/cassandra/db/ReadMessageTest.java +++ b/test/unit/org/apache/cassandra/db/ReadMessageTest.java @@ -57,7 +57,7 @@ public class ReadMessageTest rm2 = serializeAndDeserializeReadMessage(rm); assert rm2.toString().equals(rm.toString()); - rm = new SliceFromReadCommand("Table1", "row1", "foo", true, 2); + rm = new SliceFromReadCommand("Table1", "row1", "foo", true, 0, 2); rm2 = serializeAndDeserializeReadMessage(rm); assert rm2.toString().equals(rm.toString()); diff --git a/test/unit/org/apache/cassandra/db/TableTest.java b/test/unit/org/apache/cassandra/db/TableTest.java index a7efb6a79c..fb3b7f64a9 100644 --- a/test/unit/org/apache/cassandra/db/TableTest.java +++ b/test/unit/org/apache/cassandra/db/TableTest.java @@ -146,12 +146,12 @@ public class TableTest extends CleanupHelper ColumnFamily cf; // key before the rows that exists - result = table.getSliceFrom("a", "Standard2:", true, 0); + result = table.getSliceFrom("a", "Standard2:", true, 0, 1); cf = result.getColumnFamily("Standard2"); assertColumns(cf); // key after the rows that exist - result = table.getSliceFrom("z", "Standard2:", true, 0); + result = table.getSliceFrom("z", "Standard2:", true, 0, 1); cf = result.getColumnFamily("Standard2"); assertColumns(cf); } @@ -190,27 +190,27 @@ public class TableTest extends CleanupHelper Row result; ColumnFamily cf; - result = table.getSliceFrom(ROW, "Standard1:col5", true, 2); + result = table.getSliceFrom(ROW, "Standard1:col5", true, 0, 2); cf = result.getColumnFamily("Standard1"); assertColumns(cf, "col5", "col7"); - result = table.getSliceFrom(ROW, "Standard1:col4", true, 2); + result = table.getSliceFrom(ROW, "Standard1:col4", true, 0, 2); cf = result.getColumnFamily("Standard1"); - assertColumns(cf, "col4", "col5", "col7"); + assertColumns(cf, "col5", "col7"); - result = table.getSliceFrom(ROW, "Standard1:col5", false, 2); + result = table.getSliceFrom(ROW, "Standard1:col5", false, 0, 2); cf = result.getColumnFamily("Standard1"); assertColumns(cf, "col3", "col4", "col5"); - result = table.getSliceFrom(ROW, "Standard1:col6", false, 2); + result = table.getSliceFrom(ROW, "Standard1:col6", false, 0, 2); cf = result.getColumnFamily("Standard1"); assertColumns(cf, "col3", "col4", "col5"); - result = table.getSliceFrom(ROW, "Standard1:col95", true, 2); + result = table.getSliceFrom(ROW, "Standard1:col95", true, 0, 2); cf = result.getColumnFamily("Standard1"); assertColumns(cf); - result = table.getSliceFrom(ROW, "Standard1:col0", false, 2); + result = table.getSliceFrom(ROW, "Standard1:col0", false, 0, 2); cf = result.getColumnFamily("Standard1"); assertColumns(cf); } @@ -258,7 +258,7 @@ public class TableTest extends CleanupHelper Row result; ColumnFamily cfres; - result = table.getSliceFrom(ROW, "Standard1:col2", true, 3); + result = table.getSliceFrom(ROW, "Standard1:col2", true, 0, 3); cfres = result.getColumnFamily("Standard1"); assertColumns(cfres, "col2", "col3", "col4"); assertEquals(new String(cfres.getColumn("col2").value()), "valx"); @@ -286,28 +286,42 @@ public class TableTest extends CleanupHelper Row result; ColumnFamily cfres; - result = table.getSliceFrom(ROW, "Standard1:col1000", true, 3); + result = table.getSliceFrom(ROW, "Standard1:col1000", true, 0, 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); + result = table.getSliceFrom(ROW, "Standard1:col1195", true, 0, 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); + result = table.getSliceFrom(ROW, "Standard1:col1195", true, 10, 3); + cfres = result.getColumnFamily("Standard1"); + assertColumns(cfres, "col1205", "col1206", "col1207"); + assertEquals(new String(cfres.getColumn("col1205").value()), "vvvvvvvvvvvvvvvv1205"); + assertEquals(new String(cfres.getColumn("col1206").value()), "vvvvvvvvvvvvvvvv1206"); + assertEquals(new String(cfres.getColumn("col1207").value()), "vvvvvvvvvvvvvvvv1207"); + + result = table.getSliceFrom(ROW, "Standard1:col1196", false, 0, 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); + result = table.getSliceFrom(ROW, "Standard1:col1196", false, 10, 3); + cfres = result.getColumnFamily("Standard1"); + assertColumns(cfres, "col1184", "col1185", "col1186"); + assertEquals(new String(cfres.getColumn("col1184").value()), "vvvvvvvvvvvvvvvv1184"); + assertEquals(new String(cfres.getColumn("col1185").value()), "vvvvvvvvvvvvvvvv1185"); + assertEquals(new String(cfres.getColumn("col1186").value()), "vvvvvvvvvvvvvvvv1186"); + + result = table.getSliceFrom(ROW, "Standard1:col1990", true, 0, 3); cfres = result.getColumnFamily("Standard1"); assertColumns(cfres, "col1990", "col1991", "col1992"); assertEquals(new String(cfres.getColumn("col1990").value()), "vvvvvvvvvvvvvvvv1990"); @@ -342,7 +356,7 @@ public class TableTest extends CleanupHelper Row result; ColumnFamily cfres; - result = table.getSliceFrom(ROW, "Super1:", true, 10); + result = table.getSliceFrom(ROW, "Super1:", true, 0, 10); cfres = result.getColumnFamily("Super1"); assertColumns(cfres, "sc1"); assertEquals(new String(cfres.getColumn("sc1").getSubColumn("col1").value()), "val1");