Check for stale indexes, too. Use our knowledge of full text indexes to better decide if a column or index is internal to Depot's or the DB's workings. Finally, allow com.samskivert.depot.verifyschema to be set, forcing a staleness check (which slows down initialization somewhat).

This commit is contained in:
Par Winzell
2010-12-15 02:58:55 +00:00
parent 15cab8a6e2
commit f81b338cd9
5 changed files with 75 additions and 11 deletions
@@ -133,7 +133,7 @@ public class DepotMarshaller<T extends PersistentRecord> implements QueryMarshal
try {
_schemaVersion = (Integer)field.get(null);
} catch (Exception e) {
log.warning("Failed to read schema version [class=" + _pClass + "].", e);
log.warning("Failed to read schema version", "class", pClass, e);
}
}
@@ -545,9 +545,10 @@ public class DepotMarshaller<T extends PersistentRecord> implements QueryMarshal
// now check whether we need to migrate our database schema
while (true) {
if (currentVersion >= _schemaVersion) {
// TODO: we used to check for staleness here, but that's slow; currently we do it
// only after migration, we should reinstate a check maybe the first time a table
// is read or something so that developers are more likely to get the warning
// no migrations to do, but maybe we should do an explicit staleness check
if (Boolean.getBoolean("com.samskivert.depot.verifyschema")) {
checkForStaleness(TableMetaData.load(ctx, getTableName()), ctx, builder);
}
return;
}
@@ -1003,11 +1004,22 @@ public class DepotMarshaller<T extends PersistentRecord> implements QueryMarshal
meta.tableColumns.remove(fmarsh.getColumnName());
}
for (String column : meta.tableColumns) {
if (builder.isPrivateColumn(column)) {
if (builder.isPrivateColumn(column, _fullTextIndexes)) {
continue;
}
log.warning(getTableName() + " contains stale column '" + column + "'.");
log.warning("Stale column", "table", getTableName(), "column", column);
}
for (CreateIndexClause clause : _indexes) {
meta.indexColumns.remove(clause.getName());
}
for (String index : meta.indexColumns.keySet()) {
if (builder.isPrivateIndex(index, _fullTextIndexes)) {
continue;
}
log.warning("Stale index", "table", getTableName(), "index", index);
}
}
protected void checkHasPrimaryKey ()
@@ -24,6 +24,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Lists;
@@ -223,12 +224,19 @@ public class HSQLBuilder
}
@Override
public boolean isPrivateColumn (String column)
public boolean isPrivateColumn (String column, Map<String, FullTextIndex> fullTextIndexes)
{
// The HSQLDB builder does not yet have any private columns.
return false;
}
@Override
public boolean isPrivateIndex (String index, Map<String, FullTextIndex> fullTextIndexes)
{
// The HSQLDB builder does not yet have any private indexes;
return false;
}
@Override
protected String getBooleanDefault ()
{
@@ -22,6 +22,8 @@ package com.samskivert.depot.impl;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Set;
import com.samskivert.depot.PersistentRecord;
@@ -208,12 +210,19 @@ public class MySQLBuilder
}
@Override
public boolean isPrivateColumn (String column)
public boolean isPrivateColumn (String column, Map<String, FullTextIndex> fullTextIndexes)
{
// The MySQL builder does not yet have any private columns.
return false;
}
@Override
public boolean isPrivateIndex (String index, Map<String, FullTextIndex> fullTextIndexes)
{
// The MySQL builder does not yet have any private indexes.
return false;
}
@Override
protected String getBooleanDefault ()
{
@@ -23,6 +23,8 @@ package com.samskivert.depot.impl;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Set;
import com.samskivert.jdbc.DatabaseLiaison;
@@ -243,10 +245,32 @@ public class PostgreSQLBuilder
}
@Override
public boolean isPrivateColumn (String column)
public boolean isPrivateColumn (String column, Map<String, FullTextIndex> fullTextIndexes)
{
// filter out any column that we created as part of FTS support
return column.startsWith("ftsCol_");
for (FullTextIndex fti : fullTextIndexes.values()) {
if (("ftsCol_" + fti.name()).equals(column)) {
return true;
}
}
return false;
}
@Override
public boolean isPrivateIndex (String index, Map<String, FullTextIndex> fullTextIndexes)
{
// filter out any index that looks like PostgreSQL created it
if (index.endsWith("_key") || index.endsWith("_pkey")) {
return true;
}
// filter out any index that we created as part of FTS support
for (FullTextIndex fti : fullTextIndexes.values()) {
if (index.endsWith("_ftsIx_" + fti.name())) {
return true;
}
}
return false;
}
@Override
@@ -21,6 +21,8 @@
package com.samskivert.depot.impl;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.sql.Connection;
@@ -203,7 +205,16 @@ public abstract class SQLBuilder
* e.g. PostgreSQL's full text search data is stored in a table column that should otherwise
* not be visible to Depot; this method helps mask it.
*/
public abstract boolean isPrivateColumn (String column);
public abstract boolean isPrivateColumn (
String column, Map<String, FullTextIndex> fullTextIndexes);
/**
* Return true if the supplied index is an internal consideration of this {@link SQLBuilder},
* e.g. PostgreSQL automatically creates indexes that end in _key for unique columns, and its
* primary keys have indices ending in _pkey.
*/
public abstract boolean isPrivateIndex (
String index, Map<String, FullTextIndex> fullTextIndexes);
/**
* Figure out what full text search indexes already exist on this table and add the names of