I have recently read some of Microsoft's ADO .NET 3 papers. I am reminded of the distant past when I designed Kubl, which later became OpenLink Virtuoso. So I will reminisce and speculate a little.
So now is the time when polymorphic queries and mixing relational style joins and object style navigation become politically acceptable and even recommended and there finally is a workable solution to having a foreign key in the database and a pointer or set of pointers in the client application. Not to mention change tracking so as to be able to update in-memory data structures and commit a delta against the database without explicit update statements.
All these questions existed already in the mid 90s and earlier. Since I was coming from OO and LISP into the database world, I even felt these questions to be important. The solution in the earliest Kubl was to have inheritance between tables, what became the SQL 2K UNDER
clause, and a virtual column called _ROW
that would select a serialization of the primary key entry. Then there was the function row_key()
, which when applied to a _ROW
virtual column would return a database-wide unique identifier of the row, containing the key info and the key part values plus which subtable of the table was at hand. Then there was a function for dereferencing a row_key
for getting the _ROW
. And one could store row_keys
into columns and dereference these in queries. Within SQL, one could use the row_column
function to extract individual column values from a row_key
or _ROW
.
This was all fine server side. But we also had a client for Franz Inc.'s Allegro Common Lisp that talked to Kubl's ODBC listener. This client had the basic statements and prepared statements and result sets, parameters and array parameters, a little like JDBC does now. But the extra was that we could do a mapping between a Lisp struct or object and a database key, so the _ROW
would automatically materialize into the Lisp struct or class instance. And the mapping between these materializations and the row_keys
identifying them in the database were kept in a thread environment called object space. Updates could be relational-style UPDATEs
or consist of putting a _ROW
serialization in database format back into the Kubl store with a single SQL function.
This was different from just storing object serializations into LOB columns, as is often done, insofar as the object classes and data members were really database tables and columns, thus native to the DBMS, not just opaque data to be processed client-side only.
So it was then possible to program a little like is shown in the ADO .NET 3 demos today, some ten years later.
Some of these functions still exist in Virtuoso, albeit in a deprecated state, and there is no client that can use these to any advantage. Indeed, we dropped this line of work when Kubl became Virtuoso, mostly because there was no standard and no client applications that would use such features. Instead, we concentrated on virtual RDBMS, transparently accessing any third party data via ODBC.
Now however, as objects, both native SQL and Java and .NET, have become mainstream citizens of relational databases in general, Virtuoso and otherwise, and as Microsoft has legitimized accessing whole objects and not only scalar columns in result sets as part of ADO .NET 3, these things might be worth a second look.