K2's implementation of OQL follows the ODMG standard, with the following additions and omissions:
OQL queries sent to K2 must be terminated by a semicolon.
Unnamed from clauses are not allowed, so you must provide a variable name for each collection in your from clause.
The group by, having, and order by clauses are not yet supported, but the functionality of the latter can be accomplished by using the sort function. For example, the following call to sort:
sort(list("HairColor", "Name"), list(true, false), set(struct(Name: "Fred", HairColor: "Black"), struct(Name: "Wilma", HairColor: "Red"), struct(Name: "Barney", HairColor: "Blond"), struct(Name: "Betty", HairColor: "Black")));produces the following result:
list(struct(HairColor: "Black", Name: "Fred"), struct(HairColor: "Black", Name: "Betty"), struct(HairColor: "Blond", Name: "Barney"), struct(HairColor: "Red", Name: "Wilma"))The third parameter to sort must be a collection of structs. The first parameter is a list of labels, in the order in which they should be considered. The second parameter parallels the first, and indicates whether or not the field should be sorted in ascending order.
One major addition in K2's OQL is variants, or "tagged unions". These are used when we want to be able to represent data of varying type. The tag you specify is used to identify the type of data contained in the variant. For example, the two variants in this set:
set(variant(address: struct(Street: "123 Fake Street", City: "Springfield", State: "??")), variant(phone: "(888) 555-1212"))contain data of different types (one is a struct, the other a string); However, since all variants are considered to be of the same type, these variants can be put in the same collection, even though collections in K2 (and OQL) must be homogeneous. This flexibility is often required when modeling data sources which are not well-structured.
You extract the contents of a variant using another K2 addition to OQL, a case statement. This construct tests, for a variant value, which tag it contains, and evaluates a different statement for each. Note that since OQL is type-safe, all of the possible results of a case statement must have the same type. For example, if the above set were named ContactInfo, the following query:
select case (info) of address: addr --> addr.Street + ", " + addr.City + " " + addr.State, phone: ph --> ph endcase from ContactInfo info;would produce the following result:
bag("123 Fake Street, Springfield ??", "(888) 555-1212")
[Tech Docs Index]