Ownership

Ownership entails exclusive affiliation between a Node and a regular Object. When assigning an object to a node or to a node’s attribute, ensure that the object or the object’s non-primitive typed nested attributes are not referenced elsewhere by another Object or another Node.

Workaround

If an instance of the object needs to be referenced from multiple places, encapsulating this instance as a node is often recommended. However, if the object is immutable or can be made immutable for the node it’s assigned to, simply cloning the object when assigning its value to the node is a viable option.

Immutable: An immutable object retains a constant internal state once fully created. This implies that after assigning the object to a variable, neither the reference nor the internal state can be altered in any way.

Why ownership?

Conceptually

GreyCat is a Programmable Database replacing PL/SQL with an imperative language, aiming to accelerate iteration and development cycles over data. Unlike traditional programming scenarios where runtime lifecycle and persistence of an object are distinct, GreyCat offers seamless database programming by automatically synchronizing an object’s state between runtime (in RAM) and persistence (in DB/Hard Disk).

Keep in mind that we have limited RAM and usually we cannot load an entire graph into the RAM. For a node or a part of a graph created and saved into RAM during runtime, from time to time, it will be persisted into DB on the hard disk and removed from RAM. Let’s term this persisting operation as “unload”, as it involves unloading data from RAM. Later, when the value stored in a node or part of the graph is needed, it is “loaded” again into RAM. Directly referencing a plain object elsewhere causes various issues during “unload” and “load” operations.

Object referenced by another node:

Imagine one object named obj being referenced by two nodes, n1 and n2. When these nodes are saved to the hard disk, plain objects cannot be saved alone. Consequently, both n1 and n2 will create separate copies of obj without any linkage between them. If you access and update the field of obj from n1, the obj in n2 remains unaffected and unaltered. This situation disrupts the intended “sharing” relationship.

Check this image below for a better illustration:
Referenced by node

Object referenced by another plain object:

In this scenario, the circumstances are akin to the previous one. Suppose we have an object named obj referenced by a node named n1. Meanwhile, a second object named another_obj also references obj. Upon the completion of the “unload” operation, a similar situation arises on the hard disk as described in the previous paragraph. However, an essential aspect we haven’t addressed yet is that, for a node, the lifecycle of all its attributes is tied to the node. In our case, the plain object obj is erased from RAM when the node n1 is unloaded. Consequently, while another_obj holds a reference to an expired object, this reference becomes a “stray pointer”. If we reload our node n1 into RAM in the future, a new instance of obj will be created in RAM based on its value stored in n1. However, there’s still no way for another_obj to repair its reference by pointing towards the newly created instance, which we’ll call “second_copy obj”.

Check this image below for a better illustration: Referenced by node