[exo-jcr-commits] exo-jcr SVN: r5710 - in jcr/trunk/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache and 3 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Wed Feb 29 06:24:34 EST 2012


Author: tolusha
Date: 2012-02-29 06:24:32 -0500 (Wed, 29 Feb 2012)
New Revision: 5710

Added:
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/AssignRootAsParentRepair.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/DummyRepair.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InconsistencyRepair.java
Modified:
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InspectionQuery.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InspectionQueryFilteredMultivaluedProperties.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/RepositoryCheckController.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JBCLockTableHandler.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JBCShareableLockTableHandler.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java
Log:
EXOJCR-1762: auto-repair for DB inconsistency

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/AssignRootAsParentRepair.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/AssignRootAsParentRepair.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/AssignRootAsParentRepair.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2012 eXo Platform SAS.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.checker;
+
+import org.exoplatform.services.jcr.datamodel.IllegalNameException;
+import org.exoplatform.services.jcr.datamodel.InternalQName;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPath;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.datamodel.ValueData;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
+import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DBConstants;
+import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCStorageConnection;
+import org.exoplatform.services.jcr.impl.storage.jdbc.db.WorkspaceStorageConnectionFactory;
+import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.RepositoryException;
+
+/**
+ * @author <a href="abazko at exoplatform.com">Anatoliy Bazko</a>
+ * @version $Id: AssignRootAsParentRepair.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class AssignRootAsParentRepair implements InconsistencyRepair
+{
+
+   protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.AssignRootAsParentRepair");
+
+   protected final WorkspaceStorageConnectionFactory connFactory;
+
+   public AssignRootAsParentRepair(WorkspaceStorageConnectionFactory connFactory)
+   {
+      this.connFactory = connFactory;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void doRepair(ResultSet resultSet) throws SQLException
+   {
+      WorkspaceStorageConnection conn = null;
+      try
+      {
+         conn = connFactory.openConnection();
+         if (!(conn instanceof JDBCStorageConnection))
+         {
+            throw new SQLException("Connection is instance of " + conn);
+         }
+
+         if (resultSet.getInt(DBConstants.COLUMN_CLASS) == 1)
+         {
+            repairNode((JDBCStorageConnection)conn, resultSet);
+         }
+         else
+         {
+            repairProperty((JDBCStorageConnection)conn, resultSet);
+         }
+
+         conn.commit();
+      }
+      catch (RepositoryException e)
+      {
+         rollback(conn);
+         throw new SQLException(e);
+      }
+      finally
+      {
+         closeConnection(conn);
+      }
+   }
+
+   private void repairProperty(JDBCStorageConnection conn, ResultSet resultSet) throws SQLException
+   {
+      try
+      {
+         String propertyId = exctractId(resultSet);
+         QPath path = QPath.parse(resultSet.getString(DBConstants.COLUMN_NAME));
+
+         PropertyData data = new TransientPropertyData(path, propertyId, 0, 0, null, false, new ArrayList<ValueData>());
+
+         conn.delete(data);
+      }
+      catch (UnsupportedOperationException e)
+      {
+         throw new SQLException(e);
+      }
+      catch (InvalidItemStateException e)
+      {
+         throw new SQLException(e);
+      }
+      catch (IllegalStateException e)
+      {
+         throw new SQLException(e);
+      }
+      catch (RepositoryException e)
+      {
+         throw new SQLException(e);
+      }
+   }
+
+   private void repairNode(JDBCStorageConnection conn, ResultSet resultSet) throws SQLException
+   {
+      try
+      {
+         String nodeId = exctractId(resultSet);
+         int orderNum = resultSet.getInt(DBConstants.COLUMN_NORDERNUM);
+         int version = resultSet.getInt(DBConstants.COLUMN_VERSION);
+         QPath path =
+            new QPath(new QPathEntry[]{new QPathEntry(
+               InternalQName.parse(resultSet.getString(DBConstants.COLUMN_NAME)),
+               resultSet.getInt(DBConstants.COLUMN_INDEX))});
+
+         NodeData data =
+            new TransientNodeData(path, nodeId, version, null, null, orderNum, Constants.ROOT_UUID, null);
+         
+         conn.rename(data);
+      }
+      catch (IllegalStateException e)
+      {
+         throw new SQLException(e);
+      }
+      catch (RepositoryException e)
+      {
+         throw new SQLException(e);
+      }
+      catch (IllegalNameException e)
+      {
+         throw new SQLException(e);
+      }
+   }
+
+   private void closeConnection(WorkspaceStorageConnection conn) throws SQLException
+   {
+      try
+      {
+         conn.close();
+      }
+      catch (IllegalStateException e)
+      {
+         throw new SQLException(e);
+      }
+      catch (RepositoryException e)
+      {
+         throw new SQLException(e);
+      }
+   }
+
+   private void rollback(WorkspaceStorageConnection conn)
+   {
+      try
+      {
+         if (conn != null)
+         {
+            conn.rollback();
+         }
+      }
+      catch (IllegalStateException e)
+      {
+         LOG.error("Can not rollback", e);
+      }
+      catch (RepositoryException e)
+      {
+         LOG.error("Can not rollback", e);
+      }
+   }
+
+   private String exctractId(ResultSet resultSet) throws SQLException
+   {
+      String containerName = "";
+      try
+      {
+         containerName = resultSet.getString(DBConstants.CONTAINER_NAME);
+      }
+      catch (SQLException e)
+      {
+      }
+
+      return resultSet.getString(DBConstants.COLUMN_ID).substring(containerName.length());
+   }
+
+   private String concatId(ResultSet resultSet, String id) throws SQLException
+   {
+      String containerName = "";
+      try
+      {
+         containerName = resultSet.getString(DBConstants.CONTAINER_NAME);
+      }
+      catch (SQLException e)
+      {
+      }
+
+      return containerName + id;
+   }
+
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/DummyRepair.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/DummyRepair.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/DummyRepair.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 eXo Platform SAS.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.checker;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author <a href="abazko at exoplatform.com">Anatoliy Bazko</a>
+ * @version $Id: DummyRepair.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class DummyRepair implements InconsistencyRepair
+{
+
+   /**
+    * {@inheritDoc}
+    */
+   public void doRepair(ResultSet resultSet) throws SQLException
+   {
+      // do nothing
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InconsistencyRepair.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InconsistencyRepair.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InconsistencyRepair.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 eXo Platform SAS.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.checker;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author <a href="abazko at exoplatform.com">Anatoliy Bazko</a>
+ * @version $Id: RepairInconsistency.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public interface InconsistencyRepair
+{
+   /**
+    * Repair inconsistency based on resultSet.
+    * 
+    * @param resultSet
+    * @throws SQLException
+    */
+   void doRepair(ResultSet resultSet) throws SQLException;
+}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InspectionQuery.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InspectionQuery.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InspectionQuery.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -44,13 +44,19 @@
    public String[] fieldNames;
 
    /**
+    * Utility class which help to fix inconsistency.
+    */
+   public InconsistencyRepair repair;
+
+   /**
     * Data class, contains a combination of SQL states, description, field names and status  
     */
-   public InspectionQuery(String statement, String[] fieldNames, String headerMessage)
+   public InspectionQuery(String statement, String[] fieldNames, String headerMessage, InconsistencyRepair repair)
    {
       this.statement = statement;
       this.description = headerMessage;
       this.fieldNames = fieldNames;
+      this.repair = repair;
    }
 
    public String getStatement()
@@ -68,6 +74,11 @@
       return fieldNames;
    }
 
+   public InconsistencyRepair getRepair()
+   {
+      return repair;
+   }
+
    /**
     * Creates a PreparedStatement object for sending parameterized SQL statements to the database. 
     * 
@@ -82,5 +93,4 @@
    {
       return connection.prepareStatement(statement);
    }
-
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InspectionQueryFilteredMultivaluedProperties.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InspectionQueryFilteredMultivaluedProperties.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/InspectionQueryFilteredMultivaluedProperties.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -33,9 +33,10 @@
    /**
     * {@inheritDoc}
     */
-   public InspectionQueryFilteredMultivaluedProperties(String statement, String[] fieldNames, String headerMessage)
+   public InspectionQueryFilteredMultivaluedProperties(String statement, String[] fieldNames, String headerMessage,
+      InconsistencyRepair repair)
    {
-      super(statement, fieldNames, headerMessage);
+      super(statement, fieldNames, headerMessage, repair);
    }
 
    /**

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/RepositoryCheckController.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/RepositoryCheckController.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/checker/RepositoryCheckController.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -21,10 +21,8 @@
 import org.exoplatform.commons.utils.SecurityHelper;
 import org.exoplatform.management.annotations.Managed;
 import org.exoplatform.management.annotations.ManagedDescription;
-import org.exoplatform.management.annotations.ManagedName;
 import org.exoplatform.management.jmx.annotations.NameTemplate;
 import org.exoplatform.management.jmx.annotations.Property;
-import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
 import org.exoplatform.services.jcr.config.WorkspaceEntry;
 import org.exoplatform.services.jcr.core.ManageableRepository;
 import org.exoplatform.services.jcr.impl.AbstractRepositorySuspender;
@@ -311,15 +309,14 @@
       }
    }
 
-   private void doCheckDataBase(boolean autoRepair) throws RepositoryException, IOException,
-      RepositoryConfigurationException
+   private void doCheckDataBase(boolean autoRepair)
    {
       for (String wsName : repository.getWorkspaceNames())
       {
          logComment("Check DB consistency. Workspace " + wsName);
 
          JDBCWorkspaceDataContainerChecker jdbcChecker = getJDBCChecker(wsName);
-         jdbcChecker.checkDataBase();
+         jdbcChecker.checkDataBase(autoRepair);
          jdbcChecker.checkLocksInDataBase(autoRepair);
       }
    }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JBCLockTableHandler.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JBCLockTableHandler.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JBCLockTableHandler.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -20,6 +20,7 @@
 
 import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
 import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.impl.checker.DummyRepair;
 import org.exoplatform.services.jcr.impl.checker.InspectionQuery;
 import org.exoplatform.services.jcr.impl.core.lock.AbstractLockTableHandler;
 import org.exoplatform.services.log.ExoLogger;
@@ -53,7 +54,7 @@
    protected InspectionQuery getSelectQuery() throws SQLException
    {
       return new InspectionQuery("SELECT * FROM " + getTableName() + " WHERE " + getParentColumn() + "='/"
-         + CacheableLockManagerImpl.LOCKS + "'", new String[]{getIdColumn()}, "Locks table match");
+         + CacheableLockManagerImpl.LOCKS + "'", new String[]{getIdColumn()}, "Locks table match", new DummyRepair());
    }
 
    /**
@@ -62,7 +63,7 @@
    protected InspectionQuery getDeleteQuery(String nodeId) throws SQLException
    {
       return new InspectionQuery("DELETE FROM " + getTableName() + " WHERE " + getIdColumn() + "='/"
-         + CacheableLockManagerImpl.LOCKS + "/" + nodeId + "'", new String[]{}, "");
+         + CacheableLockManagerImpl.LOCKS + "/" + nodeId + "'", new String[]{}, "", new DummyRepair());
    }
 
    /**

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JBCShareableLockTableHandler.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JBCShareableLockTableHandler.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/JBCShareableLockTableHandler.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -17,6 +17,7 @@
 package org.exoplatform.services.jcr.impl.core.lock.jbosscache;
 
 import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.impl.checker.DummyRepair;
 import org.exoplatform.services.jcr.impl.checker.InspectionQuery;
 import org.exoplatform.services.jcr.impl.core.lock.LockTableHandler;
 
@@ -49,13 +50,13 @@
    {
       return new InspectionQuery("SELECT * FROM " + getTableName() + " WHERE " + getParentColumn() + "='/"
          + workspaceEntry.getUniqueName() + "/" + CacheableLockManagerImpl.LOCKS + "'", new String[]{getIdColumn()},
-         "Locks table match");
+         "Locks table match", new DummyRepair());
    }
 
    protected InspectionQuery getDeleteQuery(String nodeId) throws SQLException
    {
       return new InspectionQuery("DELETE FROM " + getTableName() + " WHERE " + getIdColumn() + "='/"
          + workspaceEntry.getUniqueName() + "/" + CacheableLockManagerImpl.LOCKS + "/" + nodeId + "'", new String[]{},
-         "");
+         "", new DummyRepair());
    }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -49,7 +49,6 @@
 import org.exoplatform.services.jcr.datamodel.QPath;
 import org.exoplatform.services.jcr.datamodel.ValueData;
 import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.InspectionReport;
 import org.exoplatform.services.jcr.impl.backup.BackupException;
 import org.exoplatform.services.jcr.impl.backup.Backupable;
 import org.exoplatform.services.jcr.impl.backup.DataRestore;
@@ -58,6 +57,7 @@
 import org.exoplatform.services.jcr.impl.backup.Suspendable;
 import org.exoplatform.services.jcr.impl.backup.rdbms.DataRestoreContext;
 import org.exoplatform.services.jcr.impl.backup.rdbms.DirectoryRestore;
+import org.exoplatform.services.jcr.impl.checker.InspectionReport;
 import org.exoplatform.services.jcr.impl.core.LocationFactory;
 import org.exoplatform.services.jcr.impl.core.NamespaceRegistryImpl;
 import org.exoplatform.services.jcr.impl.core.SessionDataManager;

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/DBConstants.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -203,68 +203,73 @@
    /**
     * COLUMN_ID.
     */
-   protected static final String COLUMN_ID = "ID";
+   public static final String COLUMN_ID = "ID";
 
    /**
     * COLUMN_PARENTID.
     */
-   protected static final String COLUMN_PARENTID = "PARENT_ID";
+   public static final String COLUMN_PARENTID = "PARENT_ID";
 
    /**
     * COLUMN_NAME.
     */
-   protected static final String COLUMN_NAME = "NAME";
+   public static final String COLUMN_NAME = "NAME";
 
    /**
     * COLUMN_VERSION.
     */
-   protected static final String COLUMN_VERSION = "VERSION";
+   public static final String COLUMN_VERSION = "VERSION";
 
    /**
+    * CONTAINER_NAME. Exists only for single-db.
+    */
+   public static final String CONTAINER_NAME = "CONTAINER_NAME";
+
+   /**
     * COLUMN_CLASS.
     */
-   protected static final String COLUMN_CLASS = "I_CLASS";
+   public static final String COLUMN_CLASS = "I_CLASS";
 
    /**
     * COLUMN_INDEX.
     */
-   protected static final String COLUMN_INDEX = "I_INDEX";
+   public static final String COLUMN_INDEX = "I_INDEX";
 
    /**
     * COLUMN_NORDERNUM.
     */
-   protected static final String COLUMN_NORDERNUM = "N_ORDER_NUM";
+   public static final String COLUMN_NORDERNUM = "N_ORDER_NUM";
 
    /**
     * COLUMN_PTYPE.
     */
-   protected static final String COLUMN_PTYPE = "P_TYPE";
+   public static final String COLUMN_PTYPE = "P_TYPE";
 
    /**
     * COLUMN_PMULTIVALUED.
     */
-   protected static final String COLUMN_PMULTIVALUED = "P_MULTIVALUED";
+   public static final String COLUMN_PMULTIVALUED = "P_MULTIVALUED";
 
    // VALUE table
    /**
     * PROPERTY_ID
     */
-   protected static final String COLUMN_VPROPERTY_ID = "PROPERTY_ID";
+   public static final String COLUMN_VPROPERTY_ID = "PROPERTY_ID";
 
    /**
     * COLUMN_VDATA.
     */
-   protected static final String COLUMN_VDATA = "DATA";
+   public static final String COLUMN_VDATA = "DATA";
 
    /**
     * COLUMN_VORDERNUM.
     */
-   protected static final String COLUMN_VORDERNUM = "ORDER_NUM";
+   public static final String COLUMN_VORDERNUM = "ORDER_NUM";
 
    /**
     * COLUMN_VSTORAGE_DESC.
     */
-   protected static final String COLUMN_VSTORAGE_DESC = "STORAGE_DESC";
+   public static final String COLUMN_VSTORAGE_DESC = "STORAGE_DESC";
 
    // Dialects
    /**

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainerChecker.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -23,6 +23,8 @@
 import org.exoplatform.services.jcr.config.WorkspaceEntry;
 import org.exoplatform.services.jcr.core.security.JCRRuntimePermissions;
 import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.checker.AssignRootAsParentRepair;
+import org.exoplatform.services.jcr.impl.checker.DummyRepair;
 import org.exoplatform.services.jcr.impl.checker.InspectionQuery;
 import org.exoplatform.services.jcr.impl.checker.InspectionQueryFilteredMultivaluedProperties;
 import org.exoplatform.services.jcr.impl.checker.InspectionReport;
@@ -41,7 +43,9 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 import javax.jcr.RepositoryException;
@@ -68,6 +72,8 @@
 
    private InspectionQuery lockInspectionQuery;
 
+   private List<InspectionQuery> itemsInspectionQuery = new ArrayList<InspectionQuery>();;
+
    private LockTableHandler lockHandler;
 
    /**
@@ -91,7 +97,7 @@
     * and has no corresponding record in LockManager persistent layer (db table); 
     * or the opposite.
     */
-   public void checkLocksInDataBase(boolean autoRepair) throws RepositoryException, IOException
+   public void checkLocksInDataBase(boolean autoRepair)
    {
       SecurityHelper.validateSecurityPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
 
@@ -117,16 +123,20 @@
       }
       catch (SQLException e)
       {
-         report.logExceptionAndSetInconsistency("Unexpected exception during LOCK DB checking.", e);
+         logExceptionAndSetInconsistency("Unexpected exception during LOCK DB checking.", e);
       }
       catch (NamingException e)
       {
-         report.logExceptionAndSetInconsistency("Unexpected exception during LOCK DB checking.", e);
+         logExceptionAndSetInconsistency("Unexpected exception during LOCK DB checking.", e);
       }
       catch (RepositoryConfigurationException e)
       {
-         report.logExceptionAndSetInconsistency("Unexpected exception during LOCK DB checking.", e);
+         logExceptionAndSetInconsistency("Unexpected exception during LOCK DB checking.", e);
       }
+      catch (RepositoryException e)
+      {
+         logExceptionAndSetInconsistency("Unexpected exception during LOCK DB checking.", e);
+      }
       finally
       {
          JDBCUtils.freeResources(resultSet, preparedStatement, jdbcConnection);
@@ -187,132 +197,17 @@
     * <p>
     * Check that database is not broken, and all base relation between jcr-items are not corrupted.
     * </p>
-    * 
-    * @param inspectionLog - log where inspection results will be placed
-    * @return InspectionLog
-    * @throws RepositoryException
-    * @throws IOException
     */
-   public void checkDataBase()
-      throws RepositoryException, IOException
+   public void checkDataBase(boolean autoRepair)
    {
       SecurityHelper.validateSecurityPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
       
-      Set<InspectionQuery> queries = new HashSet<InspectionQuery>();
-
-      // preload queries
-      queries.add(new InspectionQuery(jdbcDataContainer.multiDb
-         ? "select * from JCR_MITEM I where NOT EXISTS(select * from JCR_MITEM P where P.ID = I.PARENT_ID)"
-         : "select * from JCR_SITEM I where I.CONTAINER_NAME='" + jdbcDataContainer.containerName
-            + "' and NOT EXISTS(select * from JCR_SITEM P where P.ID = I.PARENT_ID)", new String[]{
-         DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME, DBConstants.COLUMN_CLASS},
-         "Items that do not have parent nodes"));
-
-      queries.add(new InspectionQuery(jdbcDataContainer.multiDb
-         ? "select * from JCR_MITEM N where N.I_CLASS=1 and NOT EXISTS "
-            + "(select * from JCR_MITEM P where P.I_CLASS=2 and P.PARENT_ID=N.ID "
-            + "and P.NAME='[http://www.jcp.org/jcr/1.0]primaryType')"
-         : "select * from JCR_SITEM N where N.CONTAINER_NAME='" + jdbcDataContainer.containerName
-            + "' and N.I_CLASS=1 and NOT EXISTS (select * from JCR_SITEM P "
-            + "where P.I_CLASS=2 and P.PARENT_ID=N.ID and P.NAME='[http://www.jcp.org/jcr/1.0]primaryType' "
-            + "and P.CONTAINER_NAME='" + jdbcDataContainer.containerName + "')", new String[]{DBConstants.COLUMN_ID,
-         DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME},
-         "Nodes that do not have at least one jcr:primaryType property"));
-
-      queries.add(new InspectionQuery(jdbcDataContainer.multiDb
-         ? "select * from JCR_MVALUE V where NOT EXISTS(select * from JCR_MITEM P "
-            + "where V.PROPERTY_ID = P.ID and P.I_CLASS=2)"
-         : "select * from JCR_SVALUE V where NOT EXISTS(select * from JCR_SITEM P "
-            + "where V.PROPERTY_ID = P.ID and P.I_CLASS=2)", new String[]{DBConstants.COLUMN_ID,
-         DBConstants.COLUMN_VPROPERTY_ID}, "All value records that has not owner-property record"));
-
-      queries
-         .add(new InspectionQueryFilteredMultivaluedProperties(
-            jdbcDataContainer.multiDb
-               ? "select * from JCR_MITEM P where P.I_CLASS=2 and P.P_MULTIVALUED=? and NOT EXISTS( select * from JCR_MVALUE V "
-                  + "where V.PROPERTY_ID=P.ID)"
-               : "select * from JCR_SITEM P where P.CONTAINER_NAME='"
-                  + jdbcDataContainer.containerName
-                  + "' and P.I_CLASS=2 and P.P_MULTIVALUED=? and NOT EXISTS( select * from JCR_SVALUE V where V.PROPERTY_ID=P.ID)",
-            new String[]{DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME},
-            "All properties that have not value record."));
-
-      // The differences in the queries by DB dialect.
-      // Oracle doesn't work correct with default query because empty value stored as null value.
-      String statement;
-      if (jdbcDataContainer.dbDialect.equalsIgnoreCase(DBConstants.DB_DIALECT_SYBASE))
-      {
-         statement =
-            jdbcDataContainer.multiDb
-               ? "select * from JCR_MVALUE where (STORAGE_DESC is null and DATA like null) or "
-                  + "(STORAGE_DESC is not null and not DATA like null)"
-               : "select V.* from JCR_SVALUE V, JCR_SITEM I where V.PROPERTY_ID = I.ID and I.CONTAINER_NAME='"
-                  + jdbcDataContainer.containerName
-                  + "'  AND ((STORAGE_DESC is null and DATA like null) or (STORAGE_DESC is not null and not DATA like null))";
-      }
-      else if (jdbcDataContainer.dbDialect.equalsIgnoreCase(DBConstants.DB_DIALECT_ORACLE)
-         || jdbcDataContainer.dbDialect.equalsIgnoreCase(DBConstants.DB_DIALECT_ORACLEOCI))
-      {
-         statement =
-            jdbcDataContainer.multiDb
-               ? "select * from JCR_MVALUE where (STORAGE_DESC is not null and DATA is not null)"
-               : "select V.* from JCR_SVALUE V, JCR_SITEM I where V.PROPERTY_ID = I.ID and I.CONTAINER_NAME='"
-                  + jdbcDataContainer.containerName + "'  AND (STORAGE_DESC is not null and DATA is not null)";
-      }
-      else
-      {
-         statement =
-            jdbcDataContainer.multiDb
-               ? "select * from JCR_MVALUE where (STORAGE_DESC is null and DATA is null) or "
-                  + "(STORAGE_DESC is not null and DATA is not null)"
-               : "select V.* from JCR_SVALUE V, JCR_SITEM I where V.PROPERTY_ID = I.ID and I.CONTAINER_NAME='"
-                  + jdbcDataContainer.containerName
-                  + "'  AND ((STORAGE_DESC is null and DATA is null) or (STORAGE_DESC is not null and DATA is not null))";
-      }
-      queries.add(new InspectionQuery(statement, new String[]{DBConstants.COLUMN_ID}, "Incorrect JCR_VALUE records"));
-
-      queries
-         .add(new InspectionQueryFilteredMultivaluedProperties(
-            jdbcDataContainer.multiDb
-               ? "select * from JCR_MITEM P where P.P_TYPE=9 and P.P_MULTIVALUED=? and NOT EXISTS "
-                  + "(select * from JCR_MREF R where P.ID=R.PROPERTY_ID)"
-               : "select * from JCR_SITEM P where P.CONTAINER_NAME='"
-                  + jdbcDataContainer.containerName
-                  + "' and P.P_TYPE=9 and P.P_MULTIVALUED=? and NOT EXISTS( select * from JCR_SREF R where P.ID=R.PROPERTY_ID)",
-            new String[]{DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME},
-            "Reference properties without reference records"));
-
-      // an item is its own parent. 
-      queries.add(new InspectionQuery(jdbcDataContainer.multiDb
-         ? "select * from JCR_MITEM I where I.ID = I.PARENT_ID and I.NAME <> '" + Constants.ROOT_PARENT_NAME + "'"
-         : "select * from JCR_SITEM I where I.ID = I.PARENT_ID and I.CONTAINER_NAME='"
-            + jdbcDataContainer.containerName + "' and I.NAME <> '" + Constants.ROOT_PARENT_NAME + "'", new String[]{
-         DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME}, "An item is its own parent."));
-
-      // Several versions of same item
-      queries
-         .add(new InspectionQuery(
-            jdbcDataContainer.multiDb
-               ? "select * from JCR_MITEM I where EXISTS (select * from JCR_MITEM J"
-                  + " WHERE I.PARENT_ID = J.PARENT_ID AND I.NAME = J.NAME and I.I_INDEX = J.I_INDEX and I.I_CLASS = J.I_CLASS"
-                  + " and I.VERSION != J.VERSION)"
-               : "select * from JCR_SITEM I where I.CONTAINER_NAME='"
-                  + jdbcDataContainer.containerName
-                  + "' and"
-                  + " EXISTS (select * from JCR_SITEM J WHERE I.CONTAINER_NAME = J.CONTAINER_NAME and"
-                  + " I.PARENT_ID = J.PARENT_ID AND I.NAME = J.NAME and I.I_INDEX = J.I_INDEX and I.I_CLASS = J.I_CLASS"
-                  + " and I.VERSION != J.VERSION)",
-            new String[]{DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME,
-               DBConstants.COLUMN_VERSION, DBConstants.COLUMN_CLASS, DBConstants.COLUMN_INDEX},
-            "Several versions of same item."));
-
-      // using existing DataSource to get a JDBC Connection.
-      Connection jdbcConn = jdbcDataContainer.getConnectionFactory().getJdbcConnection();
-
+      Connection jdbcConn = null;
       try
       {
-         // perform all queries on-by-one
-         for (InspectionQuery query : queries)
+         jdbcConn = jdbcDataContainer.getConnectionFactory().getJdbcConnection();
+
+         for (InspectionQuery query : itemsInspectionQuery)
          {
             PreparedStatement st = null;
             ResultSet resultSet = null;
@@ -320,32 +215,18 @@
             {
                st = query.prepareStatement(jdbcConn);
 
-               // the result of query is expected to be empty 
                resultSet = st.executeQuery();
                if (resultSet.next())
                {
-                  // but if result not empty, then inconsistency takes place
-                  report.logDescription(query.getDescription());
+                  logDescription(query.getDescription());
                   do
                   {
-                     StringBuilder record = new StringBuilder();
-                     for (String fieldName : query.getFieldNames())
+                     logBrokenObjectAndSetInconsistency(getBrokenObject(resultSet, query.getFieldNames()));
+                     if (autoRepair)
                      {
-                        record.append(fieldName);
-                        record.append('=');
-                        if (fieldName.equals(DBConstants.COLUMN_NORDERNUM)
-                           || fieldName.equals(DBConstants.COLUMN_VORDERNUM))
-                        {
-                           record.append(resultSet.getInt(fieldName));
-                        }
-                        else
-                        {
-                           record.append(resultSet.getString(fieldName));
-                        }
-                        record.append(' ');
+                        query.getRepair().doRepair(resultSet);
+                        logComment("Inconsistency has been fixed");
                      }
-
-                     report.logBrokenObjectAndSetInconsistency(record.toString());
                   }
                   while (resultSet.next());
                }
@@ -358,8 +239,12 @@
       }
       catch (SQLException e)
       {
-         report.logExceptionAndSetInconsistency("Exception during DB inspection.", e);
+         logExceptionAndSetInconsistency("Unexpected exception during DB checking.", e);
       }
+      catch (RepositoryException e)
+      {
+         logExceptionAndSetInconsistency("Unexpected exception during DB checking.", e);
+      }
       finally
       {
          JDBCUtils.freeResources(null, null, jdbcConn);
@@ -548,29 +433,121 @@
 
    private void initInspectionQueries()
    {
-      String singleDbQuery =
-         "SELECT V.PROPERTY_ID, V.ORDER_NUM, V.STORAGE_DESC from JCR_SVALUE V, JCR_SITEM I"
-            + " where I.CONTAINER_NAME='" + jdbcDataContainer.containerName
-            + "' and V.PROPERTY_ID = I.ID and STORAGE_DESC is not null";
-      String multiDbQuery =
-         "SELECT PROPERTY_ID, ORDER_NUM, STORAGE_DESC from JCR_MVALUE where STORAGE_DESC is not null";
-
       vsInspectionQuery =
-         new InspectionQuery(jdbcDataContainer.multiDb ? multiDbQuery : singleDbQuery, new String[]{
-            DBConstants.COLUMN_VPROPERTY_ID, DBConstants.COLUMN_VORDERNUM, DBConstants.COLUMN_VSTORAGE_DESC},
-            "Items with value data stored in value storage");
+         new InspectionQuery(jdbcDataContainer.multiDb
+            ? "select PROPERTY_ID, ORDER_NUM, STORAGE_DESC from JCR_MVALUE where STORAGE_DESC is not null"
+            : "select V.PROPERTY_ID, V.ORDER_NUM, V.STORAGE_DESC from JCR_SVALUE V, JCR_SITEM I"
+               + " where I.CONTAINER_NAME='" + jdbcDataContainer.containerName
+               + "' and V.PROPERTY_ID = I.ID and STORAGE_DESC is not null",
+            new String[]{DBConstants.COLUMN_VPROPERTY_ID, DBConstants.COLUMN_VORDERNUM,
+               DBConstants.COLUMN_VSTORAGE_DESC}, "Items with value data stored in value storage", new DummyRepair());
 
-      singleDbQuery =
-         "SELECT DISTINCT PARENT_ID from JCR_MITEM WHERE I_CLASS=2 "
-            + "AND (NAME='[http://www.jcp.org/jcr/1.0]lockOwner' OR NAME='[http://www.jcp.org/jcr/1.0]lockIsDeep')";
+      lockInspectionQuery =
+         new InspectionQuery(jdbcDataContainer.multiDb ? "select distinct PARENT_ID from JCR_MITEM where I_CLASS=2 AND"
+            + " (NAME='[http://www.jcp.org/jcr/1.0]lockOwner' OR NAME='[http://www.jcp.org/jcr/1.0]lockIsDeep')"
+            : "select distinct PARENT_ID from JCR_SITEM WHERE CONTAINER_NAME='" + jdbcDataContainer.containerName + "'"
+               + " AND I_CLASS=2 and (NAME='[http://www.jcp.org/jcr/1.0]lockOwner'"
+               + " OR NAME='[http://www.jcp.org/jcr/1.0]lockIsDeep')", new String[]{DBConstants.COLUMN_PARENTID},
+            "Items which have jcr:lockOwner and jcr:lockIsDeep properties", new DummyRepair());
 
-      multiDbQuery =
-         "SELECT DISTINCT PARENT_ID from JCR_SITEM WHERE CONTAINER_NAME='"
-            + jdbcDataContainer.containerName
-            + "' AND I_CLASS=2 and (NAME='[http://www.jcp.org/jcr/1.0]lockOwner' OR NAME='[http://www.jcp.org/jcr/1.0]lockIsDeep')";
+      // ITEM tables
+      itemsInspectionQuery.add(new InspectionQuery(jdbcDataContainer.multiDb
+         ? "select * from JCR_MITEM I where NOT EXISTS(select * from JCR_MITEM P where P.ID = I.PARENT_ID)"
+         : "select * from JCR_SITEM I where I.CONTAINER_NAME='" + jdbcDataContainer.containerName
+            + "' and NOT EXISTS(select * from JCR_SITEM P where P.ID = I.PARENT_ID)", new String[]{
+         DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME, DBConstants.COLUMN_CLASS},
+            "Items that do not have parent nodes", new AssignRootAsParentRepair(jdbcDataContainer
+               .getConnectionFactory())));
 
-      lockInspectionQuery =
-         new InspectionQuery(jdbcDataContainer.multiDb ? singleDbQuery : multiDbQuery,
-            new String[]{DBConstants.COLUMN_PARENTID}, "Items which have jcr:lockOwner and jcr:lockIsDeep properties");
+      itemsInspectionQuery
+         .add(new InspectionQueryFilteredMultivaluedProperties(
+            jdbcDataContainer.multiDb
+               ? "select * from JCR_MITEM P where P.I_CLASS=2 and P.P_MULTIVALUED=? and NOT EXISTS( select * from JCR_MVALUE V "
+                  + "where V.PROPERTY_ID=P.ID)" : "select * from JCR_SITEM P where P.CONTAINER_NAME='"
+                  + jdbcDataContainer.containerName + "' and P.I_CLASS=2"
+                  + " and P.P_MULTIVALUED=? and NOT EXISTS( select * from JCR_SVALUE V where V.PROPERTY_ID=P.ID)",
+            new String[]{DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME},
+            "A node that has a single valued properties with nothing declared in the VALUE table.", new DummyRepair()));
+
+      itemsInspectionQuery.add(new InspectionQuery(jdbcDataContainer.multiDb
+         ? "select * from JCR_MITEM N where N.I_CLASS=1 and NOT EXISTS "
+            + "(select * from JCR_MITEM P where P.I_CLASS=2 and P.PARENT_ID=N.ID "
+            + "and P.NAME='[http://www.jcp.org/jcr/1.0]primaryType')"
+         : "select * from JCR_SITEM N where N.CONTAINER_NAME='" + jdbcDataContainer.containerName
+            + "' and N.I_CLASS=1 and NOT EXISTS (select * from JCR_SITEM P "
+            + "where P.I_CLASS=2 and P.PARENT_ID=N.ID and P.NAME='[http://www.jcp.org/jcr/1.0]primaryType' "
+            + "and P.CONTAINER_NAME='" + jdbcDataContainer.containerName + "')", new String[]{DBConstants.COLUMN_ID,
+         DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME}, "A node that doesn't have primary type property",
+         new DummyRepair()));
+
+      itemsInspectionQuery
+         .add(new InspectionQuery(jdbcDataContainer.multiDb
+            ? "select * from JCR_MVALUE V where NOT EXISTS(select * from JCR_MITEM P "
+               + "where V.PROPERTY_ID = P.ID and P.I_CLASS=2)"
+            : "select * from JCR_SVALUE V where NOT EXISTS(select * from JCR_SITEM P "
+               + "where V.PROPERTY_ID = P.ID and P.I_CLASS=2)", new String[]{DBConstants.COLUMN_ID,
+            DBConstants.COLUMN_VPROPERTY_ID}, "All value records that has not related property record",
+            new DummyRepair()));
+
+      // The differences in the queries by DB dialect.
+      String statement;
+      if (jdbcDataContainer.dbDialect.equalsIgnoreCase(DBConstants.DB_DIALECT_SYBASE))
+      {
+         statement =
+            jdbcDataContainer.multiDb
+               ? "select * from JCR_MVALUE where (STORAGE_DESC is not null and not DATA like null)"
+               : "select V.* from JCR_SVALUE V, JCR_SITEM I where V.PROPERTY_ID = I.ID and I.CONTAINER_NAME='"
+                  + jdbcDataContainer.containerName + "' AND ((STORAGE_DESC is not null and not DATA like null))";
+      }
+      else if (jdbcDataContainer.dbDialect.equalsIgnoreCase(DBConstants.DB_DIALECT_ORACLE)
+         || jdbcDataContainer.dbDialect.equalsIgnoreCase(DBConstants.DB_DIALECT_ORACLEOCI))
+      {
+         statement =
+            jdbcDataContainer.multiDb
+               ? "select * from JCR_MVALUE where (STORAGE_DESC is not null and DATA is not null)"
+               : "select V.* from JCR_SVALUE V, JCR_SITEM I where V.PROPERTY_ID = I.ID and I.CONTAINER_NAME='"
+                  + jdbcDataContainer.containerName + "' AND (STORAGE_DESC is not null and DATA is not null)";
+      }
+      else
+      {
+         statement =
+            jdbcDataContainer.multiDb
+               ? "select * from JCR_MVALUE where (STORAGE_DESC is not null and DATA is not null)"
+               : "select V.* from JCR_SVALUE V, JCR_SITEM I where V.PROPERTY_ID = I.ID and I.CONTAINER_NAME='"
+                  + jdbcDataContainer.containerName + "' AND ((STORAGE_DESC is not null and DATA is not null))";
+      }
+      itemsInspectionQuery.add(new InspectionQuery(statement, new String[]{DBConstants.COLUMN_ID},
+         "Incorrect VALUE records. Both fields STORAGE_DESC and DATA contain not null value.", new DummyRepair()));
+
+      itemsInspectionQuery.add(new InspectionQuery(jdbcDataContainer.multiDb
+         ? "select * from JCR_MITEM I where I.ID = I.PARENT_ID and I.NAME <> '" + Constants.ROOT_PARENT_NAME + "'"
+         : "select * from JCR_SITEM I where I.ID = I.PARENT_ID and I.CONTAINER_NAME='"
+            + jdbcDataContainer.containerName + "' and I.NAME <> '" + Constants.ROOT_PARENT_NAME + "'", new String[]{
+         DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME}, "An item is its own parent.",
+         new AssignRootAsParentRepair(jdbcDataContainer.getConnectionFactory())));
+
+      itemsInspectionQuery
+         .add(new InspectionQuery(
+            jdbcDataContainer.multiDb
+               ? "select * from JCR_MITEM I where EXISTS (select * from JCR_MITEM J"
+                  + " WHERE I.PARENT_ID = J.PARENT_ID AND I.NAME = J.NAME and I.I_INDEX = J.I_INDEX and I.I_CLASS = J.I_CLASS"
+                  + " and I.VERSION != J.VERSION)"
+               : "select * from JCR_SITEM I where I.CONTAINER_NAME='"
+                  + jdbcDataContainer.containerName
+                  + "' and EXISTS (select * from JCR_SITEM J WHERE I.CONTAINER_NAME = J.CONTAINER_NAME and"
+                  + " I.PARENT_ID = J.PARENT_ID AND I.NAME = J.NAME and I.I_INDEX = J.I_INDEX and I.I_CLASS = J.I_CLASS"
+                  + " and I.VERSION != J.VERSION)",
+            new String[]{DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME,
+               DBConstants.COLUMN_VERSION, DBConstants.COLUMN_CLASS, DBConstants.COLUMN_INDEX},
+            "Several versions of same item.", new DummyRepair()));
+
+      itemsInspectionQuery.add(new InspectionQuery(jdbcDataContainer.multiDb
+         ? "select * from JCR_MITEM P, JCR_MVALUE V where P.ID=V.PROPERTY_ID and P.P_TYPE=9 and NOT EXISTS "
+            + "(select * from JCR_MREF R where P.ID=R.PROPERTY_ID)"
+         : "select * from JCR_SITEM P, JCR_SVALUE V where P.ID=V.PROPERTY_ID and P.CONTAINER_NAME='"
+            + jdbcDataContainer.containerName
+            + "' and P.P_TYPE=9 and NOT EXISTS (select * from JCR_SREF R where P.ID=R.PROPERTY_ID)", new String[]{
+         DBConstants.COLUMN_ID, DBConstants.COLUMN_PARENTID, DBConstants.COLUMN_NAME},
+         "Reference properties without reference records", new DummyRepair()));
    }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java	2012-02-29 08:24:57 UTC (rev 5709)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/TestRepositoryCheckController.java	2012-02-29 11:24:32 UTC (rev 5710)
@@ -500,6 +500,7 @@
    public void testDBUsecasesTheParentIdIsIdOfThisNodeSingleDB() throws Exception
    {
       checkDBUsecasesTheParentIdIsIdOfThisNode(helper.createRepository(container, false, false));
+      checkDBUsecasesTheParentIdIsIdOfThisNode2(helper.createRepository(container, false, false));
    }
 
    /**
@@ -508,6 +509,7 @@
    public void testDBUsecasesTheParentIdIsIdOfThisNodeMultiDB() throws Exception
    {
       checkDBUsecasesTheParentIdIsIdOfThisNode(helper.createRepository(container, true, false));
+      checkDBUsecasesTheParentIdIsIdOfThisNode2(helper.createRepository(container, true, false));
    }
 
    private void checkDBUsecasesTheParentIdIsIdOfThisNode(ManageableRepository repository) throws Exception
@@ -544,12 +546,52 @@
       conn.commit();
       conn.close();
 
-      // repository is inconsistent
-      assertTrue(checkController.checkDataBase().startsWith(
-         RepositoryCheckController.REPORT_NOT_CONSISTENT_MESSAGE));
+      assertTrue(checkController.checkDataBase().startsWith(RepositoryCheckController.REPORT_NOT_CONSISTENT_MESSAGE));
 
+      checkController.repairDataBase("yes");
+      assertTrue(checkController.checkDataBase().startsWith(RepositoryCheckController.REPORT_CONSISTENT_MESSAGE));
+
    }
 
+   private void checkDBUsecasesTheParentIdIsIdOfThisNode2(ManageableRepository repository) throws Exception
+   {
+      // create repository and add property
+      SessionImpl session =
+         (SessionImpl)repository.login(credentials, repository.getConfiguration().getSystemWorkspaceName());
+      NodeImpl node = (NodeImpl)session.getRootNode().addNode("testNode");
+      PropertyImpl prop = (PropertyImpl)node.setProperty("prop", "test");
+      session.save();
+      session.logout();
+
+      // repository is consistent
+      TesterRepositoryCheckController checkController = new TesterRepositoryCheckController(repository);
+      assertTrue(checkController.checkDataBase().startsWith(RepositoryCheckController.REPORT_CONSISTENT_MESSAGE));
+
+      WorkspaceEntry wsEntry = repository.getConfiguration().getWorkspaceEntries().get(0);
+      boolean isMultiDb = wsEntry.getContainer().getParameterBoolean(JDBCWorkspaceDataContainer.MULTIDB);
+
+      // change ITEM table
+      String sourceName = wsEntry.getContainer().getParameterValue(JDBCWorkspaceDataContainer.SOURCE_NAME);
+
+      Connection conn = ((DataSource)new InitialContext().lookup(sourceName)).getConnection();
+
+      conn.prepareStatement("DROP INDEX JCR_IDX_" + (isMultiDb ? "M" : "S") + "ITEM_PARENT").execute();
+      conn.prepareStatement("DROP INDEX JCR_IDX_" + (isMultiDb ? "M" : "S") + "ITEM_PARENT_NAME").execute();
+      conn.prepareStatement(
+         "UPDATE JCR_" + (isMultiDb ? "M" : "S") + "ITEM SET PARENT_ID = '" + (isMultiDb ? "" : wsEntry.getName())
+            + prop.getInternalIdentifier() + "' WHERE ID='" + (isMultiDb ? "" : wsEntry.getName())
+            + prop.getInternalIdentifier() + "'").execute();
+
+      conn.commit();
+      conn.close();
+
+      assertTrue(checkController.checkDataBase().startsWith(RepositoryCheckController.REPORT_NOT_CONSISTENT_MESSAGE));
+
+      checkController.repairDataBase("yes");
+      assertTrue(checkController.checkDataBase().startsWith(RepositoryCheckController.REPORT_CONSISTENT_MESSAGE));
+
+   }
+
    /**
     *  Usecase: property doens't have have parent node.
     */
@@ -681,7 +723,6 @@
    public void testDBUsecasesIncorrectValueRecordsSingleDB() throws Exception
    {
       checkDBUsecasesIncorrectValueRecords(helper.createRepository(container, false, false));
-      checkDBUsecasesIncorrectValueRecords2(helper.createRepository(container, false, false));
    }
 
    /**
@@ -690,7 +731,6 @@
    public void testDBUsecasesIncorrectValueRecordsMultiDB() throws Exception
    {
       checkDBUsecasesIncorrectValueRecords(helper.createRepository(container, true, false));
-      checkDBUsecasesIncorrectValueRecords2(helper.createRepository(container, true, false));
    }
 
    private void checkDBUsecasesIncorrectValueRecords(ManageableRepository repository) throws Exception
@@ -728,41 +768,6 @@
 
    }
 
-   private void checkDBUsecasesIncorrectValueRecords2(ManageableRepository repository) throws Exception
-   {
-      // create repository and add property
-      SessionImpl session =
-         (SessionImpl)repository.login(credentials, repository.getConfiguration().getSystemWorkspaceName());
-      PropertyImpl prop = (PropertyImpl)session.getRootNode().addNode("testNode").setProperty("prop", "test");
-      session.save();
-      session.logout();
-
-      // repository is consistent
-      TesterRepositoryCheckController checkController = new TesterRepositoryCheckController(repository);
-      assertTrue(checkController.checkDataBase().startsWith(
-         RepositoryCheckController.REPORT_CONSISTENT_MESSAGE));
-
-
-      WorkspaceEntry wsEntry = repository.getConfiguration().getWorkspaceEntries().get(0);
-      boolean isMultiDb = wsEntry.getContainer().getParameterBoolean(JDBCWorkspaceDataContainer.MULTIDB);
-
-      // change VALUE table
-      String sourceName = wsEntry.getContainer().getParameterValue(JDBCWorkspaceDataContainer.SOURCE_NAME);
-
-      Connection conn = ((DataSource)new InitialContext().lookup(sourceName)).getConnection();
-      conn.prepareStatement(
-         "UPDATE JCR_" + (isMultiDb ? "M" : "S") + "VALUE SET DATA = NULL WHERE PROPERTY_ID = '"
-            + (isMultiDb ? "" : wsEntry.getName()) + prop.getInternalIdentifier() + "'").execute();
-
-      conn.commit();
-      conn.close();
-
-      // repository is inconsistent
-      assertTrue(checkController.checkDataBase().startsWith(
-         RepositoryCheckController.REPORT_NOT_CONSISTENT_MESSAGE));
-
-   }
-
    /**
     * Usecase: value records has no item record.
     */



More information about the exo-jcr-commits mailing list