diff --git a/config/alfresco/dbscripts/db-schema-context.xml b/config/alfresco/dbscripts/db-schema-context.xml index c5680f9aab..1415fc6a24 100644 --- a/config/alfresco/dbscripts/db-schema-context.xml +++ b/config/alfresco/dbscripts/db-schema-context.xml @@ -56,6 +56,7 @@ + diff --git a/config/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.Dialect/update-activiti-nullable-columns.sql b/config/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.Dialect/update-activiti-nullable-columns.sql new file mode 100644 index 0000000000..67dc4692dc --- /dev/null +++ b/config/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.Dialect/update-activiti-nullable-columns.sql @@ -0,0 +1,48 @@ +-- +-- Title: Update ALF_ACTIVITY_FEED and ALF_ACTIVITY_FEED_CONTROL tables by setting special @@NULL@@ value for nullable columns feed_user_id and site_network. +-- Database: Generic +-- Since: V4.1 Schema 5149 +-- Author: Pavel Yurkevich +-- +-- Please contact support@alfresco.com if you need assistance with the upgrade. +-- +-- MNT-9532: SQL performance issue - WHERE ... IS NULL statements +-- +-- Record script finish +-- +-- Since oracle treats empty strings as NULLs, we have to use following format in where clause +-- ((feed_user_id IS NULL AND '' IS NULL) OR feed_user_id = '') +-- (feed_user_id IS NULL AND '' IS NULL) is Oracle specific part + +--FOREACH alf_activity_feed.id system.upgrade.alf_activity_feed.batchsize +UPDATE alf_activity_feed af + SET feed_user_id = '@@NULL@@' + WHERE + ((feed_user_id IS NULL AND '' IS NULL) OR feed_user_id = '') AND af.id >= ${LOWERBOUND} AND af.id <= ${UPPERBOUND}; + +--FOREACH alf_activity_feed.id system.upgrade.alf_activity_feed.batchsize +UPDATE alf_activity_feed af + SET site_network = '@@NULL@@' + WHERE + ((site_network IS NULL AND '' IS NULL) OR site_network = '') AND af.id >= ${LOWERBOUND} AND af.id <= ${UPPERBOUND}; + +--FOREACH alf_activity_feed_control.id system.upgrade.alf_activity_feed_control.batchsize +UPDATE alf_activity_feed_control afc + SET feed_user_id = '@@NULL@@' + WHERE + ((feed_user_id IS NULL AND '' IS NULL) OR feed_user_id = '') AND afc.id >= ${LOWERBOUND} AND afc.id <= ${UPPERBOUND}; + +--FOREACH alf_activity_feed_control.id system.upgrade.alf_activity_feed_control.batchsize +UPDATE alf_activity_feed_control afc + SET site_network = '@@NULL@@' + WHERE + ((site_network IS NULL AND '' IS NULL) OR site_network = '') AND afc.id >= ${LOWERBOUND} AND afc.id <= ${UPPERBOUND}; + +DELETE FROM alf_applied_patch WHERE id = 'patch.db-V4.1-update-activiti-nullable-columns'; +INSERT INTO alf_applied_patch + (id, description, fixes_from_schema, fixes_to_schema, applied_to_schema, target_schema, applied_on_date, applied_to_server, was_executed, succeeded, report) + VALUES + ( + 'patch.db-V4.1-update-activiti-nullable-columns', 'Manually executed script upgrade V4.1: ALF_ACTIVITY_FEED and ALF_ACTIVITY_FEED_CONTROL tables. Updates feed_user_id and site_network columns with @@NULL@@ value', + 0, 5149, -1, 5150, null, 'UNKNOWN', ${TRUE}, ${TRUE}, 'Script completed' + ); \ No newline at end of file diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-common-SqlMap.xml index 3e20628a2e..c79ee38bfa 100644 --- a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-common-SqlMap.xml +++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-common-SqlMap.xml @@ -87,22 +87,22 @@ - #{maxFeedSize} ]]> - #{maxFeedSize} ]]> @@ -171,8 +171,8 @@ @@ -181,7 +181,7 @@ @@ -218,20 +218,20 @@ delete from alf_activity_feed - where (feed_user_id IS NULL and #{feedUserId} IS NULL OR feed_user_id = #{feedUserId}) + where feed_user_id = #{feedUserId} diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-select-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-select-SqlMap.xml index e0e4d3e37e..fa203911ec 100644 --- a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-select-SqlMap.xml +++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-select-SqlMap.xml @@ -78,7 +78,7 @@ diff --git a/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/activities-select-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/activities-select-SqlMap.xml index 88555e445b..ec093e4104 100644 --- a/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/activities-select-SqlMap.xml +++ b/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/activities-select-SqlMap.xml @@ -78,7 +78,7 @@ diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index 3c3f12a793..f7acebdb36 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -3391,4 +3391,15 @@ + + + + 0 + 8005 + 8006 + + classpath:alfresco/dbscripts/upgrade/4.1/${db.script.dialect}/update-activiti-nullable-columns.sql + + + diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index 7e363998c7..612754dee5 100644 --- a/config/alfresco/version.properties +++ b/config/alfresco/version.properties @@ -23,4 +23,4 @@ version.build=r@scm-revision@-b@build-number@ # Schema number -version.schema=8005 +version.schema=8006 diff --git a/source/java/org/alfresco/repo/activities/feed/FeedTaskProcessor.java b/source/java/org/alfresco/repo/activities/feed/FeedTaskProcessor.java index 51be2d348c..ba20a7e97b 100644 --- a/source/java/org/alfresco/repo/activities/feed/FeedTaskProcessor.java +++ b/source/java/org/alfresco/repo/activities/feed/FeedTaskProcessor.java @@ -39,6 +39,7 @@ import java.util.Map; import java.util.Set; import org.alfresco.repo.activities.post.lookup.PostLookup; +import org.alfresco.repo.domain.activities.ActivitiesDAO; import org.alfresco.repo.domain.activities.ActivityFeedDAO; import org.alfresco.repo.domain.activities.ActivityFeedEntity; import org.alfresco.repo.domain.activities.ActivityPostEntity; @@ -649,7 +650,7 @@ public abstract class FeedTaskProcessor for (FeedControlEntity feedControl : feedControls) { - if (((feedControl.getSiteNetwork() == null) || (feedControl.getSiteNetwork().length() == 0)) && (feedControl.getAppTool() != null)) + if (ActivitiesDAO.KEY_ACTIVITY_NULL_VALUE.equals(feedControl.getSiteNetwork()) && (feedControl.getAppTool() != null)) { if (feedControl.getAppTool().equals(activityPost.getAppTool())) { diff --git a/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleaner.java b/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleaner.java index 930f958fc5..ec9ce858ab 100644 --- a/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleaner.java +++ b/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleaner.java @@ -27,6 +27,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import org.alfresco.model.ContentModel; +import org.alfresco.repo.domain.activities.ActivitiesDAO; import org.alfresco.repo.domain.activities.ActivityFeedDAO; import org.alfresco.repo.domain.activities.ActivityFeedEntity; import org.alfresco.repo.lock.JobLockService; @@ -305,7 +306,7 @@ public class FeedCleaner implements NodeServicePolicies.BeforeDeleteNodePolicy String feedUserId = userFeedTooMany.getFeedUserId(); // Rather than filter out the two usernames that indicate site-specific // feed entries, we can just filter them out now. - if (feedUserId == null || feedUserId.length() == 0) + if (ActivitiesDAO.KEY_ACTIVITY_NULL_VALUE.equals(feedUserId)) { if (logger.isTraceEnabled()) { diff --git a/source/java/org/alfresco/repo/domain/activities/ActivitiesDAO.java b/source/java/org/alfresco/repo/domain/activities/ActivitiesDAO.java index 1471f5cc4d..48b54594be 100644 --- a/source/java/org/alfresco/repo/domain/activities/ActivitiesDAO.java +++ b/source/java/org/alfresco/repo/domain/activities/ActivitiesDAO.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2014 Alfresco Software Limited. * * This file is part of Alfresco * @@ -25,6 +25,8 @@ import java.sql.SQLException; */ public interface ActivitiesDAO { + public static final String KEY_ACTIVITY_NULL_VALUE = "@@NULL@@"; + public void startTransaction() throws SQLException; public void commitTransaction() throws SQLException; diff --git a/source/java/org/alfresco/repo/domain/activities/ActivityFeedEntity.java b/source/java/org/alfresco/repo/domain/activities/ActivityFeedEntity.java index 31b2828380..cbc16aa17a 100644 --- a/source/java/org/alfresco/repo/domain/activities/ActivityFeedEntity.java +++ b/source/java/org/alfresco/repo/domain/activities/ActivityFeedEntity.java @@ -46,10 +46,10 @@ public class ActivityFeedEntity private Long id; // internal DB-generated id private String activityType; private String activitySummary; - private String feedUserId; + private String feedUserId = ActivitiesDAO.KEY_ACTIVITY_NULL_VALUE; private String postUserId; private NodeRef postUserAvatarNodeRef; - private String siteNetwork; + private String siteNetwork = ActivitiesDAO.KEY_ACTIVITY_NULL_VALUE; private String appTool; private Date postDate; private Date feedDate; // for debug @@ -83,7 +83,10 @@ public class ActivityFeedEntity public void setFeedUserId(String userid) { - this.feedUserId = userid; + if (userid != null && userid.length() > 0) + { + this.feedUserId = userid; + } } public String getPostUserId() @@ -103,7 +106,10 @@ public class ActivityFeedEntity public void setSiteNetwork(String siteNetwork) { - this.siteNetwork = siteNetwork; + if (siteNetwork != null && siteNetwork.length() > 0) + { + this.siteNetwork = siteNetwork; + } } public String getActivityType() diff --git a/source/java/org/alfresco/repo/domain/activities/ActivityFeedQueryEntity.java b/source/java/org/alfresco/repo/domain/activities/ActivityFeedQueryEntity.java index 7bfe72b193..3bc4504f77 100644 --- a/source/java/org/alfresco/repo/domain/activities/ActivityFeedQueryEntity.java +++ b/source/java/org/alfresco/repo/domain/activities/ActivityFeedQueryEntity.java @@ -28,9 +28,15 @@ public class ActivityFeedQueryEntity { private Long minId; private Long maxId; + private int maxFeedSize; private String feedUserId; private String siteNetwork; + public String getNullValue() + { + return ActivitiesDAO.KEY_ACTIVITY_NULL_VALUE; + } + public Long getMinId() { return minId; @@ -51,6 +57,16 @@ public class ActivityFeedQueryEntity this.maxId = maxId; } + public int getMaxFeedSize() + { + return maxFeedSize; + } + + public void setMaxFeedSize(int maxFeedSize) + { + this.maxFeedSize = maxFeedSize; + } + public String getFeedUserId() { return feedUserId; diff --git a/source/java/org/alfresco/repo/domain/activities/FeedControlEntity.java b/source/java/org/alfresco/repo/domain/activities/FeedControlEntity.java index fce7f215d1..af5ed2f40a 100644 --- a/source/java/org/alfresco/repo/domain/activities/FeedControlEntity.java +++ b/source/java/org/alfresco/repo/domain/activities/FeedControlEntity.java @@ -28,8 +28,8 @@ import org.alfresco.service.cmr.activities.FeedControl; public class FeedControlEntity { private Long id; // internal DB-generated id - private String feedUserId; - private String siteNetwork; + private String feedUserId = ActivitiesDAO.KEY_ACTIVITY_NULL_VALUE; + private String siteNetwork = ActivitiesDAO.KEY_ACTIVITY_NULL_VALUE; private String appTool; private Date lastModified; // when inserted @@ -44,13 +44,22 @@ public class FeedControlEntity public FeedControlEntity(String feedUserId) { - this.feedUserId = feedUserId; + if (feedUserId != null && feedUserId.length() > 0) + { + this.feedUserId = feedUserId; + } } public FeedControlEntity(String feedUserId, FeedControl feedControl) { - this.feedUserId = feedUserId; - this.siteNetwork = feedControl.getSiteId(); + if (feedUserId != null && feedUserId.length() > 0) + { + this.feedUserId = feedUserId; + } + if (feedControl.getSiteId() != null && feedControl.getSiteId().length() > 0) + { + this.siteNetwork = feedControl.getSiteId(); + } this.appTool = feedControl.getAppToolId(); this.lastModified = new Date(); } @@ -77,7 +86,10 @@ public class FeedControlEntity public void setSiteNetwork(String siteNetwork) { - this.siteNetwork = siteNetwork; + if (siteNetwork != null && siteNetwork.length() > 0) + { + this.siteNetwork = siteNetwork; + } } public String getAppTool() @@ -97,7 +109,10 @@ public class FeedControlEntity public void setFeedUserId(String feedUserId) { - this.feedUserId = feedUserId; + if (feedUserId != null && feedUserId.length() > 0) + { + this.feedUserId = feedUserId; + } } public Date getLastModified() diff --git a/source/java/org/alfresco/repo/domain/activities/ibatis/ActivityFeedDAOImpl.java b/source/java/org/alfresco/repo/domain/activities/ibatis/ActivityFeedDAOImpl.java index 0d2d323ed3..27c48717d7 100644 --- a/source/java/org/alfresco/repo/domain/activities/ibatis/ActivityFeedDAOImpl.java +++ b/source/java/org/alfresco/repo/domain/activities/ibatis/ActivityFeedDAOImpl.java @@ -127,7 +127,10 @@ public class ActivityFeedDAOImpl extends ActivitiesDAOImpl implements ActivityFe @Override public List selectUserFeedsToClean(int maxFeedSize) throws SQLException { - return template.selectList("alfresco.activities.select_activity_user_feeds_greater_than_max", maxFeedSize); + ActivityFeedQueryEntity params = new ActivityFeedQueryEntity(); + params.setMaxFeedSize(maxFeedSize); + + return template.selectList("alfresco.activities.select_activity_user_feeds_greater_than_max", params); } @Override @@ -197,7 +200,10 @@ public class ActivityFeedDAOImpl extends ActivitiesDAOImpl implements ActivityFe @Override public List selectSiteFeedsToClean(int maxFeedSize) throws SQLException { - return template.selectList("alfresco.activities.select_activity_site_feeds_greater_than_max", maxFeedSize); + ActivityFeedQueryEntity params = new ActivityFeedQueryEntity(); + params.setMaxFeedSize(maxFeedSize); + + return template.selectList("alfresco.activities.select_activity_site_feeds_greater_than_max", params); } @SuppressWarnings("unchecked") diff --git a/source/test-java/org/alfresco/repo/activities/feed/FeedNotifierTest.java b/source/test-java/org/alfresco/repo/activities/feed/FeedNotifierTest.java index 33e8ba9d07..f73d77d171 100644 --- a/source/test-java/org/alfresco/repo/activities/feed/FeedNotifierTest.java +++ b/source/test-java/org/alfresco/repo/activities/feed/FeedNotifierTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue; import org.alfresco.model.ContentModel; import org.alfresco.repo.activities.post.lookup.PostLookup; +import org.alfresco.repo.domain.activities.ActivitiesDAO; import org.alfresco.repo.domain.activities.ActivityFeedEntity; import org.alfresco.repo.domain.activities.ActivityPostDAO; import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; @@ -317,7 +318,7 @@ public class FeedNotifierTest boolean found = false; for (ActivityFeedEntity feed : feeds) { - if (feed.getActivityType().equals(activityType) && (feed.getSiteNetwork() == null || feed.getSiteNetwork().isEmpty())) + if (feed.getActivityType().equals(activityType) && ActivitiesDAO.KEY_ACTIVITY_NULL_VALUE.equals(feed.getSiteNetwork())) { found = true; }