Tuple.range() vs Range.startsWith(tuple.pack())?

Hi,

I wanted to check if there is any real difference between the following two ways to define a Range that would fetch all the keys with given Tuple as prefix:

  • Tuple.range()
  • Range.startsWith(tuple.pack())

Just for reference: here is the code snippet for both the methods:

Tuple::
	public Range range() {
		byte[] p = pack();
		return new Range(ByteArrayUtil.join(p, new byte[] {0x0}),
						 ByteArrayUtil.join(p, new byte[] {(byte)0xff}));
	}
Range::
	public static Range startsWith(byte[] prefix) {
		return new Range(prefix, ByteArrayUtil.strinc(prefix));
	}

Want to make sure there is no subtle difference that I am overlooking here (I understand the exact byte[] of the resultant Range will be different with two approaches, but will there be any real semantic difference between the two is one is dealing with Tuple based prefix?

In other words - could Tuple’s range() method have been implemented as Range.startswith(pack()) ?


thanks,
gaurav

I think the main difference you’ll find is that using Range.startsWith will include the tuple itself, while Tuple.range only includes proper sub-tuples. In other words, if you have a tuple t=('foo', 'bar') and you have key k=t.pack() in the database, then calling t.range() will not include k, but calling Range.startsWith(t.pack()) will. The former would only include things like ('foo', 'bar', 'baz'), where there is at least one additional element in the tuple.

It’s also the case that any keys that are of the form t.pack() + '\xff' + ... will be excluded by t.range() and included by Range.startsWith(), but such keys won’t exist if all of your keys are generated from tuples.

2 Likes

Great! I overlooked the inclusivity of the tuple itself. Thanks for pointing that out…