Split subspaces

How can we split a subspace to get its tuple elements? Looks like no APIs.

	tx.Set(store.Events.Sub(id, "type"), []byte("snapshot"))
	iter := tx.GetRange(fdb.KeyRange{Begin: store.States.Sub(""), End: store.States.Sub("\xFF")}, fdb.RangeOptions{}).Iterator()
	for iter.Advance() {
		kv, err := iter.Get()
		if err != nil {
			return err
		}
		name := subspace.FromBytes(kv.Key).last // <- Want to get the last tuple element.
		tx.Set(store.Events.Sub(id, "states", name), kv.Value)
	}

The Subspace.Unpack method takes a key in that subspace and returns the tuple parsed value from that key’s suffix, which I think is what you want.

So if you’re subspace is defined by the prefix \x02my_subspace\x00 and you have a tuple value (like, say, (string, 100)), then that’ll get packed into a single FDBKey that looks like \x02my_subspace\x00\x02string\x00\x15\x64, and then calling Subspace.Unpack(key) will return (string, 100) as a Tuple (and a nil error).

You mean subspace.Sub(1).Unpack(subspace.Sub(1, 2, 3)) returns subspace.Sub(2, 3)?

Indeed, that returns (2, 3). This will resolve my issue, thanks!

However, splitting (2, 3) is still difficult because we don’t actually know that what is the child element value. So an API to split subspaces is needed. Can you provide that API?

Hm, I’m not sure I understand the question. In particular, I’m not sure exactly what you mean by “splitting the subspace”.

What would be the inputs and outputs of your ideal API?

With the following code,

	// (1, 2, 3) is stored.
	iter := tx.GetRange(fdb.KeyRange{Begin: subspace.Sub(1), End: subspace.Sub(2)}, fdb.RangeOptions{}).Iterator()
	for iter.Advance() {
		kv, err := iter.Get()
		if err != nil {
			return err
		}
		// t is (2, 3).
		t, err := subspace.Sub(1).Unpack(kv.Key)
	}

no API to split (2, 3) into 2 and 3.

I’m not good at Go but the following code is an API to resolve the issue.

		// t is (2, 3).
		t, err := subspace.Sub(1).Unpack(kv.Key)
		// a is [...]interface{}{2, 3}.
		a := t.Array()

I’m also not an expert at go, but I think the Tuple type is itself a slice (of TupleElements), so I think you should be able to do most of the things that you would have wanted to do if you could convert it to a []interface{} (via some .Array() method).

I couldn’t find the greatest of examples of this in our recipes, but there is this here: foundationdb/table.go at 55b8ff58168c9664f31b19e8f88e2e171fe5d8fe · apple/foundationdb · GitHub You can see that this calls Unpack on a []byte to create a Tuple, and then it asks the tuple for element 0 and returns the interface{} that it found there. But I think you should be able to call all of the functions you’d expect to exist on slices on Tuples as well.

Oh, I didn’t realize that fact because IDE suggested no array methods on tuple values. Sorry!

1 Like