mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-15 15:02:20 +00:00
Merged 5.0.N (5.0.4) to 5.1.N (5.1.2)
124539 jvonka: Merged 50N-NDB (5.0.4) to 5.0.N (5.0.4) 124514: MNT-15211: NDB-specific workaround fix for trashcan restore (since NDB does not support partial rollback on constraint violation) - this fix is dialect-specific (hence does not impact existing supported DB types) - note: MySQL Cluster NDB - experimental/unsupported git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.1.N/root@124582 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -145,6 +145,9 @@
|
|||||||
<bean id="nodeDAO.org.hibernate.dialect.MySQLInnoDBDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MySQL" parent="nodeDAO.org.hibernate.dialect.Dialect" />
|
<bean id="nodeDAO.org.hibernate.dialect.MySQLInnoDBDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MySQL" parent="nodeDAO.org.hibernate.dialect.Dialect" />
|
||||||
<bean id="nodeDAO.org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MSSQL" parent="nodeDAO.org.hibernate.dialect.Dialect" />
|
<bean id="nodeDAO.org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MSSQL" parent="nodeDAO.org.hibernate.dialect.Dialect" />
|
||||||
|
|
||||||
|
<!-- WARNING: Experimental/unsupported - see AlfrescoMySQLClusterNDBDialect ! -->
|
||||||
|
<bean id="nodeDAO.org.alfresco.repo.domain.hibernate.dialect.AlfrescoMySQLClusterNDBDialect" class="org.alfresco.repo.domain.node.ibatis.NodeDAOImpl$MySQLClusterNDB" parent="nodeDAO.org.hibernate.dialect.Dialect" />
|
||||||
|
|
||||||
<bean id="lockDAO" class="org.alfresco.repo.domain.locks.ibatis.LockDAOImpl">
|
<bean id="lockDAO" class="org.alfresco.repo.domain.locks.ibatis.LockDAOImpl">
|
||||||
<property name="sqlSessionTemplate" ref="locksSqlSessionTemplate"/>
|
<property name="sqlSessionTemplate" ref="locksSqlSessionTemplate"/>
|
||||||
<property name="qnameDAO" ref="qnameDAO"/>
|
<property name="qnameDAO" ref="qnameDAO"/>
|
||||||
|
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.domain.hibernate.dialect;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.hibernate.dialect.MySQLInnoDBDialect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL Cluster NDB specific DAO overrides
|
||||||
|
*
|
||||||
|
* WARNING:
|
||||||
|
* - Experimental only (unsupported) !
|
||||||
|
* - The NDB storage engine is *not* currently supported or certified !
|
||||||
|
* - Can be used for dev/test evaluation (please give us feedback)
|
||||||
|
* - Should not be used for live/prod env with real data !
|
||||||
|
* - Requires FK support (hence NDB 7.3.x or higher)
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//note: *not* a dialect of InnoDB but, for now, extends here so that we can override those scripts
|
||||||
|
public class AlfrescoMySQLClusterNDBDialect extends MySQLInnoDBDialect
|
||||||
|
{
|
||||||
|
protected Log logger = LogFactory.getLog(AlfrescoMySQLClusterNDBDialect.class);
|
||||||
|
|
||||||
|
public AlfrescoMySQLClusterNDBDialect()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
logger.error("Using NDB with Alfresco is experimental and unsupported (do not use for live/prod envs) !");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTableTypeString() {
|
||||||
|
return " engine=NDB";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2013 Alfresco Software Limited.
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -1390,6 +1390,37 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
|
|
||||||
if (!allowAuditableAspect) addAuditableAspect = false;
|
if (!allowAuditableAspect) addAuditableAspect = false;
|
||||||
|
|
||||||
|
Long id = newNodeImplInsert(node);
|
||||||
|
node.setId(id);
|
||||||
|
|
||||||
|
Set<QName> nodeAspects = null;
|
||||||
|
if (addAuditableAspect)
|
||||||
|
{
|
||||||
|
Long auditableAspectQNameId = qnameDAO.getOrCreateQName(ContentModel.ASPECT_AUDITABLE).getFirst();
|
||||||
|
insertNodeAspect(id, auditableAspectQNameId);
|
||||||
|
nodeAspects = Collections.<QName>singleton(ContentModel.ASPECT_AUDITABLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nodeAspects = Collections.<QName>emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock the node and cache
|
||||||
|
node.lock();
|
||||||
|
nodesCache.setValue(id, node);
|
||||||
|
// Pre-populate some of the other caches so that we don't immediately query
|
||||||
|
setNodeAspectsCached(id, nodeAspects);
|
||||||
|
setNodePropertiesCached(id, Collections.<QName, Serializable>emptyMap());
|
||||||
|
|
||||||
|
if (isDebugEnabled)
|
||||||
|
{
|
||||||
|
logger.debug("Created new node: \n" + " " + node);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Long newNodeImplInsert(NodeEntity node)
|
||||||
|
{
|
||||||
Long id = null;
|
Long id = null;
|
||||||
Savepoint savepoint = controlDAO.createSavepoint("newNodeImpl");
|
Savepoint savepoint = controlDAO.createSavepoint("newNodeImpl");
|
||||||
try
|
try
|
||||||
@@ -1425,32 +1456,8 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
throw new NodeExistsException(dbTargetNode.getNodePair(), e);
|
throw new NodeExistsException(dbTargetNode.getNodePair(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.setId(id);
|
|
||||||
|
|
||||||
Set<QName> nodeAspects = null;
|
return id;
|
||||||
if (addAuditableAspect)
|
|
||||||
{
|
|
||||||
Long auditableAspectQNameId = qnameDAO.getOrCreateQName(ContentModel.ASPECT_AUDITABLE).getFirst();
|
|
||||||
insertNodeAspect(id, auditableAspectQNameId);
|
|
||||||
nodeAspects = Collections.<QName>singleton(ContentModel.ASPECT_AUDITABLE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nodeAspects = Collections.<QName>emptySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock the node and cache
|
|
||||||
node.lock();
|
|
||||||
nodesCache.setValue(id, node);
|
|
||||||
// Pre-populate some of the other caches so that we don't immediately query
|
|
||||||
setNodeAspectsCached(id, nodeAspects);
|
|
||||||
setNodePropertiesCached(id, Collections.<QName, Serializable>emptyMap());
|
|
||||||
|
|
||||||
if (isDebugEnabled)
|
|
||||||
{
|
|
||||||
logger.debug("Created new node: \n" + " " + node);
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -28,6 +28,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.ibatis.IdsEntity;
|
import org.alfresco.ibatis.IdsEntity;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.domain.node.AbstractNodeDAOImpl;
|
import org.alfresco.repo.domain.node.AbstractNodeDAOImpl;
|
||||||
@@ -37,6 +38,7 @@ import org.alfresco.repo.domain.node.Node;
|
|||||||
import org.alfresco.repo.domain.node.NodeAspectsEntity;
|
import org.alfresco.repo.domain.node.NodeAspectsEntity;
|
||||||
import org.alfresco.repo.domain.node.NodeAssocEntity;
|
import org.alfresco.repo.domain.node.NodeAssocEntity;
|
||||||
import org.alfresco.repo.domain.node.NodeEntity;
|
import org.alfresco.repo.domain.node.NodeEntity;
|
||||||
|
import org.alfresco.repo.domain.node.NodeExistsException;
|
||||||
import org.alfresco.repo.domain.node.NodeIdAndAclId;
|
import org.alfresco.repo.domain.node.NodeIdAndAclId;
|
||||||
import org.alfresco.repo.domain.node.NodePropertyEntity;
|
import org.alfresco.repo.domain.node.NodePropertyEntity;
|
||||||
import org.alfresco.repo.domain.node.NodePropertyKey;
|
import org.alfresco.repo.domain.node.NodePropertyKey;
|
||||||
@@ -1719,7 +1721,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MySQL-specific DAO overrides
|
* MySQL (InnoDB) specific DAO overrides
|
||||||
*/
|
*/
|
||||||
public static class MySQL extends NodeDAOImpl
|
public static class MySQL extends NodeDAOImpl
|
||||||
{
|
{
|
||||||
@@ -1743,6 +1745,58 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
|
|||||||
return numDeleted;
|
return numDeleted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL Cluster NDB specific DAO overrides
|
||||||
|
*
|
||||||
|
* WARNING: Experimental/unsupported - see AlfrescoMySQLClusterNDBDialect !
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public static class MySQLClusterNDB extends MySQL
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected Long newNodeImplInsert(NodeEntity node)
|
||||||
|
{
|
||||||
|
Long id = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// We need to handle existing deleted nodes.
|
||||||
|
NodeRef targetNodeRef = node.getNodeRef();
|
||||||
|
Node dbTargetNode = selectNodeByNodeRef(targetNodeRef);
|
||||||
|
if (dbTargetNode != null)
|
||||||
|
{
|
||||||
|
if (dbTargetNode.getDeleted(qnameDAO))
|
||||||
|
{
|
||||||
|
Long dbTargetNodeId = dbTargetNode.getId();
|
||||||
|
// This is OK. It happens when we create a node that existed in the past.
|
||||||
|
// Remove the row completely
|
||||||
|
deleteNodeProperties(dbTargetNodeId, (Set<Long>) null);
|
||||||
|
deleteNodeById(dbTargetNodeId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A live node exists.
|
||||||
|
throw new NodeExistsException(dbTargetNode.getNodePair(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id = insertNode(node);
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
if (e instanceof NodeExistsException)
|
||||||
|
{
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There does not appear to be any row that could prevent an insert
|
||||||
|
throw new AlfrescoRuntimeException("Failed to insert new node: " + node, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get most recent transaction made in a given commit time range
|
* Get most recent transaction made in a given commit time range
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
|
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -70,6 +69,7 @@ import org.alfresco.repo.admin.patch.AppliedPatch;
|
|||||||
import org.alfresco.repo.admin.patch.Patch;
|
import org.alfresco.repo.admin.patch.Patch;
|
||||||
import org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch;
|
import org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch;
|
||||||
import org.alfresco.repo.content.filestore.FileContentWriter;
|
import org.alfresco.repo.content.filestore.FileContentWriter;
|
||||||
|
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoMySQLClusterNDBDialect;
|
||||||
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect;
|
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect;
|
||||||
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect;
|
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect;
|
||||||
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect;
|
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect;
|
||||||
@@ -1478,6 +1478,23 @@ public class SchemaBootstrap extends AbstractLifecycleBean
|
|||||||
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=InnoDB");
|
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=InnoDB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.dialect != null && this.dialect instanceof AlfrescoMySQLClusterNDBDialect)
|
||||||
|
{
|
||||||
|
// note: enable bootstrap on MySQL Cluster NDB
|
||||||
|
/*
|
||||||
|
* WARNING: Experimental/unsupported - see AlfrescoMySQLClusterNDBDialect !
|
||||||
|
*/
|
||||||
|
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=NDB"); // belts-and-braces
|
||||||
|
sql = sql.replaceAll("(?i)ENGINE=InnoDB", "ENGINE=NDB");
|
||||||
|
|
||||||
|
sql = sql.replaceAll("(?i) BIT ", " BOOLEAN ");
|
||||||
|
sql = sql.replaceAll("(?i) BIT,", " BOOLEAN,");
|
||||||
|
|
||||||
|
sql = sql.replaceAll("(?i) string_value text", " string_value VARCHAR(1024)");
|
||||||
|
|
||||||
|
sql = sql.replaceAll("(?i) VARCHAR(4000)", "TEXT(4000)");
|
||||||
|
}
|
||||||
|
|
||||||
Object fetchedVal = executeStatement(connection, sql, fetchColumnName, optional, line, scriptFile);
|
Object fetchedVal = executeStatement(connection, sql, fetchColumnName, optional, line, scriptFile);
|
||||||
if (fetchVarName != null && fetchColumnName != null)
|
if (fetchVarName != null && fetchColumnName != null)
|
||||||
{
|
{
|
||||||
@@ -1635,6 +1652,12 @@ public class SchemaBootstrap extends AbstractLifecycleBean
|
|||||||
// serializable_value blob,
|
// serializable_value blob,
|
||||||
maxStringLength = Integer.MAX_VALUE;
|
maxStringLength = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
else if (dialect instanceof AlfrescoMySQLClusterNDBDialect)
|
||||||
|
{
|
||||||
|
// string_value varchar(1024),
|
||||||
|
// serializable_value blob,
|
||||||
|
maxStringLength = SchemaBootstrap.DEFAULT_MAX_STRING_LENGTH;
|
||||||
|
}
|
||||||
else if (dialect instanceof AlfrescoOracle9Dialect)
|
else if (dialect instanceof AlfrescoOracle9Dialect)
|
||||||
{
|
{
|
||||||
// string_value varchar2(1024 char),
|
// string_value varchar2(1024 char),
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -35,6 +35,7 @@ import javax.sql.DataSource;
|
|||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.repo.content.filestore.FileContentWriter;
|
import org.alfresco.repo.content.filestore.FileContentWriter;
|
||||||
|
import org.alfresco.repo.domain.hibernate.dialect.AlfrescoMySQLClusterNDBDialect;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.util.LogUtil;
|
import org.alfresco.util.LogUtil;
|
||||||
import org.alfresco.util.TempFileProvider;
|
import org.alfresco.util.TempFileProvider;
|
||||||
@@ -537,6 +538,23 @@ public class ScriptExecutorImpl implements ScriptExecutor
|
|||||||
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=InnoDB");
|
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=InnoDB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.dialect != null && this.dialect instanceof AlfrescoMySQLClusterNDBDialect)
|
||||||
|
{
|
||||||
|
// note: enable bootstrap on MySQL Cluster NDB
|
||||||
|
/*
|
||||||
|
* WARNING: Experimental/unsupported - see AlfrescoMySQLClusterNDBDialect !
|
||||||
|
*/
|
||||||
|
sql = sql.replaceAll("(?i)TYPE=InnoDB", "ENGINE=NDB"); // belts-and-braces
|
||||||
|
sql = sql.replaceAll("(?i)ENGINE=InnoDB", "ENGINE=NDB");
|
||||||
|
|
||||||
|
sql = sql.replaceAll("(?i) BIT ", " BOOLEAN ");
|
||||||
|
sql = sql.replaceAll("(?i) BIT,", " BOOLEAN,");
|
||||||
|
|
||||||
|
sql = sql.replaceAll("(?i) string_value text", " string_value VARCHAR(1024)");
|
||||||
|
|
||||||
|
sql = sql.replaceAll("(?i) VARCHAR(4000)", "TEXT(4000)");
|
||||||
|
}
|
||||||
|
|
||||||
Object fetchedVal = executeStatement(connection, sql, fetchColumnName, optional, line, scriptFile);
|
Object fetchedVal = executeStatement(connection, sql, fetchColumnName, optional, line, scriptFile);
|
||||||
if (fetchVarName != null && fetchColumnName != null)
|
if (fetchVarName != null && fetchColumnName != null)
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -916,6 +916,8 @@ public class ArchiveAndRestoreTest extends TestCase
|
|||||||
RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(r_);
|
RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(r_);
|
||||||
assertEquals("Restore failed", RestoreStatus.SUCCESS, report.getStatus());
|
assertEquals("Restore failed", RestoreStatus.SUCCESS, report.getStatus());
|
||||||
|
|
||||||
|
commitAndBeginNewTransaction();
|
||||||
|
|
||||||
//It is restored, still with no AUDITABLE ASPECT
|
//It is restored, still with no AUDITABLE ASPECT
|
||||||
verifyNodeExistence(r, true);
|
verifyNodeExistence(r, true);
|
||||||
verifyAspectExistence(r, ContentModel.ASPECT_AUDITABLE, false);
|
verifyAspectExistence(r, ContentModel.ASPECT_AUDITABLE, false);
|
||||||
|
Reference in New Issue
Block a user