Take the 2-minute tour ×

Virtuoso stores RDF triples in the RDF_QUAD table. In this table, IRIs are stored as IRI_ID's datatype and the values are stored in RDF_IRI table. But I don't understand the use of the RDF_PREFIX table. Is it to reduce the used space of RDF_IRI table? But how is the join done? (The RDF_PREFIX table has a integer key). The documentation doesn't explain this.

share|improve this question

1 Answer 1

up vote 1 down vote accepted

For context (which, admittedly doesn't explain why there are two tables rather than just one) the documentation says:

create table DB.DBA.RDF_PREFIX (
  RP_NAME varchar primary key,
  RP_ID int not null unique );
create table DB.DBA.RDF_IRI (
  RI_NAME varchar primary key,
  RI_ID IRI_ID not null unique );

These two tables store a mapping between internal IRI id's and their external string form. A memory-resident cache contains recently used IRIs to reduce access to this table. Function id_to_iri (in id IRI_ID) returns the IRI by its ID. Function iri_to_id (in iri varchar, in may_create_new_id) returns an IRI_ID for given string; if the string is not used before as an IRI then either NULL is returned or a new ID is allocated, depending on the second argument.

Notice that the RP_ID of RDF_PREFIX is an int, whereas the RI_ID of RDF_IRI is an IRI_ID. Even though they both have varchar primary keys, the IDs to which they map those names are not the same type. In fact, it appears is appears that even though the primary key of RDF_IRI is a varchar, it isn't the same kind of varchar as that in RDF_PREFIX. The following example shows this, I think. Example 1.5.44 How can I perform search for predicate values from the documentation gives an example of its use. I'm not enough of a SQL'er to say exactly what's happening in that example, but it might be a good start to see how RDF_PREFIX gets used. Here's a snippet from that example:

        WHERE (RP_NAME >= path) AND (RP_NAME < path || chr(255)) ) do
      declare fourbytes varchar;
      fourbytes := '----';
      fourbytes[0] := bit_shift (RP_ID, -24);
      fourbytes[1] := bit_and (bit_shift (RP_ID, -16), 255);
      fourbytes[2] := bit_and (bit_shift (RP_ID, -8), 255);
      fourbytes[3] := bit_and (RP_ID, 255);

      for ( SELECT RI_NAME, RI_ID from RDF_IRI
            WHERE (RI_NAME >= fourbytes) AND (RI_NAME < fourbytes || chr(255)) ) do
          if (exists (SELECT TOP 1 1 FROM RDF_QUAD WHERE P=RI_ID))
            result (case when (dump_iri_ids) then RI_ID else RP_NAME || subseq (RI_NAME, 4) end);

Notice that the varchar fourbytes used for retrieving values from RDF_IRI is construct by bitshifting the int that comes the RDF_PREFIX table. I'm not enough of a SQL'er to explain all the details, but it looks to me like the keys to RDF_PREFIX and RDF_IRI are really different kinds of varchars. In RDF_PREFIX, the RP_NAME actually looks like an IRI, but RDF_IRI's RI_NAME is just a sequence of bytes.

share|improve this answer

Your Answer


