Last active
February 21, 2018 14:39
-
-
Save ben-manes/5638489 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A validator to verify that the jOOQ generated tables match the database table metadata. | |
* | |
* @author Ben Manes ([email protected]) | |
*/ | |
final class SchemaValidator { | |
private static final Logger logger = LoggerFactory.getLogger(SchemaValidator.class); | |
private final List<Schema> schemas; | |
private final DSLContext db; | |
public SchemaValidator(DSLContext db, List<Schema> schemas) { | |
this.schemas = schemas; | |
this.db = db; | |
} | |
/** Validates that the generated table against the runtime schema. */ | |
public void validate() { | |
Stopwatch stopwatch = new Stopwatch().start(); | |
Set<Table<?>> generatedTables = getTablesFor(schemas); | |
Map<String, Table<?>> databaseTables = getTablesByName(db.meta().getTables()); | |
boolean valid = true; | |
for (Table<?> generatedTable : generatedTables) { | |
String tableName = getTableName(generatedTable); | |
Table<?> databaseTable = databaseTables.get(tableName); | |
valid &= isValid(generatedTable, databaseTable); | |
} | |
logger.debug("Validated database table mappings in {}", stopwatch); | |
if (!valid) { | |
logger.error("Shutting down due to failing database schema validation"); | |
System.exit(1); | |
} | |
} | |
/** Returns whether the generated table matches the database table. */ | |
private boolean isValid(Table<?> generatedTable, Table<?> databaseTable) { | |
if (databaseTable == null) { | |
logger.error("Table {} not found", generatedTable.getName()); | |
return false; | |
} | |
NavigableSet<String> generatedMetadata = getFieldMetadata(generatedTable); | |
NavigableSet<String> databaseMetadata = getFieldMetadata(databaseTable); | |
if (!generatedMetadata.equals(databaseMetadata)) { | |
logger.error("Table {} has different field metadata (expected {} but was {})", | |
generatedTable.getName(), generatedMetadata, databaseMetadata); | |
return false; | |
} | |
return true; | |
} | |
/** Retrieves the tables in the jOOQ generated schemas without the schema prefixes in the name. */ | |
private Set<Table<?>> getTablesFor(List<Schema> schemas) { | |
Set<Table<?>> tables = Sets.newHashSet(); | |
for (Schema schema : schemas) { | |
for (Table<?> table : schema.getTables()) { | |
tables.add(table.asTable(getTableName(table))); | |
} | |
} | |
return tables; | |
} | |
/** Creates a mapping of the table name to the table instance. */ | |
private Map<String, Table<?>> getTablesByName(Iterable<Table<?>> tables) { | |
Map<String, Table<?>> tablesByName = Maps.newHashMap(); | |
for (Table<?> table : tables) { | |
tablesByName.put(getTableName(table), table); | |
} | |
return tablesByName; | |
} | |
/** Returns a table normalized name for lookups. */ | |
private static String getTableName(Table<?> table) { | |
return table.getName().toLowerCase(); | |
} | |
/** | |
* Retrieves the comparable field metadata from the database table. Currently this is only the | |
* field names as the data types may use custom converters. | |
*/ | |
private NavigableSet<String> getFieldMetadata(Table<?> table) { | |
NavigableSet<String> metadata = Sets.newTreeSet(); | |
for (Field<?> field : table.fieldsRow().fields()) { | |
metadata.add(field.getName().toLowerCase()); | |
} | |
return metadata; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment