Complex Values

Previous Next

The idea of a Value in InfinityDB corresponds not to a suffix of a single Item but to all the suffixes of a set of Items having a common prefix. Such a set of suffixes is called a subspace, and there are very many situations where subspaces are important.

In the case of the the Entity-Attribute-Value model, the common prefix of a Value is comprised of the EntityClass component, the Entity components, and the Attribute component. However, any common prefix can be used.

Each of these 'complex' Value structures can be added to an existing database on the fly for backwards compatability of new application versions with existing databases. Sometimes older applications can work with the extended structure as well.

Set Values

Set-Valued Attributes can also be called Multi-Valued Attributes. Suppose we have stored data in the following way:
	EntityClass PERSON = new EntityClass(0); // 0 is the unique id for people
	Attribute CREDIT_CARD = new Attribute(29); //29 is the unique id for people
	..
	Cu cu = Cu.alloc().append(PERSON).append(732)
		.append(CREDIT_CARD).append(9193013132);
	db.insert(cu);

Above, the EntityClass (like a Relation Table) is PERSON, the Entity (like a Relational primary Key) is 732, the Attribute (like a Relational column) is CREDIT_CARD, and the Value (like a Relational column value) is 9193013132. So far, the semantics map to a single value in the relational model.

However, if person 732 gets more credit cards, we just insert one Item for each new card, changing only the Value part, and we have a multi-value Attribute. So, it is simple to convert a single-value Attribute into a multi-value, i.e. set-valued Attribute at runtime, providing compatability with existing databases. Older applications will usually not be compatible with the altered databases, but new applications can extend and use existing databases.

Now in order to enumerate the cards, we use a prefix of everything up to but not including the Value:

	cu.clear().append(PERSON).append(personId).append(CREDIT_CARD);
	int protectedPrefixLength = cu.length();
	while (db.next(cu, protectedPrefixLength)) {
		System.out.println(cu.longAt(protectedPrefixLength));
	}
The above code is typical for enumerating the suffixes of any set of Items. The multiple Values can be considered a set, and there are many operations that can work with generic sets of suffixes. Multi-value Attributes are important in Inversion.  

Composite Values

If we need to separate the numbers from the various card companies because the numbers are not enough to identify a card uniquely, we create a composite Value:
	cu.clear().append(PERSON).append(personId).append(CREDIT_CARD)
			.append(9193013132).append("MC");

The Value is now two components long: 9193013132 "MC". The "MC" could be put first if desired.

This composite Attribute can be created and stored into an existing database having only the simple numeric credit card numbers, so the number collision problem can be overcome even if it is discovered after databases have been created. Enhanced application code can watch for the composite card-number/card-issuer Values and use the card-type info as it is available:

	cu.clear().append(PERSON).append(personId).append(CREDIT_CARD);
	int offsetOfCreditCard = cu.length();
	while (db.next(cu, offsetOfCreditCard)) {
		long creditCard = cu.longAt(offsetOfCreditCard);
		int offsetAfterCreditCard = cu.skipComponent(offsetOfCreditCard);
		String issuer = "MC"; // default in older db's
		if (offsetAfterCreditCard < cu.length()) { // got a "MC"/"Visa" component
			issuer = cu.stringAt(offsetAfterCreditCard);
		}
		System.out.println("personId: " + personId + 
			" card: " + creditCard +
			" issuer" + issuer);
	}
 

Heterogenous Values

It is not necessary for an Attribute always to have Values of a single fixed Java primitive data type. For example, if we have created databases with long components for the part number because the Values appeared always to be numeric, and then we discover that there are letters and dashes in some part numbers, we can begin to store a combination of long components and String components in the same existing database along with the long's. The resulting Values are heterogenous. The sort order is not convenient if the Value is part of a set, however: the Strings and longs will be appear separately (see the Cu javadoc for more on inter-type sorting.) In this case, when a set of long Values is discovered and a new String Value is to be added to it, the long components can be be converted to string components dynamically.

Storing these new string components is easy: just append the Strings to the Cu in place of the usual long component as the Value before inserting. For retrieval:

	cu.clear().append(SUPPLIER).append(supplierId).append(S_PART_NO);
	int offsetOfPartNo = cu.length();
	while (db.next(cu, offsetOfPartNo)) {
		Object partId = cu.componentAt(offsetOfPartNo);
		System.out.println("supplerId: " + supplierId + 
			" partNo: " + partNo);
		// output for numeric partNo's is like
		// supplierId: 183 partNo: 99311
		// output for string partNo's is like:
		// supplierId: 183 partNo: "93-A-00015"
	}
Above we have simply replaced the cu.longAt(offsetOfPartNo) with cu.componentAt(offsetOfPartNo). This method is completely generic, and will parse out any component at the given offset. If the component is a long or other primitive, the result will be a primitive wrapper, e.g. Long. If the component is an Attribute, an instance of Attribute is returned. This generic form is, of course, not type-safe to the invoker, and will require instanceof and casting in some situations, so the strongly-typed methods like cu.longAt(int offset) are usually preferred. The Objects returned can also be directly appended to a Cu: the Cu.append(Object) will append the primitive wrappers with the appropriate primitive component types. There is additional Object construction, however, while longAt(offset) does none.  

Further Value Structures

See Long Objects to see how to store CharacterLongObjects and BinaryLongObjects under a common prefix or as an EAV Value. See Index Components to see how to store unlimited-length multi-dimensional arrays under a common prefix or as an EAV Value. Of course there are more to invent. Possibilities that have been used include hierarchical 'directory' trees, long editable texts, text content indexes with multiple segments, and so on.

Previous Next


Copyright © 1997-2006 Boiler Bay.