From 62f65bf9acebece489730da8d660f35a45c62640 Mon Sep 17 00:00:00 2001 From: Mandy Chessell Date: Sat, 9 Nov 2024 21:02:24 +0000 Subject: [PATCH] Fixes to PostgreSQL Repository Connector for CTS Signed-off-by: Mandy Chessell --- ...geria-open-metadata-conformance-suite.http | 28 +- .../types/TestValidTypeDefEvent.java | 260 ++- .../resource/jdbc/JDBCResourceConnector.java | 318 ++-- .../resource/jdbc/ffdc/JDBCErrorCode.java | 12 +- .../configure-postgres-repository.http | 12 + .../postgres-cts-configure.http | 151 ++ .../postgres-cts-results.http | 57 + .../PostgresOMRSMetadataCollection.java | 78 +- .../PostgresOMRSMetadataStore.java | 6 +- .../database/DatabaseStore.java | 1442 +++++++++-------- .../database/QueryBuilder.java | 174 +- .../mappers/ClassificationMapper.java | 1 + .../mappers/EntityMapper.java | 4 +- .../mappers/RelationshipMapper.java | 1 - .../mappers/RepositoryMapper.java | 37 +- .../schema/RepositoryColumn.java | 2 +- .../schema/RepositoryTable.java | 16 - ...-repository-services-local-repository.http | 2 +- .../search/PropertyComparisonOperator.java | 7 +- .../OMRSRepositoryHelper.java | 15 + .../LocalOMRSMetadataCollection.java | 19 +- .../OMRSRepositoryContentHelper.java | 91 +- .../OMRSRepositoryContentValidator.java | 136 +- .../Egeria-glossary-manager-omvs.http | 47 +- 24 files changed, 1699 insertions(+), 1217 deletions(-) create mode 100644 open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/postgres-cts-configure.http create mode 100644 open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/postgres-cts-results.http diff --git a/open-metadata-conformance-suite/Egeria-open-metadata-conformance-suite.http b/open-metadata-conformance-suite/Egeria-open-metadata-conformance-suite.http index 2acd64de7b6..f0f93c19cbe 100644 --- a/open-metadata-conformance-suite/Egeria-open-metadata-conformance-suite.http +++ b/open-metadata-conformance-suite/Egeria-open-metadata-conformance-suite.http @@ -12,12 +12,6 @@ @cohort=ctsCohort -### -# group: Configuration -# @name Query cSuite server's configuration -# Query the current configuration of the conformance suite server. -GET {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ctsServer}}/configuration - ### # group: Configuration # @name Set cSuite server's user Id @@ -73,7 +67,9 @@ Content-Type: application/json { "class": "RepositoryConformanceWorkbenchConfig", - "tutRepositoryServerName": "{{tutServer}}" + "tutRepositoryServerName": "{{tutServer}}", + "maxSearchResults": 20, + "testEntityTypes": ["Asset"] } @@ -107,12 +103,17 @@ DELETE {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ # Remove all of the configuration for the open metadata conformance suite. DELETE {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ctsServer}}/conformance-suite-workbenches + + ### # group: Starting/Stopping CTS server -# @name Activate conformance suite using config +# @name Start conformance suite using config # Activate open metadata conformance suite services. POST {{baseURL}}/open-metadata/platform-services/users/{{adminUserId}}/server-platform/servers/{{ctsServer}}/instance + + + ### # group: Starting/Stopping CTS server # @name Deactivate conformance suite server @@ -153,4 +154,13 @@ GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{ad # group: Getting Results # @name Retrieve report of a specific test case # Retrieve the results of all failed test cases. -GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{adminUserId}}/report/test-cases/repository-entity-reference-copy-lifecycle-ConceptModelElement \ No newline at end of file +GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{adminUserId}}/report/test-cases/repository-entity-reference-copy-lifecycle-ConceptModelElement + + +### +# group: Configuration +# @name Query cSuite server's configuration +# Query the current configuration of the conformance suite server. +GET {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ctsServer}}/configuration + +### \ No newline at end of file diff --git a/open-metadata-conformance-suite/open-metadata-conformance-suite-server/src/main/java/org/odpi/openmetadata/conformance/tests/repository/types/TestValidTypeDefEvent.java b/open-metadata-conformance-suite/open-metadata-conformance-suite-server/src/main/java/org/odpi/openmetadata/conformance/tests/repository/types/TestValidTypeDefEvent.java index 7c8f79365e8..e44c09dfcdf 100644 --- a/open-metadata-conformance-suite/open-metadata-conformance-suite-server/src/main/java/org/odpi/openmetadata/conformance/tests/repository/types/TestValidTypeDefEvent.java +++ b/open-metadata-conformance-suite/open-metadata-conformance-suite-server/src/main/java/org/odpi/openmetadata/conformance/tests/repository/types/TestValidTypeDefEvent.java @@ -198,146 +198,142 @@ protected void run() throws Exception defaultProfileId, defaultRequirementId); - verifyCondition(((metadataCollectionId != null) && (metadataCollectionId.equals(repositoryConformanceWorkPad.getTutMetadataCollectionId()))), - assertion6, - assertionMsg6, - defaultProfileId, - defaultRequirementId); - - addDiscoveredProperty(metadataCollectionIdPropertyName, - originator.getMetadataCollectionId(), - defaultProfileId, - defaultRequirementId); - - serverName = originator.getServerName(); - - verifyCondition((serverName != null), - assertion7, - assertionMsg7, - defaultProfileId, - defaultRequirementId); - - verifyCondition(((serverName != null) && (serverName.equals(repositoryConformanceWorkPad.getTutServerName()))), - assertion8, - assertionMsg8, - defaultProfileId, - defaultRequirementId); - - addDiscoveredProperty(serverNamePropertyName, - serverName, - defaultProfileId, - defaultRequirementId); - - if (originator.getServerType() != null) + if ((metadataCollectionId != null) && (metadataCollectionId.equals(repositoryConformanceWorkPad.getTutMetadataCollectionId()))) { - addDiscoveredProperty(serverTypePropertyName, - originator.getServerType(), + /* + * Only check type events from the TUT. + */ + addDiscoveredProperty(metadataCollectionIdPropertyName, + originator.getMetadataCollectionId(), defaultProfileId, defaultRequirementId); - } - - if (originator.getOrganizationName() != null) - { - addDiscoveredProperty(orgNamePropertyName, - originator.getOrganizationName(), + serverName = originator.getServerName(); + verifyCondition((serverName != null), + assertion7, + assertionMsg7, + defaultProfileId, + defaultRequirementId); + verifyCondition(((serverName != null) && (serverName.equals(repositoryConformanceWorkPad.getTutServerName()))), + assertion8, + assertionMsg8, + defaultProfileId, + defaultRequirementId); + addDiscoveredProperty(serverNamePropertyName, + serverName, defaultProfileId, defaultRequirementId); - } - } - - if (eventType != null) - { - addDiscoveredProperty(eventTypePropertyName, - eventType.getName(), - defaultProfileId, - defaultRequirementId); - - typeDef = event.getTypeDef(); - attributeTypeDef = event.getAttributeTypeDef(); - - switch (eventType) - { - case NEW_TYPEDEF_EVENT: - case DELETED_TYPEDEF_EVENT: - case RE_IDENTIFIED_TYPEDEF_EVENT: - verifyCondition((typeDef != null), - assertion9, - assertionMsg9, - defaultProfileId, - defaultRequirementId); - verifyCondition((attributeTypeDef == null), - assertion10, - assertionMsg10, - defaultProfileId, - defaultRequirementId); - - if (typeDef != null) - { - addDiscoveredProperty(typeDefGUIDPropertyName, - typeDef.getGUID(), - defaultProfileId, - defaultRequirementId); - addDiscoveredProperty(typeDefNamePropertyName, - typeDef.getName(), - defaultProfileId, - defaultRequirementId); - } - break; - - case UPDATED_TYPEDEF_EVENT: - /* - * If this is a type update event then it does not have the (new) TypeDef available, - * so verify that the event contains the patch. - */ - TypeDefPatch typeDefPatch = event.getTypeDefPatch(); - verifyCondition((typeDefPatch != null), - assertion13, - assertionMsg13, - defaultProfileId, - defaultRequirementId); - verifyCondition((typeDef == null), - assertion9, - assertionMsg9, - defaultProfileId, - defaultRequirementId); - verifyCondition((attributeTypeDef == null), - assertion10, - assertionMsg10, - defaultProfileId, - defaultRequirementId); - break; - - case NEW_ATTRIBUTE_TYPEDEF_EVENT: - case DELETED_ATTRIBUTE_TYPEDEF_EVENT: - case RE_IDENTIFIED_ATTRIBUTE_TYPEDEF_EVENT: - verifyCondition((attributeTypeDef != null), - assertion11, - assertionMsg11, - defaultProfileId, - defaultRequirementId); - verifyCondition((typeDef == null), - assertion12, - assertionMsg12, - defaultProfileId, - defaultRequirementId); - - if (attributeTypeDef != null) + if (originator.getServerType() != null) + { + addDiscoveredProperty(serverTypePropertyName, + originator.getServerType(), + defaultProfileId, + defaultRequirementId); + } + + if (originator.getOrganizationName() != null) + { + addDiscoveredProperty(orgNamePropertyName, + originator.getOrganizationName(), + defaultProfileId, + defaultRequirementId); + } + + if (eventType != null) + { + addDiscoveredProperty(eventTypePropertyName, + eventType.getName(), + defaultProfileId, + defaultRequirementId); + + + typeDef = event.getTypeDef(); + attributeTypeDef = event.getAttributeTypeDef(); + + switch (eventType) { - addDiscoveredProperty(attributeTypeDefGUIDPropertyName, - attributeTypeDef.getGUID(), - defaultProfileId, - defaultRequirementId); - addDiscoveredProperty(attributeTypeDefNamePropertyName, - attributeTypeDef.getName(), - defaultProfileId, - defaultRequirementId); + case NEW_TYPEDEF_EVENT: + case DELETED_TYPEDEF_EVENT: + case RE_IDENTIFIED_TYPEDEF_EVENT: + verifyCondition((typeDef != null), + assertion9, + assertionMsg9, + defaultProfileId, + defaultRequirementId); + verifyCondition((attributeTypeDef == null), + assertion10, + assertionMsg10, + defaultProfileId, + defaultRequirementId); + + if (typeDef != null) + { + addDiscoveredProperty(typeDefGUIDPropertyName, + typeDef.getGUID(), + defaultProfileId, + defaultRequirementId); + addDiscoveredProperty(typeDefNamePropertyName, + typeDef.getName(), + defaultProfileId, + defaultRequirementId); + } + break; + + case UPDATED_TYPEDEF_EVENT: + /* + * If this is a type update event then it does not have the (new) TypeDef available, + * so verify that the event contains the patch. + */ + TypeDefPatch typeDefPatch = event.getTypeDefPatch(); + verifyCondition((typeDefPatch != null), + assertion13, + assertionMsg13, + defaultProfileId, + defaultRequirementId); + verifyCondition((typeDef == null), + assertion9, + assertionMsg9, + defaultProfileId, + defaultRequirementId); + verifyCondition((attributeTypeDef == null), + assertion10, + assertionMsg10, + defaultProfileId, + defaultRequirementId); + break; + + case NEW_ATTRIBUTE_TYPEDEF_EVENT: + case DELETED_ATTRIBUTE_TYPEDEF_EVENT: + case RE_IDENTIFIED_ATTRIBUTE_TYPEDEF_EVENT: + verifyCondition((attributeTypeDef != null), + assertion11, + assertionMsg11, + defaultProfileId, + defaultRequirementId); + verifyCondition((typeDef == null), + assertion12, + assertionMsg12, + defaultProfileId, + defaultRequirementId); + + if (attributeTypeDef != null) + { + addDiscoveredProperty(attributeTypeDefGUIDPropertyName, + attributeTypeDef.getGUID(), + defaultProfileId, + defaultRequirementId); + addDiscoveredProperty(attributeTypeDefNamePropertyName, + attributeTypeDef.getName(), + defaultProfileId, + defaultRequirementId); + } + break; + + case TYPEDEF_ERROR_EVENT: + + break; } - break; - - case TYPEDEF_ERROR_EVENT: - - break; + } } } diff --git a/open-metadata-implementation/adapters/open-connectors/data-store-connectors/jdbc-resource-connector/src/main/java/org/odpi/openmetadata/adapters/connectors/resource/jdbc/JDBCResourceConnector.java b/open-metadata-implementation/adapters/open-connectors/data-store-connectors/jdbc-resource-connector/src/main/java/org/odpi/openmetadata/adapters/connectors/resource/jdbc/JDBCResourceConnector.java index e74202273cd..3daef162f59 100644 --- a/open-metadata-implementation/adapters/open-connectors/data-store-connectors/jdbc-resource-connector/src/main/java/org/odpi/openmetadata/adapters/connectors/resource/jdbc/JDBCResourceConnector.java +++ b/open-metadata-implementation/adapters/open-connectors/data-store-connectors/jdbc-resource-connector/src/main/java/org/odpi/openmetadata/adapters/connectors/resource/jdbc/JDBCResourceConnector.java @@ -11,6 +11,7 @@ import org.odpi.openmetadata.frameworks.auditlog.ComponentDescription; import org.odpi.openmetadata.frameworks.connectors.ConnectorBase; import org.odpi.openmetadata.frameworks.connectors.ffdc.ConnectorCheckedException; +import org.odpi.openmetadata.frameworks.connectors.ffdc.PropertyServerException; import org.odpi.openmetadata.frameworks.connectors.properties.EndpointProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -202,9 +203,9 @@ public synchronized DataSource getDataSource() * Issue the supplied DDL statements. * * @param ddlStatements statements to execute - * @throws SQLException problem communicating with the database + * @throws PropertyServerException problem communicating with the database */ - public void addDatabaseDefinitions(List ddlStatements) throws SQLException + public void addDatabaseDefinitions(List ddlStatements) throws PropertyServerException { if ((ddlStatements != null) && (!ddlStatements.isEmpty())) { @@ -223,22 +224,37 @@ public void addDatabaseDefinitions(List ddlStatements) throws SQLExcept * Issue a SQL command that expects no results. * * @param sqlCommand command to issue - * @throws SQLException something went wrong + * @throws PropertyServerException something went wrong */ - public void issueSQLCommand(String sqlCommand) throws SQLException + public void issueSQLCommand(String sqlCommand) throws PropertyServerException { - if (jdbcConnection.isClosed()) + final String methodName = "issueSQLCommand"; + + try { - jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); - } + if (jdbcConnection.isClosed()) + { + jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); + } - log.debug(sqlCommand); + log.debug(sqlCommand); - PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); + PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); - preparedStatement.execute(); + preparedStatement.execute(); - preparedStatement.close(); + preparedStatement.close(); + } + catch (SQLException sqlException) + { + throw new PropertyServerException(JDBCErrorCode.UNEXPECTED_SQL_EXCEPTION.getMessageDefinition(jdbcDatabaseName, + sqlCommand, + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); + } } @@ -251,40 +267,55 @@ public void issueSQLCommand(String sqlCommand) throws SQLException * @param timestampColumnName name of the column with the timestamp * @param columnNameTypeMap map of resulting column names and values to include in the results * @return Map of column names to data values that represent the requested row - * @throws SQLException there was a problem calling the database + * @throws PropertyServerException there was a problem calling the database */ public Map getLatestRow(String tableName, String identifierColumnName, String identifierColumnValue, String timestampColumnName, - Map columnNameTypeMap) throws SQLException + Map columnNameTypeMap) throws PropertyServerException { + final String methodName = "getLatestRow"; + String sqlCommand = "SELECT * FROM " + tableName + " WHERE " + identifierColumnName + " = ? AND " + timestampColumnName + " = (SELECT MAX(" + timestampColumnName + ") FROM " + tableName + " WHERE " + identifierColumnName + " = ?)"; - if (jdbcConnection.isClosed()) + try { - jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); - } + if (jdbcConnection.isClosed()) + { + jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); + } - log.debug(sqlCommand); + log.debug(sqlCommand); - PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); + PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); - preparedStatement.setString(1, identifierColumnValue); - preparedStatement.setString(2, identifierColumnValue); + preparedStatement.setString(1, identifierColumnValue); + preparedStatement.setString(2, identifierColumnValue); - ResultSet resultSet = preparedStatement.executeQuery(); + ResultSet resultSet = preparedStatement.executeQuery(); - Map results = this.getRowFromResultSet(resultSet, columnNameTypeMap); + Map results = this.getRowFromResultSet(resultSet, columnNameTypeMap); - resultSet.close(); - preparedStatement.close(); + resultSet.close(); + preparedStatement.close(); - return results; + return results; + } + catch (SQLException sqlException) + { + throw new PropertyServerException(JDBCErrorCode.UNEXPECTED_SQL_EXCEPTION.getMessageDefinition(jdbcDatabaseName, + sqlCommand, + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); + } } @@ -295,31 +326,46 @@ public Map getLatestRow(String tableName, * @param whereClause condition describing how to match the desired columns * @param columnNameTypeMap map of resulting column names and values to include in the results * @return row consisting of column names to data values that represent the requested row - * @throws SQLException there was a problem calling the database + * @throws PropertyServerException there was a problem calling the database */ public Map getMatchingRow(String tableName, String whereClause, - Map columnNameTypeMap) throws SQLException + Map columnNameTypeMap) throws PropertyServerException { + final String methodName = "getMatchingRow"; + String sqlCommand = "SELECT * FROM " + tableName + " WHERE " + whereClause; - if (jdbcConnection.isClosed()) + try { - jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); - } + if (jdbcConnection.isClosed()) + { + jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); + } - log.debug(sqlCommand); + log.debug(sqlCommand); - PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); + PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); - ResultSet resultSet = preparedStatement.executeQuery(); + ResultSet resultSet = preparedStatement.executeQuery(); - Map results = this.getRowFromResultSet(resultSet, columnNameTypeMap); + Map results = this.getRowFromResultSet(resultSet, columnNameTypeMap); - resultSet.close(); - preparedStatement.close(); + resultSet.close(); + preparedStatement.close(); - return results; + return results; + } + catch (SQLException sqlException) + { + throw new PropertyServerException(JDBCErrorCode.UNEXPECTED_SQL_EXCEPTION.getMessageDefinition(jdbcDatabaseName, + sqlCommand, + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); + } } @@ -330,31 +376,46 @@ public Map getMatchingRow(String tableName, * @param whereClause condition describing how to match the desired columns * @param columnNameTypeMap map of resulting column names and values to include in the results * @return list of rows consisting of column names to data values that represent the requested row - * @throws SQLException there was a problem calling the database + * @throws PropertyServerException there was a problem calling the database */ public List> getMatchingRows(String tableName, String whereClause, - Map columnNameTypeMap) throws SQLException + Map columnNameTypeMap) throws PropertyServerException { + final String methodName = "getMatchingRows"; + String sqlCommand = "SELECT * FROM " + tableName + " WHERE " + whereClause; - if (jdbcConnection.isClosed()) + try { - jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); - } + if (jdbcConnection.isClosed()) + { + jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); + } - log.debug(sqlCommand); + log.debug(sqlCommand); - PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); + PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); - ResultSet resultSet = preparedStatement.executeQuery(); + ResultSet resultSet = preparedStatement.executeQuery(); - List> results = this.getRowsFromResultSet(resultSet, columnNameTypeMap); + List> results = this.getRowsFromResultSet(resultSet, columnNameTypeMap); - resultSet.close(); - preparedStatement.close(); + resultSet.close(); + preparedStatement.close(); - return results; + return results; + } + catch (SQLException sqlException) + { + throw new PropertyServerException(JDBCErrorCode.UNEXPECTED_SQL_EXCEPTION.getMessageDefinition(jdbcDatabaseName, + sqlCommand, + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); + } } @@ -364,28 +425,43 @@ public List> getMatchingRows(String tab * @param sqlCommand condition describing how to match the desired columns * @param columnNameTypeMap map of resulting column names and values to include in the results * @return list of rows consisting of column names to data values that represent the requested row - * @throws SQLException there was a problem calling the database + * @throws PropertyServerException there was a problem calling the database */ public List> getMatchingRows(String sqlCommand, - Map columnNameTypeMap) throws SQLException + Map columnNameTypeMap) throws PropertyServerException { - if (jdbcConnection.isClosed()) + final String methodName = "getMatchingRows"; + + try { - jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); - } + if (jdbcConnection.isClosed()) + { + jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); + } - log.debug(sqlCommand); + log.debug(sqlCommand); - PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); + PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); - ResultSet resultSet = preparedStatement.executeQuery(); + ResultSet resultSet = preparedStatement.executeQuery(); - List> results = this.getRowsFromResultSet(resultSet, columnNameTypeMap); + List> results = this.getRowsFromResultSet(resultSet, columnNameTypeMap); - resultSet.close(); - preparedStatement.close(); + resultSet.close(); + preparedStatement.close(); - return results; + return results; + } + catch (SQLException sqlException) + { + throw new PropertyServerException(JDBCErrorCode.UNEXPECTED_SQL_EXCEPTION.getMessageDefinition(jdbcDatabaseName, + sqlCommand, + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); + } } @@ -395,30 +471,45 @@ public List> getMatchingRows(String sql * @param tableName name of the table to query * @param columnNameTypeMap map of resulting column names and values to include in the results * @return list of rows consisting of column names to data values that represent the requested row - * @throws SQLException there was a problem calling the database + * @throws PropertyServerException there was a problem calling the database */ public List> getRows(String tableName, - Map columnNameTypeMap) throws SQLException + Map columnNameTypeMap) throws PropertyServerException { + final String methodName = "geRows"; + String sqlCommand = "SELECT * FROM " + tableName; - if (jdbcConnection.isClosed()) + try { - jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); - } + if (jdbcConnection.isClosed()) + { + jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); + } - log.debug(sqlCommand); + log.debug(sqlCommand); - PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); + PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); - ResultSet resultSet = preparedStatement.executeQuery(); + ResultSet resultSet = preparedStatement.executeQuery(); - List> results = this.getRowsFromResultSet(resultSet, columnNameTypeMap); + List> results = this.getRowsFromResultSet(resultSet, columnNameTypeMap); - resultSet.close(); - preparedStatement.close(); + resultSet.close(); + preparedStatement.close(); - return results; + return results; + } + catch (SQLException sqlException) + { + throw new PropertyServerException(JDBCErrorCode.UNEXPECTED_SQL_EXCEPTION.getMessageDefinition(jdbcDatabaseName, + sqlCommand, + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); + } } @@ -528,57 +619,70 @@ private List> getRowsFromResultSet(ResultSet * * @param tableName name of the table where the row is to be added * @param columnNameValueMap column names, values and types - * @throws SQLException problem executing the command + * @throws PropertyServerException problem executing the command */ public void insertRowIntoTable(String tableName, - Map columnNameValueMap) throws SQLException + Map columnNameValueMap) throws PropertyServerException { final String methodName = "insertRowIntoTable"; String sqlCommand = "INSERT INTO " + tableName + this.getInsertColumnList(columnNameValueMap) + " ON CONFLICT DO NOTHING"; - if (jdbcConnection.isClosed()) + try { - jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); - } - - log.debug(sqlCommand); + if (jdbcConnection.isClosed()) + { + jdbcConnection = DriverManager.getConnection(jdbcDatabaseURL); + } - PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); + log.debug(sqlCommand); - int parameterIndex = 1; - for (String columnName : columnNameValueMap.keySet()) - { - JDBCDataValue jdbcDataValue = columnNameValueMap.get(columnName); + PreparedStatement preparedStatement = jdbcConnection.prepareStatement(sqlCommand); - if (jdbcDataValue.getScaleOrLength() == 0) + int parameterIndex = 1; + for (String columnName : columnNameValueMap.keySet()) { - preparedStatement.setObject(parameterIndex, - jdbcDataValue.getDataValue(), - jdbcDataValue.getTargetSQLType()); + JDBCDataValue jdbcDataValue = columnNameValueMap.get(columnName); + + if (jdbcDataValue.getScaleOrLength() == 0) + { + preparedStatement.setObject(parameterIndex, + jdbcDataValue.getDataValue(), + jdbcDataValue.getTargetSQLType()); + } + else + { + preparedStatement.setObject(parameterIndex, + jdbcDataValue.getDataValue(), + jdbcDataValue.getTargetSQLType(), + jdbcDataValue.getScaleOrLength()); + } + + parameterIndex++; } - else + + int rowsInserted = preparedStatement.executeUpdate(); + + if ((rowsInserted > 1) && (auditLog != null)) { - preparedStatement.setObject(parameterIndex, - jdbcDataValue.getDataValue(), - jdbcDataValue.getTargetSQLType(), - jdbcDataValue.getScaleOrLength()); + auditLog.logMessage(methodName, + JDBCAuditCode.UNEXPECTED_ROW_COUNT_FROM_DATABASE.getMessageDefinition(jdbcDatabaseName, + Integer.toString(rowsInserted), + sqlCommand)); } - parameterIndex++; + preparedStatement.close(); } - - int rowsInserted = preparedStatement.executeUpdate(); - - if ((rowsInserted > 1) && (auditLog != null)) + catch (SQLException sqlException) { - auditLog.logMessage(methodName, - JDBCAuditCode.UNEXPECTED_ROW_COUNT_FROM_DATABASE.getMessageDefinition(jdbcDatabaseName, - Integer.toString(rowsInserted), - sqlCommand)); + throw new PropertyServerException(JDBCErrorCode.UNEXPECTED_SQL_EXCEPTION.getMessageDefinition(jdbcDatabaseName, + sqlCommand, + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); } - - preparedStatement.close(); } @@ -587,10 +691,10 @@ public void insertRowIntoTable(String tableName, * * @param tableName name of the table where the row is to be added * @param rows list of column names, values and types - * @throws SQLException problem executing the command + * @throws PropertyServerException problem executing the command */ public void insertRowsIntoTable(String tableName, - List> rows) throws SQLException + List> rows) throws PropertyServerException { if (rows != null) { diff --git a/open-metadata-implementation/adapters/open-connectors/data-store-connectors/jdbc-resource-connector/src/main/java/org/odpi/openmetadata/adapters/connectors/resource/jdbc/ffdc/JDBCErrorCode.java b/open-metadata-implementation/adapters/open-connectors/data-store-connectors/jdbc-resource-connector/src/main/java/org/odpi/openmetadata/adapters/connectors/resource/jdbc/ffdc/JDBCErrorCode.java index c388c375f92..25baef85900 100644 --- a/open-metadata-implementation/adapters/open-connectors/data-store-connectors/jdbc-resource-connector/src/main/java/org/odpi/openmetadata/adapters/connectors/resource/jdbc/ffdc/JDBCErrorCode.java +++ b/open-metadata-implementation/adapters/open-connectors/data-store-connectors/jdbc-resource-connector/src/main/java/org/odpi/openmetadata/adapters/connectors/resource/jdbc/ffdc/JDBCErrorCode.java @@ -56,7 +56,17 @@ public enum JDBCErrorCode implements ExceptionMessageSet "The JDBC resource connector detected a missing value for column {0} during method {1} in mapper {2}", "The connector is unable to process the current request because of a missing value in the database.", "Investigate the contents of the database and the SQL requests used to populate it."), - ; ; + + + /** + * JDBC-RESOURCE-CONNECTOR-500-003 - The JDBC resource connector for database {0} received an unexpected SQL exception from request '{1}' during method {2}; the error message was: {4} + */ + UNEXPECTED_SQL_EXCEPTION(500, "JDBC-RESOURCE-CONNECTOR-500-003", + "The JDBC resource connector for database {0} received an unexpected SQL exception from request '{1}' during method {2}; the error message was: {4}", + "The connector is unable to process the current request because the database returned an unexpected error.", + "Use the details from the SQL error message and the SQL request to determine the cause of the error and retry the request once it is resolved."), + + ; private final int httpErrorCode; private final String errorMessageId; diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/configure-postgres-repository.http b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/configure-postgres-repository.http index b0ae143f991..dfd573b5d63 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/configure-postgres-repository.http +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/configure-postgres-repository.http @@ -116,6 +116,17 @@ POST {{baseURL}}/open-metadata/platform-services/users/{{adminUserId}}/server-pl +### +# @name Load open metadata archive file +# Load a file that contains open metadata types and instances. +POST {{baseURL}}/open-metadata/server-operations/users/{{adminUserId}}/servers/postgres-metadata-store/instance/open-metadata-archives/file +Content-Type: text/plain + +content-packs/SimpleCatalogV1.omarchive + + + + ### # @name Load open metadata archive file # Load a file that contains open metadata types and instances. @@ -126,6 +137,7 @@ content-packs/SimpleCatalogV2.omarchive + ### # @name Load open metadata archive file # Load a file that contains open metadata types and instances. diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/postgres-cts-configure.http b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/postgres-cts-configure.http new file mode 100644 index 00000000000..f026fd545b6 --- /dev/null +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/postgres-cts-configure.http @@ -0,0 +1,151 @@ +# +# These commands rebuild the sample configuration documents for postgres-metadata-server +# They use IntelliJ's HTTP Client. +# +@baseURL=https://localhost:9443 +@adminUserId=garygeeke +@auditLogTopic=logging +@localMatadataCollectionId=3fe67e5a-28eb-42bb-910c-600c3a8d6fb2 + +@ctsServer=ctsServer +@ctsUserId=cts +@ctsPassword=secret + +@tutServer=postgres-metadata-store +@tutPlatformURLroot=https://localhost:9443 + +@cohort=ctsCohort + + +### +# @name Set cSuite server's user Id +# Set up the user Id that this server should use on open metadata requests. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ctsServer}}/server-user-id? + id={{ctsUserId}} + +### +# @name Set up event bus to connect to cohort topics +# Set up the common properties needed to call your event bus. These properties are passed in the request body. +# This request just sets up the defaults that will be incorporated into any future configuration that includes an event bus topic. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ctsServer}}/event-bus +Content-Type: application/json + + +{ +"producer": +{ +"bootstrap.servers":"{{kafkaEndpoint}}" +}, +"consumer": +{ +"bootstrap.servers":"{{kafkaEndpoint}}" +} +} + +### +# @name Enable access to the cohort (CTS Server) +# Request registration to a cohort. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ctsServer}}/cohorts/{{cohort}} + +### +# @name Configure the test of an open metadata repository +# Activate the repository workbench tests to validate the behaviour of a specific repository. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ctsServer}}/conformance-suite-workbenches/repository-workbench/repositories +Content-Type: application/json + +{ + "class": "RepositoryConformanceWorkbenchConfig", + "tutRepositoryServerName": "{{tutServer}}", + "maxSearchResults": 20, + "testEntityTypes": ["Asset"] +} + + +### +# @name Configure the test of an open metadata server platform +# Activate the repository workbench tests to validate the behaviour of a specific server platform. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{ctsServer}}/conformance-suite-workbenches/platform-workbench/platforms +Content-Type: application/json + +{ + "urlRoot": "{{tutPlatformURLroot}}" +} + + +### +# @name Start conformance suite using config +# Activate open metadata conformance suite services. +POST {{baseURL}}/open-metadata/platform-services/users/{{adminUserId}}/server-platform/servers/{{ctsServer}}/instance + + + +### +# --------------------------------------------- +# Metadata Assess Store: TUT +# +### +# Set up the user Id that this server should use on open metadata requests when it is processing events (and consequently there is no end user id to use). +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{tutServer}}/server-user-id?id=tutnpa + +### +# Set up the description of this server. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{tutServer}}/server-description +Content-Type: text/plain + +A metadata store that uses a postgreSQL-backed repository + + +### +# @name Enable the PostgreSQL Repository +# Set up the local repository to use the PostgreSQL Repository implementation. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{tutServer}}/local-repository/mode/postgres-repository +Content-Type: application/json + +{ + "databaseURL": "{{postgreSQLDatabaseURL}}?currentSchema=repository_postgres_metadata_store", + "databaseSchema": "repository_postgres_metadata_store", + "secretsStore": "{{secretsStore}}", + "secretsCollectionName": "{{postgreSQLServerCollectionName}}" +} + +### +# @name Set local metadata collection id +# Set up a human friendly name for the collection of metadata that originates from this metadata server. This name is used in events and messages to help people diagnose problems in the cohort. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{tutServer}}/local-repository/metadata-collection-id +Content-Type: text/plain + +{{localMatadataCollectionId}} + + +### +# Set up the common properties needed to call your event bus. The value of {{kafkaEndpoint}} is resolved in the +# application.properties file using the `platform.placeholder.variables` property. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{tutServer}}/event-bus +Content-Type: application/json + +{ +"producer": +{ +"bootstrap.servers":"{{kafkaEndpoint}}" +}, +"consumer": +{ +"bootstrap.servers":"{{kafkaEndpoint}}" +} +} + + +### +# @name Enable access to the cohort (TUT Server) +# Request registration to a cohort. +POST {{baseURL}}/open-metadata/admin-services/users/{{adminUserId}}/servers/{{tutServer}}/cohorts/{{cohort}} + + +### +# @name start server +# Restart the postgres-metadata-store server on the OMAG Server Platform. +POST {{baseURL}}/open-metadata/platform-services/users/{{adminUserId}}/server-platform/servers/{{tutServer}}/instance + + +### + diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/postgres-cts-results.http b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/postgres-cts-results.http new file mode 100644 index 00000000000..c8a4d8d7e8a --- /dev/null +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/postgres-cts-results.http @@ -0,0 +1,57 @@ +# +# These commands rebuild the sample configuration documents for postgres-metadata-server +# They use IntelliJ's HTTP Client. +# +@baseURL=https://localhost:9443 +@adminUserId=garygeeke +@auditLogTopic=logging +@localMatadataCollectionId=3fe67e5a-28eb-42bb-910c-600c3a8d6fb2 + +@ctsServer=ctsServer +@ctsUserId=cts +@ctsPassword=secret + +@tutServer=postgres-metadata-store +@tutPlatformURLroot=https://localhost:9443 + +@cohort=ctsCohort + + +### +# group: Getting Results +# @name Retrieve platform workbench results +# Retrieve the results from the platform workbench tests. +GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{adminUserId}}/report/workbenches/platform-workbench + +### +# group: Getting Results +# @name Retrieve repository workbench results +# Retrieve the results from the repository workbench tests. +GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{adminUserId}}/report/workbenches/repository-workbench + +### +# group: Getting Results +# @name Retrieve full report of results +# Retrieve all of the results of the conformance suite testing. +GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{adminUserId}}/report + +### +# group: Getting Results +# @name Retrieve summary report of results +# Retrieve all of the results of the conformance suite testing. +GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{adminUserId}}/report/summary + +### +# group: Getting Results +# @name Retrieve report of failed test cases +# Retrieve the results of all failed test cases. +GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{adminUserId}}/report/test-cases/failed + +### +# group: Getting Results +# @name Retrieve report of a specific test case +# Retrieve the results of all failed test cases. +GET {{baseURL}}/servers/{{ctsServer}}/open-metadata/conformance-suite/users/{{adminUserId}}/report/test-cases/repository-entity-reference-copy-lifecycle-ConceptModelElement + +### + diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/PostgresOMRSMetadataCollection.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/PostgresOMRSMetadataCollection.java index bca39d17548..c4fc6639aec 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/PostgresOMRSMetadataCollection.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/PostgresOMRSMetadataCollection.java @@ -144,7 +144,7 @@ public EntitySummary getEntitySummary(String userId, /* * Perform operation */ - EntitySummary entity = repositoryStore.getEntitySummary(guid, null); + EntitySummary entity = repositoryStore.getEntitySummary(guid); repositoryValidator.validateEntityFromStore(repositoryName, guid, entity, methodName); repositoryValidator.validateEntityIsNotDeleted(repositoryName, entity, methodName); @@ -325,25 +325,14 @@ public List getRelationshipsForEntity(String u repositoryValidator.validateEntityFromStore(repositoryName, entityGUID, entity, methodName); repositoryValidator.validateEntityIsNotDeleted(repositoryName, entity, methodName); - List entityRelationships = repositoryStore.getRelationshipsForEntity(entityGUID, - relationshipTypeGUID, - fromRelationshipElement, - limitResultsByStatus, - asOfTime, - sequencingProperty, - sequencingOrder, - pageSize); - - if ((entityRelationships == null) || (entityRelationships.isEmpty())) - { - return null; - } - - return repositoryHelper.formatRelationshipResults(entityRelationships, - fromRelationshipElement, - sequencingProperty, - sequencingOrder, - pageSize); + return repositoryStore.getRelationshipsForEntity(entityGUID, + relationshipTypeGUID, + fromRelationshipElement, + limitResultsByStatus, + asOfTime, + sequencingProperty, + sequencingOrder, + pageSize); } @@ -418,9 +407,7 @@ public List findEntitiesByProperty(String userI /* * Perform operation */ - List foundEntities = repositoryStore.findEntitiesByProperty(entityTypeGUID, matchProperties, matchCriteria, fromEntityElement, limitResultsByStatus, limitResultsByClassification, asOfTime, sequencingProperty, sequencingOrder, pageSize); - - return repositoryHelper.formatEntityResults(foundEntities, fromEntityElement, sequencingProperty, sequencingOrder, pageSize); + return repositoryStore.findEntitiesByProperty(entityTypeGUID, matchProperties, matchCriteria, fromEntityElement, limitResultsByStatus, limitResultsByClassification, asOfTime, sequencingProperty, sequencingOrder, pageSize); } @@ -493,9 +480,7 @@ public List findEntities(String userId, /* * Perform operation */ - List foundEntities = repositoryStore.findEntities(entityTypeGUID, entitySubtypeGUIDs, matchProperties, fromEntityElement, limitResultsByStatus, matchClassifications, asOfTime, sequencingProperty, sequencingOrder, pageSize); - - return repositoryHelper.formatEntityResults(foundEntities, fromEntityElement, sequencingProperty, sequencingOrder, pageSize); + return repositoryStore.findEntities(entityTypeGUID, entitySubtypeGUIDs, matchProperties, fromEntityElement, limitResultsByStatus, matchClassifications, asOfTime, sequencingProperty, sequencingOrder, pageSize); } @@ -573,9 +558,7 @@ public List findEntitiesByClassification(String /* * Perform operation */ - List foundEntities = repositoryStore.findEntitiesByClassification(entityTypeGUID, classificationName, matchClassificationProperties, matchCriteria, fromEntityElement, limitResultsByStatus, asOfTime, sequencingProperty, sequencingOrder, pageSize); - - return repositoryHelper.formatEntityResults(foundEntities, fromEntityElement, sequencingProperty, sequencingOrder, pageSize); + return repositoryStore.findEntitiesByClassification(entityTypeGUID, classificationName, matchClassificationProperties, matchCriteria, fromEntityElement, limitResultsByStatus, asOfTime, sequencingProperty, sequencingOrder, pageSize); } @@ -648,13 +631,8 @@ public List findEntitiesByPropertyValue(String use /* * Process operation - * - * This is a brute force implementation of locating in entity since it iterates through all - * the stored entities. */ - List foundEntities = repositoryStore.findEntitiesByPropertyValue(entityTypeGUID, searchCriteria, fromEntityElement, limitResultsByStatus, limitResultsByClassification, asOfTime, sequencingProperty, sequencingOrder, pageSize); - - return repositoryHelper.formatEntityResults(foundEntities, fromEntityElement, sequencingProperty, sequencingOrder, pageSize); + return repositoryStore.findEntitiesByPropertyValue(entityTypeGUID, searchCriteria, fromEntityElement, limitResultsByStatus, limitResultsByClassification, asOfTime, sequencingProperty, sequencingOrder, pageSize); } @@ -917,13 +895,7 @@ public List findRelationships(String userId, /* * Perform operation */ - List foundRelationships = repositoryStore.findRelationships(relationshipTypeGUID, relationshipSubtypeGUIDs, matchProperties, fromRelationshipElement, limitResultsByStatus, asOfTime, sequencingProperty, sequencingOrder, pageSize); - - return repositoryHelper.formatRelationshipResults(foundRelationships, - fromRelationshipElement, - sequencingProperty, - sequencingOrder, - pageSize); + return repositoryStore.findRelationships(relationshipTypeGUID, relationshipSubtypeGUIDs, matchProperties, fromRelationshipElement, limitResultsByStatus, asOfTime, sequencingProperty, sequencingOrder, pageSize); } @@ -998,17 +970,8 @@ public List findRelationshipsByProperty(String /* * Perform operation - * - * This is a brute force implementation of locating a relationship since it iterates through all - * the stored entities. */ - List foundRelationships = repositoryStore.findRelationshipsByProperty(relationshipTypeGUID, matchProperties, matchCriteria, fromRelationshipElement, limitResultsByStatus, asOfTime, sequencingProperty, sequencingOrder, pageSize); - - return repositoryHelper.formatRelationshipResults(foundRelationships, - fromRelationshipElement, - sequencingProperty, - sequencingOrder, - pageSize); + return repositoryStore.findRelationshipsByProperty(relationshipTypeGUID, matchProperties, matchCriteria, fromRelationshipElement, limitResultsByStatus, asOfTime, sequencingProperty, sequencingOrder, pageSize); } @@ -1077,17 +1040,8 @@ public List findRelationshipsByPropertyValue(String /* * Perform operation - * - * This is a brute force implementation of locating a relationship since it iterates through all - * the stored relationships. */ - List foundRelationships = repositoryStore.findRelationshipsByPropertyValue(relationshipTypeGUID, searchCriteria, fromRelationshipElement, limitResultsByStatus, asOfTime, sequencingProperty, sequencingOrder, pageSize); - - return repositoryHelper.formatRelationshipResults(foundRelationships, - fromRelationshipElement, - sequencingProperty, - sequencingOrder, - pageSize); + return repositoryStore.findRelationshipsByPropertyValue(relationshipTypeGUID, searchCriteria, fromRelationshipElement, limitResultsByStatus, asOfTime, sequencingProperty, sequencingOrder, pageSize); } diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/PostgresOMRSMetadataStore.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/PostgresOMRSMetadataStore.java index 627ca7859c5..f33676be13a 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/PostgresOMRSMetadataStore.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/PostgresOMRSMetadataStore.java @@ -140,10 +140,10 @@ private Date getAsOfTime(Date suppliedAsOfTime) * @return entity object * @throws RepositoryErrorException problem forming entity proxy */ - synchronized EntitySummary getEntitySummary(String guid, Date asOfTime) throws RepositoryErrorException + EntitySummary getEntitySummary(String guid) throws RepositoryErrorException { DatabaseStore databaseStore = new DatabaseStore(jdbcResourceConnector, repositoryName, repositoryHelper); - EntityMapper storedEntity = databaseStore.getEntityFromStore(guid, getAsOfTime(asOfTime)); + EntityMapper storedEntity = databaseStore.getEntityFromStore(guid, getAsOfTime(null)); if (storedEntity != null) { @@ -566,7 +566,7 @@ List getRelationshipsForEntity(String entityGU DatabaseStore databaseStore = new DatabaseStore(jdbcResourceConnector, repositoryName, repositoryHelper); - List storedRelationships = databaseStore.retrieveRelationships(queryBuilder.getAsOfTimeWhereClause(), getAsOfTime(asOfTime)); + List storedRelationships = databaseStore.retrieveRelationships(queryBuilder, getAsOfTime(asOfTime)); return getRelationshipsFromMappers(storedRelationships); } diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/database/DatabaseStore.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/database/DatabaseStore.java index bf442bc8092..47e4d6d3809 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/database/DatabaseStore.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/database/DatabaseStore.java @@ -11,6 +11,7 @@ import org.odpi.openmetadata.adapters.repositoryservices.postgres.repositoryconnector.mappers.*; import org.odpi.openmetadata.adapters.repositoryservices.postgres.repositoryconnector.schema.RepositoryColumn; import org.odpi.openmetadata.adapters.repositoryservices.postgres.repositoryconnector.schema.RepositoryTable; +import org.odpi.openmetadata.frameworks.connectors.ffdc.PropertyServerException; import org.odpi.openmetadata.repositoryservices.connectors.stores.metadatacollectionstore.repositoryconnector.OMRSRepositoryHelper; import org.odpi.openmetadata.repositoryservices.ffdc.exception.RepositoryErrorException; @@ -70,7 +71,7 @@ public ControlMapper getControlTable() throws RepositoryErrorException return new ControlMapper(repositoryName, controlTable); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -99,7 +100,7 @@ public void saveControlTable(ControlMapper controlMapper) throws RepositoryError jdbcResourceConnector.insertRowIntoTable(RepositoryTable.CONTROL.getTableName(), controlMapper.getControlTableRow()); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -127,28 +128,62 @@ public EntityMapper getEntityForUpdate(String guid) throws RepositoryErrorExcept /** - * Retrieve the version of an entity from the database that was active at the requested time. - * Null is returned if there were no active instance. + * Retrieve a relationship from the database. * - * @param guid unique identifier of the entity - * @param asOfTime requested time for the version - * @return entity mapper + * @param guid unique identifier of the relationship + * @return Relationship mapper * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - public EntityMapper getEntityFromStore(String guid, - Date asOfTime) throws RepositoryErrorException + public RelationshipMapper getRelationshipForUpdate(String guid) throws RepositoryErrorException { - final String methodName = "getEntityFromStore"; + return getRelationshipFromStore(guid, null); + } + + + /** + * Retrieve details about an entity from the store. The entity mapper is returned to allow the caller to choose + * what style of entity to return. + * + * @param entityGUID unique identifier of the entity + * @param classificationName name of classification + * @return classification mapper containing all that is known about the latest version of the classification + * @throws RepositoryErrorException either a problem accessing the database or a mapping problem with the contents retrieved + */ + public ClassificationMapper getClassificationForUpdate(String entityGUID, + String classificationName) throws RepositoryErrorException + { + final String methodName = "getClassificationForUpdate"; try { - Map entityRow = jdbcResourceConnector.getMatchingRow(RepositoryTable.ENTITY.getTableName(), - RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "'" + getAsOfTimeClause(asOfTime), - RepositoryTable.ENTITY.getColumnNameTypeMap()); + Map classificationRow = jdbcResourceConnector.getMatchingRow(RepositoryTable.CLASSIFICATION.getTableName(), + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + entityGUID + + "' and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + "'" + + getAsOfTimeClause(null), + RepositoryTable.CLASSIFICATION.getColumnNameTypeMap()); - return this.getCompleteEntityFromStore(guid, entityRow); + if (classificationRow != null) + { + BaseMapper baseMapper = new BaseMapper(repositoryName); + + long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), classificationRow, true); + + String whereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + entityGUID + + "' and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + + "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + version; + + + List> classificationProperties = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName(), + whereClause, + RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getColumnNameTypeMap()); + return new ClassificationMapper(classificationRow, classificationProperties, repositoryHelper, repositoryName); + } + else + { + return null; + } } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -162,100 +197,59 @@ public EntityMapper getEntityFromStore(String guid, /** - * Retrieve the related information for an entity. - * Null is returned if there were no active instance. + * Return the list of home classifications for an entity. * * @param guid unique identifier of the entity - * @param entityRow appropriate row from table - * @return entity mapper - * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned + * @param localMetadataCollectionId unique identifier of the local metadata collection + * @param asOfTime database time + * @return list of classifications or null + * @throws RepositoryErrorException problem communicating with the database */ - public EntityMapper getCompleteEntityFromStore(String guid, - Map entityRow) throws RepositoryErrorException + public List getHomeClassifications(String guid, + String localMetadataCollectionId, + Date asOfTime) throws RepositoryErrorException { - final String methodName = "getCompleteEntityFromStore"; + final String methodName = "getHomeClassifications"; try { - if (entityRow != null) - { - Object versionObject = entityRow.get(RepositoryColumn.VERSION.getColumnName()).getDataValue(); + String whereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "' and " + RepositoryColumn.METADATA_COLLECTION_GUID.getColumnName() + " = '" + localMetadataCollectionId + "' and " + this.getAsOfTimeClause(asOfTime) + ";"; - if (versionObject != null) - { - String whereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + versionObject; + List> classifications = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION.getTableName(), + whereClause, + RepositoryTable.CLASSIFICATION.getColumnNameTypeMap()); - List> entityProperties = jdbcResourceConnector.getMatchingRows(RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getTableName(), - whereClause, - RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getColumnNameTypeMap()); + List classificationMappers = null; - List> classifications = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION.getTableName(), - whereClause, - RepositoryTable.CLASSIFICATION.getColumnNameTypeMap()); + if (classifications != null) + { + classificationMappers = new ArrayList<>(); - Map classificationRowsMap = new HashMap<>(); - if (classifications != null) + for (Map classificationRow : classifications) + { + if (classificationRow != null) { - for (Map classificationRow : classifications) - { - String classificationName = baseMapper.getStringPropertyFromColumn(RepositoryColumn.CLASSIFICATION_NAME.getColumnName(), classificationRow, true); - - MapperResultRows classificationMapperRow = new MapperResultRows(); - - classificationMapperRow.principleTableRow = classificationRow; + Object classificationName = classificationRow.get(RepositoryColumn.CLASSIFICATION_NAME.getColumnName()).getDataValue(); - classificationRowsMap.put(classificationName, classificationMapperRow); - } + String classificationWhereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + " and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + "' and " + this.getAsOfTimeClause(asOfTime); - List> classificationAttributes = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName(), - whereClause, + List> classificationProperties = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName(), + classificationWhereClause, RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getColumnNameTypeMap()); - if (classificationAttributes != null) - { - for (Map classificationAttributeRow : classificationAttributes) - { - String classificationName = baseMapper.getStringPropertyFromColumn(RepositoryColumn.CLASSIFICATION_NAME.getColumnName(), classificationAttributeRow, true); - - MapperResultRows mapperResultRows = classificationRowsMap.get(classificationName); - - if (mapperResultRows.propertyTableRows == null) - { - mapperResultRows.propertyTableRows = new ArrayList<>(); - } - - mapperResultRows.propertyTableRows.add(classificationAttributeRow); - } - } - } - - List classificationMappers = null; - - if (classifications != null) - { - classificationMappers = new ArrayList<>(); - - for (String classificationName : classificationRowsMap.keySet()) - { - MapperResultRows classificationRow = classificationRowsMap.get(classificationName); - - if (classificationRow != null) - { - ClassificationMapper classificationMapper = new ClassificationMapper(classificationRow.principleTableRow, - classificationRow.propertyTableRows, - repositoryHelper, - repositoryName); + ClassificationMapper classificationMapper = new ClassificationMapper(classificationRow, + classificationProperties, + repositoryHelper, + repositoryName); - classificationMappers.add(classificationMapper); - } - } + classificationMappers.add(classificationMapper); } - - return new EntityMapper(entityRow, entityProperties, classificationMappers, repositoryHelper, repositoryName); } } + + return classificationMappers; } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -265,218 +259,41 @@ public EntityMapper getCompleteEntityFromStore(String guid, methodName, sqlException); } - - return null; } /** - * Retrieve the related information for a list of entities that were identified in a query. - * Null is returned if there were no instances returned from the query. + * Retrieve the version of an entity from the database that was active at the requested time. + * Null is returned if there were no active instance. * - * @param entityGUIDs list of unique identifiers for the matching entities - * @param asOfTime time for the database query - * @return list of entity mappers + * @param guid unique identifier of the entity + * @param asOfTime requested time for the version + * @return entity mapper * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - private List getCompleteEntitiesFromStore(List entityGUIDs, - Date asOfTime) throws RepositoryErrorException + public EntityMapper getEntityFromStore(String guid, + Date asOfTime) throws RepositoryErrorException { - final String methodName = "getCompleteEntitiesFromStore"; + final String methodName = "getEntityFromStore"; - if ((entityGUIDs != null) && (!entityGUIDs.isEmpty())) + try { - try - { - Map mapperResultRowsMap = new HashMap<>(); - - QueryBuilder queryBuilder = new QueryBuilder(repositoryHelper, repositoryName); - - queryBuilder.setGUIDList(entityGUIDs); - queryBuilder.setAsOfTime(asOfTime); - - String whereClause = queryBuilder.getAsOfTimeWhereClause(); - - List> entityRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.ENTITY.getTableName(), - whereClause, - RepositoryTable.ENTITY.getColumnNameTypeMap()); - - if (entityRows != null) - { - StringBuilder entityWhereClause = new StringBuilder(); - boolean firstEntity = true; - - for (Map entityRow : entityRows) - { - String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), entityRow, true); - long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), entityRow, true); - - if (firstEntity) - { - firstEntity = false; - } - else - { - entityWhereClause.append(" or "); - } - - entityWhereClause.append(queryBuilder.getPrimaryKeysClause(instanceGUID, version, null)); - - MapperResultRows mapperResultRows = new MapperResultRows(); - mapperResultRows.principleTableRow = entityRow; - - mapperResultRowsMap.put(instanceGUID, mapperResultRows); - } - - List> entityAttributeRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getTableName(), - entityWhereClause.toString(), - RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getColumnNameTypeMap()); - - if (entityAttributeRows != null) - { - for (Map entityAttributeRow : entityAttributeRows) - { - String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), entityAttributeRow, true); - - MapperResultRows mapperResultRows = mapperResultRowsMap.get(instanceGUID); - - if (mapperResultRows.propertyTableRows == null) - { - mapperResultRows.propertyTableRows = new ArrayList<>(); - } - - mapperResultRows.propertyTableRows.add(entityAttributeRow); - } - } - - List> classifications = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION.getTableName(), - whereClause, - RepositoryTable.CLASSIFICATION.getColumnNameTypeMap()); - - if (classifications != null) - { - StringBuilder classificationWhereClause = new StringBuilder(); - boolean firstClassification = true; - - for (Map classificationRow : classifications) - { - String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), classificationRow, true); - String classificationName = baseMapper.getStringPropertyFromColumn(RepositoryColumn.CLASSIFICATION_NAME.getColumnName(), classificationRow, true); - long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), classificationRow, true); - - if (firstClassification) - { - firstClassification = false; - } - else - { - classificationWhereClause.append(" or "); - } - - classificationWhereClause.append(queryBuilder.getPrimaryKeysClause(instanceGUID, version, classificationName)); - - MapperResultRows mapperResultRows = mapperResultRowsMap.get(instanceGUID); - - if (mapperResultRows.propertyTableRows == null) - { - mapperResultRows.propertyTableRows = new ArrayList<>(); - } - - MapperResultRows classificationMapperRow = mapperResultRows.classifications.get(classificationName); - - if (classificationMapperRow == null) - { - classificationMapperRow = new MapperResultRows(); - } - - classificationMapperRow.principleTableRow = classificationRow; - - mapperResultRows.classifications.put(classificationName, classificationMapperRow); - } - - List> classificationAttributes = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName(), - classificationWhereClause.toString(), - RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getColumnNameTypeMap()); - - if (classificationAttributes != null) - { - for (Map classificationAttributeRow : classificationAttributes) - { - String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), classificationAttributeRow, true); - String classificationName = baseMapper.getStringPropertyFromColumn(RepositoryColumn.CLASSIFICATION_NAME.getColumnName(), classificationAttributeRow, true); - - MapperResultRows mapperResultRows = mapperResultRowsMap.get(instanceGUID); - - MapperResultRows classificationAttributesMapperResults = mapperResultRows.classifications.get(classificationName); - - if (classificationAttributesMapperResults.propertyTableRows == null) - { - classificationAttributesMapperResults.propertyTableRows = new ArrayList<>(); - } - - classificationAttributesMapperResults.propertyTableRows.add(classificationAttributeRow); - } - } - } - - if (!mapperResultRowsMap.isEmpty()) - { - List entityMappers = new ArrayList<>(); - - for (MapperResultRows mapperResultRows : mapperResultRowsMap.values()) - { - List classificationMappers = null; - - if (mapperResultRows.classifications != null) - { - classificationMappers = new ArrayList<>(); - - for (String classificationName : mapperResultRows.classifications.keySet()) - { - MapperResultRows classificationMapperResults = mapperResultRows.classifications.get(classificationName); - ClassificationMapper classificationMapper = new ClassificationMapper(classificationMapperResults.principleTableRow, - classificationMapperResults.propertyTableRows, - repositoryHelper, - repositoryName); - - classificationMappers.add(classificationMapper); - } - } - - entityMappers.add(new EntityMapper(mapperResultRows.principleTableRow, mapperResultRows.propertyTableRows, classificationMappers, repositoryHelper, repositoryName)); - } + Map entityRow = jdbcResourceConnector.getMatchingRow(RepositoryTable.ENTITY.getTableName(), + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "'" + getAsOfTimeClause(asOfTime), + RepositoryTable.ENTITY.getColumnNameTypeMap()); - return entityMappers; - } - } - } - catch (SQLException sqlException) - { - throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, - sqlException.getClass().getName(), - methodName, - sqlException.getMessage()), - this.getClass().getName(), - methodName, - sqlException); - } + return this.getCompleteEntityFromStore(guid, entityRow); + } + catch (PropertyServerException sqlException) + { + throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, + sqlException.getClass().getName(), + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); } - - return null; - } - - - - /** - * Retrieve a relationship from the database. - * - * @param guid unique identifier of the relationship - * @return Relationship mapper - * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned - */ - public RelationshipMapper getRelationshipForUpdate(String guid) throws RepositoryErrorException - { - return getRelationshipFromStore(guid, null); } @@ -502,7 +319,7 @@ public RelationshipMapper getRelationshipFromStore(String guid, return this.getCompleteRelationshipFromStore(guid, relationshipRow, asOfTime); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -516,42 +333,53 @@ public RelationshipMapper getRelationshipFromStore(String guid, /** - * Retrieve the related information for a relationship. - * Null is returned if there was no active instance. + * This query is issued against a join of the entity table and the entity attribute table. * - * @param guid unique identifier of the relationship - * @param relationshipRow appropriate row from table - * @param asOfTime time for the database query - * @return relationship mapper + * @param classificationQueryBuilder filled with conditions for the where clause for the SQL query + * @param entityQueryBuilder filled with conditions for the where clause for the SQL query + * @param asOfTime database time + * @return list of matching entity mappers or null if nothing matches * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - public RelationshipMapper getCompleteRelationshipFromStore(String guid, - Map relationshipRow, - Date asOfTime) throws RepositoryErrorException + public List retrieveEntitiesByProperties(QueryBuilder entityQueryBuilder, + QueryBuilder classificationQueryBuilder, + Date asOfTime) throws RepositoryErrorException { - final String methodName = "getCompleteRelationshipFromStore"; + final String methodName = "retrieveEntitiesByProperties"; + + String sqlEntityQuery = entityQueryBuilder.getPropertyJoinQuery(RepositoryTable.ENTITY.getTableName(), + RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getTableName()) + + " where " + entityQueryBuilder.getAsOfTimeWhereClause(); try { - if (relationshipRow != null) - { - long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), relationshipRow, true); - String end1GUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_1_GUID.getColumnName(), relationshipRow, true); - String end2GUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_2_GUID.getColumnName(), relationshipRow, true); - - String whereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + version; + List> entityRows; - List> relationshipProperties = jdbcResourceConnector.getMatchingRows(RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getTableName(), - whereClause, - RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getColumnNameTypeMap()); + if (classificationQueryBuilder == null) + { + entityRows = jdbcResourceConnector.getMatchingRows(sqlEntityQuery + entityQueryBuilder.getSequenceAndPaging(), + RepositoryTable.ENTITY.getColumnNameTypeMap()); + } + else + { + String sqlClassificationQuery = classificationQueryBuilder.getPropertyJoinQuery(RepositoryTable.CLASSIFICATION.getTableName(), + RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName()) + + " where " + classificationQueryBuilder.getAsOfTimeWhereClause(); - EntityMapper end1Mapper = this.getEntityFromStore(end1GUID, asOfTime); - EntityMapper end2Mapper = this.getEntityFromStore(end2GUID, asOfTime); + entityRows = jdbcResourceConnector.getMatchingRows(sqlEntityQuery + " and " + + RepositoryColumn.INSTANCE_GUID.getColumnName(RepositoryTable.ENTITY.getTableName()) + + " in (" + sqlClassificationQuery + ")" + + entityQueryBuilder.getSequenceAndPaging(), + RepositoryTable.ENTITY.getColumnNameTypeMap()); + } - return new RelationshipMapper(relationshipRow, relationshipProperties, end1Mapper, end2Mapper, repositoryHelper, repositoryName); + if (entityRows != null) + { + Map entityMappers = this.getCompleteEntitiesFromStore(entityRows, asOfTime); + return new ArrayList<>(entityMappers.values()); } } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -567,176 +395,177 @@ public RelationshipMapper getCompleteRelationshipFromStore(String /** - * Retrieve the related information for a list of relationships that were identified in a query. - * Null is returned if there were no instances returned from the query. + * This query is issued against the relationship table. * - * @param relationshipGUIDs list of unique identifiers for the matching relationships - * @param asOfTime time for the database query - * @return list of relationship mappers + * @param queryBuilder where clause for the SQL query + * @param asOfTime database time + * @return list of matching relationship mappers or null if nothing matches * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - private List getCompleteRelationshipsFromStore(List relationshipGUIDs, - Date asOfTime) throws RepositoryErrorException + public List retrieveRelationships(QueryBuilder queryBuilder, + Date asOfTime) throws RepositoryErrorException { - final String methodName = "getCompleteRelationshipsFromStore"; + final String methodName = "retrieveRelationships"; - if ((relationshipGUIDs != null) && (!relationshipGUIDs.isEmpty())) + try { - try - { - Map mapperResultRowsMap = new HashMap<>(); - - QueryBuilder queryBuilder = new QueryBuilder(repositoryHelper, repositoryName); - - queryBuilder.setGUIDList(relationshipGUIDs); - queryBuilder.setAsOfTime(asOfTime); - - String whereClause = queryBuilder.getAsOfTimeWhereClause(); - - List> relationshipRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.RELATIONSHIP.getTableName(), - whereClause, - RepositoryTable.RELATIONSHIP.getColumnNameTypeMap()); - - if (relationshipRows != null) - { - Map guidVersionMap = new HashMap<>(); - - for (Map relationshipRow : relationshipRows) - { - String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), relationshipRow, true); - Long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), relationshipRow, true); - - guidVersionMap.put(instanceGUID, version); - - MapperResultRows mapperResultRows = new MapperResultRows(); - mapperResultRows.principleTableRow = relationshipRow; - - mapperResultRowsMap.put(instanceGUID, mapperResultRows); - } - - List> relationshipAttributeRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getTableName(), - queryBuilder.getGUIDListPropertiesQueryWhereClause(guidVersionMap), - RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getColumnNameTypeMap()); - - if (relationshipAttributeRows != null) - { - for (Map relationshipAttributeRow : relationshipAttributeRows) - { - String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), relationshipAttributeRow, true); + List> relationshipRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.RELATIONSHIP.getTableName(), + queryBuilder.getAsOfTimeWhereClause() + queryBuilder.getSequenceAndPaging(), + RepositoryTable.RELATIONSHIP.getColumnNameTypeMap()); - MapperResultRows mapperResultRows = mapperResultRowsMap.get(instanceGUID); + if (relationshipRows != null) + { + return this.getCompleteRelationshipsFromStore(relationshipRows, asOfTime); + } + } + catch (PropertyServerException sqlException) + { + throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, + sqlException.getClass().getName(), + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); + } - if (mapperResultRows.propertyTableRows == null) - { - mapperResultRows.propertyTableRows = new ArrayList<>(); - } + return null; + } - mapperResultRows.propertyTableRows.add(relationshipAttributeRow); - } - } - if (!mapperResultRowsMap.isEmpty()) - { - List relationshipMappers = new ArrayList<>(); + /** + * This query is issued against a join of the relationship table and the relationship attribute table. + * + * @param queryBuilder populated with details of the where clause for the SQL query + * @param asOfTime database time + * @return list of matching relationship mappers or null if nothing matches + * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned + */ + public List retrieveRelationshipsByProperties(QueryBuilder queryBuilder, + Date asOfTime) throws RepositoryErrorException + { + final String methodName = "retrieveRelationships"; - for (MapperResultRows mapperResultRows : mapperResultRowsMap.values()) - { - String end1GUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_1_GUID.getColumnName(), mapperResultRows.principleTableRow, true); - String end2GUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_2_GUID.getColumnName(), mapperResultRows.principleTableRow, true); + String sqlQuery = queryBuilder.getPropertyJoinQuery(RepositoryTable.RELATIONSHIP.getTableName(), + RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getTableName()) + + " where " + queryBuilder.getAsOfTimeWhereClause() + queryBuilder.getSequenceAndPaging(); - EntityMapper end1Mapper = this.getEntityFromStore(end1GUID, asOfTime); - EntityMapper end2Mapper = this.getEntityFromStore(end2GUID, asOfTime); - relationshipMappers.add(new RelationshipMapper(mapperResultRows.principleTableRow, mapperResultRows.propertyTableRows, end1Mapper, end2Mapper, repositoryHelper, repositoryName)); - } + try + { + List> relationshipRows = jdbcResourceConnector.getMatchingRows(sqlQuery, RepositoryTable.RELATIONSHIP.getColumnNameTypeMap()); - return relationshipMappers; - } - } - } - catch (SQLException sqlException) + if (relationshipRows != null) { - throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, - sqlException.getClass().getName(), - methodName, - sqlException.getMessage()), - this.getClass().getName(), - methodName, - sqlException); + return this.getCompleteRelationshipsFromStore(relationshipRows, asOfTime); } } + catch (PropertyServerException sqlException) + { + throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, + sqlException.getClass().getName(), + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); + } return null; } /** - * Gather information from a database retrieval that can be used to build a mapper - * (entity or relationship). + * Retrieve the related information for an entity. + * Null is returned if there were no active instance. + * + * @param guid unique identifier of the entity + * @param entityRow appropriate row from table + * @return entity mapper + * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - static class MapperResultRows + public EntityMapper getCompleteEntityFromStore(String guid, + Map entityRow) throws RepositoryErrorException { - Map principleTableRow = null; - List> propertyTableRows = null; + final String methodName = "getCompleteEntityFromStore"; - Map classifications = null; - } + try + { + if (entityRow != null) + { + Object versionObject = entityRow.get(RepositoryColumn.VERSION.getColumnName()).getDataValue(); + if (versionObject != null) + { + String whereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + versionObject; - /** - * Create the part of the where clause that ensures that the correct version is returned. - * - * @param asOfTime database time to issue the query for - null means the latest version - * @return fragment of SQL - */ - private String getAsOfTimeClause(Date asOfTime) - { - if (asOfTime == null) - { - return " and " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " is null"; + List> entityProperties = jdbcResourceConnector.getMatchingRows(RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getTableName(), + whereClause, + RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getColumnNameTypeMap()); + + Map> classificationMappersForEntityGUIDs = getClassificationMappersForEntityGUIDs(whereClause); + + + return new EntityMapper(entityRow, + entityProperties, + classificationMappersForEntityGUIDs.get(guid), + repositoryHelper, + repositoryName); + } + } } - else + catch (PropertyServerException sqlException) { - return " and (" + RepositoryColumn.VERSION_START_TIME.getColumnName() + " < '" + asOfTime + "' and (" + RepositoryColumn.VERSION_END_TIME.getColumnName() + " is null or " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " > '" + asOfTime + "'))"; + throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, + sqlException.getClass().getName(), + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); } + + return null; } /** - * Return the list of versions for an entity. + * Retrieve the related information for a relationship. + * Null is returned if there was no active instance. * - * @param guid unique identifier of the instance - * @param fromTime starting time - * @param toTime ending time - * @param oldestFirst ordering - * @return list of instance versions - * @throws RepositoryErrorException problem communicating with the database + * @param guid unique identifier of the relationship + * @param relationshipRow appropriate row from table + * @param asOfTime time for the database query + * @return relationship mapper + * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - public List getEntityHistoryFromStore(String guid, - Date fromTime, - Date toTime, - boolean oldestFirst) throws RepositoryErrorException + public RelationshipMapper getCompleteRelationshipFromStore(String guid, + Map relationshipRow, + Date asOfTime) throws RepositoryErrorException { - final String methodName = "getEntityHistoryFromStore"; - - List entityMappers = new ArrayList<>(); + final String methodName = "getCompleteRelationshipFromStore"; try { - List> entityRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.ENTITY.getTableName(), - RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "'" + - getDateRangeClause(fromTime, toTime, oldestFirst), - RepositoryTable.ENTITY.getColumnNameTypeMap()); + if (relationshipRow != null) + { + long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), relationshipRow, true); + String end1GUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_1_GUID.getColumnName(), relationshipRow, true); + String end2GUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_2_GUID.getColumnName(), relationshipRow, true); + + String whereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + version; - if (entityRows != null) - { - for (Map entityRow : entityRows) - { - entityMappers.add(this.getCompleteEntityFromStore(guid, entityRow)); - } + List> relationshipProperties = jdbcResourceConnector.getMatchingRows(RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getTableName(), + whereClause, + RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getColumnNameTypeMap()); + + EntityMapper end1Mapper = this.getEntityFromStore(end1GUID, asOfTime); + EntityMapper end2Mapper = this.getEntityFromStore(end2GUID, asOfTime); + + return new RelationshipMapper(relationshipRow, relationshipProperties, end1Mapper, end2Mapper, repositoryHelper, repositoryName); } } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -747,164 +576,268 @@ public List getEntityHistoryFromStore(String guid, sqlException); } - if (! entityMappers.isEmpty()) - { - return entityMappers; - } - return null; } /** - * Return the list of versions for a relationship. + * Retrieve the entities requested. * - * @param guid unique identifier of the relationship - * @param fromTime starting time - * @param toTime ending time - * @param oldestFirst ordering - * @return list of instance versions - * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned + * @param entityGUIDs list of GUIDs to retrieve + * @param asOfTime time required + * @return map of guids and the corresponding entity mapper + * @throws RepositoryErrorException problem retrieving values from the database */ - public List getRelationshipHistoryFromStore(String guid, - Date fromTime, - Date toTime, - boolean oldestFirst) throws RepositoryErrorException + private Map getCompleteEntitiesFromGUIDs(List entityGUIDs, + Date asOfTime) throws RepositoryErrorException { - final String methodName = "getRelationshipHistoryFromStore"; + final String methodName = "getCompleteEntitiesFromGUIDs"; - List relationshipMappers = new ArrayList<>(); + Map entities = new HashMap<>(); - try + if ((entityGUIDs != null) && (!entityGUIDs.isEmpty())) { - List> relationshipRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.RELATIONSHIP.getTableName(), - RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "'" + - getDateRangeClause(fromTime, toTime, oldestFirst), - RepositoryTable.RELATIONSHIP.getColumnNameTypeMap()); + try + { + QueryBuilder queryBuilder = new QueryBuilder(repositoryHelper, repositoryName); - if (relationshipRows != null) + queryBuilder.setGUIDList(entityGUIDs); + queryBuilder.setAsOfTime(asOfTime); + + List> entityRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.ENTITY.getTableName(), + queryBuilder.getAsOfTimeWhereClause() + queryBuilder.getSequenceAndPaging(), + RepositoryTable.ENTITY.getColumnNameTypeMap()); + + return this.getCompleteEntitiesFromStore(entityRows, asOfTime); + } + catch (PropertyServerException sqlException) { - for (Map relationshipRow : relationshipRows) - { - Date asOfTime = baseMapper.getDatePropertyFromColumn(RepositoryColumn.VERSION_START_TIME.getColumnName(), relationshipRow, true); - relationshipMappers.add(this.getCompleteRelationshipFromStore(guid, relationshipRow, asOfTime)); - } + throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, + sqlException.getClass().getName(), + methodName, + sqlException.getMessage()), + this.getClass().getName(), + methodName, + sqlException); } } - catch (SQLException sqlException) - { - throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, - sqlException.getClass().getName(), - methodName, - sqlException.getMessage()), - this.getClass().getName(), - methodName, - sqlException); - } - - if (! relationshipMappers.isEmpty()) - { - return relationshipMappers; - } - return null; + return entities; } /** - * Create the part of the where clause that ensures that the correct version is returned. + * Retrieve the related information for a list of entities that were identified in a query. + * Null is returned if there were no instances returned from the query. * - * @param fromTime starting time - * @param toTime ending time - * @param oldestFirst ordering - * @return fragment of SQL + * @param entityRows list of database rows for the matching entities + * @param asOfTime time for the database query + * @return map of guids to entity mappers + * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - private String getDateRangeClause(Date fromTime, - Date toTime, - boolean oldestFirst) + private Map getCompleteEntitiesFromStore(List> entityRows, + Date asOfTime) throws RepositoryErrorException { - if ((fromTime == null) && (toTime == null)) - { - return getOrderByDateClause(oldestFirst); - } - else if (fromTime == null) - { - return " and (" + RepositoryColumn.VERSION_START_TIME.getColumnName() + " < '" + toTime + "')" + getOrderByDateClause(oldestFirst); - } - else if (toTime == null) - { - return " and (" + RepositoryColumn.VERSION_END_TIME.getColumnName() + " is null or " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " > '" + fromTime + "')" + getOrderByDateClause(oldestFirst); - } - else + if ((entityRows != null) && (! entityRows.isEmpty())) { - return " and (" + RepositoryColumn.VERSION_START_TIME.getColumnName() + " < '" + toTime + "' and (" + RepositoryColumn.VERSION_END_TIME.getColumnName() + " is null or " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " > '" + fromTime + "'))" + getOrderByDateClause(oldestFirst); + /* + * Get the attributes for each of the entities returned + */ + Map databaseResultRowsMap = this.getAttributesDatabaseResults(entityRows, + RepositoryTable.ENTITY_ATTRIBUTE_VALUE); + + /* + * Entities have an additional complication in that they have classifications. These are matched by + * asOfTime because their versions are independent of the entity versions. + */ + QueryBuilder queryBuilder = new QueryBuilder(repositoryHelper, repositoryName); + + queryBuilder.setGUIDList(new ArrayList<>(databaseResultRowsMap.keySet())); + queryBuilder.setAsOfTime(asOfTime); + + Map> classificationMappersForEntityGUIDs = getClassificationMappersForEntityGUIDs(queryBuilder.getAsOfTimeWhereClause() + queryBuilder.getSequenceAndPaging()); + + /* + * All of the information is assembled to build the entity mappers. + */ + if (! databaseResultRowsMap.isEmpty()) + { + Map entityMappers = new HashMap<>(); + + for (String instanceGUID : databaseResultRowsMap.keySet()) + { + DatabaseResultRows databaseResultRows = databaseResultRowsMap.get(instanceGUID); + + entityMappers.put(instanceGUID, new EntityMapper(databaseResultRows.principleTableRow, + databaseResultRows.propertyTableRows, + classificationMappersForEntityGUIDs.get(instanceGUID), + repositoryHelper, + repositoryName)); + } + + return entityMappers; + } } + + return null; } /** - * Create an order by statement. + * Retrieve the related information for a list of relationships that were identified in a query. + * Null is returned if there were no instances returned from the query. * - * @param oldestFirst ordering - * @return fragment of sql + * @param relationshipRows list of the matching relationships + * @param asOfTime time for the database query + * @return list of relationship mappers + * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - private String getOrderByDateClause(boolean oldestFirst) + private List getCompleteRelationshipsFromStore(List> relationshipRows, + Date asOfTime) throws RepositoryErrorException { - if (oldestFirst) - { - return " order by " + RepositoryColumn.VERSION_START_TIME.getColumnName() + " asc"; - } - else + if ((relationshipRows != null) && (! relationshipRows.isEmpty())) { - return " order by " + RepositoryColumn.VERSION_START_TIME.getColumnName() + " desc"; + Map mapperResultRowsMap = this.getAttributesDatabaseResults(relationshipRows, + RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE); + + if (! mapperResultRowsMap.isEmpty()) + { + /* + * Relationships each link to two entities. Retrieve details about the linked ends + */ + List entityGUIDs = new ArrayList<>(); + for (Map relationshipRow : relationshipRows) + { + String entityGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_1_GUID.getColumnName(), relationshipRow, true); + + if (! entityGUIDs.contains(entityGUID)) + { + entityGUIDs.add(entityGUID); + } + + entityGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_2_GUID.getColumnName(), relationshipRow, true); + + if (! entityGUIDs.contains(entityGUID)) + { + entityGUIDs.add(entityGUID); + } + } + + Map entityEnds = getCompleteEntitiesFromGUIDs(entityGUIDs, asOfTime); + + /* + * All of the information is available to create the relationships + */ + List relationshipMappers = new ArrayList<>(); + + for (DatabaseResultRows databaseResultRows : mapperResultRowsMap.values()) + { + String end1GUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_1_GUID.getColumnName(), databaseResultRows.principleTableRow, true); + String end2GUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.END_2_GUID.getColumnName(), databaseResultRows.principleTableRow, true); + + EntityMapper end1Mapper = entityEnds.get(end1GUID); + EntityMapper end2Mapper = entityEnds.get(end2GUID); + + relationshipMappers.add(new RelationshipMapper(databaseResultRows.principleTableRow, databaseResultRows.propertyTableRows, end1Mapper, end2Mapper, repositoryHelper, repositoryName)); + } + + return relationshipMappers; + } } + + return null; } /** - * Retrieve details about an entity from the store. The entity mapper is returned to allow the caller to choose - * what style of entity to return. + * Retrieve the attribute rows that match the instance rows returned. * - * @param entityGUID unique identifier of the entity - * @param classificationName name of classification - * @return classification mapper containing all that is known about the latest version of the classification - * @throws RepositoryErrorException either a problem accessing the database or a mapping problem with the contents retrieved + * @param instanceRows rows from principle instance table (entity or relationship) + * @param attributesTable the attributes table to retrieve from + * @return organised database results + * @throws RepositoryErrorException unexpected exception retrieving values from the database */ - public ClassificationMapper getClassificationForUpdate(String entityGUID, - String classificationName) throws RepositoryErrorException + private Map getAttributesDatabaseResults(List> instanceRows, + RepositoryTable attributesTable) throws RepositoryErrorException { - final String methodName = "getClassificationForUpdate"; + final String methodName = "getAttributesDatabaseResults"; try { - Map classificationRow = jdbcResourceConnector.getMatchingRow(RepositoryTable.CLASSIFICATION.getTableName(), - RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + entityGUID + - "' and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + "'" + - getAsOfTimeClause(null), - RepositoryTable.CLASSIFICATION.getColumnNameTypeMap()); + Map databaseResultRowsMap = new HashMap<>(); - if (classificationRow != null) + QueryBuilder queryBuilder = new QueryBuilder(repositoryHelper, repositoryName); + List instanceGUIDs = new ArrayList<>(); + + StringBuilder instanceWhereClause = new StringBuilder(); + boolean firstInstance = true; + + /* + * Step through the results and use the first row returned for each instance GUID. + * Build up a composite query that returns all of the attributes for all of + * the instances. + */ + for (Map instanceRow : instanceRows) { - BaseMapper baseMapper = new BaseMapper(repositoryName); + String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), instanceRow, true); - long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), classificationRow, true); + if (! instanceGUIDs.contains(instanceGUID)) + { + /* + * New instance. + */ + instanceGUIDs.add(instanceGUID); - String whereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + entityGUID + - "' and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + - "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + version; + /* + * The retrieve of the properties is by version for speed. + */ + long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), instanceRow, true); + if (firstInstance) + { + firstInstance = false; + } + else + { + instanceWhereClause.append(" or "); + } - List> classificationProperties = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName(), - whereClause, - RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getColumnNameTypeMap()); - return new ClassificationMapper(classificationRow, classificationProperties, repositoryHelper, repositoryName); + instanceWhereClause.append(queryBuilder.getPrimaryKeysClause(instanceGUID, version, null)); + + DatabaseResultRows databaseResultRows = new DatabaseResultRows(); + databaseResultRows.principleTableRow = instanceRow; + + databaseResultRowsMap.put(instanceGUID, databaseResultRows); + } } - else + + /* + * Retrieve the attribute rows and organize them by instance GUID. + */ + List> attributeRows = jdbcResourceConnector.getMatchingRows(attributesTable.getTableName(), + instanceWhereClause.toString(), + attributesTable.getColumnNameTypeMap()); + + if (attributeRows != null) { - return null; + for (Map attributeRow : attributeRows) + { + String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), attributeRow, true); + + DatabaseResultRows databaseResultRows = databaseResultRowsMap.get(instanceGUID); + + if (databaseResultRows.propertyTableRows == null) + { + databaseResultRows.propertyTableRows = new ArrayList<>(); + } + + databaseResultRows.propertyTableRows.add(attributeRow); + } } + + return databaseResultRowsMap; } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -917,60 +850,155 @@ public ClassificationMapper getClassificationForUpdate(String entityGUID, } - /** - * Return the list of home classifications for an entity. - * - * @param guid unique identifier of the entity - * @param localMetadataCollectionId unique identifier of the local metadata collection - * @param asOfTime database time - * @return list of classifications or null - * @throws RepositoryErrorException problem communicating with the database - */ - public List getHomeClassifications(String guid, - String localMetadataCollectionId, - Date asOfTime) throws RepositoryErrorException - { - final String methodName = "getHomeClassifications"; + /** + * Return the list of classifications for each of the requested entityGUIDs. + * + * @param whereClause the lists the required guids and the asOfTime. + * @return map of guids to lists of associated classification mappers (maybe empty but not null) + * @throws RepositoryErrorException unexpected problem retrieving related information from the database. + */ + private Map> getClassificationMappersForEntityGUIDs(String whereClause) throws RepositoryErrorException + { + final String methodName = "getClassificationMappersForEntityGUIDs"; + + Map> classificationMappersForEntity = new HashMap<>(); + + try + { + /* + * Retrieve the rows of classifications for the requested entities at the requested time. + */ + List> classifications = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION.getTableName(), + whereClause, + RepositoryTable.CLASSIFICATION.getColumnNameTypeMap()); + + if (classifications != null) + { + /* + * Since one or more of the entities has at least one classification, then we need to match the version + * of these classifications with the entity GUID, in order to retrieve the correct version of the + * classification for the desired time. (This is because the version of the classification is + * independent of the version of the entity). + */ + Map mapperResultRowsMap = new HashMap<>(); + QueryBuilder queryBuilder = new QueryBuilder(repositoryHelper, repositoryName); + + StringBuilder classificationWhereClause = new StringBuilder(); + + boolean firstClassification = true; + + for (Map classificationRow : classifications) + { + String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), classificationRow, true); + String classificationName = baseMapper.getStringPropertyFromColumn(RepositoryColumn.CLASSIFICATION_NAME.getColumnName(), classificationRow, true); + long version = baseMapper.getLongPropertyFromColumn(RepositoryColumn.VERSION.getColumnName(), classificationRow, true); + + if (firstClassification) + { + firstClassification = false; + } + else + { + classificationWhereClause.append(" or "); + } + + classificationWhereClause.append(queryBuilder.getPrimaryKeysClause(instanceGUID, version, classificationName)); + + DatabaseResultRows databaseResultRows = mapperResultRowsMap.get(instanceGUID); + + if (databaseResultRows == null) + { + databaseResultRows = new DatabaseResultRows(); + } + + if (databaseResultRows.propertyTableRows == null) + { + databaseResultRows.propertyTableRows = new ArrayList<>(); + } + + if (databaseResultRows.classifications == null) + { + databaseResultRows.classifications = new HashMap<>(); + } + + DatabaseResultRows classificationMapperRow = databaseResultRows.classifications.get(classificationName); + + if (classificationMapperRow == null) + { + classificationMapperRow = new DatabaseResultRows(); + } + + classificationMapperRow.principleTableRow = classificationRow; + + databaseResultRows.classifications.put(classificationName, classificationMapperRow); + mapperResultRowsMap.put(instanceGUID, databaseResultRows); + } + + /* + * Now we know which versions of each classification we need for each entity, we can retrieve all of the attributes for all of these entities. + * The returned rows are then organizes with their classification into mapperResultRowsMap. + */ + List> classificationAttributes = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName(), + classificationWhereClause.toString(), + RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getColumnNameTypeMap()); - try - { - String whereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "' and " + RepositoryColumn.METADATA_COLLECTION_GUID.getColumnName() + " = '" + localMetadataCollectionId + "' and " + this.getAsOfTimeClause(asOfTime) + ";"; + if (classificationAttributes != null) + { + for (Map classificationAttributeRow : classificationAttributes) + { + String instanceGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), classificationAttributeRow, true); + String classificationName = baseMapper.getStringPropertyFromColumn(RepositoryColumn.CLASSIFICATION_NAME.getColumnName(), classificationAttributeRow, true); - List> classifications = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION.getTableName(), - whereClause, - RepositoryTable.CLASSIFICATION.getColumnNameTypeMap()); + DatabaseResultRows databaseResultRows = mapperResultRowsMap.get(instanceGUID); - List classificationMappers = null; + DatabaseResultRows classificationAttributesMapperResults = databaseResultRows.classifications.get(classificationName); - if (classifications != null) - { - classificationMappers = new ArrayList<>(); + if (classificationAttributesMapperResults.propertyTableRows == null) + { + classificationAttributesMapperResults.propertyTableRows = new ArrayList<>(); + } - for (Map classificationRow : classifications) + classificationAttributesMapperResults.propertyTableRows.add(classificationAttributeRow); + } + } + + /* + * All of the results are retrieved and organized. What remains is to build the classification + * mappers for each entity. + */ + if (! mapperResultRowsMap.isEmpty()) { - if (classificationRow != null) + for (String instanceGUID : mapperResultRowsMap.keySet()) { - Object classificationName = classificationRow.get(RepositoryColumn.CLASSIFICATION_NAME.getColumnName()).getDataValue(); + DatabaseResultRows databaseResultRows = mapperResultRowsMap.get(instanceGUID); - String classificationWhereClause = RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + " and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + "' and " + this.getAsOfTimeClause(asOfTime); - List> classificationProperties = jdbcResourceConnector.getMatchingRows(RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName(), - classificationWhereClause, - RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getColumnNameTypeMap()); + if ((databaseResultRows != null) && (databaseResultRows.classifications != null)) + { + List classificationMappers = new ArrayList<>(); - ClassificationMapper classificationMapper = new ClassificationMapper(classificationRow, - classificationProperties, - repositoryHelper, - repositoryName); + for (String classificationName : databaseResultRows.classifications.keySet()) + { + DatabaseResultRows classificationMapperResults = databaseResultRows.classifications.get(classificationName); + ClassificationMapper classificationMapper = new ClassificationMapper(classificationMapperResults.principleTableRow, + classificationMapperResults.propertyTableRows, + repositoryHelper, + repositoryName); - classificationMappers.add(classificationMapper); + classificationMappers.add(classificationMapper); + } + + if (! classificationMappers.isEmpty()) + { + classificationMappersForEntity.put(instanceGUID, classificationMappers); + } + } } } - } - return classificationMappers; + } } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -980,61 +1008,60 @@ public List getHomeClassifications(String guid, methodName, sqlException); } + + return classificationMappersForEntity; } /** - * This query is issued against a join of the entity table and the entity attribute table. + * Gather information from a database retrieval that can be used to build a mapper + * (entity or relationship). + */ + static class DatabaseResultRows + { + Map principleTableRow = null; + List> propertyTableRows = null; + + Map classifications = null; + } + + + + /** + * Return the list of versions for an entity. * - * @param classificationQueryBuilder filled with conditions for the where clause for the SQL query - * @param entityQueryBuilder filled with conditions for the where clause for the SQL query - * @param asOfTime database time - * @return list of matching entity mappers or null if nothing matches - * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned + * @param guid unique identifier of the instance + * @param fromTime starting time + * @param toTime ending time + * @param oldestFirst ordering + * @return list of instance versions + * @throws RepositoryErrorException problem communicating with the database */ - public List retrieveEntitiesByProperties(QueryBuilder entityQueryBuilder, - QueryBuilder classificationQueryBuilder, - Date asOfTime) throws RepositoryErrorException + public List getEntityHistoryFromStore(String guid, + Date fromTime, + Date toTime, + boolean oldestFirst) throws RepositoryErrorException { - final String methodName = "retrieveEntitiesByProperties"; + final String methodName = "getEntityHistoryFromStore"; - String sqlEntityQuery = entityQueryBuilder.getPropertyJoinQuery(RepositoryTable.ENTITY.getTableName(), - RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getTableName()) + - " where " + entityQueryBuilder.getAsOfTimeWhereClause(); + List entityMappers = new ArrayList<>(); try { - List> entityRows; - - if (classificationQueryBuilder == null) - { - entityRows = jdbcResourceConnector.getMatchingRows(sqlEntityQuery, RepositoryTable.getSingleColumnNameTypeMap(RepositoryColumn.INSTANCE_GUID)); - } - else - { - String sqlClassificationQuery = classificationQueryBuilder.getPropertyJoinQuery(RepositoryTable.CLASSIFICATION.getTableName(), - RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName()) + - " where " + classificationQueryBuilder.getAsOfTimeWhereClause(); - - entityRows = jdbcResourceConnector.getMatchingRows("(" + sqlClassificationQuery + ") union (" + sqlEntityQuery + ")", - RepositoryTable.getSingleColumnNameTypeMap(RepositoryColumn.INSTANCE_GUID)); - } + List> entityRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.ENTITY.getTableName(), + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "'" + + getDateRangeClause(fromTime, toTime, oldestFirst), + RepositoryTable.ENTITY.getColumnNameTypeMap()); if (entityRows != null) { - List entityGUIDs = new ArrayList<>(); - for (Map entityRow : entityRows) { - String guid = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), entityRow, true); - - entityGUIDs.add(guid); + entityMappers.add(this.getCompleteEntityFromStore(guid, entityRow)); } - - return this.getCompleteEntitiesFromStore(entityGUIDs, asOfTime); } } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1045,44 +1072,51 @@ public List retrieveEntitiesByProperties(QueryBuilder entityQueryB sqlException); } + if (! entityMappers.isEmpty()) + { + return entityMappers; + } + return null; } /** - * This query is issued against the relationship table. + * Return the list of versions for a relationship. * - * @param whereClause where clause for the SQL query - * @param asOfTime database time - * @return list of matching relationship mappers or null if nothing matches + * @param guid unique identifier of the relationship + * @param fromTime starting time + * @param toTime ending time + * @param oldestFirst ordering + * @return list of instance versions * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned */ - public List retrieveRelationships(String whereClause, - Date asOfTime) throws RepositoryErrorException + public List getRelationshipHistoryFromStore(String guid, + Date fromTime, + Date toTime, + boolean oldestFirst) throws RepositoryErrorException { - final String methodName = "retrieveRelationships"; + final String methodName = "getRelationshipHistoryFromStore"; + + List relationshipMappers = new ArrayList<>(); try { List> relationshipRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.RELATIONSHIP.getTableName(), - whereClause, + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "'" + + getDateRangeClause(fromTime, toTime, oldestFirst), RepositoryTable.RELATIONSHIP.getColumnNameTypeMap()); if (relationshipRows != null) { - List relationshipGUIDs = new ArrayList<>(); - for (Map relationshipRow : relationshipRows) { - String guid = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), relationshipRow, true); - - relationshipGUIDs.add(guid); + Date asOfTime = baseMapper.getDatePropertyFromColumn(RepositoryColumn.VERSION_START_TIME.getColumnName(), relationshipRow, true); + relationshipMappers.add(this.getCompleteRelationshipFromStore(guid, relationshipRow, asOfTime)); } - - return this.getCompleteRelationshipsFromStore(relationshipGUIDs, asOfTime); } } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1093,62 +1127,84 @@ public List retrieveRelationships(String whereClause, sqlException); } + if (! relationshipMappers.isEmpty()) + { + return relationshipMappers; + } + return null; } /** - * This query is issued against a join of the relationship table and the relationship attribute table. + * Create the part of the where clause that ensures that the correct version is returned. * - * @param queryBuilder populated with details of the where clause for the SQL query - * @param asOfTime database time - * @return list of matching relationship mappers or null if nothing matches - * @throws RepositoryErrorException problem communicating with the database, or mapping the values returned + * @param asOfTime database time to issue the query for - null means the latest version + * @return fragment of SQL */ - public List retrieveRelationshipsByProperties(QueryBuilder queryBuilder, - Date asOfTime) throws RepositoryErrorException + private String getAsOfTimeClause(Date asOfTime) { - final String methodName = "retrieveRelationships"; - - String sqlQuery = queryBuilder.getPropertyJoinQuery(RepositoryTable.RELATIONSHIP.getTableName(), - RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getTableName()) + - " where " + queryBuilder.getAsOfTimeWhereClause(); - - - try + if (asOfTime == null) + { + return " and " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " is null"; + } + else { - List> relationshipRows = jdbcResourceConnector.getMatchingRows(sqlQuery, RepositoryTable.getSingleColumnNameTypeMap(RepositoryColumn.INSTANCE_GUID)); + return " and (" + RepositoryColumn.VERSION_START_TIME.getColumnName() + " < '" + asOfTime + "' and (" + RepositoryColumn.VERSION_END_TIME.getColumnName() + " is null or " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " > '" + asOfTime + "'))"; + } + } - if (relationshipRows != null) - { - List relationshipGUIDs = new ArrayList<>(); - for (Map relationshipRow : relationshipRows) - { - String guid = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), relationshipRow, true); + /** + * Create the part of the where clause that ensures that the correct version is returned. + * + * @param fromTime starting time + * @param toTime ending time + * @param oldestFirst ordering + * @return fragment of SQL + */ + private String getDateRangeClause(Date fromTime, + Date toTime, + boolean oldestFirst) + { + if ((fromTime == null) && (toTime == null)) + { + return getOrderByDateClause(oldestFirst); + } + else if (fromTime == null) + { + return " and (" + RepositoryColumn.VERSION_START_TIME.getColumnName() + " < '" + toTime + "')" + getOrderByDateClause(oldestFirst); + } + else if (toTime == null) + { + return " and (" + RepositoryColumn.VERSION_END_TIME.getColumnName() + " is null or " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " > '" + fromTime + "')" + getOrderByDateClause(oldestFirst); + } + else + { + return " and (" + RepositoryColumn.VERSION_START_TIME.getColumnName() + " < '" + toTime + "' and (" + RepositoryColumn.VERSION_END_TIME.getColumnName() + " is null or " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " > '" + fromTime + "'))" + getOrderByDateClause(oldestFirst); + } + } - relationshipGUIDs.add(guid); - } - return this.getCompleteRelationshipsFromStore(relationshipGUIDs, asOfTime); - } + /** + * Create an order by statement. + * + * @param oldestFirst ordering + * @return fragment of sql + */ + private String getOrderByDateClause(boolean oldestFirst) + { + if (oldestFirst) + { + return " order by " + RepositoryColumn.VERSION_START_TIME.getColumnName() + " asc"; } - catch (SQLException sqlException) + else { - throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, - sqlException.getClass().getName(), - methodName, - sqlException.getMessage()), - this.getClass().getName(), - methodName, - sqlException); + return " order by " + RepositoryColumn.VERSION_START_TIME.getColumnName() + " desc"; } - - return null; } - /** * Add an entity to the database. Its header information (and effectivity dates) goes into the * entity table. The properties go into the entity attribute values table. @@ -1170,7 +1226,7 @@ public void addEntityToStore(EntityMapper entityMapper) throws RepositoryErrorEx saveClassifications(entityMapper.getClassificationMappers()); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1212,7 +1268,7 @@ public void addEntityProxyToStore(EntityMapper entityMapper) throws RepositoryEr saveClassifications(entityMapper.getClassificationMappers()); } } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1263,7 +1319,7 @@ public void saveClassification(ClassificationMapper classificationMapper) throws jdbcResourceConnector.insertRowsIntoTable(RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName(), classificationMapper.getClassificationPropertiesTableRows()); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1302,7 +1358,7 @@ public void addRelationshipToStore(RelationshipMapper relationshipMapper) throws jdbcResourceConnector.insertRowsIntoTable(RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getTableName(), relationshipMapper.getRelationshipPropertiesTableRows()); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1333,7 +1389,7 @@ public void updatePreviousEntityVersionEndTime(EntityMapper entityMapper, " set " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " = '" + versionEndTime + "' where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + entityMapper.getEntityDetail().getGUID() + "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + entityMapper.getEntityDetail().getVersion() + ";"); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1366,7 +1422,7 @@ public void updatePreviousClassificationVersionEndTime(ClassificationMapper clas "' and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationMapper.getClassification().getName() + "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + classificationMapper.getClassification().getVersion() + ";"); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1397,7 +1453,7 @@ public void updatePreviousRelationshipVersionEndTime(RelationshipMapper relation " set " + RepositoryColumn.VERSION_END_TIME.getColumnName() + " = '" + versionEndTime + "' where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + relationshipMapper.getRelationship().getGUID() + "' and " + RepositoryColumn.VERSION.getColumnName() + " = " + relationshipMapper.getRelationship().getVersion() + ";"); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1427,7 +1483,7 @@ public void purgeClassification(String entityGUID, jdbcResourceConnector.issueSQLCommand("delete from " + RepositoryTable.CLASSIFICATION.getTableName() + " where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + entityGUID + "' and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + "';"); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1452,12 +1508,34 @@ public void purgeEntity(String guid) throws RepositoryErrorException { final String methodName = "purgeEntity"; + try { + List> relationshipRows = jdbcResourceConnector.getMatchingRows(RepositoryTable.RELATIONSHIP.getTableName(), + "(" + RepositoryColumn.END_1_GUID.getColumnName() + " = '" + guid + + "' or " + RepositoryColumn.END_2_GUID.getColumnName() + " = '" + guid + "')", + RepositoryTable.RELATIONSHIP.getColumnNameTypeMap()); + + if (relationshipRows != null) + { + for (Map relationshipRow : relationshipRows) + { + String relationshipGUID = baseMapper.getStringPropertyFromColumn(RepositoryColumn.INSTANCE_GUID.getColumnName(), relationshipRow, true); + + this.purgeRelationship(relationshipGUID); + } + } + jdbcResourceConnector.issueSQLCommand("delete from " + RepositoryTable.ENTITY.getTableName() + " where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "';"); + jdbcResourceConnector.issueSQLCommand("delete from " + RepositoryTable.ENTITY_ATTRIBUTE_VALUE.getTableName() + + " where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "';"); + jdbcResourceConnector.issueSQLCommand("delete from " + RepositoryTable.CLASSIFICATION.getTableName() + + " where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "';"); + jdbcResourceConnector.issueSQLCommand("delete from " + RepositoryTable.CLASSIFICATION_ATTRIBUTE_VALUE.getTableName() + + " where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "';"); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), @@ -1486,8 +1564,10 @@ public void purgeRelationship(String guid) throws RepositoryErrorException { jdbcResourceConnector.issueSQLCommand("delete from " + RepositoryTable.RELATIONSHIP.getTableName() + " where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "';"); + jdbcResourceConnector.issueSQLCommand("delete from " + RepositoryTable.RELATIONSHIP_ATTRIBUTE_VALUE.getTableName() + + " where " + RepositoryColumn.INSTANCE_GUID.getColumnName() + " = '" + guid + "';"); } - catch (SQLException sqlException) + catch (PropertyServerException sqlException) { throw new RepositoryErrorException(PostgresErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(repositoryName, sqlException.getClass().getName(), diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/database/QueryBuilder.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/database/QueryBuilder.java index 05aeae8d79d..c4495fc4ba5 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/database/QueryBuilder.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/database/QueryBuilder.java @@ -12,6 +12,7 @@ import org.odpi.openmetadata.repositoryservices.connectors.stores.metadatacollectionstore.properties.SequencingOrder; import org.odpi.openmetadata.repositoryservices.connectors.stores.metadatacollectionstore.properties.instances.*; import org.odpi.openmetadata.repositoryservices.connectors.stores.metadatacollectionstore.properties.search.*; +import org.odpi.openmetadata.repositoryservices.connectors.stores.metadatacollectionstore.properties.typedefs.PrimitiveDefCategory; import org.odpi.openmetadata.repositoryservices.connectors.stores.metadatacollectionstore.properties.typedefs.TypeDef; import org.odpi.openmetadata.repositoryservices.connectors.stores.metadatacollectionstore.repositoryconnector.OMRSRepositoryHelper; import org.odpi.openmetadata.repositoryservices.ffdc.exception.RepositoryErrorException; @@ -22,7 +23,6 @@ import java.util.Date; import java.util.Iterator; import java.util.List; -import java.util.Map; /** * Translates open metadata query requests into SQL fragments that can be assembled before issuing @@ -148,10 +148,11 @@ public void setMatchProperties(InstanceProperties matchProperties, */ private String getMatchPropertiesClause() throws RepositoryErrorException { - if (matchProperties != null) + if ((matchProperties != null) && (matchProperties.getPropertyCount() > 0 || matchProperties.getEffectiveFromTime() != null || (matchProperties.getEffectiveToTime() != null))) { String matchOperand = "' and "; - PropertyComparisonOperator operator = PropertyComparisonOperator.LIKE; + PropertyComparisonOperator stringPropertyOperator = PropertyComparisonOperator.LIKE; + PropertyComparisonOperator numericPropertyOperator = PropertyComparisonOperator.EQ; if (matchCriteria == MatchCriteria.ANY) { @@ -159,7 +160,8 @@ private String getMatchPropertiesClause() throws RepositoryErrorException } else if (matchCriteria == MatchCriteria.NONE) { - operator = PropertyComparisonOperator.NEQ; + stringPropertyOperator = PropertyComparisonOperator.NOT_LIKE; + numericPropertyOperator = PropertyComparisonOperator.NEQ; } StringBuilder stringBuilder = new StringBuilder(" and ("); @@ -170,7 +172,7 @@ else if (matchCriteria == MatchCriteria.NONE) stringBuilder.append(this.getNestedPropertyComparisonClause(null, null, OpenMetadataProperty.EFFECTIVE_FROM_TIME.name, - operator, + numericPropertyOperator, matchProperties.getEffectiveFromTime())); firstProperty = false; } @@ -189,7 +191,7 @@ else if (matchCriteria == MatchCriteria.NONE) stringBuilder.append(this.getNestedPropertyComparisonClause(null, null, OpenMetadataProperty.EFFECTIVE_TO_TIME.name, - operator, + numericPropertyOperator, matchProperties.getEffectiveToTime())); } @@ -204,7 +206,8 @@ else if (matchCriteria == MatchCriteria.NONE) stringBuilder.append(getPropertyComparisonFromInstanceProperties(matchProperties, null, null, - operator, + stringPropertyOperator, + numericPropertyOperator, matchOperand)); } @@ -223,14 +226,16 @@ else if (matchCriteria == MatchCriteria.NONE) * @param instanceProperties collection of properties to work on (most will be primitives) * @param propertyTableName name of table holding the properties * @param topLevelPropertyName parent attribute name - not null when dealing with nested properties - * @param operator how to compare the property value stored with the property value supplied. + * @param stringPropertyOperator how to compare the property value stored with the property value supplied. + * @param numericPropertyOperator how to compare the property value stored with the property value supplied. * @param matchOperand how to combine the results from different properties * @return sql fragment wrapped in parentheses. Forms part of a where clause */ private String getPropertyComparisonFromInstanceProperties(InstanceProperties instanceProperties, String propertyTableName, String topLevelPropertyName, - PropertyComparisonOperator operator, + PropertyComparisonOperator stringPropertyOperator, + PropertyComparisonOperator numericPropertyOperator, String matchOperand) throws RepositoryErrorException { if ((instanceProperties != null) && (instanceProperties.getPropertyCount() > 0)) @@ -260,18 +265,29 @@ private String getPropertyComparisonFromInstanceProperties(InstanceProperties if (instancePropertyValue instanceof PrimitivePropertyValue primitivePropertyValue) { - stringBuilder.append(this.getNestedPropertyComparisonClause(propertyTableName, - topLevelPropertyName, - leafPropertyName, - operator, - primitivePropertyValue.getPrimitiveValue())); + if (primitivePropertyValue.getPrimitiveDefCategory() == PrimitiveDefCategory.OM_PRIMITIVE_TYPE_STRING) + { + stringBuilder.append(this.getNestedPropertyComparisonClause(propertyTableName, + topLevelPropertyName, + leafPropertyName, + stringPropertyOperator, + primitivePropertyValue.getPrimitiveValue())); + } + else + { + stringBuilder.append(this.getNestedPropertyComparisonClause(propertyTableName, + topLevelPropertyName, + leafPropertyName, + numericPropertyOperator, + primitivePropertyValue.getPrimitiveValue())); + } } else if (instancePropertyValue instanceof EnumPropertyValue enumPropertyValue) { stringBuilder.append(this.getNestedPropertyComparisonClause(propertyTableName, topLevelPropertyName, leafPropertyName, - operator, + stringPropertyOperator, enumPropertyValue.getSymbolicName())); } else if (instancePropertyValue instanceof MapPropertyValue mapPropertyValue) @@ -279,7 +295,8 @@ else if (instancePropertyValue instanceof MapPropertyValue mapPropertyValue) stringBuilder.append(getPropertyComparisonFromInstanceProperties(mapPropertyValue.getMapValues(), propertyTableName, leafPropertyName, - operator, + stringPropertyOperator, + numericPropertyOperator, matchOperand)); } else if (instancePropertyValue instanceof ArrayPropertyValue arrayPropertyValue) @@ -287,7 +304,8 @@ else if (instancePropertyValue instanceof ArrayPropertyValue arrayPropertyValue) stringBuilder.append(getPropertyComparisonFromInstanceProperties(arrayPropertyValue.getArrayValues(), propertyTableName, leafPropertyName, - operator, + stringPropertyOperator, + numericPropertyOperator, matchOperand)); } else if (instancePropertyValue instanceof StructPropertyValue structPropertyValue) @@ -295,7 +313,8 @@ else if (instancePropertyValue instanceof StructPropertyValue structPropertyValu stringBuilder.append(getPropertyComparisonFromInstanceProperties(structPropertyValue.getAttributes(), propertyTableName, leafPropertyName, - operator, + stringPropertyOperator, + numericPropertyOperator, matchOperand)); } } @@ -390,6 +409,10 @@ private String getNestedPropertyComparisonClause(String prop { return sqlClause + " and " + RepositoryColumn.PROPERTY_VALUE.getColumnName() + " like '" + propertyValue + "') "; } + case NOT_LIKE -> + { + return sqlClause + " and " + RepositoryColumn.PROPERTY_VALUE.getColumnName() + " not like '" + propertyValue + "') "; + } case NOT_NULL -> { return sqlClause; @@ -437,6 +460,10 @@ private String getNestedPropertyComparisonClause(String prop { return " (" + propertyColumn + " like '" + propertyValue + "') "; } + case NOT_LIKE -> + { + return " (" + propertyColumn + " not like '" + propertyValue + "') "; + } } } @@ -488,25 +515,20 @@ private String getSearchPropertiesClause() throws RepositoryErrorException * @param topLevelPropertyName parent attribute name - not null when dealing with nested properties * @return sql fragment wrapped in parentheses. Forms part of a where clause */ - private String getPropertyComparisonFromPropertyConditions(SearchProperties searchProperties, - String propertyTableName, - String topLevelPropertyName) throws RepositoryErrorException + private String getPropertyComparisonFromPropertyConditions(SearchProperties searchProperties, + String propertyTableName, + String topLevelPropertyName) throws RepositoryErrorException { if ((searchProperties != null) && (searchProperties.getConditions() != null) && (! searchProperties.getConditions().isEmpty())) { - String matchOperand = "' and "; - PropertyComparisonOperator operator = PropertyComparisonOperator.EQ; + String matchOperand = " and "; if (searchProperties.getMatchCriteria() == MatchCriteria.ANY) { - matchOperand = "' or "; - } - else if (searchProperties.getMatchCriteria() == MatchCriteria.NONE) - { - operator = PropertyComparisonOperator.NEQ; + matchOperand = " or "; } - StringBuilder stringBuilder = new StringBuilder(" ("); + StringBuilder stringBuilder = new StringBuilder(" and ("); boolean firstProperty = true; for (PropertyCondition propertyCondition : searchProperties.getConditions()) @@ -538,17 +560,17 @@ else if (searchProperties.getMatchCriteria() == MatchCriteria.NONE) if (instancePropertyValue instanceof PrimitivePropertyValue primitivePropertyValue) { stringBuilder.append(this.getNestedPropertyComparisonClause(propertyTableName, - topLevelPropertyName, - leafPropertyName, - operator, - primitivePropertyValue.getPrimitiveValue())); + topLevelPropertyName, + leafPropertyName, + propertyCondition.getOperator(), + primitivePropertyValue.getPrimitiveValue())); } else if (instancePropertyValue instanceof EnumPropertyValue enumPropertyValue) { stringBuilder.append(this.getNestedPropertyComparisonClause(propertyTableName, topLevelPropertyName, leafPropertyName, - operator, + propertyCondition.getOperator(), enumPropertyValue.getSymbolicName())); } else if (instancePropertyValue instanceof MapPropertyValue mapPropertyValue) @@ -556,7 +578,8 @@ else if (instancePropertyValue instanceof MapPropertyValue mapPropertyValue) stringBuilder.append(getPropertyComparisonFromInstanceProperties(mapPropertyValue.getMapValues(), propertyTableName, leafPropertyName, - operator, + propertyCondition.getOperator(), + propertyCondition.getOperator(), matchOperand)); } else if (instancePropertyValue instanceof ArrayPropertyValue arrayPropertyValue) @@ -564,7 +587,8 @@ else if (instancePropertyValue instanceof ArrayPropertyValue arrayPropertyValue) stringBuilder.append(getPropertyComparisonFromInstanceProperties(arrayPropertyValue.getArrayValues(), propertyTableName, leafPropertyName, - operator, + propertyCondition.getOperator(), + propertyCondition.getOperator(), matchOperand)); } else if (instancePropertyValue instanceof StructPropertyValue structPropertyValue) @@ -572,7 +596,8 @@ else if (instancePropertyValue instanceof StructPropertyValue structPropertyValu stringBuilder.append(getPropertyComparisonFromInstanceProperties(structPropertyValue.getAttributes(), propertyTableName, leafPropertyName, - operator, + propertyCondition.getOperator(), + propertyCondition.getOperator(), matchOperand)); } } @@ -1148,7 +1173,7 @@ public String getPrimaryKeysClause(String instanceGUID, if (classificationName != null) { - sqlFragment = sqlFragment + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + "'"; + sqlFragment = sqlFragment + " and " + RepositoryColumn.CLASSIFICATION_NAME.getColumnName() + " = '" + classificationName + "' "; } return sqlFragment + ")"; @@ -1168,55 +1193,13 @@ public String getPrimaryKeysClause(String instanceGUID, public String getPropertyJoinQuery(String principleTableName, String propertiesTableName) { - return "select distinct " + RepositoryColumn.INSTANCE_GUID.getColumnName(principleTableName) + - " from " + principleTableName + - " left outer join " + propertiesTableName + - " on " + RepositoryColumn.INSTANCE_GUID.getColumnName(principleTableName) + " = " + RepositoryColumn.INSTANCE_GUID.getColumnName(propertiesTableName) + - " and " + RepositoryColumn.VERSION.getColumnName(principleTableName) + " = " + RepositoryColumn.VERSION.getColumnName(propertiesTableName); + return "select * from " + principleTableName + + " left outer join " + propertiesTableName + + " on " + RepositoryColumn.INSTANCE_GUID.getColumnName(principleTableName) + " = " + RepositoryColumn.INSTANCE_GUID.getColumnName(propertiesTableName) + + " and " + RepositoryColumn.VERSION.getColumnName(principleTableName) + " = " + RepositoryColumn.VERSION.getColumnName(propertiesTableName); } - /** - * Return a starch string for properties of an entity or relationship. - * - * @param guidVersionMap map - * @return sql fragment - */ - public String getGUIDListPropertiesQueryWhereClause(Map guidVersionMap) - { - if (guidVersionMap != null) - { - StringBuilder stringBuilder = new StringBuilder(); - boolean firstGUID = true; - - for (String instanceGUID : guidVersionMap.keySet()) - { - if (firstGUID) - { - firstGUID = false; - } - else - { - stringBuilder.append(" or "); - } - - stringBuilder.append("("); - stringBuilder.append(RepositoryColumn.INSTANCE_GUID.getColumnName()); - stringBuilder.append(" = '"); - stringBuilder.append(instanceGUID); - stringBuilder.append("' and "); - stringBuilder.append(RepositoryColumn.VERSION.getColumnName()); - stringBuilder.append(" = "); - stringBuilder.append(guidVersionMap.get(instanceGUID)); - stringBuilder.append(")"); - } - - return stringBuilder.toString(); - } - - return " "; - } - /** * Return the where clause built up from the query parameters supplied. * @@ -1234,9 +1217,7 @@ public String getAsOfTimeWhereClause() throws RepositoryErrorException getSearchClassificationsClause() + getTypeClause() + getLimitResultsByClassificationClaus() + - getLimitResultsByStatusClause() + - getSequencingOrder() + - getPaging(); + getLimitResultsByStatusClause(); if (log.isDebugEnabled()) { @@ -1248,6 +1229,25 @@ public String getAsOfTimeWhereClause() throws RepositoryErrorException } + /** + * The sequencing (order by) and paging (limit/offset) can only be added at the end and may only include + * + * @return sql fragment + */ + public String getSequenceAndPaging() + { + String clause = getSequencingOrder() + + getPaging(); + + if (log.isDebugEnabled()) + { + log.debug(this.toString()); + log.debug(clause); + } + + return clause + ";"; + } + /** * toString() JSON-style diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/ClassificationMapper.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/ClassificationMapper.java index 848b7096bd4..692b3744565 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/ClassificationMapper.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/ClassificationMapper.java @@ -84,6 +84,7 @@ public Classification getClassification() throws RepositoryErrorException Classification newClassification = new Classification(); super.fillInstanceAuditHeader(newClassification, classificationTableRow); + newClassification.setName(super.getStringPropertyFromColumn(RepositoryColumn.CLASSIFICATION_NAME.getColumnName(), classificationTableRow, true)); newClassification.setProperties(super.getInstanceProperties(classificationTableRow, classificationPropertiesTableRows)); classification = newClassification; diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/EntityMapper.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/EntityMapper.java index 131252c1ede..4f0b23512ea 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/EntityMapper.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/EntityMapper.java @@ -270,7 +270,7 @@ else if (entityProxy != null) null, null, null, - entityDetail); + entityProxy); } super.setUpBooleanValueInRow(newEntityTableRow, true, RepositoryColumn.IS_PROXY.getColumnName()); @@ -367,7 +367,7 @@ else if (entityProxy != null) methodName); } - if (! uniquePropertiesTableRows.isEmpty()) + if ((uniquePropertiesTableRows != null) && (! uniquePropertiesTableRows.isEmpty())) { return uniquePropertiesTableRows; } diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/RelationshipMapper.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/RelationshipMapper.java index 6e7dba16aa2..59084bb80f4 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/RelationshipMapper.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/RelationshipMapper.java @@ -11,7 +11,6 @@ import org.odpi.openmetadata.repositoryservices.connectors.stores.metadatacollectionstore.repositoryconnector.OMRSRepositoryHelper; import org.odpi.openmetadata.repositoryservices.ffdc.exception.RepositoryErrorException; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/RepositoryMapper.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/RepositoryMapper.java index fdcb93726da..f14320f63f0 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/RepositoryMapper.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/mappers/RepositoryMapper.java @@ -858,6 +858,7 @@ private void setUpTypeNameInRow(Map instanceTableRow, * Add the values from the header into a table row. * * @param instanceTableRow row + * @param instanceGUID unique identifier of the instance * @param classificationName optional classification name * @param effectiveFromTime effective from (optional) * @param effectiveToTime effective to (optional) @@ -872,17 +873,31 @@ protected void extractValuesFromInstanceHeader(Map instan Date versionEndTime, InstanceHeader instanceHeader) throws RepositoryErrorException { - extractValuesFromInstanceAuditHeader(instanceTableRow, - instanceHeader.getGUID(), - classificationName, - effectiveFromTime, - effectiveToTime, - versionEndTime, - instanceHeader); - - super.setUpStringValueInRow(instanceTableRow, instanceHeader.getInstanceURL(), RepositoryColumn.INSTANCE_URL.getColumnName(), false); - super.setUpStringValueInRow(instanceTableRow, instanceHeader.getInstanceLicense(), RepositoryColumn.INSTANCE_LICENCE.getColumnName(), false); - super.setUpStringValueInRow(instanceTableRow, instanceHeader.getReIdentifiedFromGUID(), RepositoryColumn.REIDENTIFIED_FROM_GUID.getColumnName(), false); + final String methodName = "extractValuesFromInstanceHeader"; + final String parameterName = "instanceTableRow"; + + if (instanceTableRow != null) + { + extractValuesFromInstanceAuditHeader(instanceTableRow, + instanceHeader.getGUID(), + classificationName, + effectiveFromTime, + effectiveToTime, + versionEndTime, + instanceHeader); + + super.setUpStringValueInRow(instanceTableRow, instanceHeader.getInstanceURL(), RepositoryColumn.INSTANCE_URL.getColumnName(), false); + super.setUpStringValueInRow(instanceTableRow, instanceHeader.getInstanceLicense(), RepositoryColumn.INSTANCE_LICENCE.getColumnName(), false); + super.setUpStringValueInRow(instanceTableRow, instanceHeader.getReIdentifiedFromGUID(), RepositoryColumn.REIDENTIFIED_FROM_GUID.getColumnName(), false); + } + else + { + throw new RepositoryErrorException(PostgresErrorCode.MISSING_MAPPING_VALUE.getMessageDefinition(parameterName, + methodName, + this.getClass().getName()), + this.getClass().getName(), + methodName); + } } diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/schema/RepositoryColumn.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/schema/RepositoryColumn.java index 4801eebdfa1..8252ddef483 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/schema/RepositoryColumn.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/schema/RepositoryColumn.java @@ -22,7 +22,7 @@ public enum RepositoryColumn implements PostgreSQLColumn METADATA_COLLECTION_GUID("metadata_collection_guid", ColumnType.STRING, "Unique identifier of a metadata collection.", true), - METADATA_COLLECTION_NAME("metadata_collection_name", ColumnType.STRING, "Unique name of a metadata collection.", true), + METADATA_COLLECTION_NAME("metadata_collection_name", ColumnType.STRING, "Unique name of a metadata collection.", false), INSTANCE_PROVENANCE_TYPE("instance_provenance_type", ColumnType.STRING, "Category of metadata collection.", true), REPLICATED_BY("replicated_by", ColumnType.STRING, "Metadata collection guid responsible for propagating updates about this instance.", false), diff --git a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/schema/RepositoryTable.java b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/schema/RepositoryTable.java index 85245438113..300551efe7a 100644 --- a/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/schema/RepositoryTable.java +++ b/open-metadata-implementation/adapters/open-connectors/repository-services-connectors/open-metadata-collection-store-connectors/postgres-repository-connector/src/main/java/org/odpi/openmetadata/adapters/repositoryservices/postgres/repositoryconnector/schema/RepositoryTable.java @@ -327,22 +327,6 @@ public Map getColumnNameTypeMap() } - /** - * Return the name to type map for the supplied column. - * - * @param column column to set up - * @return map - */ - public static Map getSingleColumnNameTypeMap(RepositoryColumn column) - { - Map columnNameTypeMap = new HashMap<>(); - - columnNameTypeMap.put(column.getColumnName(), column.getColumnType().getJdbcType()); - - return columnNameTypeMap; - } - - /** * Return the list of foreign keys for this table. * diff --git a/open-metadata-implementation/repository-services/Egeria-repository-services-local-repository.http b/open-metadata-implementation/repository-services/Egeria-repository-services-local-repository.http index ff88b0515c7..4cab8abfadc 100644 --- a/open-metadata-implementation/repository-services/Egeria-repository-services-local-repository.http +++ b/open-metadata-implementation/repository-services/Egeria-repository-services-local-repository.http @@ -29,7 +29,7 @@ GET {{baseURL}}/servers/{{server}}/open-metadata/repository-services/users/{{use ### -@entityGUID=108b85fe-d7b8-45c3-9fb8-742ac4e4fb14 +@entityGUID=84e3f4d7-bd2b-4f34-9a34-7f018a7570fd ### diff --git a/open-metadata-implementation/repository-services/repository-services-apis/src/main/java/org/odpi/openmetadata/repositoryservices/connectors/stores/metadatacollectionstore/properties/search/PropertyComparisonOperator.java b/open-metadata-implementation/repository-services/repository-services-apis/src/main/java/org/odpi/openmetadata/repositoryservices/connectors/stores/metadatacollectionstore/properties/search/PropertyComparisonOperator.java index 277ab660c8a..eb3ed0fa648 100644 --- a/open-metadata-implementation/repository-services/repository-services-apis/src/main/java/org/odpi/openmetadata/repositoryservices/connectors/stores/metadatacollectionstore/properties/search/PropertyComparisonOperator.java +++ b/open-metadata-implementation/repository-services/repository-services-apis/src/main/java/org/odpi/openmetadata/repositoryservices/connectors/stores/metadatacollectionstore/properties/search/PropertyComparisonOperator.java @@ -102,7 +102,12 @@ public enum PropertyComparisonOperator implements Serializable /** * Has a value that matches the provided regular expression (strings only). */ - LIKE (9, "Like", "Has a value that matches the provided regular expression (strings only)."); + LIKE (9, "Like", "Has a value that matches the provided regular expression (strings only)."), + + /** + * Has a value that matches the provided regular expression (strings only). + */ + NOT_LIKE (10, "Not Like", "Has a value that does not match the provided regular expression (strings only)."); private static final long serialVersionUID = 1L; diff --git a/open-metadata-implementation/repository-services/repository-services-apis/src/main/java/org/odpi/openmetadata/repositoryservices/connectors/stores/metadatacollectionstore/repositoryconnector/OMRSRepositoryHelper.java b/open-metadata-implementation/repository-services/repository-services-apis/src/main/java/org/odpi/openmetadata/repositoryservices/connectors/stores/metadatacollectionstore/repositoryconnector/OMRSRepositoryHelper.java index 59457dd57f5..d5b0417429e 100644 --- a/open-metadata-implementation/repository-services/repository-services-apis/src/main/java/org/odpi/openmetadata/repositoryservices/connectors/stores/metadatacollectionstore/repositoryconnector/OMRSRepositoryHelper.java +++ b/open-metadata-implementation/repository-services/repository-services-apis/src/main/java/org/odpi/openmetadata/repositoryservices/connectors/stores/metadatacollectionstore/repositoryconnector/OMRSRepositoryHelper.java @@ -1079,6 +1079,21 @@ List formatRelationshipResults(List fullResults, PropertyErrorException; + /** + * Compare the properties of two instances and determine the sort order based on the nominated property value and + * sort order. + * + * @param instance1Properties properties from first instance + * @param instance2Properties properties from second instance + * @param propertyName name of property to compare + * @param sequencingOrder ascending or descending order + * @return sort result + */ + int compareProperties(InstanceProperties instance1Properties, + InstanceProperties instance2Properties, + String propertyName, + SequencingOrder sequencingOrder); + /** * Retrieve an escaped version of the provided string that can be passed to methods that expect regular expressions, * without being interpreted as a regular expression (i.e. the returned string will be interpreted as a literal -- diff --git a/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositoryconnector/LocalOMRSMetadataCollection.java b/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositoryconnector/LocalOMRSMetadataCollection.java index 57ef7967b77..9600a64eed6 100644 --- a/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositoryconnector/LocalOMRSMetadataCollection.java +++ b/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositoryconnector/LocalOMRSMetadataCollection.java @@ -1466,21 +1466,17 @@ private List setLocalProvenanceInEntityList(List i } else { - /* - * We have seen duplicate instances coming out of XTDB - the map de-duplicates. - */ - Map resultList = new HashMap<>(); + List resultList = new ArrayList<>(); for (EntityDetail entity : instanceList) { if (entity != null) { - setLocalProvenanceThroughoutEntity(entity); - resultList.put(entity.getGUID(), entity); + resultList.add(entity); } } - return new ArrayList<>(resultList.values()); + return resultList; } } @@ -1499,21 +1495,18 @@ private List setLocalProvenanceInRelationshipList(List resultList = new HashMap<>(); + List resultList = new ArrayList<>(); for (Relationship relationship : instanceList) { if (relationship != null) { setLocalProvenanceThroughoutRelationship(relationship); - resultList.put(relationship.getGUID(), relationship); + resultList.add(relationship); } } - return new ArrayList<>(resultList.values()); + return resultList; } } diff --git a/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositorycontentmanager/OMRSRepositoryContentHelper.java b/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositorycontentmanager/OMRSRepositoryContentHelper.java index 4600f6cdc14..d7a05e97d40 100644 --- a/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositorycontentmanager/OMRSRepositoryContentHelper.java +++ b/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositorycontentmanager/OMRSRepositoryContentHelper.java @@ -2538,12 +2538,10 @@ public List formatEntityResults(List fullResults, if (sequencingOrder.equals(SequencingOrder.PROPERTY_ASCENDING) || sequencingOrder.equals(SequencingOrder.PROPERTY_DESCENDING)) { // If the sequencing is property-based, handover to the property comparator - fullResults.sort((one, two) -> OMRSRepositoryContentHelper.compareProperties( - one.getProperties(), - two.getProperties(), - sequencingProperty, - sequencingOrder - )); + fullResults.sort((one, two) -> this.compareProperties(one.getProperties(), + two.getProperties(), + sequencingProperty, + sequencingOrder)); } else { @@ -2610,12 +2608,10 @@ public List formatRelationshipResults(List fullRe if (sequencingOrder.equals(SequencingOrder.PROPERTY_ASCENDING) || sequencingOrder.equals(SequencingOrder.PROPERTY_DESCENDING)) { // If the sequencing is property-based, handover to the property comparator - fullResults.sort((one, two) -> OMRSRepositoryContentHelper.compareProperties( - one.getProperties(), - two.getProperties(), - sequencingProperty, - sequencingOrder - )); + fullResults.sort((one, two) -> this.compareProperties(one.getProperties(), + two.getProperties(), + sequencingProperty, + sequencingOrder)); } else { @@ -2765,10 +2761,10 @@ else if (createOne == null) * @param sequencingOrder ascending or descending order * @return sort result */ - private static int compareProperties(InstanceProperties instance1Properties, - InstanceProperties instance2Properties, - String propertyName, - SequencingOrder sequencingOrder) + public int compareProperties(InstanceProperties instance1Properties, + InstanceProperties instance2Properties, + String propertyName, + SequencingOrder sequencingOrder) { // todo need to add support for properties in the instance header eg createdBy @@ -2865,51 +2861,26 @@ else if (!o1PropertyTypeName.equals(o2PropertyTypeName)) */ private static int typeSpecificCompare(String typeName, Object v1, Object v2) { - int sortOrder; - switch (typeName) - { - case "boolean": - sortOrder = ((Boolean) v1).compareTo((Boolean) v2); - break; - case "byte": - sortOrder = ((Byte) v1).compareTo((Byte) v2); - break; - case "char": - sortOrder = ((Character) v1).compareTo((Character) v2); - break; - case "short": - sortOrder = ((Short) v1).compareTo((Short) v2); - break; - case "integer": - sortOrder = ((Integer) v1).compareTo((Integer) v2); - break; - case "long": - sortOrder = ((Long) v1).compareTo((Long) v2); - break; - case "float": - sortOrder = ((Float) v1).compareTo((Float) v2); - break; - case "double": - sortOrder = ((Double) v1).compareTo((Double) v2); - break; - case "biginteger": - sortOrder = ((BigInteger) v1).compareTo((BigInteger) v2); - break; - case "bigdecimal": - sortOrder = ((BigDecimal) v1).compareTo((BigDecimal) v2); - break; - case "string": - sortOrder = ((String) v1).compareTo((String) v2); - break; - case "date": - sortOrder = ((Date) v1).compareTo((Date) v2); - break; - default: + return switch (typeName) + { + case "boolean" -> ((Boolean) v1).compareTo((Boolean) v2); + case "byte" -> ((Byte) v1).compareTo((Byte) v2); + case "char" -> ((Character) v1).compareTo((Character) v2); + case "short" -> ((Short) v1).compareTo((Short) v2); + case "integer" -> ((Integer) v1).compareTo((Integer) v2); + case "long" -> ((Long) v1).compareTo((Long) v2); + case "float" -> ((Float) v1).compareTo((Float) v2); + case "double" -> ((Double) v1).compareTo((Double) v2); + case "biginteger" -> ((BigInteger) v1).compareTo((BigInteger) v2); + case "bigdecimal" -> ((BigDecimal) v1).compareTo((BigDecimal) v2); + case "string" -> ((String) v1).compareTo((String) v2); + case "date" -> ((Date) v1).compareTo((Date) v2); + default -> + { log.debug("Property type not catered for in compare function"); - sortOrder = 0; - } - - return sortOrder; + yield 0; + } + }; } diff --git a/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositorycontentmanager/OMRSRepositoryContentValidator.java b/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositorycontentmanager/OMRSRepositoryContentValidator.java index 12f9e47bd50..d4af9ccf970 100644 --- a/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositorycontentmanager/OMRSRepositoryContentValidator.java +++ b/open-metadata-implementation/repository-services/repository-services-implementation/src/main/java/org/odpi/openmetadata/repositoryservices/localrepository/repositorycontentmanager/OMRSRepositoryContentValidator.java @@ -61,7 +61,6 @@ public OMRSRepositoryContentValidator(OMRSRepositoryContentManager repositoryCon /** * Return a boolean flag indicating whether the list of TypeDefs passed are compatible with the * all known typedefs. - * * A valid TypeDef is one that matches name, GUID and version to the full list of TypeDefs. * If a new TypeDef is present, it is added to the enterprise list. * @@ -83,7 +82,6 @@ public void validateEnterpriseTypeDefs(String sourceName, /** * Return a boolean flag indicating whether the list of TypeDefs passed are compatible with the * all known typedefs. - * * A valid TypeDef is one that matches name, GUID and version to the full list of TypeDefs. * If a new TypeDef is present, it is added to the enterprise list. * @@ -445,10 +443,57 @@ public boolean validEntity(String sourceName, { final String methodName = "validEntity"; - return validInstance(sourceName, entity, methodName, false); + return validInstance(sourceName, entity, methodName, false) && + validClassifications(sourceName, entity); } + /** + * Check that the classifications for an entity are valid. + * + * @param sourceName source of the request (used for logging) + * @param entity entity to test + * @return boolean result + */ + private boolean validClassifications(String sourceName, + EntitySummary entity) + { + final String methodName = "validClassifications"; + + if (entity.getClassifications() != null) + { + for (Classification classification : entity.getClassifications()) + { + if (classification == null) + { + return false; + } + + if (classification.getName() == null) + { + repositoryContentManager.logNullInstance(sourceName, methodName); + return false; + } + + if (! this.validInstanceAuditHeader(sourceName, + entity.getGUID() + ":" + classification.getName(), + classification, + methodName, + false)) + { + return false; + } + + if (! classification.getName().equals(classification.getType().getTypeDefName())) + { + return false; + } + } + } + + return true; + } + /** * Test that the supplied entity is valid. * @@ -563,6 +608,67 @@ private boolean validInstance(String sourceName, } + /** + * Test that the supplied instance is valid. + * + * @param sourceName source of the request (used for logging) + * @param identifier identifier of the instance (typically guid - but may include classification name) + * @param instance instance to test + * @param methodName calling method + * @param fromStore is the entity from the store? + * @return boolean result + */ + private boolean validInstanceAuditHeader(String sourceName, + String identifier, + InstanceAuditHeader instance, + String methodName, + boolean fromStore) + { + if (instance == null) + { + repositoryContentManager.logNullInstance(sourceName, methodName); + return false; + } + + InstanceType instanceType = instance.getType(); + + if (instanceType == null) + { + repositoryContentManager.logNullType(sourceName, methodName); + return false; + } + + if (! validTypeDefId(sourceName, + instanceType.getTypeDefGUID(), + instanceType.getTypeDefName(), + instanceType.getTypeDefCategory())) + { + /* + * Error already logged + */ + return false; + } + + if (! fromStore) + { + String homeMetadataCollectionId = instance.getMetadataCollectionId(); + + if (homeMetadataCollectionId == null) + { + repositoryContentManager.logNullMetadataCollectionId(sourceName, + instanceType.getTypeDefGUID(), + instanceType.getTypeDefName(), + instanceType.getTypeDefCategory().getName(), + identifier, + methodName); + return false; + } + } + + return true; + } + + /** * Verify that the identifiers for an instance are correct. * @@ -1923,7 +2029,7 @@ public void validateSearchCriteria(String sourceName, String searchCriteria, String methodName) throws InvalidParameterException { - if ((searchCriteria == null) || (searchCriteria.length() == 0)) + if ((searchCriteria == null) || (searchCriteria.isEmpty())) { throw new InvalidParameterException(OMRSErrorCode.NO_SEARCH_CRITERIA.getMessageDefinition(parameterName, methodName, @@ -1936,13 +2042,19 @@ public void validateSearchCriteria(String sourceName, /** - * {@inheritDoc} + * Validate the property-based search conditions. + * + * @param sourceName source of the request (used for logging) + * @param parameterName name of the parameter that passed the property-based conditions + * @param matchProperties property-based conditions + * @param methodName method receiving the call + * @throws InvalidParameterException property-based conditions are invalid */ @Override - public void validateSearchProperties(String sourceName, - String parameterName, + public void validateSearchProperties(String sourceName, + String parameterName, SearchProperties matchProperties, - String methodName) throws InvalidParameterException + String methodName) throws InvalidParameterException { if (matchProperties == null) { @@ -1992,9 +2104,8 @@ else if (value == null) break; case LIKE: // For the LIKE operator, only a PrimitiveTypePropertyValue of type string is allowed - if (value instanceof PrimitivePropertyValue) + if (value instanceof PrimitivePropertyValue ppv) { - PrimitivePropertyValue ppv = (PrimitivePropertyValue) value; if (!ppv.getPrimitiveDefCategory().equals(OM_PRIMITIVE_TYPE_STRING)) { throw new InvalidParameterException(OMRSErrorCode.INVALID_LIKE_CONDITION.getMessageDefinition(), @@ -2016,9 +2127,8 @@ else if (value == null) case GT: case GTE: // For the <, <=, >=, > operators, only numeric or date types are allowed - if (value instanceof PrimitivePropertyValue) + if (value instanceof PrimitivePropertyValue ppv) { - PrimitivePropertyValue ppv = (PrimitivePropertyValue) value; PrimitiveDefCategory pdc = ppv.getPrimitiveDefCategory(); if (! (pdc.equals(OM_PRIMITIVE_TYPE_DATE) || pdc.equals(OM_PRIMITIVE_TYPE_SHORT) @@ -2079,7 +2189,7 @@ public void validateSearchClassifications(String sourceName, for (ClassificationCondition condition : matchClassifications.getConditions()) { String classificationName = condition.getName(); - if (classificationName == null || classificationName.equals("")) + if (classificationName == null || classificationName.isBlank()) { throw new InvalidParameterException(OMRSErrorCode.INVALID_CLASSIFICATION_SEARCH.getMessageDefinition(), this.getClass().getName(), diff --git a/open-metadata-implementation/view-services/glossary-manager/Egeria-glossary-manager-omvs.http b/open-metadata-implementation/view-services/glossary-manager/Egeria-glossary-manager-omvs.http index ce6ed5b3da9..954106f973c 100644 --- a/open-metadata-implementation/view-services/glossary-manager/Egeria-glossary-manager-omvs.http +++ b/open-metadata-implementation/view-services/glossary-manager/Egeria-glossary-manager-omvs.http @@ -39,6 +39,9 @@ Content-Type: application/json } } +### + +@glossaryGUID= add guid here ### # group: Glossaries @@ -83,7 +86,7 @@ Content-Type: application/json # group: Glossaries # @name Delete a glossary # Remove a glossary from the repository. -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/{{glossaryGUID}}/remove +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/{{glossaryGUID}}/remove Content-Type: application/json { @@ -98,7 +101,7 @@ Content-Type: application/json # group: Glossaries # @name Create a category # Save the returned guid in the domain1GUID variable. -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/{{glossaryGUID}}/categories +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/{{glossaryGUID}}/categories Content-Type: application/json { @@ -112,6 +115,10 @@ Content-Type: application/json } } +### + +@glossaryCategoryGUID=add guid here + ### # group: Glossaries # @name Retrieve ALL the categories for my glossary @@ -125,7 +132,7 @@ Content-Type: application/json # group: Glossaries # @name Create a controlled glossary term in a glossary # Add the returned guid as orgGlossaryTerm1GUID variable. -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/{{glossaryGUID}}/terms/new-controlled +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/{{glossaryGUID}}/terms/new-controlled Content-Type: application/json { @@ -150,11 +157,15 @@ Content-Type: application/json "initialStatus" : "DRAFT" } +### + +@glossaryTermGUID = add guid here + ### # group: Glossaries # @name Create a copy of a glossary term # Add the returned guid as adGlossaryTerm1GUID variable. -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/{{glossaryGUID}}/terms/from-template/{{glossaryTermGUID}} +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/{{glossaryGUID}}/terms/from-template/{{glossaryTermGUID}} Content-Type: application/json { @@ -172,7 +183,7 @@ Content-Type: application/json ### # group: Glossaries # @name Add the data field values classification to the glossary term -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/terms/{{glossaryTermGUID}}/is-data-field +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/classification-manager/glossaries/terms/{{glossaryTermGUID}}/is-data-field Content-Type: application/json { @@ -190,7 +201,7 @@ Content-Type: application/json ### # group: Glossaries # @name Add the confidentiality classification to the glossary term -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/elements/{{glossaryTermGUID}}/confidentiality +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/classification-manager/elements/{{glossaryTermGUID}}/confidentiality Content-Type: application/json { @@ -205,7 +216,7 @@ Content-Type: application/json ### # group: Glossaries # @name Add the subject area classification to the glossary term -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/elements/{{glossaryTermGUID}}/subject-area-member +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/classification-manager/elements/{{glossaryTermGUID}}/subject-area-member Content-Type: application/json { @@ -220,7 +231,7 @@ Content-Type: application/json ### # group: Glossaries # @name Update a glossary term in a glossary -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/terms/{{glossaryTermGUID}}/update? +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/terms/{{glossaryTermGUID}}/update? isMergeUpdate=true Content-Type: application/json @@ -237,7 +248,7 @@ Content-Type: application/json ### # group: Glossaries # @name Update a glossary term's version identfier -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/terms/{{glossaryTermGUID}}/update? +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/terms/{{glossaryTermGUID}}/update? isMergeUpdate=true Content-Type: application/json @@ -253,7 +264,7 @@ Content-Type: application/json ### # group: Glossaries # @name Add a glossary term to a cateogry -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/categories/{{glossaryCategoryGUID}}/terms/{{glossaryTermGUID}} +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/categories/{{glossaryCategoryGUID}}/terms/{{glossaryTermGUID}} Content-Type: application/json { @@ -266,13 +277,13 @@ Content-Type: application/json ### # group: Glossaries # @name Remove a glossary term from a category -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/categories/{{glossaryCategoryGUID}}/terms/{{glossaryTermGUID}}/remove +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/categories/{{glossaryCategoryGUID}}/terms/{{glossaryTermGUID}}/remove Content-Type: application/json ### # group: Glossaries # @name Change the status of a glossary term in a glossary -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/terms/{{glossaryTermGUID}}/status +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/terms/{{glossaryTermGUID}}/status Content-Type: application/json { @@ -283,7 +294,7 @@ Content-Type: application/json ### # group: Glossaries # @name Undo an update to the glossary term -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/terms/{{glossaryTermGUID}}/undo +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/terms/{{glossaryTermGUID}}/undo Content-Type: application/json ### @@ -364,6 +375,10 @@ POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/eleme pageSize=0 Content-Type: application/json +### + +@glossaryTermRevisionLogGUID=add guid here + ### # group: Glossaries # @name Retrieve the revision history for a glossary term @@ -376,7 +391,7 @@ Content-Type: application/json ### # group: Glossaries # @name Search for term by version identifier -POST {{baseURL}}/servers/{{viewServer}}/open-metadata/framework-services/asset-manager/open-metadata-store/users/{{user}}/metadata-elements/by-search-specification? +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/metadata-explorer/metadata-elements/by-search-specification? startFrom=0& pageSize=0& forLineage=false& @@ -406,7 +421,7 @@ Content-Type: application/json ### # group: Glossaries -# @name Delete a. glossary term +# @name Delete a glossary term # This call retrieves the details of the Abu Dhabi glossary and checks the adGlossaryGUID is set up properly. -POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-browser/glossaries/terms/{{glossaryTermGUID}}/remove +POST {{baseURL}}/servers/{{viewServer}}/api/open-metadata/glossary-manager/glossaries/terms/{{glossaryTermGUID}}/remove Content-Type: application/json