Skip to content

Commit

Permalink
BUGFIX: dynamisch bepalen join columns voor segment tabel (#833)
Browse files Browse the repository at this point in the history
* BUGFIX: dynamisch bepalen join columns voor segment tabel

* DHUB-2734: fix small format issues

* DHUB-2734: fix sonar issues
  • Loading branch information
ahup committed Apr 28, 2023
1 parent e6845cf commit 8ec0dfd
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static java.util.function.Function.identity;
import static java.util.function.Predicate.not;
import static org.dotwebstack.framework.backend.postgres.helpers.PostgresSpatialHelper.getSegmentsTableName;
import static org.dotwebstack.framework.core.helpers.ExceptionHelper.illegalStateException;
import static org.dotwebstack.framework.core.helpers.ExceptionHelper.invalidConfigurationException;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
Expand Down Expand Up @@ -58,15 +60,41 @@ class PostgresSpatialBackendModule implements SpatialBackendModule<PostgresSpati
String.format("SELECT %s, %s, %s FROM geometry_columns where %s LIKE '%%__segments'", F_TABLE_SCHEMA,
F_TABLE_NAME, F_GEOMETRY_COLUMN, F_TABLE_NAME);

private static final String FOREIGNKEYS_SEGMENT_TABLE_STMT =
"SELECT DISTINCT kcu.column_name AS join_column_name, tc.table_schema, tc.constraint_name, tc.table_name, "
+ "ccu.table_schema AS foreign_table_schema, ccu.table_name AS foreign_table_name, "
+ "ccu.column_name AS referenced_column_name" + " FROM information_schema.table_constraints AS tc "
+ " JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name"
+ " AND tc.table_schema = kcu.table_schema"
+ " JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name"
+ " AND ccu.table_schema = tc.table_schema "
+ "WHERE kcu.column_name <> 'tile_id' AND tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='%s'";
static final String FOREIGNKEYS_SEGMENT_TABLE_STMT = """
WITH cte_fk_constraints
AS
( SELECT
unnest(con.conkey) AS "parent",
unnest(con.confkey) AS "child",
con.confrelid,
con.conrelid,
ns.nspname AS schema_name,
cl.relname AS table_name,
con.conname AS fk_name
FROM
pg_class cl
join pg_namespace ns on cl.relnamespace = ns.oid
join pg_constraint con on con.conrelid = cl.oid
WHERE
cl.relname = '%s'
AND con.contype = 'f'
)
SELECT
constr.schema_name,
constr.table_name,
constr.fk_name,
child.attname AS join_column_name,
cl.relname as referenced_table_name,
parent.attname AS referenced_column_name
FROM cte_fk_constraints constr
JOIN pg_attribute parent ON
parent.attrelid = constr.confrelid AND parent.attnum = constr.child
JOIN pg_class cl ON
cl.oid = constr.confrelid
JOIN pg_attribute child ON
child.attrelid = constr.conrelid AND child.attnum = constr.parent
""";

private final Map<String, GeometryMetadata> geoMetadataByTableColumn;

Expand All @@ -82,8 +110,7 @@ private Map<String, GeometryMetadata> getGeoMetadataByTableColumn(PostgresClient
return postgresClient.fetch(GEO_COLUMNS_STMT)
.map(row -> mapToGeoMetadata(row, segmentsTables))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
.onErrorContinue((e, i) -> LOG.warn("Retrieving geometry columns failed. Exception: {}", e.getMessage()))
.onErrorReturn(Map.of())
.onErrorMap(exception -> invalidConfigurationException("Retrieving geometry columns failed.", exception))
.block();
}

Expand All @@ -94,12 +121,13 @@ private Map<String, GeometrySegmentsTable> retrieveSegmentsTables(PostgresClient
var tableName = (String) row.get(F_TABLE_NAME);
var geoColumn = (String) row.get(F_GEOMETRY_COLUMN);
var joinColumns = getJoinColumns(tableName, postgresClient);

return joinColumns
.switchIfEmpty(Mono.error(illegalStateException("Empty join columns for segments table %s", tableName)))
.map(joinColumnList -> createSegmentsTable(schemaName, tableName, geoColumn, joinColumnList));
})
.collect(Collectors.toMap(GeometrySegmentsTable::getTableName, identity()))
.onErrorContinue((e, i) -> LOG.warn("Retrieving segments tables failed. Exception: {}", e.getMessage()))
.onErrorReturn(Map.of())
.onErrorMap(exception -> invalidConfigurationException(exception.getMessage()))
.block();
}

Expand Down Expand Up @@ -163,7 +191,8 @@ private Map.Entry<String, List<PostgresObjectField>> createAllFieldsPerTableName
var tableNames = objectType.getTable()
.split("\\.");
var table = tableNames[tableNames.length - 1];
return new AbstractMap.SimpleEntry<>(table, getFields(objectType));
var fields = getFields(objectType);
return new AbstractMap.SimpleEntry<>(table, fields);
}

private List<PostgresObjectField> getFields(PostgresObjectType objectType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.dotwebstack.framework.backend.postgres;

import static graphql.Assert.assertTrue;
import static org.dotwebstack.framework.backend.postgres.PostgresSpatialBackendModule.FOREIGNKEYS_SEGMENT_TABLE_STMT;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasEntry;
Expand All @@ -17,11 +19,13 @@
import org.dotwebstack.framework.backend.postgres.model.PostgresObjectField;
import org.dotwebstack.framework.backend.postgres.model.PostgresObjectType;
import org.dotwebstack.framework.backend.postgres.model.PostgresSpatialReferenceSystem;
import org.dotwebstack.framework.core.InvalidConfigurationException;
import org.dotwebstack.framework.core.model.ObjectField;
import org.dotwebstack.framework.core.model.ObjectType;
import org.dotwebstack.framework.core.model.Schema;
import org.dotwebstack.framework.ext.spatial.model.Spatial;
import org.dotwebstack.framework.ext.spatial.model.SpatialReferenceSystem;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
Expand All @@ -30,22 +34,19 @@
@ExtendWith(MockitoExtension.class)
class PostgresSpatialBackendModuleTest {

private static final String FOREIGNKEYS_SEGMENT_TABLE_STMT =
"SELECT DISTINCT kcu.column_name AS join_column_name, tc.table_schema, tc.constraint_name, tc.table_name, "
+ "ccu.table_schema AS foreign_table_schema, ccu.table_name AS foreign_table_name, "
+ "ccu.column_name AS referenced_column_name" + " FROM information_schema.table_constraints AS tc "
+ " JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name"
+ " AND tc.table_schema = kcu.table_schema"
+ " JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name"
+ " AND ccu.table_schema = tc.table_schema "
+ "WHERE kcu.column_name <> 'tile_id' AND tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='%s'";

@Test
void contructor_throwsNoException_onError() {
void contructor_throwsException_onError() {
var schema = mock(Schema.class);
var postgresClient = mockDatabaseCalls(Flux.error(new RuntimeException("Something went wrong.")));

assertDoesNotThrow(() -> new PostgresSpatialBackendModule(schema, postgresClient));
Exception exception = Assertions.assertThrows(InvalidConfigurationException.class, () -> {
new PostgresSpatialBackendModule(schema, postgresClient);
});

String expectedMessage = "Something went wrong.";
String actualMessage = exception.getMessage();

assertTrue(actualMessage.equals(expectedMessage));
}

@Test
Expand Down

0 comments on commit 8ec0dfd

Please sign in to comment.