mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Factored the ancestor-descendent and merged from-to relationships
out of AVMNode. Easier to get hibernate to do what I want and appears to be a little more efficient as it removes several FK constraints from a frequently updated table. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3137 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -19,6 +19,9 @@ package org.alfresco.repo.avm;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.hibernate.Query;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all repository file system like objects.
|
* Base class for all repository file system like objects.
|
||||||
* @author britt
|
* @author britt
|
||||||
@@ -35,16 +38,6 @@ abstract class AVMNodeImpl implements AVMNode, Serializable
|
|||||||
*/
|
*/
|
||||||
private int fVersionID;
|
private int fVersionID;
|
||||||
|
|
||||||
/**
|
|
||||||
* The ancestor of this.
|
|
||||||
*/
|
|
||||||
private AVMNode fAncestor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The node that was merged into this.
|
|
||||||
*/
|
|
||||||
private AVMNode fMergedFrom;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Repository that owns this.
|
* The Repository that owns this.
|
||||||
*/
|
*/
|
||||||
@@ -87,8 +80,6 @@ abstract class AVMNodeImpl implements AVMNode, Serializable
|
|||||||
{
|
{
|
||||||
fID = id;
|
fID = id;
|
||||||
fVersionID = -1;
|
fVersionID = -1;
|
||||||
fAncestor = null;
|
|
||||||
fMergedFrom = null;
|
|
||||||
fRepository = repo;
|
fRepository = repo;
|
||||||
fIsRoot = false;
|
fIsRoot = false;
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
@@ -107,7 +98,14 @@ abstract class AVMNodeImpl implements AVMNode, Serializable
|
|||||||
*/
|
*/
|
||||||
public void setAncestor(AVMNode ancestor)
|
public void setAncestor(AVMNode ancestor)
|
||||||
{
|
{
|
||||||
fAncestor = ancestor;
|
if (ancestor == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HistoryLinkImpl link = new HistoryLinkImpl();
|
||||||
|
link.setAncestor(ancestor);
|
||||||
|
link.setDescendent(this);
|
||||||
|
SuperRepository.GetInstance().getSession().save(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,7 +114,10 @@ abstract class AVMNodeImpl implements AVMNode, Serializable
|
|||||||
*/
|
*/
|
||||||
public AVMNode getAncestor()
|
public AVMNode getAncestor()
|
||||||
{
|
{
|
||||||
return fAncestor;
|
Session sess = SuperRepository.GetInstance().getSession();
|
||||||
|
Query query = sess.createQuery("select hl.ancestor from HistoryLinkImpl hl where hl.descendent = :desc");
|
||||||
|
query.setEntity("desc", this);
|
||||||
|
return (AVMNode)query.uniqueResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,7 +126,14 @@ abstract class AVMNodeImpl implements AVMNode, Serializable
|
|||||||
*/
|
*/
|
||||||
public void setMergedFrom(AVMNode mergedFrom)
|
public void setMergedFrom(AVMNode mergedFrom)
|
||||||
{
|
{
|
||||||
fMergedFrom = mergedFrom;
|
if (mergedFrom == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MergeLinkImpl link = new MergeLinkImpl();
|
||||||
|
link.setMfrom(mergedFrom);
|
||||||
|
link.setMto(this);
|
||||||
|
SuperRepository.GetInstance().getSession().save(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,7 +142,10 @@ abstract class AVMNodeImpl implements AVMNode, Serializable
|
|||||||
*/
|
*/
|
||||||
public AVMNode getMergedFrom()
|
public AVMNode getMergedFrom()
|
||||||
{
|
{
|
||||||
return fMergedFrom;
|
Session sess = SuperRepository.GetInstance().getSession();
|
||||||
|
Query query = sess.createQuery("select ml.mfrom from MergeLinkImpl ml where ml.mto = :to");
|
||||||
|
query.setEntity("to", this);
|
||||||
|
return (AVMNode)query.uniqueResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
49
source/java/org/alfresco/repo/avm/HistoryLink.java
Normal file
49
source/java/org/alfresco/repo/avm/HistoryLink.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006 Alfresco, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Mozilla Public License version 1.1
|
||||||
|
* with a permitted attribution clause. You may obtain a
|
||||||
|
* copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.alfresco.org/legal/license.txt
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||||
|
* either express or implied. See the License for the specific
|
||||||
|
* language governing permissions and limitations under the
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.avm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for the ancestor-descendent relationship.
|
||||||
|
* @author britt
|
||||||
|
*/
|
||||||
|
interface HistoryLink
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Set the ancestor part of this.
|
||||||
|
* @param ancestor
|
||||||
|
*/
|
||||||
|
public void setAncestor(AVMNode ancestor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ancestor part of this.
|
||||||
|
* @return The ancestor.
|
||||||
|
*/
|
||||||
|
public AVMNode getAncestor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the descendent part of this.
|
||||||
|
* @param descendent
|
||||||
|
*/
|
||||||
|
public void setDescendent(AVMNode descendent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the descendent part of this.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public AVMNode getDescendent();
|
||||||
|
}
|
75
source/java/org/alfresco/repo/avm/HistoryLinkImpl.java
Normal file
75
source/java/org/alfresco/repo/avm/HistoryLinkImpl.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006 Alfresco, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Mozilla Public License version 1.1
|
||||||
|
* with a permitted attribution clause. You may obtain a
|
||||||
|
* copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.alfresco.org/legal/license.txt
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||||
|
* either express or implied. See the License for the specific
|
||||||
|
* language governing permissions and limitations under the
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.avm;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds a ancestor-descendent relationship.
|
||||||
|
* @author britt
|
||||||
|
*/
|
||||||
|
class HistoryLinkImpl implements HistoryLink, Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -430859344980137718L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ancestor.
|
||||||
|
*/
|
||||||
|
private AVMNode fAncestor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The descendent.
|
||||||
|
*/
|
||||||
|
private AVMNode fDescendent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the ancestor part of this.
|
||||||
|
* @param ancestor
|
||||||
|
*/
|
||||||
|
public void setAncestor(AVMNode ancestor)
|
||||||
|
{
|
||||||
|
fAncestor = ancestor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ancestor part of this.
|
||||||
|
* @return The ancestor.
|
||||||
|
*/
|
||||||
|
public AVMNode getAncestor()
|
||||||
|
{
|
||||||
|
return fAncestor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the descendent part of this.
|
||||||
|
* @param descendent
|
||||||
|
*/
|
||||||
|
public void setDescendent(AVMNode descendent)
|
||||||
|
{
|
||||||
|
fDescendent = descendent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the descendent part of this.
|
||||||
|
* @return The descendent.
|
||||||
|
*/
|
||||||
|
public AVMNode getDescendent()
|
||||||
|
{
|
||||||
|
return fDescendent;
|
||||||
|
}
|
||||||
|
}
|
49
source/java/org/alfresco/repo/avm/MergeLink.java
Normal file
49
source/java/org/alfresco/repo/avm/MergeLink.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006 Alfresco, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Mozilla Public License version 1.1
|
||||||
|
* with a permitted attribution clause. You may obtain a
|
||||||
|
* copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.alfresco.org/legal/license.txt
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||||
|
* either express or implied. See the License for the specific
|
||||||
|
* language governing permissions and limitations under the
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.avm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the interface for the merged from - to relationship.
|
||||||
|
* @author britt
|
||||||
|
*/
|
||||||
|
interface MergeLink
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Set the from part.
|
||||||
|
* @param from
|
||||||
|
*/
|
||||||
|
public void setMfrom(AVMNode from);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the from part.
|
||||||
|
* @return The from part.
|
||||||
|
*/
|
||||||
|
public AVMNode getMfrom();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the to part.
|
||||||
|
* @param to
|
||||||
|
*/
|
||||||
|
public void setMto(AVMNode to);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the to part.
|
||||||
|
* @return The to part.
|
||||||
|
*/
|
||||||
|
public AVMNode getMto();
|
||||||
|
}
|
75
source/java/org/alfresco/repo/avm/MergeLinkImpl.java
Normal file
75
source/java/org/alfresco/repo/avm/MergeLinkImpl.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006 Alfresco, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Mozilla Public License version 1.1
|
||||||
|
* with a permitted attribution clause. You may obtain a
|
||||||
|
* copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.alfresco.org/legal/license.txt
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||||
|
* either express or implied. See the License for the specific
|
||||||
|
* language governing permissions and limitations under the
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.avm;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This contains a single merged from-to relationship.
|
||||||
|
* @author britt
|
||||||
|
*/
|
||||||
|
class MergeLinkImpl implements MergeLink, Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 6672271083042424944L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The node that was merged from.
|
||||||
|
*/
|
||||||
|
private AVMNode fFrom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The node that was merged to.
|
||||||
|
*/
|
||||||
|
private AVMNode fTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the from part.
|
||||||
|
* @param from
|
||||||
|
*/
|
||||||
|
public void setMfrom(AVMNode from)
|
||||||
|
{
|
||||||
|
fFrom = from;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the from part.
|
||||||
|
* @return The from part.
|
||||||
|
*/
|
||||||
|
public AVMNode getMfrom()
|
||||||
|
{
|
||||||
|
return fFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the to part.
|
||||||
|
* @param to
|
||||||
|
*/
|
||||||
|
public void setMto(AVMNode to)
|
||||||
|
{
|
||||||
|
fTo = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the to part.
|
||||||
|
* @return The to part.
|
||||||
|
*/
|
||||||
|
public AVMNode getMto()
|
||||||
|
{
|
||||||
|
return fTo;
|
||||||
|
}
|
||||||
|
}
|
@@ -184,6 +184,7 @@ class OrphanReaper implements Runnable
|
|||||||
{
|
{
|
||||||
public void perform(Session session)
|
public void perform(Session session)
|
||||||
{
|
{
|
||||||
|
SuperRepository.GetInstance().setSession(session);
|
||||||
Query query = session.getNamedQuery("FindOrphans");
|
Query query = session.getNamedQuery("FindOrphans");
|
||||||
query.setMaxResults(fBatchSize);
|
query.setMaxResults(fBatchSize);
|
||||||
List<AVMNode> nodes = (List<AVMNode>)query.list();
|
List<AVMNode> nodes = (List<AVMNode>)query.list();
|
||||||
@@ -196,28 +197,48 @@ class OrphanReaper implements Runnable
|
|||||||
for (AVMNode node : nodes)
|
for (AVMNode node : nodes)
|
||||||
{
|
{
|
||||||
// Save away the ancestor and merged from fields from this node.
|
// Save away the ancestor and merged from fields from this node.
|
||||||
AVMNode ancestor = node.getAncestor();
|
query = session.createQuery("from HistoryLinkImpl hl where hl.descendent = :desc");
|
||||||
AVMNode mergedFrom = node.getMergedFrom();
|
query.setEntity("desc", node);
|
||||||
// Get all the nodes that have this node as ancestor.
|
HistoryLink hlink = (HistoryLink)query.uniqueResult();
|
||||||
query = session.getNamedQuery("AVMNode.GetDescendents");
|
AVMNode ancestor = null;
|
||||||
query.setEntity("node", node);
|
if (hlink != null)
|
||||||
List<AVMNode> descendents = (List<AVMNode>)query.list();
|
|
||||||
for (AVMNode desc : descendents)
|
|
||||||
{
|
{
|
||||||
|
ancestor = hlink.getAncestor();
|
||||||
|
session.delete(hlink);
|
||||||
|
}
|
||||||
|
query = session.createQuery("from MergeLinkImpl ml where ml.mto = :to");
|
||||||
|
query.setEntity("to", node);
|
||||||
|
MergeLink mlink = (MergeLink)query.uniqueResult();
|
||||||
|
AVMNode mergedFrom = null;
|
||||||
|
if (mlink != null)
|
||||||
|
{
|
||||||
|
mergedFrom = mlink.getMfrom();
|
||||||
|
session.delete(mlink);
|
||||||
|
}
|
||||||
|
// Get all the nodes that have this node as ancestor.
|
||||||
|
query = session.getNamedQuery("HistoryLink.ByAncestor");
|
||||||
|
query.setEntity("node", node);
|
||||||
|
List<HistoryLink> links = (List<HistoryLink>)query.list();
|
||||||
|
for (HistoryLink link : links)
|
||||||
|
{
|
||||||
|
AVMNode desc = link.getDescendent();
|
||||||
desc.setAncestor(ancestor);
|
desc.setAncestor(ancestor);
|
||||||
if (desc.getMergedFrom() == null)
|
if (desc.getMergedFrom() == null)
|
||||||
{
|
{
|
||||||
desc.setMergedFrom(mergedFrom);
|
desc.setMergedFrom(mergedFrom);
|
||||||
}
|
}
|
||||||
|
session.delete(link);
|
||||||
}
|
}
|
||||||
// Get all the nodes that have this node as mergedFrom
|
// Get all the nodes that have this node as mergedFrom
|
||||||
query = session.getNamedQuery("AVMNode.GetMergedTo");
|
query = session.getNamedQuery("MergeLink.ByFrom");
|
||||||
query.setEntity("merged", node);
|
query.setEntity("merged", node);
|
||||||
List<AVMNode> merged = (List<AVMNode>)query.list();
|
List<MergeLink> mlinks = (List<MergeLink>)query.list();
|
||||||
for (AVMNode merge : merged)
|
for (MergeLink link : mlinks)
|
||||||
{
|
{
|
||||||
merge.setMergedFrom(ancestor);
|
link.getMto().setMergedFrom(ancestor);
|
||||||
|
session.delete(link);
|
||||||
}
|
}
|
||||||
|
session.flush();
|
||||||
node = AVMNodeUnwrapper.Unwrap(node);
|
node = AVMNodeUnwrapper.Unwrap(node);
|
||||||
// Extra work for directories.
|
// Extra work for directories.
|
||||||
if (node instanceof DirectoryNode)
|
if (node instanceof DirectoryNode)
|
||||||
|
@@ -37,7 +37,7 @@ public class PurgeTest extends AVMServiceTestBase
|
|||||||
setupBasicTree();
|
setupBasicTree();
|
||||||
BulkLoader loader = new BulkLoader(fService);
|
BulkLoader loader = new BulkLoader(fService);
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
loader.recursiveLoad("source", "main:/");
|
loader.recursiveLoad("source/web", "main:/");
|
||||||
System.err.println("Load time: " + (System.currentTimeMillis() - start) + "ms");
|
System.err.println("Load time: " + (System.currentTimeMillis() - start) + "ms");
|
||||||
fService.createSnapshot("main");
|
fService.createSnapshot("main");
|
||||||
System.err.println("Load time + snapshot: " + (System.currentTimeMillis() - start) + "ms");
|
System.err.println("Load time + snapshot: " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
@@ -24,14 +24,6 @@
|
|||||||
<version column="vers"
|
<version column="vers"
|
||||||
name="vers"
|
name="vers"
|
||||||
type="long"/>
|
type="long"/>
|
||||||
<!-- BasicAttributes are attributes that pretty much all AVMNodes will
|
|
||||||
have. -->
|
|
||||||
<many-to-one name="ancestor" column="ancestor_id"
|
|
||||||
class="AVMNodeImpl"/>
|
|
||||||
<!-- Nothing does anything with this yet. We'll need it for
|
|
||||||
complete versioning semantics. -->
|
|
||||||
<many-to-one name="mergedFrom" column="merged_from"
|
|
||||||
class="AVMNodeImpl"/>
|
|
||||||
<!-- This should really be not null, but I haven't figured out
|
<!-- This should really be not null, but I haven't figured out
|
||||||
the right way to build the relation so that nullability constraints
|
the right way to build the relation so that nullability constraints
|
||||||
won't cause violations in the db during saves. -->
|
won't cause violations in the db during saves. -->
|
||||||
@@ -174,6 +166,18 @@
|
|||||||
column="parent_id"/>
|
column="parent_id"/>
|
||||||
</composite-id>
|
</composite-id>
|
||||||
</class>
|
</class>
|
||||||
|
<class name="HistoryLinkImpl" proxy="HistoryLink" table="history_links">
|
||||||
|
<composite-id>
|
||||||
|
<key-many-to-one name="ancestor" class="AVMNodeImpl" column="ancestor"/>
|
||||||
|
<key-many-to-one name="descendent" class="AVMNodeImpl" column="descendent"/>
|
||||||
|
</composite-id>
|
||||||
|
</class>
|
||||||
|
<class name="MergeLinkImpl" proxy="MergeLink" table="merge_links">
|
||||||
|
<composite-id>
|
||||||
|
<key-many-to-one name="mfrom" class="AVMNodeImpl" column="mfrom"/>
|
||||||
|
<key-many-to-one name="mto" class="AVMNodeImpl" column="mto"/>
|
||||||
|
</composite-id>
|
||||||
|
</class>
|
||||||
<query name="ChildEntry.ByNameParent">
|
<query name="ChildEntry.ByNameParent">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
from ChildEntryImpl ce
|
from ChildEntryImpl ce
|
||||||
@@ -210,14 +214,28 @@
|
|||||||
</query>
|
</query>
|
||||||
<query name="AVMNode.GetDescendents">
|
<query name="AVMNode.GetDescendents">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
from AVMNodeImpl an
|
select hl.descendent
|
||||||
where an.ancestor = :node
|
from HistoryLinkImpl hl
|
||||||
|
where hl.ancestor = :node
|
||||||
|
]]>
|
||||||
|
</query>
|
||||||
|
<query name="HistoryLink.ByAncestor">
|
||||||
|
<![CDATA[
|
||||||
|
from HistoryLinkImpl hl
|
||||||
|
where hl.ancestor = :node
|
||||||
]]>
|
]]>
|
||||||
</query>
|
</query>
|
||||||
<query name="AVMNode.GetMergedTo">
|
<query name="AVMNode.GetMergedTo">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
from AVMNodeImpl an
|
select ml.mto
|
||||||
where an.mergedFrom = :merged
|
from MergeLinkImpl ml
|
||||||
|
where ml.mfrom = :merged
|
||||||
|
]]>
|
||||||
|
</query>
|
||||||
|
<query name="MergeLink.ByFrom">
|
||||||
|
<![CDATA[
|
||||||
|
from MergeLinkImpl ml
|
||||||
|
where ml.mfrom = :merged
|
||||||
]]>
|
]]>
|
||||||
</query>
|
</query>
|
||||||
<query name="VersionRoot.GetVersionRoot">
|
<query name="VersionRoot.GetVersionRoot">
|
||||||
|
Reference in New Issue
Block a user