Adding data to a stable variable

Consider data like this:

stable var = {
  mainData: Text;
};

Suppose, I want to change it to:

stable var = {
  mainData: Text;
  additionalData: ?Text;
};

It would be very nice if I were be able to update the canister to the new datatype (with additionalData set to null). It would be even more nice if it worked upgrade of collections:

stable var = Buffer.Buffer<{
  mainData: Text;
}>;

to:

stable var = Buffer.Buffer<{
  mainData: Text;
  additionalData: ?Text;
}>;

Is anything like this available and/or planned?

No, not at the moment. The current implementation of stable variables, which use a form of Candid under the hood, actually does support this, accidentally, but only if you (foolishly) ignore the warning about type compatibility.

We deliberately don’t want to allow this for now because it implies that upgrade has do to some sort of transformation on all stable data (or do it lazily) which won’t scale well to lots of data (just as our current implementation does not scale well).

It also gets in the way of stable data formats that want to preserve sharing (i.e. the graph structure) of existing data, another direction we want to move towards (and are actively investigating). Suppose two fields alias the same value and evolve in different ways. Then the aliasing cannot be preserved.

Your workaround is to declare a new stable variable, initialized from the old one but adding the new fields, or adding a second variable just holding the additional field (think adding a column to table).

Another option might be for us to extend Motoko subtyping to allow subtyping to add optional fields, with a change in semantics of field access to default missing fields of optional type to null, but I’m not sure the type theory for that ends well (though it might).

1 Like