Search code examples
jcrmodeshapejcr-sql2

How to search JCR nodes with a version label


Following code segment is used to add a label to a node using ModeShape. What query string I could use to query this node with the QueryManager? It seems that the nodes from versionHistory side cannot be queried with the QueryManager.

        VersionHistory history = session.getWorkspace().getVersionManager()
                .getVersionHistory(node.getPath());
        history.addVersionLabel(version.getName(), "label", true);

I cannot find any nodes with the following query relating to version history. Is there anything missing from this query?

            Query query = queryManager
                    .createQuery("select * from [nt:base]", Query.JCR_SQL2);

Thanks!


Solution

  • All of the version information is stored on the nt:versionHistory nodes under the /jcr:system/jcr:versionStorage area of the workspace (shared amongst all workspaces in a repository). The structure of this area looks something like this:

      + jcr:system
        + jcr:versionStorage   {jcr:primaryType = mode:versionStorage}
          + b4   {jcr:primaryType = mode:versionHistoryFolder}
            + 6d   {jcr:primaryType = mode:versionHistoryFolder}
              + de   {jcr:primaryType = mode:versionHistoryFolder}
                + 298905f76361779339fa3ccacc4f47664255   {jcr:primaryType = nt:versionHistory}
                  + jcr:versionLabels  {jcr:primaryType = nt:versionLabels}
                  + jcr:rootVersion  {jcr:primaryType = nt:version}
                    - jcr:uuid = ...
                    - jcr:created = ...
                    + jcr:frozenNode  {jcr:primaryType = nt:frozenNode}
                      - jcr:frozenUuid
                      - jcr:frozenPrimaryType
                      - jcr:frozenMixinTypes
    

    The jcr:versionLabels node contains a property for each label, where the name of the property is the label string and the value of the property is a REFERENCE to the version to which that label applies.

    In order to find the labeled version of a versionable node, you'll actually have to query the contents of this "/jcr:system/jcr:versionStorage" area, using the appropriate types and join constraints.

    For example, to find the version with a particular label "foo", you'd do something like this:

    SELECT versioned.* FROM [nt:frozenNode] AS versioned JOIN [nt:version] AS version ON ISCHILDNODE(versioned,version) JOIN [nt:versionLabels] AS label ON label.myLabel = version.[jcr:uuid]
    

    This search all of the nt:versionLabels nodes looking for a property named 'myLabel' (which is the name of your label), and then finds the nt:version node to which that points, and the nt:frozenNode that is the copy of the versionable node for that version.

    As you can see, the version history representations as prescribed by the JCR specification are quite difficult to query.

    Alternatively, you could do this in two steps:

    1. use a query to find the jcr:uuid of the version(s) that has a particular label
    2. for each of those identifiers, find the UUID of the versionable node and use the VersionManager to look up the version history for that node and find the labeled version.