Skip to content

Commit

Permalink
Merge pull request #288 from IGNF/issue_287
Browse files Browse the repository at this point in the history
Issue 287
  • Loading branch information
cboucheIGN authored Sep 21, 2022
2 parents 7e14c6d + 228f46b commit c8e3fcc
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import fr.ign.validator.database.Database;
import fr.ign.validator.database.RowIterator;
import fr.ign.validator.model.AttributeType;
import fr.ign.validator.model.TableModel;
import fr.ign.validator.model.constraint.ForeignKeyConstraint;

/**
Expand All @@ -34,15 +36,15 @@ public ForeignKeyMismatch(String id, String file, String values) {
* Retreive all Foreign Key Mismatch by perfoming an SQL query to database
*
* @param database
* @param tableName
* @param tableModel
* @param foreignKey
* @return
* @throws SQLException
* @throws IOException
*/
public List<ForeignKeyMismatch> foreignKeyNotFound(
Database database,
String tableName,
TableModel tableModel,
ForeignKeyConstraint foreignKey) throws SQLException, IOException {

// TODO validate condition to avoid SQL injection and crashes
Expand All @@ -54,38 +56,35 @@ public List<ForeignKeyMismatch> foreignKeyNotFound(
+ " LIKE "
+ " target." + foreignKey.getTargetColumnNames().get(i);
if (i == 0) {
conditions.add(" WHERE " + condition);
conditions.add("WHERE " + condition);
} else {
conditions.add(" AND " + condition);
conditions.add("AND " + condition);
}
}

// Query exemple
// sub request retrieve all foreign key match
// SELECT r.__id, r.__file, TYPEPSC, STYPEPSC
// FROM PRESCRIPTION_SURF AS r WHERE r.__id NOT IN (
// SELECT a.__id FROM PRESCRIPTION_SURF AS a
// JOIN PrescriptionUrbaType AS b
// ON (a.TYPEPSC LIKE b.TYPEPSC AND a.STYPEPSC LIKE b.STYPEPSC) )
List<String> nullableClause = new ArrayList<String>();
for (int i = 0; i < foreignKey.getSourceColumnNames().size(); i++) {
String name = foreignKey.getSourceColumnNames().get(i);
AttributeType<?> attribute = tableModel.getFeatureType().getAttribute(name);
if (attribute == null || attribute.getConstraints().isRequired()) {
continue;
}
String condition = "AND " + name + " IS NOT NULL";
nullableClause.add(condition);
}

// String query = "SELECT r.__id, r.__file, "
// + String.join(", ", foreignKey.getSourceColumnNames())
// + " FROM " + tableName + " AS r"
// + " WHERE r.__id NOT IN ("
// + " SELECT a.__id "
// + " FROM " + tableName + " AS a"
// + " JOIN " + foreignKey.getTargetTableName() + " AS b"
// + " ON (" + String.join(" AND ", conditions) + ")"
// + " )";
String tableName = tableModel.getName();

String query = "SELECT src.__id, src.__file, "
+ String.join(", ", foreignKey.getSourceColumnNames())
+ " FROM " + tableName + " AS src"
+ " WHERE NOT EXISTS ( "
+ " SELECT true "
+ " FROM " + foreignKey.getTargetTableName() + " AS target "
+ String.join("", conditions)
+ ")";
+ String.join(" ", conditions)
+ ") "
+ String.join(" ", nullableClause);

RowIterator it = database.query(query);

List<ForeignKeyMismatch> result = new ArrayList<ForeignKeyMismatch>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private void doValidate(Context context, Database database) throws SQLException,

List<ForeignKeyMismatch> mismatchs = foreignKeyFinder.foreignKeyNotFound(
database,
tableModel.getName(),
tableModel,
foreignKey
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ public void testParseOk() {
Assert.assertEquals("(VALUE,SUB_VALUE) REFERENCES MY_REFERENCE(TYPE,SUB_TYPE)", constraint.toString());
}

@Test
public void testParseGPU() {
String constraintString = "(STYPEP) REFERENCES ListeStypepCC(STYPEP)";
ForeignKeyConstraint constraint = ForeignKeyConstraint.parseForeignKey(constraintString);

Assert.assertEquals("(STYPEP) REFERENCES ListeStypepCC(STYPEP)", constraint.toString());
}

@Test
public void testParseFormat2() {
String constraintString = " ( VALUE , SUB_VALUE ) REFERENCES MY_REFERENCE ( TYPE, SUB_TYPE ) ";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ public void setUp() throws NoSuchAuthorityCodeException, FactoryException {
// creates attributes "TYPE", "SUB_TYPE"
AttributeType<String> attribute = new StringType();
attribute.setName("TYPE");
attribute.getConstraints().setRequired(true);
AttributeType<String> attribute2 = new StringType();
attribute2.getConstraints().setRequired(true);
attribute2.setName("SUB_TYPE");

List<AttributeType<?>> attributes = new ArrayList<>();
Expand All @@ -74,8 +76,10 @@ public void setUp() throws NoSuchAuthorityCodeException, FactoryException {
attribute.setName("ID");
AttributeType<String> attribute2 = new StringType();
attribute2.setName("VALUE");
attribute2.getConstraints().setRequired(true);
AttributeType<String> attribute3 = new StringType();
attribute3.setName("SUB_VALUE");
attribute3.getConstraints().setRequired(false);

List<AttributeType<?>> attributes = new ArrayList<>();
attributes.add(attribute);
Expand Down Expand Up @@ -187,4 +191,64 @@ public void testNotValid() throws Exception {

}

@Test
public void testNullValueNotValid() throws Exception {
// creates an empty database
File path = new File(folder.getRoot(), "document_database.db");
Database database = new Database(path);

// add the table TEST into the database
database.query("CREATE TABLE MY_TABLE(__id TEXT, __file TEXT, id TEXT, value TEXT, sub_value TEXT);");
database.query("INSERT INTO MY_TABLE(id, value, sub_value) VALUES ('id1', 'type1', 'sub_type1');");
database.query("INSERT INTO MY_TABLE(id, value, sub_value) VALUES ('id2', 'type1', 'sub_type2');");
database.query("INSERT INTO MY_TABLE(id, value, sub_value) VALUES ('id3', 'type2', 'sub_type1');");
database.query("INSERT INTO MY_TABLE(id, value, sub_value) VALUES ('id4', 'type2', null);");
database.query("INSERT INTO MY_TABLE(id, value, sub_value) VALUES ('id4', 'type2', 'sub_type5');");
database.query("INSERT INTO MY_TABLE(id, value, sub_value) VALUES ('id4', null, 'sub_type5');");

// add the table RELATION into the database
database.query("CREATE TABLE MY_REFERENCE(__id TEXT, __file TEXT, type TEXT, sub_type TEXT);");
database.query("INSERT INTO MY_REFERENCE(type, sub_type) VALUES ('type1', 'sub_type1');");
database.query("INSERT INTO MY_REFERENCE(type, sub_type) VALUES ('type1', 'sub_type2');");
database.query("INSERT INTO MY_REFERENCE(type, sub_type) VALUES ('type2', 'sub_type5');");

// check that the validator doesn't send any error
ForeignKeyValidator validator = new ForeignKeyValidator();
validator.validate(context, database);

Assert.assertEquals(2, reportBuilder.getErrorsByCode(CoreErrorCodes.TABLE_FOREIGN_KEY_NOT_FOUND).size());

List<ValidatorError> errors = reportBuilder.getErrorsByCode(CoreErrorCodes.TABLE_FOREIGN_KEY_NOT_FOUND);
int index = 0;
// check first error
{
ValidatorError error = errors.get(index++);
assertEquals("--", error.getAttribute());
assertEquals(null, error.getId());
assertEquals("", error.getFeatureId());
assertEquals("MY_TABLE", error.getFileModel());
assertEquals(ErrorScope.FEATURE, error.getScope());
assertEquals(
"La correspondance (VALUE, SUB_VALUE) = (type2, sub_type1) n'est pas autorisée, car non présente dans la liste de référence MY_REFERENCE.",
error.getMessage()
);
assertEquals("SAMPLE_MODEL", error.getDocumentModel());
}

{
ValidatorError error = errors.get(index++);
assertEquals("--", error.getAttribute());
assertEquals(null, error.getId());
assertEquals("", error.getFeatureId());
assertEquals("MY_TABLE", error.getFileModel());
assertEquals(ErrorScope.FEATURE, error.getScope());
assertEquals(
"La correspondance (VALUE, SUB_VALUE) = (null, sub_type5) n'est pas autorisée, car non présente dans la liste de référence MY_REFERENCE.",
error.getMessage()
);
assertEquals("SAMPLE_MODEL", error.getDocumentModel());
}

}

}

0 comments on commit c8e3fcc

Please sign in to comment.