diff --git a/.docs/.prometheus/metrics-generate.sh b/.docs/.prometheus/metrics-generate.sh new file mode 100755 index 0000000000000000000000000000000000000000..2e78c1cef1778fd2c924d0e3d98af76700c91e6b --- /dev/null +++ b/.docs/.prometheus/metrics-generate.sh @@ -0,0 +1,4 @@ +#!/bin/bash +mvn -f ./dbrepo-metadata-service/pom.xml install +mvn -f ./dbrepo-data-service/pom.xml -pl rest-service -Dtest="PrometheusEndpointMvcTest" test +mvn -f ./dbrepo-metadata-service/pom.xml -pl rest-service -Dtest="PrometheusEndpointMvcTest" test diff --git a/.docs/.swagger/api-analyse.yaml b/.docs/.swagger/api-analyse.yaml deleted file mode 100644 index 211d54bd1510e217398c8cc6c6b89582d7e45941..0000000000000000000000000000000000000000 --- a/.docs/.swagger/api-analyse.yaml +++ /dev/null @@ -1,205 +0,0 @@ -components: - securitySchemes: - basicAuth: - in: header - scheme: basic - type: http - bearerAuth: - bearerFormat: JWT - in: header - scheme: bearer - type: http -externalDocs: - description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/__APPVERSION__/ -info: - contact: - email: andreas.rauber@tuwien.ac.at - name: Prof. Andreas Rauber - description: Service that analyses data structures - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 - title: Database Repository Analyse Service API - version: __APPVERSION__ -openapi: 3.0.0 -paths: - /api/analyse/database/{database_id}/table/{table_id}/statistics: - get: - operationId: analyse_table_stat - parameters: - - example: 1 - in: path - name: database_id - required: true - schema: - format: int64 - type: integer - - example: 1 - in: path - name: table_id - required: true - schema: - format: int64 - type: integer - responses: - '202': - content: - application/json: - schema: - $ref: '#/components/schemas/TableStats' - description: Determined statistics - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Missing parameters - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Table not found - security: - - bearerAuth: [] - - basicAuth: [] - summary: Determine table statistics - tags: - - analyse-endpoint - /api/analyse/datatypes: - get: - consumes: - - application/json - description: This is a simple API which returns the datatypes of a (path) csv - file - operationId: analyse_datatypes - parameters: - - example: filename_s3_key - in: query - name: filename - required: true - schema: - type: string - - example: ',' - in: query - name: separator - required: true - schema: - type: string - - example: 'false' - in: query - name: enum - required: false - schema: - type: boolean - - example: '2.5' - in: query - name: enum_tol - required: false - schema: - type: float - produces: - - application/json - responses: - '202': - content: - application/json: - schema: - $ref: '#/components/schemas/DataTypesDto' - description: Determined data types successfully - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Failed to determine data types - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Failed to find file in Storage Service - '500': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Unexpected system error - summary: Determine datatypes - tags: - - analyse-endpoint - /api/analyse/keys: - get: - consumes: - - application/json - description: This is a simple API which returns the primary keys + ranking of - a (path) csv file - operationId: analyse_keys - parameters: - - example: filename_s3_key - in: query - name: filename - required: true - schema: - type: string - - example: ',' - in: query - name: separator - required: true - schema: - type: string - produces: - - application/json - responses: - '202': - content: - application/json: - schema: - $ref: '#/components/schemas/KeysDto' - description: Determined keys successfully - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Failed to determine keys - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Failed to find file in Storage Service or is empty - '500': - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorDto' - description: Unexpected system error - summary: Determine primary keys - tags: - - analyse-endpoint - /health: - get: - consumes: - - application/json - description: This is a simple API which checks if the application is healthy - produces: - - application/json - responses: - '200': - description: OK - schema: - properties: - status: - example: UP - type: string - type: object - summary: Check if application is running - tags: - - health-endpoint -servers: - - description: Generated server url - url: http://localhost:5000 - - description: Sandbox - url: https://test.dbrepo.tuwien.ac.at diff --git a/.docs/.swagger/api-data.yaml b/.docs/.swagger/api-data.yaml deleted file mode 100644 index 662cecc3177d98c6f68882b8aafc6a882447eac6..0000000000000000000000000000000000000000 --- a/.docs/.swagger/api-data.yaml +++ /dev/null @@ -1,3118 +0,0 @@ -openapi: 3.0.1 -info: - title: Database Repository Data Service API - description: Service that manages the data - contact: - name: Prof. Andreas Rauber - email: andreas.rauber@tuwien.ac.at - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 - version: 1.4.3 -externalDocs: - description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.4.3/system-services-metadata/ -servers: -- url: http://localhost - description: Development instance -- url: https://test.dbrepo.tuwien.ac.at - description: Staging instance -paths: - /api/database/{databaseId}/view/{viewId}/data: - get: - tags: - - view-endpoint - summary: Get view data - operationId: getData - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: viewId - in: path - required: true - schema: - type: integer - format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time - responses: - "200": - description: Returned view data - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - security: - - basicAuth: [] - - bearerAuth: [] - head: - tags: - - view-endpoint - summary: Get view data - operationId: getData_1 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: viewId - in: path - required: true - schema: - type: integer - format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time - responses: - "200": - description: Returned view data - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/table/{tableId}/data: - get: - tags: - - table-endpoint - summary: Find table data - operationId: getData_2 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - responses: - "200": - description: Found table data - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - security: - - basicAuth: [] - - bearerAuth: [] - put: - tags: - - table-endpoint - summary: Update table data - operationId: updateTuple - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TupleUpdateDto' - required: true - responses: - "202": - description: Updated table data - security: - - basicAuth: [] - - bearerAuth: [] - post: - tags: - - table-endpoint - summary: Create table data - operationId: createTuple - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TupleDto' - required: true - responses: - "201": - description: Created table data - security: - - basicAuth: [] - - bearerAuth: [] - delete: - tags: - - table-endpoint - summary: Delete table data - operationId: deleteTuple - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TupleDeleteDto' - required: true - responses: - "202": - description: Deleted table data - security: - - basicAuth: [] - - bearerAuth: [] - head: - tags: - - table-endpoint - summary: Find table data - operationId: getData_3 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - responses: - "200": - description: Found table data - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/subset/{subsetId}/data: - get: - tags: - - subset-endpoint - summary: Re-execute some query - operationId: getData_4 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: subsetId - in: path - required: true - schema: - type: integer - format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - responses: - "200": - description: Get subset data - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - security: - - bearerAuth: [] - - basicAuth: [] - head: - tags: - - subset-endpoint - summary: Re-execute some query - operationId: getData_5 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: subsetId - in: path - required: true - schema: - type: integer - format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - responses: - "200": - description: Get subset data - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}: - put: - tags: - - database-endpoint - summary: Update user password in database - operationId: update - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateUserPasswordDto' - required: true - responses: - "202": - description: Created a new database - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - "400": - description: Database create query is malformed or image is not supported - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - basicAuth: [] - /api/database/{databaseId}/subset/{queryId}: - put: - tags: - - subset-endpoint - summary: Persist some query - operationId: persist - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: queryId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/QueryPersistDto' - required: true - responses: - "202": - description: Persist query successful - content: - application/json: - schema: - $ref: '#/components/schemas/QueryDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/access/{userId}: - put: - tags: - - access-endpoint - summary: Modify access to some database - operationId: update_1 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateDatabaseAccessDto' - required: true - responses: - "404": - description: Database or user not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Modify access query or database connection is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: Access could not be updated in the data service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Modify access not permitted when no access is granted in the - first place - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Modify access succeeded - security: - - basicAuth: [] - post: - tags: - - access-endpoint - summary: Give access to some database - operationId: create_4 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateDatabaseAccessDto' - required: true - responses: - "202": - description: Granting access succeeded - "404": - description: Database or user not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "405": - description: Granting access not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Failed giving access - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Granting access query or database connection is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: Access could not be created in the data service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - basicAuth: [] - delete: - tags: - - access-endpoint - summary: Revoke access to some database - operationId: revoke - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - "202": - description: Revoked access successfully - "400": - description: Modify access query or database connection is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: "User, database with access was not found" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: Access could not be revoked in the data service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Revoke of access not permitted as no access was found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - basicAuth: [] - /api/database: - post: - tags: - - database-endpoint - summary: Create database - operationId: create - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/CreateDatabaseDto' - required: true - responses: - "201": - description: Created a new database - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - "400": - description: Database create query is malformed or image is not supported - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - basicAuth: [] - /api/database/{databaseId}/view: - post: - tags: - - view-endpoint - summary: Create view - operationId: create_1 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ViewCreateDto' - required: true - responses: - "202": - description: Created a new view - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/table: - post: - tags: - - table-endpoint - summary: Create table - operationId: create_2 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TableCreateDto' - required: true - responses: - "202": - description: Created a new table - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - security: - - basicAuth: [] - /api/database/{databaseId}/table/{tableId}/data/import: - post: - tags: - - table-endpoint - summary: Insert data from csv - operationId: importData - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ImportCsvDto' - required: true - responses: - "202": - description: Import successfully - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/subset: - get: - tags: - - subset-endpoint - summary: Find subsets - operationId: findAllById - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: persisted - in: query - required: false - schema: - type: boolean - responses: - "200": - description: Found subsets - content: - application/json: - schema: - type: string - security: - - basicAuth: [] - - bearerAuth: [] - post: - tags: - - subset-endpoint - summary: Create subset - operationId: create_3 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: page - in: query - required: false - schema: - type: integer - format: int64 - - name: size - in: query - required: false - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ExecuteStatementDto' - required: true - responses: - "201": - description: Created subset - content: - application/json: - schema: - $ref: '#/components/schemas/QueryResultDto' - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/table/{tableId}/history: - get: - tags: - - table-endpoint - summary: Find table history - operationId: getHistory - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "200": - description: Found table history - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/table/{tableId}/export: - get: - tags: - - table-endpoint - summary: Export table data - operationId: exportData - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time - responses: - "200": - description: Exported table data - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/subset/{subsetId}: - get: - tags: - - subset-endpoint - summary: Find subset - operationId: findById - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: subsetId - in: path - required: true - schema: - type: integer - format: int64 - - name: timestamp - in: query - required: false - schema: - type: string - format: date-time - responses: - "200": - description: Found subset - content: - '*/*': - schema: - type: object - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/view/{viewId}: - delete: - tags: - - view-endpoint - summary: Delete view in database - operationId: delete - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: viewId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "201": - description: Deleted table - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - security: - - basicAuth: [] - - bearerAuth: [] - /api/database/{databaseId}/table/{tableId}: - delete: - tags: - - table-endpoint - summary: Delete table in database - operationId: delete_1 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "201": - description: Deleted table - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - security: - - basicAuth: [] -components: - schemas: - QueryResultDto: - required: - - headers - - id - - result - type: object - properties: - result: - type: array - items: - type: object - additionalProperties: - type: object - headers: - type: array - items: - type: object - additionalProperties: - type: integer - format: int32 - id: - type: integer - format: int64 - UpdateUserPasswordDto: - required: - - password - - username - type: object - properties: - username: - type: string - password: - type: string - ColumnBriefDto: - required: - - column_type - - database_id - - id - - internal_name - - name - - table_id - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: date - alias: - type: string - database_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - internal_name: - type: string - example: mdb_date - column_type: - type: string - example: date - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - ColumnDto: - required: - - auto_generated - - column_type - - database_id - - id - - internal_name - - is_null_allowed - - is_public - - name - - ordinal_position - - table_id - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Date - alias: - type: string - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - mean: - type: number - example: 45.4 - median: - type: number - example: 51 - concept: - $ref: '#/components/schemas/ConceptDto' - unit: - $ref: '#/components/schemas/UnitDto' - table: - $ref: '#/components/schemas/TableDto' - views: - type: array - items: - $ref: '#/components/schemas/ViewDto' - enums: - type: array - items: - type: string - sets: - type: array - items: - type: string - database_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - ordinal_position: - type: integer - format: int32 - example: 0 - internal_name: - type: string - example: mdb_date - date_format: - $ref: '#/components/schemas/ImageDateDto' - auto_generated: - type: boolean - example: false - index_length: - type: integer - format: int64 - length: - type: integer - format: int64 - column_type: - type: string - example: string - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - data_length: - type: integer - format: int64 - example: 34300 - max_data_length: - type: integer - format: int64 - example: 34300 - num_rows: - type: integer - format: int64 - example: 32 - val_min: - type: number - example: 0 - val_max: - type: number - example: 100 - std_dev: - type: number - example: 5.32 - is_public: - type: boolean - example: true - is_null_allowed: - type: boolean - example: false - ConceptDto: - required: - - columns - - created - - id - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - columns: - type: array - items: - $ref: '#/components/schemas/ColumnBriefDto' - ConstraintsDto: - type: object - properties: - uniques: - type: array - items: - $ref: '#/components/schemas/UniqueDto' - checks: - uniqueItems: true - type: array - items: - type: string - foreign_keys: - type: array - items: - $ref: '#/components/schemas/ForeignKeyDto' - primary_key: - uniqueItems: true - type: array - items: - type: string - ContainerDto: - required: - - created - - host - - id - - image - - internal_name - - name - - sidecar_host - - sidecar_port - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - host: - type: string - port: - type: integer - format: int32 - image: - $ref: '#/components/schemas/ImageDto' - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - internal_name: - type: string - example: data-db - sidecar_host: - type: string - sidecar_port: - type: integer - format: int32 - ui_host: - type: string - ui_port: - type: integer - format: int32 - CreatorDto: - required: - - creator_name - - id - type: object - properties: - id: - type: integer - format: int64 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Brown University - creator_name: - type: string - example: "Carberry, Josiah" - name_type: - type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: - type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: - type: string - example: ORCID - enum: - - ORCID - - ROR - - ISNI - - GRID - name_identifier_scheme_uri: - type: string - example: https://orcid.org/ - affiliation_identifier: - type: string - example: https://ror.org/05gq02987 - affiliation_identifier_scheme: - type: string - example: ROR - enum: - - ROR - - GRID - - ISNI - affiliation_identifier_scheme_uri: - type: string - example: https://ror.org/ - DatabaseAccessDto: - required: - - created - - type - - user - type: object - properties: - user: - $ref: '#/components/schemas/UserDto' - type: - type: string - enum: - - read - - write_own - - write_all - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - DatabaseDto: - required: - - contact - - container - - created - - creator - - exchange_name - - id - - internal_name - - is_public - - name - - owner - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality - tables: - type: array - items: - $ref: '#/components/schemas/TableDto' - views: - type: array - items: - $ref: '#/components/schemas/ViewDto' - container: - $ref: '#/components/schemas/ContainerDto' - accesses: - type: array - items: - $ref: '#/components/schemas/DatabaseAccessDto' - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - subsets: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - creator: - $ref: '#/components/schemas/UserDto' - contact: - $ref: '#/components/schemas/UserDto' - owner: - $ref: '#/components/schemas/UserDto' - image: - type: array - items: - type: string - format: byte - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - exchange_name: - type: string - example: dbrepo - exchange_type: - type: string - example: topic - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - ForeignKeyDto: - type: object - properties: - name: - type: string - columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - referenced_table: - $ref: '#/components/schemas/TableBriefDto' - referenced_columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - on_update: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - on_delete: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - IdentifierDescriptionDto: - required: - - id - type: object - properties: - id: - type: integer - format: int64 - description: - type: string - example: "Air quality reports at Stephansplatz, Vienna" - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - example: Abstract - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - IdentifierDto: - required: - - created - - created_by - - creator - - creators - - database_id - - execution - - id - - last_modified - - publication_year - - publisher - - query - - query_hash - - query_normalized - - titles - - type - type: object - properties: - id: - type: integer - format: int64 - type: - type: string - enum: - - database - - subset - - table - - view - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierTitleDto' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierDescriptionDto' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunderDto' - query: - type: string - example: "SELECT `id`, `value`, `location` FROM `air_quality` WHERE `location`\ - \ = \"09:STEF\"" - execution: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - doi: - type: string - example: 10.1038/nphys1170 - publisher: - type: string - example: TU Wien - creator: - $ref: '#/components/schemas/UserDto' - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - licenses: - type: array - items: - $ref: '#/components/schemas/LicenseDto' - creators: - type: array - items: - $ref: '#/components/schemas/CreatorDto' - status: - type: string - enum: - - draft - - published - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - database_id: - type: integer - format: int64 - example: 1 - query_id: - type: integer - format: int64 - example: 1 - table_id: - type: integer - format: int64 - example: 1 - view_id: - type: integer - format: int64 - example: 1 - query_normalized: - type: string - example: "SELECT `id`, `value`, `location` FROM `air_quality` WHERE `location`\ - \ = \"09:STEF\"" - related_identifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifierDto' - query_hash: - type: string - description: query hash in sha512 - result_hash: - type: string - example: 34fe82cda2c53f13f8d90cfd7a3469e3a939ff311add50dce30d9136397bf8e5 - result_number: - type: integer - format: int64 - example: 1 - publication_day: - type: integer - format: int32 - example: 15 - publication_month: - type: integer - format: int32 - example: 12 - publication_year: - type: integer - format: int32 - example: 2022 - created_by: - type: string - format: uuid - last_modified: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - IdentifierFunderDto: - required: - - funder_name - - id - type: object - properties: - id: - type: integer - format: int64 - funder_name: - type: string - example: European Commission - funder_identifier: - type: string - example: http://doi.org/10.13039/501100000780 - funder_identifier_type: - type: string - example: Crossref Funder ID - enum: - - Crossref Funder ID - - ROR - - GND - - ISNI - - Other - scheme_uri: - type: string - example: http://doi.org/ - award_number: - type: string - example: "824087" - award_title: - type: string - example: EOSC-Life - IdentifierTitleDto: - required: - - id - type: object - properties: - id: - type: integer - format: int64 - title: - type: string - example: Airquality Demonstrator - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle - - Other - ImageDateDto: - required: - - created_at - - database_format - - has_time - - id - - unix_format - type: object - properties: - id: - type: integer - format: int64 - database_format: - type: string - example: '%d.%c.%Y' - unix_format: - type: string - example: dd.MM.YYYY - has_time: - type: boolean - example: false - created_at: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - ImageDto: - required: - - default_port - - dialect - - driver_class - - id - - jdbc_method - - name - - registry - - version - type: object - properties: - id: - type: integer - format: int64 - registry: - type: string - example: docker.io/library - name: - type: string - example: mariadb - version: - type: string - example: "10.5" - dialect: - type: string - example: org.hibernate.dialect.MariaDBDialect - driver_class: - type: string - example: org.mariadb.jdbc.Driver - date_formats: - type: array - items: - $ref: '#/components/schemas/ImageDateDto' - jdbc_method: - type: string - example: mariadb - default_port: - type: integer - format: int32 - example: 3306 - LicenseDto: - required: - - identifier - - uri - type: object - properties: - identifier: - type: string - example: MIT - uri: - type: string - example: https://opensource.org/licenses/MIT - description: - type: string - example: "A short and simple permissive license with conditions only requiring\ - \ preservation of copyright and license notices. Licensed works, modifications,\ - \ and larger works may be distributed under different terms and without\ - \ source code." - RelatedIdentifierDto: - required: - - id - - relation - - type - - value - type: object - properties: - id: - type: integer - format: int64 - value: - type: string - example: 10.70124/dc4zh-9ce78 - type: - type: string - example: DOI - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - example: Cites - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - TableBriefDto: - required: - - columns - - description - - id - - internal_name - - is_versioned - - name - - owner - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality in Austria - owner: - $ref: '#/components/schemas/UserBriefDto' - columns: - type: array - items: - $ref: '#/components/schemas/ColumnBriefDto' - internal_name: - type: string - example: air_quality - is_versioned: - type: boolean - example: true - TableDto: - required: - - columns - - constraints - - created - - created_by - - creator - - database_id - - id - - internal_name - - is_public - - is_versioned - - name - - owner - - queue_name - - routing_key - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - alias: - type: string - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - creator: - $ref: '#/components/schemas/UserDto' - owner: - $ref: '#/components/schemas/UserDto' - description: - type: string - example: Air Quality in Austria - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - constraints: - $ref: '#/components/schemas/ConstraintsDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_versioned: - type: boolean - example: true - created_by: - type: string - format: uuid - queue_name: - type: string - example: air_quality - queue_type: - type: string - example: quorum - routing_key: - type: string - example: dbrepo.1.2 - is_public: - type: boolean - example: true - num_rows: - type: integer - format: int64 - example: 5 - data_length: - type: integer - description: in bytes - format: int64 - example: 16384 - max_data_length: - type: integer - description: in bytes - format: int64 - example: 0 - avg_row_length: - type: integer - description: in bytes - format: int64 - example: 3276 - UniqueDto: - required: - - columns - - table - - uid - type: object - properties: - uid: - type: integer - format: int64 - table: - $ref: '#/components/schemas/TableDto' - columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - UnitDto: - required: - - columns - - created - - id - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - columns: - type: array - items: - $ref: '#/components/schemas/ColumnBriefDto' - UserAttributesDto: - required: - - language - - theme - type: object - properties: - theme: - type: string - example: light - orcid: - type: string - example: https://orcid.org/0000-0002-1825-0097 - affiliation: - type: string - example: Brown University - language: - type: string - example: en - UserBriefDto: - required: - - id - - username - type: object - properties: - id: - type: string - format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - username: - type: string - description: Only contains lowercase characters - example: jcarberry - name: - type: string - example: Josiah Carberry - orcid: - type: string - example: 0000-0002-1825-0097 - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: - type: string - example: Carberry - UserDto: - required: - - attributes - - id - - username - type: object - properties: - id: - type: string - format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - username: - type: string - description: Only contains lowercase characters - example: jcarberry - name: - type: string - example: Josiah Carberry - attributes: - $ref: '#/components/schemas/UserAttributesDto' - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: - type: string - example: Carberry - ViewDto: - required: - - created - - creator - - database - - database_id - - id - - internal_name - - name - - query - - query_hash - type: object - properties: - id: - type: integer - format: int64 - database: - $ref: '#/components/schemas/DatabaseDto' - name: - type: string - example: Air Quality - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - query: - type: string - example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - creator: - $ref: '#/components/schemas/UserDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - initial_view: - type: boolean - description: True if it is the default view for the database - example: true - query_hash: - type: string - example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 - last_modified: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - ApiErrorDto: - required: - - code - - message - - status - type: object - properties: - status: - type: string - example: NOT_FOUND - enum: - - 100 CONTINUE - - 101 SWITCHING_PROTOCOLS - - 102 PROCESSING - - 103 EARLY_HINTS - - 103 CHECKPOINT - - 200 OK - - 201 CREATED - - 202 ACCEPTED - - 203 NON_AUTHORITATIVE_INFORMATION - - 204 NO_CONTENT - - 205 RESET_CONTENT - - 206 PARTIAL_CONTENT - - 207 MULTI_STATUS - - 208 ALREADY_REPORTED - - 226 IM_USED - - 300 MULTIPLE_CHOICES - - 301 MOVED_PERMANENTLY - - 302 FOUND - - 302 MOVED_TEMPORARILY - - 303 SEE_OTHER - - 304 NOT_MODIFIED - - 305 USE_PROXY - - 307 TEMPORARY_REDIRECT - - 308 PERMANENT_REDIRECT - - 400 BAD_REQUEST - - 401 UNAUTHORIZED - - 402 PAYMENT_REQUIRED - - 403 FORBIDDEN - - 404 NOT_FOUND - - 405 METHOD_NOT_ALLOWED - - 406 NOT_ACCEPTABLE - - 407 PROXY_AUTHENTICATION_REQUIRED - - 408 REQUEST_TIMEOUT - - 409 CONFLICT - - 410 GONE - - 411 LENGTH_REQUIRED - - 412 PRECONDITION_FAILED - - 413 PAYLOAD_TOO_LARGE - - 413 REQUEST_ENTITY_TOO_LARGE - - 414 URI_TOO_LONG - - 414 REQUEST_URI_TOO_LONG - - 415 UNSUPPORTED_MEDIA_TYPE - - 416 REQUESTED_RANGE_NOT_SATISFIABLE - - 417 EXPECTATION_FAILED - - 418 I_AM_A_TEAPOT - - 419 INSUFFICIENT_SPACE_ON_RESOURCE - - 420 METHOD_FAILURE - - 421 DESTINATION_LOCKED - - 422 UNPROCESSABLE_ENTITY - - 423 LOCKED - - 424 FAILED_DEPENDENCY - - 425 TOO_EARLY - - 426 UPGRADE_REQUIRED - - 428 PRECONDITION_REQUIRED - - 429 TOO_MANY_REQUESTS - - 431 REQUEST_HEADER_FIELDS_TOO_LARGE - - 451 UNAVAILABLE_FOR_LEGAL_REASONS - - 500 INTERNAL_SERVER_ERROR - - 501 NOT_IMPLEMENTED - - 502 BAD_GATEWAY - - 503 SERVICE_UNAVAILABLE - - 504 GATEWAY_TIMEOUT - - 505 HTTP_VERSION_NOT_SUPPORTED - - 506 VARIANT_ALSO_NEGOTIATES - - 507 INSUFFICIENT_STORAGE - - 508 LOOP_DETECTED - - 509 BANDWIDTH_LIMIT_EXCEEDED - - 510 NOT_EXTENDED - - 511 NETWORK_AUTHENTICATION_REQUIRED - message: - type: string - example: Error message - code: - type: string - example: error.service.code - TupleUpdateDto: - required: - - data - - keys - type: object - properties: - data: - type: object - additionalProperties: - type: object - keys: - type: object - additionalProperties: - type: object - QueryPersistDto: - required: - - persist - type: object - properties: - persist: - type: boolean - example: true - QueryDto: - required: - - created - - creator - - database_id - - execution - - id - - identifiers - - is_persisted - - last_modified - - query - - query_hash - - query_normalized - type: object - properties: - id: - type: integer - format: int64 - creator: - $ref: '#/components/schemas/UserDto' - execution: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - query: - type: string - example: SELECT `id` FROM `air_quality` - type: - type: string - example: query - enum: - - query - - view - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - database_id: - type: integer - format: int64 - query_normalized: - type: string - example: SELECT `id` FROM `air_quality` - query_hash: - type: string - example: 17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76 - is_persisted: - type: boolean - example: true - result_hash: - type: string - example: 17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76 - result_number: - type: integer - format: int64 - example: 1 - last_modified: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - UpdateDatabaseAccessDto: - required: - - type - type: object - properties: - type: - type: string - enum: - - read - - write_own - - write_all - CreateDatabaseDto: - required: - - container_id - - internal_name - - password - - privileged_password - - privileged_username - - user_id - - username - type: object - properties: - username: - type: string - example: foobar - password: - type: string - example: s3cr3t - container_id: - type: integer - format: int64 - example: 1 - internal_name: - type: string - example: weather - privileged_username: - type: string - example: root - privileged_password: - type: string - example: mariadb - user_id: - type: string - format: uuid - example: 0e695ea5-9249-4a75-a77a-eeac3ec1c2c0 - ViewCreateDto: - required: - - is_public - - name - - query - type: object - properties: - name: - type: string - example: Air Quality - query: - type: string - example: SELECT `id` FROM `air_quality` - is_public: - type: boolean - example: true - ColumnCreateDto: - required: - - name - - null_allowed - - type - type: object - properties: - name: - type: string - example: Date - type: - type: string - example: string - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - dfid: - type: integer - description: date format id - format: int64 - enums: - type: array - description: "enum values, only considered when type = ENUM" - items: - type: string - description: "enum values, only considered when type = ENUM" - sets: - type: array - description: "set values, only considered when type = SET" - items: - type: string - description: "set values, only considered when type = SET" - index_length: - type: integer - format: int64 - null_allowed: - type: boolean - example: true - ConstraintsCreateDto: - required: - - checks - - foreign_keys - - primary_key - - uniques - type: object - properties: - uniques: - type: array - items: - type: array - items: - type: string - checks: - uniqueItems: true - type: array - items: - type: string - foreign_keys: - type: array - items: - $ref: '#/components/schemas/ForeignKeyCreateDto' - primary_key: - uniqueItems: true - type: array - items: - type: string - ForeignKeyCreateDto: - required: - - columns - - referenced_columns - - referenced_table - type: object - properties: - columns: - type: array - items: - type: string - referenced_table: - type: string - referenced_columns: - type: array - items: - type: string - on_update: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - on_delete: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - TableCreateDto: - required: - - columns - - constraints - - name - - need_sequence - type: object - properties: - name: - maxLength: 64 - minLength: 1 - type: string - example: Air Quality - description: - maxLength: 180 - minLength: 0 - type: string - example: Air Quality in Austria - columns: - type: array - items: - $ref: '#/components/schemas/ColumnCreateDto' - constraints: - $ref: '#/components/schemas/ConstraintsCreateDto' - need_sequence: - type: boolean - TupleDto: - required: - - data - type: object - properties: - data: - type: object - additionalProperties: - type: object - ImportCsvDto: - required: - - location - - separator - type: object - properties: - location: - type: string - example: file.csv - separator: - type: string - example: "," - quote: - type: string - example: '"' - skip_lines: - minimum: 0 - type: integer - format: int64 - false_element: - type: string - true_element: - type: string - null_element: - type: string - example: NA - line_termination: - type: string - example: \r\n - ExecuteStatementDto: - required: - - statement - type: object - properties: - statement: - type: string - example: SELECT `id` FROM `air_quality` - TupleDeleteDto: - required: - - keys - type: object - properties: - keys: - type: object - additionalProperties: - type: object - securitySchemes: - basicAuth: - type: http - scheme: basic - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT diff --git a/.docs/.swagger/api-metadata.yaml b/.docs/.swagger/api-metadata.yaml deleted file mode 100644 index 46906b87864cb1c8f7ed95dac2dbeb7ba89056ad..0000000000000000000000000000000000000000 --- a/.docs/.swagger/api-metadata.yaml +++ /dev/null @@ -1,7396 +0,0 @@ -openapi: 3.0.1 -info: - title: Database Repository Metadata Service API - description: Service that manages the metadata - contact: - name: Prof. Andreas Rauber - email: andreas.rauber@tuwien.ac.at - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 - version: 1.4.3 -externalDocs: - description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.4.3/system-services-metadata/ -servers: -- url: http://localhost - description: Development instance -- url: https://test.dbrepo.tuwien.ac.at - description: Staging instance -paths: - /api/database: - get: - tags: - - database-endpoint - summary: List databases - operationId: list - parameters: - - name: internal_name - in: query - required: false - schema: - type: string - responses: - "200": - description: List of databases - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DatabaseDto' - post: - tags: - - database-endpoint - summary: Create database - operationId: create_5 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseCreateDto' - required: true - responses: - "503": - description: Connection to the database failed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Database create query is malformed or image is not supported - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "409": - description: Query store could not be created - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Database create permission is missing or grant permissions - at broker service failed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "201": - description: Created a new database - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - "404": - description: "Container, user or database could not be found" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - head: - tags: - - database-endpoint - summary: List databases - operationId: list_1 - parameters: - - name: internal_name - in: query - required: false - schema: - type: string - responses: - "200": - description: List of databases - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/DatabaseDto' - /api/database/{databaseId}/access/{userId}: - get: - tags: - - access-endpoint - summary: Check access to some database - operationId: find - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - "200": - description: Found database access - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseAccessDto' - "403": - description: No access to this database - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: Database not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - put: - tags: - - access-endpoint - summary: Modify access to some database - operationId: update_4 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateDatabaseAccessDto' - required: true - responses: - "202": - description: Modify access succeeded - "403": - description: Modify access not permitted when no access is granted in the - first place - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: Access could not be updated in the data service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "502": - description: Access could not be updated due to connection error in the - data service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: Database or user not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Modify access query or database connection is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - post: - tags: - - access-endpoint - summary: Give access to some database - operationId: create_8 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateDatabaseAccessDto' - required: true - responses: - "503": - description: Access could not be created in the data service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Granting access query or database connection is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Failed giving access - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "405": - description: Granting access not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Granting access succeeded - "404": - description: Database or user not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "502": - description: Access could not be created due to connection error - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - access-endpoint - summary: Revoke access to some database - operationId: revoke - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - "202": - description: Revoked access successfully - "403": - description: Revoke of access not permitted as no access was found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: "User, database with access was not found" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: Access could not be revoked in the data service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Modify access query or database connection is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "502": - description: Access could not be created due to connection error - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - head: - tags: - - access-endpoint - summary: Check access to some database - operationId: find_1 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - "200": - description: Found database access - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseAccessDto' - "403": - description: No access to this database - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: Database not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/user/{userId}: - get: - tags: - - user-endpoint - summary: Get a user info - operationId: find_2 - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - "200": - description: Found user - content: - application/json: - schema: - $ref: '#/components/schemas/UserDto' - "403": - description: Find user is not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: User was not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - put: - tags: - - user-endpoint - summary: Modify user information - operationId: modify - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdateDto' - required: true - responses: - "202": - description: Modified user information - content: - application/json: - schema: - $ref: '#/components/schemas/UserDto' - "400": - description: Modify user query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/user/{userId}/password: - put: - tags: - - user-endpoint - summary: Modify user password - operationId: password - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserPasswordDto' - required: true - responses: - "202": - description: Modified user password - content: - application/json: - schema: - $ref: '#/components/schemas/UserDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/user/token: - put: - tags: - - user-endpoint - summary: Refresh user token - operationId: refreshToken - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/RefreshTokenRequestDto' - required: true - responses: - "202": - description: Refreshed user token - content: - application/json: - schema: - $ref: '#/components/schemas/TokenDto' - post: - tags: - - user-endpoint - summary: Obtain user token - operationId: getToken - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/LoginRequestDto' - required: true - responses: - "202": - description: Obtained user token - content: - application/json: - schema: - $ref: '#/components/schemas/TokenDto' - /api/ontology/{ontologyId}: - get: - tags: - - ontology-endpoint - summary: Find one ontology - operationId: find_3 - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "200": - description: Find one ontology - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyDto' - "404": - description: Could not find ontology - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - put: - tags: - - ontology-endpoint - summary: Update an ontology - operationId: update - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyModifyDto' - required: true - responses: - "202": - description: Updated ontology successfully - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyDto' - "404": - description: Could not find ontology - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - ontology-endpoint - summary: Delete an ontology - operationId: delete - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "202": - description: Deleted ontology successfully - content: - application/json: {} - "404": - description: Could not find ontology - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/message/{messageId}: - put: - tags: - - message-endpoint - summary: Update maintenance message - operationId: update_1 - parameters: - - name: messageId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/BannerMessageUpdateDto' - required: true - responses: - "404": - description: Could not find message - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Updated message - content: - application/json: - schema: - $ref: '#/components/schemas/BannerMessageBriefDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - message-endpoint - summary: Delete maintenance message - operationId: delete_1 - parameters: - - name: messageId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "404": - description: Could not find message - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Deleted message - content: - application/json: {} - security: - - bearerAuth: [] - - basicAuth: [] - /api/image/{imageId}: - get: - tags: - - image-endpoint - summary: Find some image - operationId: findById - parameters: - - name: imageId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "200": - description: Found image - content: - application/json: - schema: - $ref: '#/components/schemas/ImageDto' - "404": - description: Image could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - put: - tags: - - image-endpoint - summary: Update some image - operationId: update_2 - parameters: - - name: imageId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ImageChangeDto' - required: true - responses: - "202": - description: Updated image successfully - content: - application/json: - schema: - $ref: '#/components/schemas/ImageDto' - "404": - description: Image could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - image-endpoint - summary: Delete some image - operationId: delete_2 - parameters: - - name: imageId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "202": - description: Deleted image successfully - "404": - description: Image could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/identifier/{identifierId}: - get: - tags: - - identifier-endpoint - summary: Find some identifier - operationId: find_6 - parameters: - - name: identifierId - in: path - required: true - schema: - type: integer - format: int64 - - name: Accept - in: header - required: true - schema: - type: string - responses: - "404": - description: Identifier could not be found - content: - text/csv: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: "Identifier could not be exported, the requested style is not\ - \ known" - content: - text/bibliography: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "410": - description: Failed to retrieve from S3 endpoint - content: - text/csv: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "409": - description: Exported resource was not found - content: - text/csv: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Found identifier successfully - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierDto' - application/ld+json: - schema: - $ref: '#/components/schemas/LdDatasetDto' - text/csv: {} - text/xml: {} - text/bibliography: {} - text/bibliography; style=apa: {} - text/bibliography; style=ieee: {} - text/bibliography; style=bibtex: {} - "422": - description: Failed to retrieve from database sidecar - content: - text/csv: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: Identifier could not exported from database as it is not reachable - content: - text/csv: - schema: - $ref: '#/components/schemas/ApiErrorDto' - put: - tags: - - identifier-endpoint - summary: Save identifier - operationId: save - parameters: - - name: identifierId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierSaveDto' - required: true - responses: - "404": - description: "Failed to find database, table or view" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Identifier form contains invalid request data - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Saved identifier - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierDto' - "503": - description: DataCite system did not respond - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "405": - description: Creating identifier not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Insufficient access rights or authorities - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - identifier-endpoint - summary: Delete some identifier - operationId: delete_3 - parameters: - - name: identifierId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "404": - description: Identifier or database could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Deleted identifier - content: - '*/*': - schema: - type: object - "403": - description: Deleting identifier not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/identifier/{identifierId}/publish: - put: - tags: - - identifier-endpoint - summary: Publish identifier - operationId: publish - parameters: - - name: identifierId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "404": - description: "Failed to find database, table or view" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Identifier form contains invalid request data - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: DataCite system did not respond - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "405": - description: Creating identifier not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Published identifier - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierDto' - "403": - description: Insufficient access rights or authorities - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/visibility: - put: - tags: - - database-endpoint - summary: Update database visibility - operationId: visibility - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseModifyVisibilityDto' - required: true - responses: - "202": - description: Visibility modified successfully - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - "403": - description: Visibility modification is not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: Database could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/table/{tableId}: - get: - tags: - - table-endpoint - summary: Get information about table - operationId: findById_2 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "200": - description: Find table successfully - content: - application/json: - schema: - $ref: '#/components/schemas/TableDto' - "403": - description: Access to the database is forbidden - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: "Table, database or container could not be found" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: Could not communicate with the broker service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - put: - tags: - - table-endpoint - summary: Update table statistics - operationId: updateStatistic - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TableStatisticDto' - required: true - responses: - "202": - description: Updated table statistics successfully - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - table-endpoint - summary: Delete a table - operationId: delete_5 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "202": - description: Delete table successfully - "403": - description: Access to the database is forbidden - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: "Table, database or container could not be found" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Delete table query resulted in an invalid query statement - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/table/{tableId}/column/{columnId}: - put: - tags: - - table-endpoint - summary: Update a table column semantic mapping - operationId: update_3 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - - name: columnId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ColumnSemanticsUpdateDto' - required: true - responses: - "404": - description: Table or database could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Updated column semantics successfully - content: - application/json: - schema: - $ref: '#/components/schemas/ColumnDto' - "400": - description: Update semantic concept query is malformed or update unit of - measurement query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Access to the database is forbidden - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/owner: - put: - tags: - - database-endpoint - summary: Update database owner - operationId: transfer - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseTransferDto' - required: true - responses: - "404": - description: Database or user could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Transfer of ownership was successful - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - "403": - description: Transfer of ownership is not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/image: - put: - tags: - - database-endpoint - summary: Update database image - operationId: modifyImage - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseModifyImageDto' - required: true - responses: - "403": - description: Modify of image is not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: Database or user could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "410": - description: File was not found in the Storage Service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Modify of image was successful - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/user: - get: - tags: - - user-endpoint - summary: Find all users - operationId: findAll - responses: - "200": - description: List users - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/UserBriefDto' - post: - tags: - - user-endpoint - summary: Create user - operationId: create - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/SignupRequestDto' - required: true - responses: - "417": - description: User with e-mail already exists - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: default role not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "409": - description: User with username already exists - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "201": - description: Created user - content: - application/json: - schema: - $ref: '#/components/schemas/UserBriefDto' - "400": - description: Parameters are not well-formed (likely email) - content: - application/json: {} - /api/ontology: - get: - tags: - - ontology-endpoint - summary: List all ontologies - operationId: findAll_2 - responses: - "200": - description: List all ontologies - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/OntologyDto' - post: - tags: - - ontology-endpoint - summary: Register a new ontology - operationId: create_1 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyCreateDto' - required: true - responses: - "201": - description: Registered ontology successfully - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/message: - get: - tags: - - message-endpoint - summary: Find maintenance messages - operationId: list_2 - parameters: - - name: filter - in: query - required: false - schema: - type: string - responses: - "200": - description: List messages - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/BannerMessageDto' - post: - tags: - - message-endpoint - summary: Create maintenance message - operationId: create_2 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/BannerMessageCreateDto' - required: true - responses: - "201": - description: Created message - content: - application/json: - schema: - $ref: '#/components/schemas/BannerMessageBriefDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/image: - get: - tags: - - image-endpoint - summary: Find all images - operationId: findAll_3 - responses: - "200": - description: List images - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ContainerImage' - post: - tags: - - image-endpoint - summary: Create image - operationId: create_3 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ImageCreateDto' - required: true - responses: - "201": - description: Created image - content: - application/json: - schema: - $ref: '#/components/schemas/ImageDto' - "400": - description: Image specification is invalid - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "409": - description: Image already exists - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/identifier: - get: - tags: - - identifier-endpoint - summary: Find all identifiers - operationId: findAll_4 - parameters: - - name: dbid - in: query - required: false - schema: - type: integer - format: int64 - - name: qid - in: query - required: false - schema: - type: integer - format: int64 - - name: vid - in: query - required: false - schema: - type: integer - format: int64 - - name: tid - in: query - required: false - schema: - type: integer - format: int64 - - name: Accept - in: header - required: true - schema: - type: string - responses: - "406": - description: "Identifier could not be exported, the requested style is not\ - \ known" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Found identifiers successfully - content: - application/json: - schema: - type: string - application/ld+json: - schema: - type: string - post: - tags: - - identifier-endpoint - summary: Draft identifier - operationId: create_4 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierCreateDto' - required: true - responses: - "201": - description: Drafted identifier - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierDto' - "404": - description: "Failed to find database, table or view" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Identifier form contains invalid request data - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "503": - description: DataCite system did not respond - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "405": - description: Creating identifier not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Insufficient access rights or authorities - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/view: - get: - tags: - - view-endpoint - summary: Find all views - operationId: findAll_5 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "404": - description: Database or user could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Find views successfully - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ViewBriefDto' - security: - - bearerAuth: [] - - basicAuth: [] - post: - tags: - - view-endpoint - summary: Create a view - operationId: create_6 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ViewCreateDto' - required: true - responses: - "503": - description: Connection to the database failed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Create view query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: Database or user could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "401": - description: Credentials missing - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "201": - description: Create view successfully - content: - application/json: - schema: - $ref: '#/components/schemas/ViewBriefDto' - "403": - description: Credentials missing - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "423": - description: Create view resulted in an invalid query statement - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "405": - description: Create view is not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/table: - get: - tags: - - table-endpoint - summary: List all tables - operationId: list_4 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "403": - description: List tables not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: List tables - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/TableBriefDto' - "404": - description: Database could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - post: - tags: - - table-endpoint - summary: Create a table - operationId: create_7 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TableCreateDto' - required: true - responses: - "409": - description: Create table conflicts with existing table name - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "201": - description: Created a new table - content: - application/json: - schema: - $ref: '#/components/schemas/TableBriefDto' - "400": - description: Create table query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: "Database, container or user could not be found" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Create table not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/container: - get: - tags: - - container-endpoint - summary: Find all containers - operationId: findAll_6 - parameters: - - name: limit - in: query - required: false - schema: - type: integer - format: int32 - responses: - "200": - description: List containers - content: - application/json: - schema: - type: array - items: - type: string - post: - tags: - - container-endpoint - summary: Create container - operationId: create_9 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/ContainerCreateDto' - required: true - responses: - "409": - description: Container name already exists - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "201": - description: Created a new container - content: - application/json: - schema: - $ref: '#/components/schemas/ContainerBriefDto' - "404": - description: Container image or user could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/unit: - get: - tags: - - unit-endpoint - summary: List semantic units - operationId: findAll_1 - responses: - "200": - description: Find all semantic units - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/UnitDto' - /api/ontology/{ontologyId}/entity: - get: - tags: - - ontology-endpoint - summary: Find entities - operationId: find_4 - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 - - name: label - in: query - required: false - schema: - type: string - - name: uri - in: query - required: false - schema: - type: string - responses: - "400": - description: Filter params are invalid - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "417": - description: Generated query or uri is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Found entities - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/EntityDto' - "404": - description: Could not find ontology - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "422": - description: Ontology does not have rdf or sparql endpoint - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/oai: - get: - tags: - - metadata-endpoint - summary: Get the record - operationId: identify_1_1_1_1 - parameters: - - name: verb - in: query - - name: parameters - in: query - required: true - schema: - $ref: '#/components/schemas/OaiListIdentifiersParameters' - responses: - "200": - description: List containers - content: - text/xml: {} - /api/message/message/{messageId}: - get: - tags: - - message-endpoint - summary: Find one maintenance message - operationId: find_5 - parameters: - - name: messageId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "404": - description: Could not find message - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Get messages - content: - application/json: - schema: - $ref: '#/components/schemas/BannerMessageDto' - /api/license: - get: - tags: - - license-endpoint - summary: Get all licenses - operationId: list_3 - responses: - "200": - description: List of licenses - content: - application/json: - schema: - type: array - items: - type: string - /api/identifier/retrieve: - get: - tags: - - identifier-endpoint - summary: Retrieve metadata from identifier - operationId: retrieve - parameters: - - name: url - in: query - required: true - schema: - type: string - responses: - "404": - description: Failed to find metadata for identifier - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Retrieved metadata from identifier - content: - application/json: - schema: - $ref: '#/components/schemas/IdentifierDto' - /api/database/{databaseId}: - get: - tags: - - database-endpoint - summary: Find some database - operationId: findById_1 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "503": - description: Connection to the broker service could not be established - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Database found successfully - content: - application/json: - schema: - $ref: '#/components/schemas/DatabaseDto' - "404": - description: Database or exchange could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/view/{viewId}: - get: - tags: - - view-endpoint - summary: Find one view - operationId: find_7 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: viewId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "404": - description: "Database, view or user could not be found" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Find view successfully - content: - application/json: - schema: - $ref: '#/components/schemas/ViewDto' - "403": - description: Find view is not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - view-endpoint - summary: Delete one view - operationId: delete_4 - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: viewId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "503": - description: Connection to the database failed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Delete view successfully - "404": - description: "Database, view or user could not be found" - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "423": - description: Delete view resulted in an invalid query statement - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "405": - description: Delete view is not permitted - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "403": - description: Deletion not allowed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "400": - description: Delete view query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/table/{tableId}/suggest: - get: - tags: - - table-endpoint - summary: Suggest table semantics - operationId: analyseTable - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "417": - description: Generated query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Suggested table semantics successfully - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/TableColumnEntityDto' - "404": - description: Could not find the table - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "422": - description: Ontology does not have rdf or sparql endpoint - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/database/{databaseId}/table/{tableId}/column/{columnId}/suggest: - get: - tags: - - table-endpoint - summary: Suggest table column semantics - operationId: analyseTableColumn - parameters: - - name: databaseId - in: path - required: true - schema: - type: integer - format: int64 - - name: tableId - in: path - required: true - schema: - type: integer - format: int64 - - name: columnId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "417": - description: Generated query is malformed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "404": - description: Could not find the table column - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "200": - description: Suggested table column semantics successfully - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/TableColumnEntityDto' - "422": - description: Ontology does not have rdf or sparql endpoint - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - /api/container/{containerId}: - get: - tags: - - container-endpoint - summary: Find some container - operationId: findById_3 - parameters: - - name: containerId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "200": - description: Found container - content: - application/json: - schema: - $ref: '#/components/schemas/ContainerDto' - "404": - description: Container image could not be found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - delete: - tags: - - container-endpoint - summary: Delete some container - operationId: delete_6 - parameters: - - name: containerId - in: path - required: true - schema: - type: integer - format: int64 - responses: - "404": - description: Container not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - "202": - description: Deleted container successfully - content: - '*/*': - schema: - type: object - security: - - bearerAuth: [] - - basicAuth: [] - /api/concept: - get: - tags: - - concept-endpoint - summary: List semantic concepts - operationId: findAll_7 - responses: - "200": - description: Find all semantic concepts - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/ConceptDto' -components: - schemas: - ColumnBriefDto: - required: - - column_type - - database_id - - id - - internal_name - - name - - table_id - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: date - alias: - type: string - database_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - internal_name: - type: string - example: mdb_date - column_type: - type: string - example: date - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - ColumnDto: - required: - - auto_generated - - column_type - - database_id - - id - - internal_name - - is_null_allowed - - is_public - - name - - ordinal_position - - table_id - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Date - alias: - type: string - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - mean: - type: number - example: 45.4 - median: - type: number - example: 51 - concept: - $ref: '#/components/schemas/ConceptDto' - unit: - $ref: '#/components/schemas/UnitDto' - table: - $ref: '#/components/schemas/TableDto' - views: - type: array - items: - $ref: '#/components/schemas/ViewDto' - enums: - type: array - items: - type: string - sets: - type: array - items: - type: string - database_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - ordinal_position: - type: integer - format: int32 - example: 0 - internal_name: - type: string - example: mdb_date - date_format: - $ref: '#/components/schemas/ImageDateDto' - auto_generated: - type: boolean - example: false - index_length: - type: integer - format: int64 - length: - type: integer - format: int64 - column_type: - type: string - example: string - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - data_length: - type: integer - format: int64 - example: 34300 - max_data_length: - type: integer - format: int64 - example: 34300 - num_rows: - type: integer - format: int64 - example: 32 - val_min: - type: number - example: 0 - val_max: - type: number - example: 100 - std_dev: - type: number - example: 5.32 - is_public: - type: boolean - example: true - is_null_allowed: - type: boolean - example: false - ConceptDto: - required: - - columns - - created - - id - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - columns: - type: array - items: - $ref: '#/components/schemas/ColumnBriefDto' - ConstraintsDto: - type: object - properties: - uniques: - type: array - items: - $ref: '#/components/schemas/UniqueDto' - checks: - uniqueItems: true - type: array - items: - type: string - foreign_keys: - type: array - items: - $ref: '#/components/schemas/ForeignKeyDto' - primary_key: - uniqueItems: true - type: array - items: - type: string - ContainerDto: - required: - - created - - host - - id - - image - - internal_name - - name - - sidecar_host - - sidecar_port - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - host: - type: string - port: - type: integer - format: int32 - image: - $ref: '#/components/schemas/ImageDto' - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - internal_name: - type: string - example: data-db - sidecar_host: - type: string - sidecar_port: - type: integer - format: int32 - ui_host: - type: string - ui_port: - type: integer - format: int32 - CreatorDto: - required: - - creator_name - - id - type: object - properties: - id: - type: integer - format: int64 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Brown University - creator_name: - type: string - example: "Carberry, Josiah" - name_type: - type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: - type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: - type: string - example: ORCID - enum: - - ORCID - - ROR - - ISNI - - GRID - name_identifier_scheme_uri: - type: string - example: https://orcid.org/ - affiliation_identifier: - type: string - example: https://ror.org/05gq02987 - affiliation_identifier_scheme: - type: string - example: ROR - enum: - - ROR - - GRID - - ISNI - affiliation_identifier_scheme_uri: - type: string - example: https://ror.org/ - DatabaseAccessDto: - required: - - created - - type - - user - type: object - properties: - user: - $ref: '#/components/schemas/UserDto' - type: - type: string - enum: - - read - - write_own - - write_all - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - DatabaseDto: - required: - - contact - - container - - created - - creator - - exchange_name - - id - - internal_name - - is_public - - name - - owner - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality - tables: - type: array - items: - $ref: '#/components/schemas/TableDto' - container: - $ref: '#/components/schemas/ContainerDto' - accesses: - type: array - items: - $ref: '#/components/schemas/DatabaseAccessDto' - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - subsets: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - creator: - $ref: '#/components/schemas/UserDto' - contact: - $ref: '#/components/schemas/UserDto' - owner: - $ref: '#/components/schemas/UserDto' - image: - type: array - items: - type: string - format: byte - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - exchange_name: - type: string - example: dbrepo - exchange_type: - type: string - example: topic - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - ForeignKeyDto: - type: object - properties: - name: - type: string - columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - referenced_table: - $ref: '#/components/schemas/TableBriefDto' - referenced_columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - on_update: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - on_delete: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - IdentifierDescriptionDto: - required: - - id - type: object - properties: - id: - type: integer - format: int64 - description: - type: string - example: "Air quality reports at Stephansplatz, Vienna" - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - example: Abstract - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - IdentifierDto: - required: - - created - - created_by - - creator - - creators - - database_id - - execution - - id - - last_modified - - publication_year - - publisher - - query - - query_hash - - query_normalized - - titles - - type - type: object - properties: - id: - type: integer - format: int64 - type: - type: string - enum: - - database - - subset - - table - - view - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierTitleDto' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierDescriptionDto' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunderDto' - query: - type: string - example: "SELECT `id`, `value`, `location` FROM `air_quality` WHERE `location`\ - \ = \"09:STEF\"" - execution: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - doi: - type: string - example: 10.1038/nphys1170 - publisher: - type: string - example: TU Wien - creator: - $ref: '#/components/schemas/UserDto' - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - licenses: - type: array - items: - $ref: '#/components/schemas/LicenseDto' - creators: - type: array - items: - $ref: '#/components/schemas/CreatorDto' - status: - type: string - enum: - - draft - - published - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - database_id: - type: integer - format: int64 - example: 1 - query_id: - type: integer - format: int64 - example: 1 - table_id: - type: integer - format: int64 - example: 1 - view_id: - type: integer - format: int64 - example: 1 - query_normalized: - type: string - example: "SELECT `id`, `value`, `location` FROM `air_quality` WHERE `location`\ - \ = \"09:STEF\"" - related_identifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifierDto' - query_hash: - type: string - description: query hash in sha512 - result_hash: - type: string - example: 34fe82cda2c53f13f8d90cfd7a3469e3a939ff311add50dce30d9136397bf8e5 - result_number: - type: integer - format: int64 - example: 1 - publication_day: - type: integer - format: int32 - example: 15 - publication_month: - type: integer - format: int32 - example: 12 - publication_year: - type: integer - format: int32 - example: 2022 - created_by: - type: string - format: uuid - last_modified: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - IdentifierFunderDto: - required: - - funder_name - - id - type: object - properties: - id: - type: integer - format: int64 - funder_name: - type: string - example: European Commission - funder_identifier: - type: string - example: http://doi.org/10.13039/501100000780 - funder_identifier_type: - type: string - example: Crossref Funder ID - enum: - - Crossref Funder ID - - ROR - - GND - - ISNI - - Other - scheme_uri: - type: string - example: http://doi.org/ - award_number: - type: string - example: "824087" - award_title: - type: string - example: EOSC-Life - IdentifierTitleDto: - required: - - id - type: object - properties: - id: - type: integer - format: int64 - title: - type: string - example: Airquality Demonstrator - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle - - Other - ImageDateDto: - required: - - created_at - - database_format - - has_time - - id - - unix_format - type: object - properties: - id: - type: integer - format: int64 - database_format: - type: string - example: '%d.%c.%Y' - unix_format: - type: string - example: dd.MM.YYYY - has_time: - type: boolean - example: false - created_at: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - ImageDto: - required: - - default_port - - dialect - - driver_class - - id - - jdbc_method - - name - - registry - - version - type: object - properties: - id: - type: integer - format: int64 - registry: - type: string - example: docker.io/library - name: - type: string - example: mariadb - version: - type: string - example: "10.5" - dialect: - type: string - example: org.hibernate.dialect.MariaDBDialect - driver_class: - type: string - example: org.mariadb.jdbc.Driver - date_formats: - type: array - items: - $ref: '#/components/schemas/ImageDateDto' - jdbc_method: - type: string - example: mariadb - default_port: - type: integer - format: int32 - example: 3306 - LicenseDto: - required: - - identifier - - uri - type: object - properties: - identifier: - type: string - example: MIT - uri: - type: string - example: https://opensource.org/licenses/MIT - description: - type: string - example: "A short and simple permissive license with conditions only requiring\ - \ preservation of copyright and license notices. Licensed works, modifications,\ - \ and larger works may be distributed under different terms and without\ - \ source code." - RelatedIdentifierDto: - required: - - id - - relation - - type - - value - type: object - properties: - id: - type: integer - format: int64 - value: - type: string - example: 10.70124/dc4zh-9ce78 - type: - type: string - example: DOI - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - example: Cites - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - TableBriefDto: - required: - - columns - - description - - id - - internal_name - - is_versioned - - name - - owner - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality in Austria - owner: - $ref: '#/components/schemas/UserBriefDto' - columns: - type: array - items: - $ref: '#/components/schemas/ColumnBriefDto' - internal_name: - type: string - example: air_quality - is_versioned: - type: boolean - example: true - TableDto: - required: - - columns - - constraints - - created - - created_by - - creator - - database_id - - id - - internal_name - - is_public - - is_versioned - - name - - owner - - queue_name - - routing_key - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - alias: - type: string - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - creator: - $ref: '#/components/schemas/UserDto' - owner: - $ref: '#/components/schemas/UserDto' - description: - type: string - example: Air Quality in Austria - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - columns: - type: array - items: - $ref: '#/components/schemas/ColumnDto' - constraints: - $ref: '#/components/schemas/ConstraintsDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_versioned: - type: boolean - example: true - created_by: - type: string - format: uuid - queue_name: - type: string - example: air_quality - queue_type: - type: string - example: quorum - routing_key: - type: string - example: dbrepo.1.2 - is_public: - type: boolean - example: true - num_rows: - type: integer - format: int64 - example: 5 - data_length: - type: integer - description: in bytes - format: int64 - example: 16384 - max_data_length: - type: integer - description: in bytes - format: int64 - example: 0 - avg_row_length: - type: integer - description: in bytes - format: int64 - example: 3276 - UniqueDto: - required: - - table - - uid - type: object - properties: - uid: - type: integer - format: int64 - table: - $ref: '#/components/schemas/TableDto' - UnitDto: - required: - - columns - - created - - id - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - columns: - type: array - items: - $ref: '#/components/schemas/ColumnBriefDto' - UserAttributesDto: - required: - - language - - theme - type: object - properties: - theme: - type: string - example: light - orcid: - type: string - example: https://orcid.org/0000-0002-1825-0097 - affiliation: - type: string - example: Brown University - language: - type: string - example: en - UserBriefDto: - required: - - id - - username - type: object - properties: - id: - type: string - format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - username: - type: string - description: Only contains lowercase characters - example: jcarberry - name: - type: string - example: Josiah Carberry - orcid: - type: string - example: 0000-0002-1825-0097 - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: - type: string - example: Carberry - UserDto: - required: - - attributes - - id - - username - type: object - properties: - id: - type: string - format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - username: - type: string - description: Only contains lowercase characters - example: jcarberry - name: - type: string - example: Josiah Carberry - attributes: - $ref: '#/components/schemas/UserAttributesDto' - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: - type: string - example: Carberry - ViewDto: - required: - - created - - creator - - database - - database_id - - id - - internal_name - - name - - query - - query_hash - type: object - properties: - id: - type: integer - format: int64 - database: - $ref: '#/components/schemas/DatabaseDto' - name: - type: string - example: Air Quality - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - query: - type: string - example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - creator: - $ref: '#/components/schemas/UserDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - initial_view: - type: boolean - description: True if it is the default view for the database - example: true - query_hash: - type: string - example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 - last_modified: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - ApiErrorDto: - required: - - code - - message - - status - type: object - properties: - status: - type: string - example: NOT_FOUND - enum: - - 100 CONTINUE - - 101 SWITCHING_PROTOCOLS - - 102 PROCESSING - - 103 EARLY_HINTS - - 103 CHECKPOINT - - 200 OK - - 201 CREATED - - 202 ACCEPTED - - 203 NON_AUTHORITATIVE_INFORMATION - - 204 NO_CONTENT - - 205 RESET_CONTENT - - 206 PARTIAL_CONTENT - - 207 MULTI_STATUS - - 208 ALREADY_REPORTED - - 226 IM_USED - - 300 MULTIPLE_CHOICES - - 301 MOVED_PERMANENTLY - - 302 FOUND - - 302 MOVED_TEMPORARILY - - 303 SEE_OTHER - - 304 NOT_MODIFIED - - 305 USE_PROXY - - 307 TEMPORARY_REDIRECT - - 308 PERMANENT_REDIRECT - - 400 BAD_REQUEST - - 401 UNAUTHORIZED - - 402 PAYMENT_REQUIRED - - 403 FORBIDDEN - - 404 NOT_FOUND - - 405 METHOD_NOT_ALLOWED - - 406 NOT_ACCEPTABLE - - 407 PROXY_AUTHENTICATION_REQUIRED - - 408 REQUEST_TIMEOUT - - 409 CONFLICT - - 410 GONE - - 411 LENGTH_REQUIRED - - 412 PRECONDITION_FAILED - - 413 PAYLOAD_TOO_LARGE - - 413 REQUEST_ENTITY_TOO_LARGE - - 414 URI_TOO_LONG - - 414 REQUEST_URI_TOO_LONG - - 415 UNSUPPORTED_MEDIA_TYPE - - 416 REQUESTED_RANGE_NOT_SATISFIABLE - - 417 EXPECTATION_FAILED - - 418 I_AM_A_TEAPOT - - 419 INSUFFICIENT_SPACE_ON_RESOURCE - - 420 METHOD_FAILURE - - 421 DESTINATION_LOCKED - - 422 UNPROCESSABLE_ENTITY - - 423 LOCKED - - 424 FAILED_DEPENDENCY - - 425 TOO_EARLY - - 426 UPGRADE_REQUIRED - - 428 PRECONDITION_REQUIRED - - 429 TOO_MANY_REQUESTS - - 431 REQUEST_HEADER_FIELDS_TOO_LARGE - - 451 UNAVAILABLE_FOR_LEGAL_REASONS - - 500 INTERNAL_SERVER_ERROR - - 501 NOT_IMPLEMENTED - - 502 BAD_GATEWAY - - 503 SERVICE_UNAVAILABLE - - 504 GATEWAY_TIMEOUT - - 505 HTTP_VERSION_NOT_SUPPORTED - - 506 VARIANT_ALSO_NEGOTIATES - - 507 INSUFFICIENT_STORAGE - - 508 LOOP_DETECTED - - 509 BANDWIDTH_LIMIT_EXCEEDED - - 510 NOT_EXTENDED - - 511 NETWORK_AUTHENTICATION_REQUIRED - message: - type: string - example: Error message - code: - type: string - example: error.service.code - UserUpdateDto: - required: - - language - - theme - type: object - properties: - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Brown University - orcid: - type: string - example: 0000-0002-1825-0097 - theme: - type: string - example: dark - language: - type: string - example: en - UserPasswordDto: - required: - - password - type: object - properties: - password: - type: string - RefreshTokenRequestDto: - required: - - refresh_token - type: object - properties: - refresh_token: - type: string - example: refresh_token - TokenDto: - required: - - access_token - - expires_in - - id_token - - not-before-policy - - refresh_expires_in - - refresh_token - - scope - - session_state - - token_type - type: object - properties: - scope: - type: string - access_token: - type: string - expires_in: - type: integer - format: int64 - refresh_token: - type: string - refresh_expires_in: - type: integer - format: int64 - id_token: - type: string - session_state: - type: string - token_type: - type: string - not-before-policy: - type: integer - format: int64 - OntologyModifyDto: - required: - - prefix - - uri - type: object - properties: - uri: - type: string - example: Ontology URI - prefix: - type: string - example: Ontology prefix - sparql_endpoint: - type: string - example: Ontology SPARQL endpoint - rdf_path: - type: string - example: rdf/om-2.0.rdf - OntologyDto: - required: - - created - - id - - prefix - - rdf - - sparql - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - example: http://www.wikidata.org/ - prefix: - type: string - example: wd - sparql: - type: boolean - example: true - rdf: - type: boolean - example: false - creator: - $ref: '#/components/schemas/UserBriefDto' - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - uri_pattern: - type: string - example: http://www.wikidata.org/entity/.* - sparql_endpoint: - type: string - example: https://query.wikidata.org/sparql - rdf_path: - type: string - example: rdf/om-2.0.rdf - BannerMessageUpdateDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: https://example.com - link_text: - type: string - example: More - display_start: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - display_end: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - BannerMessageBriefDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: https://example.com - link_text: - type: string - example: More - ImageChangeDto: - required: - - dialect - - driver_class - - jdbc_method - - registry - type: object - properties: - registry: - type: string - example: docker.io/library - defaultPort: - maximum: 65535 - minimum: 1024 - type: integer - format: int32 - example: 5432 - dialect: - type: string - example: Postgres - driver_class: - type: string - example: org.postgresql.Driver - jdbc_method: - type: string - example: postgresql - CreatorSaveDto: - required: - - creator_name - - id - type: object - properties: - id: - type: integer - format: int64 - example: 1 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Wesleyan University - creator_name: - type: string - example: "Carberry, Josiah" - name_type: - type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: - type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: - type: string - example: ORCID - enum: - - ORCID - - ROR - - ISNI - - GRID - affiliation_identifier: - type: string - example: https://ror.org/04d836q62 - affiliation_identifier_scheme: - type: string - example: ROR - enum: - - ROR - - GRID - - ISNI - IdentifierFunderSaveDto: - required: - - funder_name - - id - type: object - properties: - id: - type: integer - format: int64 - example: 1 - funder_name: - type: string - example: European Commission - funder_identifier: - type: string - example: http://doi.org/10.13039/501100000780 - funder_identifier_type: - type: string - example: Crossref Funder ID - enum: - - Crossref Funder ID - - ROR - - GND - - ISNI - - Other - scheme_uri: - type: string - example: http://doi.org/ - award_number: - type: string - example: "824087" - award_title: - type: string - example: EOSC-Life - IdentifierSaveDescriptionDto: - required: - - description - - id - type: object - properties: - id: - type: integer - format: int64 - example: 1 - description: - type: string - example: "Air quality reports at Stephansplatz, Vienna" - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - example: Abstract - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - IdentifierSaveDto: - required: - - creators - - database_id - - id - - publication_year - - publisher - - titles - - type - type: object - properties: - id: - type: integer - format: int64 - example: 1 - type: - type: string - example: database - enum: - - database - - subset - - table - - view - doi: - type: string - example: 10.1111/11111111 - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierSaveTitleDto' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierSaveDescriptionDto' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunderSaveDto' - licenses: - type: array - items: - $ref: '#/components/schemas/LicenseDto' - publisher: - type: string - example: TU Wien - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - creators: - type: array - items: - $ref: '#/components/schemas/CreatorSaveDto' - database_id: - type: integer - format: int64 - example: 1 - query_id: - type: integer - format: int64 - view_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - publication_day: - type: integer - format: int32 - example: 15 - publication_month: - type: integer - format: int32 - example: 12 - publication_year: - type: integer - format: int32 - example: 2022 - related_identifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifierSaveDto' - IdentifierSaveTitleDto: - required: - - id - - title - type: object - properties: - id: - type: integer - format: int64 - example: 1 - title: - type: string - example: Airquality Demonstrator - language: - type: string - example: en - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - type: - type: string - example: Subtitle - enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle - - Other - RelatedIdentifierSaveDto: - required: - - id - - relation - - type - - value - type: object - properties: - id: - type: integer - format: int64 - example: 1 - value: - type: string - example: 10.70124/dc4zh-9ce78 - type: - type: string - example: DOI - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - example: Cites - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - DatabaseModifyVisibilityDto: - required: - - is_public - type: object - properties: - is_public: - type: boolean - example: true - ColumnStatisticDto: - required: - - mean - - median - - std_dev - - val_max - - val_min - type: object - properties: - mean: - type: number - median: - type: number - std_dev: - type: number - val_min: - type: number - val_max: - type: number - TableStatisticDto: - required: - - columns - type: object - properties: - columns: - type: object - additionalProperties: - $ref: '#/components/schemas/ColumnStatisticDto' - ColumnSemanticsUpdateDto: - type: object - properties: - concept_uri: - type: string - unit_uri: - type: string - DatabaseTransferDto: - required: - - id - type: object - properties: - id: - type: string - format: uuid - DatabaseModifyImageDto: - type: object - properties: - key: - type: string - UpdateDatabaseAccessDto: - required: - - type - type: object - properties: - type: - type: string - enum: - - read - - write_own - - write_all - SignupRequestDto: - required: - - email - - password - - username - type: object - properties: - username: - pattern: "^[a-z0-9]{3,}$" - type: string - example: user - email: - type: string - example: user@example.com - password: - type: string - LoginRequestDto: - required: - - password - - username - type: object - properties: - username: - type: string - example: user - password: - type: string - OntologyCreateDto: - required: - - prefix - - uri - type: object - properties: - uri: - type: string - example: Ontology URI - prefix: - type: string - example: Ontology prefix - sparql_endpoint: - type: string - example: Ontology SPARQL endpoint - BannerMessageCreateDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: https://example.com - link_text: - type: string - example: More - display_start: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - display_end: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - ImageCreateDto: - required: - - default_port - - dialect - - driver_class - - jdbc_method - - name - - registry - - version - type: object - properties: - registry: - type: string - example: docker.io/library - name: - type: string - example: mariadb - version: - type: string - dialect: - type: string - driver_class: - type: string - jdbc_method: - type: string - default_port: - maximum: 65535 - minimum: 1024 - type: integer - format: int32 - IdentifierCreateDto: - required: - - creators - - database_id - - publication_year - - publisher - - titles - - type - type: object - properties: - type: - type: string - example: database - enum: - - database - - subset - - table - - view - doi: - type: string - example: 10.1111/11111111 - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierSaveTitleDto' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierSaveDescriptionDto' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunderSaveDto' - licenses: - type: array - items: - $ref: '#/components/schemas/LicenseDto' - publisher: - type: string - example: TU Wien - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - creators: - type: array - items: - $ref: '#/components/schemas/CreatorSaveDto' - database_id: - type: integer - format: int64 - example: 1 - query_id: - type: integer - format: int64 - view_id: - type: integer - format: int64 - table_id: - type: integer - format: int64 - publication_day: - type: integer - format: int32 - example: 15 - publication_month: - type: integer - format: int32 - example: 12 - publication_year: - type: integer - format: int32 - example: 2022 - related_identifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifierSaveDto' - DatabaseCreateDto: - required: - - container_id - - is_public - - name - type: object - properties: - name: - type: string - example: Air Quality - container_id: - type: integer - format: int64 - example: 1 - is_public: - type: boolean - example: true - ViewCreateDto: - required: - - is_public - - name - - query - type: object - properties: - name: - type: string - example: Air Quality - query: - type: string - example: SELECT `id` FROM `air_quality` - is_public: - type: boolean - example: true - ViewBriefDto: - required: - - created - - creator - - database_id - - id - - internal_name - - name - - query - - query_hash - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: Air Quality - identifier: - $ref: '#/components/schemas/IdentifierDto' - query: - type: string - example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - creator: - $ref: '#/components/schemas/UserDto' - database_id: - type: integer - format: int64 - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - initial_view: - type: boolean - description: True if it is the default view for the database - example: true - query_hash: - type: string - example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 - last_modified: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - ColumnCreateDto: - required: - - name - - null_allowed - - type - type: object - properties: - name: - type: string - example: Date - type: - type: string - example: string - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - dfid: - type: integer - description: date format id - format: int64 - enums: - type: array - description: "enum values, only considered when type = ENUM" - items: - type: string - description: "enum values, only considered when type = ENUM" - sets: - type: array - description: "set values, only considered when type = SET" - items: - type: string - description: "set values, only considered when type = SET" - index_length: - type: integer - format: int64 - null_allowed: - type: boolean - example: true - ConstraintsCreateDto: - required: - - checks - - foreign_keys - - primary_key - - uniques - type: object - properties: - uniques: - type: array - items: - type: array - items: - type: string - checks: - uniqueItems: true - type: array - items: - type: string - foreign_keys: - type: array - items: - $ref: '#/components/schemas/ForeignKeyCreateDto' - primary_key: - uniqueItems: true - type: array - items: - type: string - ForeignKeyCreateDto: - required: - - columns - - referenced_columns - - referenced_table - type: object - properties: - columns: - type: array - items: - type: string - referenced_table: - type: string - referenced_columns: - type: array - items: - type: string - on_update: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - on_delete: - type: string - enum: - - restrict - - cascade - - set_null - - no_action - - set_default - TableCreateDto: - required: - - columns - - constraints - - name - type: object - properties: - name: - maxLength: 64 - minLength: 1 - type: string - example: Air Quality - description: - maxLength: 180 - minLength: 0 - type: string - example: Air Quality in Austria - columns: - type: array - items: - $ref: '#/components/schemas/ColumnCreateDto' - constraints: - $ref: '#/components/schemas/ConstraintsCreateDto' - need_sequence: - type: boolean - ContainerCreateDto: - required: - - host - - image_id - - name - - privileged_password - - privileged_username - - sidecar_host - - sidecar_port - type: object - properties: - name: - type: string - example: Air Quality - host: - type: string - description: Hostname of container - port: - type: integer - description: Port of container - format: int32 - image_id: - type: integer - description: Image ID - format: int64 - sidecar_host: - type: string - sidecar_port: - type: integer - format: int32 - ui_host: - type: string - ui_port: - type: integer - format: int32 - privileged_username: - type: string - description: Username of privileged user - example: root - privileged_password: - type: string - description: Password of privileged user - ContainerBriefDto: - required: - - created - - hash - - id - - image - - internal_name - - name - - running - type: object - properties: - id: - type: integer - format: int64 - hash: - type: string - example: f829dd8a884182d0da846f365dee1221fd16610a14c81b8f9f295ff162749e50 - name: - type: string - example: Air Quality - image: - $ref: '#/components/schemas/ImageBriefDto' - running: - type: boolean - example: true - created: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - internal_name: - type: string - example: air-quality - ImageBriefDto: - required: - - id - - jdbc_method - - name - - version - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - example: mariadb - version: - type: string - example: "10.5" - jdbc_method: - type: string - example: mariadb - EntityDto: - required: - - label - - uri - type: object - properties: - uri: - type: string - example: https://www.wikidata.org/entity/Q1686799 - label: - type: string - example: Apache Jena - description: - type: string - example: open source semantic web framework for Java - OaiListIdentifiersParameters: - type: object - properties: - metadataPrefix: - type: string - from: - type: string - until: - type: string - set: - type: string - resumptionToken: - type: string - parametersString: - type: string - fromDate: - type: string - format: date-time - untilDate: - type: string - format: date-time - BannerMessageDto: - required: - - id - - message - - type - type: object - properties: - id: - type: integer - format: int64 - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: https://example.com - link_text: - type: string - example: More - display_start: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - display_end: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - Constraints: - type: object - properties: - uniques: - type: array - items: - $ref: '#/components/schemas/Unique' - foreignKeys: - type: array - items: - $ref: '#/components/schemas/ForeignKey' - checks: - uniqueItems: true - type: array - items: - type: string - primaryKey: - type: array - items: - $ref: '#/components/schemas/PrimaryKey' - Container: - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - internalName: - type: string - host: - type: string - port: - type: integer - format: int32 - sidecarHost: - type: string - sidecarPort: - type: integer - format: int32 - uiHost: - type: string - uiPort: - type: integer - format: int32 - uiAdditionalFlags: - type: string - databases: - type: array - items: - $ref: '#/components/schemas/Database' - image: - $ref: '#/components/schemas/ContainerImage' - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - privilegedUsername: - type: string - privilegedPassword: - type: string - ContainerImage: - type: object - properties: - id: - type: integer - format: int64 - name: - type: string - registry: - type: string - version: - type: string - driverClass: - type: string - dialect: - type: string - jdbcMethod: - type: string - defaultPort: - type: integer - format: int32 - dateFormats: - type: array - items: - $ref: '#/components/schemas/ContainerImageDate' - containers: - type: array - items: - $ref: '#/components/schemas/Container' - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - ContainerImageDate: - type: object - properties: - id: - type: integer - format: int64 - iid: - type: integer - format: int64 - image: - $ref: '#/components/schemas/ContainerImage' - example: - type: string - hasTime: - type: boolean - databaseFormat: - type: string - unixFormat: - type: string - createdAt: - type: string - format: date-time - Creator: - type: object - properties: - id: - type: integer - format: int64 - firstname: - type: string - lastname: - type: string - creatorName: - type: string - nameType: - type: string - enum: - - PERSONAL - - ORGANIZATIONAL - nameIdentifier: - type: string - nameIdentifierScheme: - type: string - enum: - - ORCID - - ROR - - ISNI - - GRID - nameIdentifierSchemeUri: - type: string - affiliation: - type: string - affiliationIdentifier: - type: string - affiliationIdentifierScheme: - type: string - enum: - - ROR - - GRID - - ISNI - affiliationIdentifierSchemeUri: - type: string - identifier: - $ref: '#/components/schemas/Identifier' - apaName: - type: string - bibtexName: - type: string - ieeeName: - type: string - Database: - type: object - properties: - id: - type: integer - format: int64 - createdBy: - type: string - format: uuid - creator: - $ref: '#/components/schemas/User' - ownedBy: - type: string - format: uuid - owner: - $ref: '#/components/schemas/User' - cid: - type: integer - format: int64 - container: - $ref: '#/components/schemas/Container' - name: - type: string - internalName: - type: string - exchangeName: - type: string - description: - type: string - contactPerson: - type: string - format: uuid - contact: - $ref: '#/components/schemas/User' - identifiers: - type: array - items: - $ref: '#/components/schemas/Identifier' - subsets: - type: array - items: - $ref: '#/components/schemas/Identifier' - tables: - type: array - items: - $ref: '#/components/schemas/Table' - views: - type: array - items: - $ref: '#/components/schemas/View' - accesses: - type: array - items: - $ref: '#/components/schemas/DatabaseAccess' - isPublic: - type: boolean - image: - type: array - items: - type: string - format: byte - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - DatabaseAccess: - type: object - properties: - huserid: - type: string - format: uuid - user: - $ref: '#/components/schemas/User' - hdbid: - type: integer - format: int64 - database: - $ref: '#/components/schemas/Database' - type: - type: string - enum: - - AccessType.READ - - AccessType.WRITE_OWN - - AccessType.WRITE_ALL - created: - type: string - format: date-time - ForeignKey: - type: object - properties: - fkid: - type: integer - format: int64 - name: - type: string - table: - $ref: '#/components/schemas/Table' - referencedTable: - $ref: '#/components/schemas/Table' - references: - type: array - items: - $ref: '#/components/schemas/ForeignKeyReference' - onUpdate: - type: string - enum: - - ReferenceType.RESTRICT - - ReferenceType.CASCADE - - ReferenceType.SET_NULL - - ReferenceType.NO_ACTION - - ReferenceType.SET_DEFAULT - onDelete: - type: string - enum: - - ReferenceType.RESTRICT - - ReferenceType.CASCADE - - ReferenceType.SET_NULL - - ReferenceType.NO_ACTION - - ReferenceType.SET_DEFAULT - ForeignKeyReference: - type: object - properties: - id: - type: integer - format: int64 - foreignKey: - $ref: '#/components/schemas/ForeignKey' - column: - $ref: '#/components/schemas/TableColumn' - referencedColumn: - $ref: '#/components/schemas/TableColumn' - Identifier: - type: object - properties: - id: - type: integer - format: int64 - queryId: - type: integer - format: int64 - tableId: - type: integer - format: int64 - viewId: - type: integer - format: int64 - creators: - type: array - items: - $ref: '#/components/schemas/Creator' - publisher: - type: string - status: - type: string - enum: - - DRAFT - - PUBLISHED - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - titles: - type: array - items: - $ref: '#/components/schemas/IdentifierTitle' - descriptions: - type: array - items: - $ref: '#/components/schemas/IdentifierDescription' - funders: - type: array - items: - $ref: '#/components/schemas/IdentifierFunder' - licenses: - type: array - items: - $ref: '#/components/schemas/License' - type: - type: string - enum: - - DATABASE - - SUBSET - - TABLE - - VIEW - query: - type: string - queryNormalized: - type: string - queryHash: - type: string - resultHash: - type: string - execution: - type: string - format: date-time - resultNumber: - type: integer - format: int64 - publicationYear: - type: integer - format: int32 - publicationMonth: - type: integer - format: int32 - publicationDay: - type: integer - format: int32 - database: - $ref: '#/components/schemas/Database' - relatedIdentifiers: - type: array - items: - $ref: '#/components/schemas/RelatedIdentifier' - doi: - type: string - createdBy: - type: string - format: uuid - creator: - $ref: '#/components/schemas/User' - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - IdentifierDescription: - type: object - properties: - id: - type: integer - format: int64 - description: - type: string - descriptionType: - type: string - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - identifier: - $ref: '#/components/schemas/Identifier' - IdentifierFunder: - type: object - properties: - id: - type: integer - format: int64 - funderName: - type: string - funderIdentifier: - type: string - funderIdentifierType: - type: string - enum: - - CROSSREF_FUNDER_ID - - ROR - - GND - - ISNI - - OTHER - schemeUri: - type: string - awardNumber: - type: string - awardTitle: - type: string - identifier: - $ref: '#/components/schemas/Identifier' - IdentifierTitle: - type: object - properties: - id: - type: integer - format: int64 - title: - type: string - titleType: - type: string - enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle - - Other - language: - type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - "no" - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - identifier: - $ref: '#/components/schemas/Identifier' - License: - type: object - properties: - identifier: - type: string - uri: - type: string - description: - type: string - PrimaryKey: - type: object - properties: - pkid: - type: integer - format: int64 - table: - $ref: '#/components/schemas/Table' - column: - $ref: '#/components/schemas/TableColumn' - RelatedIdentifier: - type: object - properties: - id: - type: integer - format: int64 - value: - type: string - type: - type: string - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - identifier: - $ref: '#/components/schemas/Identifier' - Table: - type: object - properties: - id: - type: integer - format: int64 - tdbid: - type: integer - format: int64 - createdBy: - type: string - format: uuid - creator: - $ref: '#/components/schemas/User' - ownedBy: - type: string - format: uuid - owner: - $ref: '#/components/schemas/User' - name: - type: string - internalName: - type: string - queueName: - type: string - description: - type: string - database: - $ref: '#/components/schemas/Database' - columns: - type: array - items: - $ref: '#/components/schemas/TableColumn' - identifiers: - type: array - items: - $ref: '#/components/schemas/Identifier' - constraints: - $ref: '#/components/schemas/Constraints' - isVersioned: - type: boolean - numRows: - type: integer - format: int64 - dataLength: - type: integer - format: int64 - maxDataLength: - type: integer - format: int64 - avgRowLength: - type: integer - format: int64 - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - TableColumn: - type: object - properties: - id: - type: integer - format: int64 - dateFormat: - $ref: '#/components/schemas/ContainerImageDate' - table: - $ref: '#/components/schemas/Table' - views: - type: array - items: - $ref: '#/components/schemas/View' - name: - type: string - autoGenerated: - type: boolean - internalName: - type: string - indexLength: - type: integer - format: int64 - alias: - type: string - columnType: - type: string - enum: - - TableColumnType.CHAR - - TableColumnType.VARCHAR - - TableColumnType.BINARY - - TableColumnType.VARBINARY - - TableColumnType.TINYBLOB - - TableColumnType.TINYTEXT - - TableColumnType.TEXT - - TableColumnType.BLOB - - TableColumnType.MEDIUMTEXT - - TableColumnType.MEDIUMBLOB - - TableColumnType.LONGTEXT - - TableColumnType.LONGBLOB - - TableColumnType.ENUM - - TableColumnType.SET - - TableColumnType.BIT - - TableColumnType.TINYINT - - TableColumnType.BOOL - - TableColumnType.SMALLINT - - TableColumnType.MEDIUMINT - - TableColumnType.INT - - TableColumnType.BIGINT - - TableColumnType.FLOAT - - TableColumnType.DOUBLE - - TableColumnType.DECIMAL - - TableColumnType.DATE - - TableColumnType.DATETIME - - TableColumnType.TIMESTAMP - - TableColumnType.TIME - - TableColumnType.YEAR - length: - type: integer - format: int64 - isNullAllowed: - type: boolean - ordinalPosition: - type: integer - format: int32 - created: - type: string - format: date-time - concept: - $ref: '#/components/schemas/TableColumnConcept' - unit: - $ref: '#/components/schemas/TableColumnUnit' - enums: - type: array - items: - type: string - sets: - type: array - items: - type: string - size: - type: integer - format: int64 - d: - type: integer - format: int64 - min: - type: number - max: - type: number - mean: - type: number - median: - type: number - stdDev: - type: number - lastModified: - type: string - format: date-time - TableColumnConcept: - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - columns: - type: array - items: - $ref: '#/components/schemas/TableColumn' - TableColumnUnit: - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - name: - type: string - description: - type: string - created: - type: string - format: date-time - columns: - type: array - items: - $ref: '#/components/schemas/TableColumn' - Unique: - type: object - properties: - uid: - type: integer - format: int64 - name: - type: string - table: - $ref: '#/components/schemas/Table' - columns: - type: array - items: - $ref: '#/components/schemas/TableColumn' - User: - type: object - properties: - id: - type: string - format: uuid - username: - type: string - firstname: - type: string - lastname: - type: string - email: - type: string - orcid: - type: string - affiliation: - type: string - language: - type: string - accesses: - type: array - items: - $ref: '#/components/schemas/DatabaseAccess' - theme: - type: string - mariadbPassword: - type: string - View: - type: object - properties: - id: - type: integer - format: int64 - vdbid: - type: integer - format: int64 - createdBy: - type: string - format: uuid - creator: - $ref: '#/components/schemas/User' - name: - type: string - internalName: - type: string - isPublic: - type: boolean - isInitialView: - type: boolean - query: - type: string - queryHash: - type: string - identifiers: - type: array - items: - $ref: '#/components/schemas/Identifier' - database: - $ref: '#/components/schemas/Database' - columns: - type: array - items: - $ref: '#/components/schemas/ViewColumn' - created: - type: string - format: date-time - lastModified: - type: string - format: date-time - ViewColumn: - type: object - properties: - id: - type: integer - format: int64 - alias: - type: string - ordinalPosition: - type: integer - format: int32 - view: - $ref: '#/components/schemas/View' - column: - $ref: '#/components/schemas/TableColumn' - LdCreatorDto: - required: - - '@type' - - name - type: object - properties: - name: - type: string - sameAs: - type: string - givenName: - type: string - familyName: - type: string - '@type': - type: string - LdDatasetDto: - required: - - '@context' - - '@type' - - citation - - creator - - description - - hasPart - - identifier - - name - - temporalCoverage - - url - - version - type: object - properties: - name: - type: string - description: - type: string - url: - type: string - identifier: - type: array - items: - type: string - license: - type: string - creator: - type: array - items: - $ref: '#/components/schemas/LdCreatorDto' - citation: - type: string - hasPart: - type: array - items: - $ref: '#/components/schemas/LdDatasetDto' - temporalCoverage: - type: string - version: - type: string - format: date-time - '@context': - type: string - '@type': - type: string - TableColumnEntityDto: - required: - - column_id - - database_id - - table_id - - uri - type: object - properties: - uri: - type: string - example: https://www.wikidata.org/entity/Q1686799 - label: - type: string - example: Apache Jena - description: - type: string - example: open source semantic web framework for Java - database_id: - type: integer - format: int64 - example: 1 - table_id: - type: integer - format: int64 - example: 1 - column_id: - type: integer - format: int64 - example: 1 - securitySchemes: - basicAuth: - type: http - scheme: basic - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT diff --git a/.docs/.swagger/api-search.yaml b/.docs/.swagger/api-search.yaml deleted file mode 100644 index 0bd4f541c863562a6df0e3181aa4d20b0f964d4c..0000000000000000000000000000000000000000 --- a/.docs/.swagger/api-search.yaml +++ /dev/null @@ -1,385 +0,0 @@ -components: - securitySchemes: - basicAuth: - in: header - scheme: basic - type: http - bearerAuth: - bearerFormat: JWT - in: header - scheme: bearer - type: http -externalDocs: - description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/__APPVERSION__/ -info: - contact: - email: andreas.rauber@tuwien.ac.at - name: Prof. Andreas Rauber - description: Service that searches the search database - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 - title: Database Repository Search Service API - version: __APPVERSION__ -openapi: 3.0.0 -paths: - /api/search: - get: - consumes: - - application/json - description: Performs a fuzzy search - operationId: post_fuzzy_search - parameters: - - in: query - required: true - schema: - properties: - q: - example: air quality - type: string - type: string - produces: - - application/json - responses: - '200': - content: - application/json: - schema: - properties: - results: - items: - type: object - type: array - type: object - description: OK, contains the elements formatted as an array of JSON arrays - '415': - description: Wrong accept type - summary: Performs a fuzzy search - tags: - - search-endpoint - /api/search/database/{database_id}: - delete: - consumes: - - application/json - description: Deletes a database - operationId: delete_database - produces: - - application/json - responses: - '202': - content: - application/json: - schema: - properties: - id: - example: 1 - implementation: int64 - type: integer - required: - - id - type: object - description: Deleted database successfully - '404': - content: - application/json: - schema: - properties: - message: - example: Message - type: string - success: - example: false - type: boolean - required: - - success - - message - type: object - description: Database not found - security: - - bearerAuth: [] - - basicAuth: [] - summary: Deletes a database - tags: - - database-endpoint - put: - consumes: - - application/json - description: Updates a database - operationId: update_database - parameters: - - in: body - name: body - required: true - schema: - properties: - internal_name: - example: air_quality_abcd - type: string - name: - example: Air Quality - type: string - type: object - produces: - - application/json - responses: - '202': - content: - application/json: - schema: - properties: - id: - example: 1 - implementation: int64 - type: integer - required: - - id - type: object - description: Updated database successfully - '400': - content: - application/json: - schema: - properties: - message: - example: Message - type: string - success: - example: false - type: boolean - required: - - success - - message - type: object - description: Invalid schema - '404': - content: - application/json: - schema: - properties: - message: - example: Message - type: string - success: - example: false - type: boolean - required: - - success - - message - type: object - description: Database not found - security: - - bearerAuth: [] - - basicAuth: [] - summary: Updates a database - tags: - - database-endpoint - /api/search/{index}: - get: - consumes: - - application/json - description: Gets the index - operationId: get_index - parameters: - - description: The search type. - in: path - name: type - required: true - schema: - enum: - - database - - table - - view - - column - - user - - identifier - - concept - - unit - type: string - - in: body - name: body - required: true - schema: - properties: - field_value_pairs: - type: object - search_term: - example: air quality - type: string - t1: - example: 0 - type: integer - t2: - example: 100 - type: integer - type: object - produces: - - application/json - responses: - '200': - content: - application/json: - schema: - properties: - results: - items: - type: object - type: array - type: - description: Same as the requested type - enum: - - database - - table - - view - - column - - user - - identifier - - concept - - unit - type: string - type: object - description: OK, contains the elements formatted as an array of JSON arrays - summary: Gets the index - tags: - - search-endpoint - /api/search/{type}: - post: - consumes: - - application/json - description: Performs a general search - operationId: post_general_search - parameters: - - description: The search type. - in: path - name: type - required: true - schema: - enum: - - database - - table - - view - - column - - user - - identifier - - concept - - unit - type: string - - in: query - name: t1 - schema: - type: integer - - in: query - name: t2 - schema: - type: integer - - in: body - name: body - required: true - schema: - properties: - field_value_pairs: - type: object - search_term: - example: air quality - type: string - type: object - produces: - - application/json - responses: - '200': - content: - application/json: - schema: - properties: - results: - items: - type: object - type: array - type: - description: Same as the requested type - enum: - - database - - table - - view - - column - - user - - identifier - - concept - - unit - type: string - type: object - description: OK, contains the elements formatted as an array of JSON arrays - summary: Performs a general search - tags: - - search-endpoint - /api/search/{type}/fields: - get: - operationId: get_fields - parameters: - - description: The search type. - in: path - name: type - required: true - schema: - enum: - - database - - table - - view - - column - - user - - identifier - - concept - - unit - type: string - responses: - '200': - content: - application/json: - schema: - properties: - results: - items: - properties: - attr_friendly_name: - example: Name - type: string - attr_name: - example: name - type: string - type: - description: OpenSearch data types. - example: string - type: string - type: object - type: array - type: object - description: List of fields - '404': - description: Invalid type. - summary: Get searchable fields - tags: - - search-endpoint - /health: - get: - consumes: - - application/json - description: 'Return UP if the instance is ready to serve connections. - - ' - produces: - - application/json - responses: - '200': - description: OK, service is up and running - schema: - $ref: '#/definitions/Column' - '404': - description: Service is not yet ready - summary: Return a healthcheck - tags: - - actuator -servers: - - description: Generated server url - url: http://localhost:4000 - - description: Sandbox - url: https://test.dbrepo.tuwien.ac.at diff --git a/.docs/.swagger/api-sidecar.yaml b/.docs/.swagger/api-sidecar.yaml deleted file mode 100644 index 0d455b252691166485a4c388a6c3085f422a5e34..0000000000000000000000000000000000000000 --- a/.docs/.swagger/api-sidecar.yaml +++ /dev/null @@ -1,106 +0,0 @@ -components: - securitySchemes: - basicAuth: - in: header - scheme: basic - type: http - bearerAuth: - bearerFormat: JWT - in: header - scheme: bearer - type: http -externalDocs: - description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/__APPVERSION__/ -info: - contact: - email: andreas.rauber@tuwien.ac.at - name: Prof. Andreas Rauber - description: Sidecar that downloads the import .csv file - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 - title: Database Repository Data Database sidecar API - version: __APPVERSION__ -openapi: 3.0.0 -paths: - /health: - get: - consumes: - - application/json - description: 'Return UP if the instance is ready to serve connections. - - ' - produces: - - application/json - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/Health' - description: OK, service is up and running - '404': - description: Service is not yet ready - summary: Return a healthcheck - tags: - - actuator - /sidecar/export/{filename}: - post: - consumes: - - application/json - description: 'Exports a specific .csv file to the Storage Service via S3 - - ' - parameters: - - description: Name of the object file to export to the Storage Service - in: path - name: filename - required: true - produces: - - application/json - responses: - '202': - content: {} - description: Exported the .csv - '400': - description: The Storage Service could not be contacted or .csv was not - found. - security: - - bearerAuth: [] - - basicAuth: [] - summary: Exports a .csv to the Storage Service - tags: - - sidecar - /sidecar/import/{filename}: - post: - consumes: - - application/json - description: 'Imports a specific .csv file from the Storage Service via S3 - - ' - parameters: - - description: Name of the object file to import from the Storage Service - in: path - name: filename - required: true - produces: - - application/json - responses: - '202': - content: {} - description: Imported the .csv - '400': - description: The Storage Service could not be contacted or .csv was not - found. - security: - - bearerAuth: [] - - basicAuth: [] - summary: Imports a .csv from the Storage Service - tags: - - sidecar -servers: - - description: Generated server url - url: http://localhost:8080 - - description: Sandbox - url: https://test.dbrepo.tuwien.ac.at diff --git a/.docs/.swagger/api-upload.yaml b/.docs/.swagger/api-upload.yaml deleted file mode 100644 index b08342a5433dfef4b25bc211cd76c60e753778c4..0000000000000000000000000000000000000000 --- a/.docs/.swagger/api-upload.yaml +++ /dev/null @@ -1,30 +0,0 @@ -openapi: 3.0.0 -info: - title: Database Repository Upload Service API - description: Service that manages the uploads - contact: - name: Prof. Andreas Rauber - email: andreas.rauber@tuwien.ac.at - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0 - version: __APPVERSION__ -externalDocs: - description: Sourcecode Documentation - url: https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services -servers: - - url: http://localhost:1080 - description: Generated server url - - url: https://test.dbrepo.tuwien.ac.at - description: Sandbox -paths: - /api/upload/files: - post: - tags: - - upload-endpoint - summary: Uploads a file - operationId: upload - responses: - "201": - description: "Successfully uploaded a file" - security: { } \ No newline at end of file diff --git a/.docs/.swagger/api.base.yaml b/.docs/.swagger/api.base.yaml new file mode 100644 index 0000000000000000000000000000000000000000..aa83c853cedca25eb3f4e27f59ba01fd24cd043b --- /dev/null +++ b/.docs/.swagger/api.base.yaml @@ -0,0 +1,30 @@ +components: + securitySchemes: + basicAuth: + in: header + scheme: basic + type: http + bearerAuth: + bearerFormat: JWT + in: header + scheme: bearer + type: http +externalDocs: + description: Sourcecode Documentation + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/ +info: + contact: + email: andreas.rauber@tuwien.ac.at + name: Prof. Andreas Rauber + description: The REST API + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 + title: DBRepo REST API + version: 1.4.4 +openapi: 3.1.0 +servers: + - description: Test Instance + url: https://test.dbrepo.tuwien.ac.at + - description: Local Instance + url: http://localhost diff --git a/.docs/.swagger/api.yaml b/.docs/.swagger/api.yaml new file mode 100644 index 0000000000000000000000000000000000000000..607276e81a651c7f1fd0b91a1894d7a2c8aef9b4 --- /dev/null +++ b/.docs/.swagger/api.yaml @@ -0,0 +1,3874 @@ +components: + securitySchemes: + basicAuth: + in: header + scheme: basic + type: http + bearerAuth: + bearerFormat: JWT + in: header + scheme: bearer + type: http +externalDocs: + description: Sourcecode Documentation + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/ +info: + contact: + email: andreas.rauber@tuwien.ac.at + name: Prof. Andreas Rauber + description: The REST API + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 + title: DBRepo REST API + version: 1.4.4 +openapi: 3.1.0 +servers: + - description: Test Instance + url: https://test.dbrepo.tuwien.ac.at + - description: Local Instance + url: http://localhost +paths: + /api/database: + post: + tags: + - database-endpoint + summary: Create database + operationId: create + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDatabaseDto' + required: true + responses: + "201": + description: Created a database + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseDto' + "400": + description: Database create query is malformed or image is not supported + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to create query store in database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find container in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + /api/database/{databaseId}/access/{userId}: + put: + tags: + - access-endpoint + summary: Update access to some database + operationId: update_1 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: userId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateDatabaseAccessDto' + required: true + responses: + "400": + description: Update access query or database connection is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to update access in database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to update access + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database/user in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Update access succeeded + security: + - basicAuth: [] + post: + tags: + - access-endpoint + summary: Give access to some database + operationId: create_4 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: userId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateDatabaseAccessDto' + required: true + responses: + "417": + description: Failed to give access in the database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Granting access succeeded + content: + '*/*': + schema: + type: object + "503": + description: Failed to establish connection to metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to give access + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database/user in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Granting access query or database connection is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + delete: + tags: + - access-endpoint + summary: Revoke access to some database + operationId: revoke + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: userId + in: path + required: true + schema: + type: string + format: uuid + responses: + "400": + description: Revoke access query or database connection is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to revoke access in database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to revoke access + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database/user in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Revoked access successfully + content: + '*/*': + schema: + type: object + security: + - basicAuth: [] + /api/user/{userId}: + get: + tags: + - user-endpoint + summary: Get a user info + operationId: find_2 + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + responses: + "403": + description: Find user is not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found user + content: + application/json: + schema: + $ref: '#/components/schemas/UserDto' + "404": + description: User was not found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + put: + tags: + - user-endpoint + summary: Modify user information + operationId: modify + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdateDto' + required: true + responses: + "404": + description: Failed to find database/user in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to modify user metadata + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Modify user query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Modified user information + content: + application/json: + schema: + $ref: '#/components/schemas/UserDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/user/{userId}/password: + put: + tags: + - user-endpoint + summary: Modify user password + operationId: password + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserPasswordDto' + required: true + responses: + "403": + description: Not allowed to change foreign user password + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database/user in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to get user in auth service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Modified user password + content: + application/json: + schema: + $ref: '#/components/schemas/UserDto' + "502": + description: Connection to auth service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/user/token: + put: + tags: + - user-endpoint + summary: Refresh user token + operationId: refreshToken + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RefreshTokenRequestDto' + required: true + responses: + "202": + description: Refreshed user token + content: + application/json: + schema: + $ref: '#/components/schemas/TokenDto' + "502": + description: Connection to auth service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Invalid refresh token + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + post: + tags: + - user-endpoint + summary: Obtain user token + operationId: getToken + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/LoginRequestDto' + required: true + responses: + "404": + description: Failed to find user in auth database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to get user in auth service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Obtained user token + content: + application/json: + schema: + $ref: '#/components/schemas/TokenDto' + "403": + description: Not allowed to get token + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "428": + description: Account is not fully setup in auth service (requires password change?) + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to auth service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + /api/ontology/{ontologyId}: + get: + tags: + - ontology-endpoint + summary: Find one ontology + operationId: find_3 + parameters: + - name: ontologyId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "404": + description: Could not find ontology + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Find one ontology + content: + application/json: + schema: + $ref: '#/components/schemas/OntologyDto' + put: + tags: + - ontology-endpoint + summary: Update an ontology + operationId: update + parameters: + - name: ontologyId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OntologyModifyDto' + required: true + responses: + "404": + description: Could not find ontology + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Updated ontology successfully + content: + application/json: + schema: + $ref: '#/components/schemas/OntologyDto' + security: + - bearerAuth: [] + - basicAuth: [] + delete: + tags: + - ontology-endpoint + summary: Delete an ontology + operationId: delete + parameters: + - name: ontologyId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "404": + description: Could not find ontology + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Deleted ontology successfully + content: + application/json: {} + security: + - bearerAuth: [] + - basicAuth: [] + /api/message/{messageId}: + put: + tags: + - message-endpoint + summary: Update maintenance message + operationId: update_1 + parameters: + - name: messageId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BannerMessageUpdateDto' + required: true + responses: + "202": + description: Updated message + content: + application/json: + schema: + $ref: '#/components/schemas/BannerMessageBriefDto' + "404": + description: Could not find message + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + delete: + tags: + - message-endpoint + summary: Delete maintenance message + operationId: delete_1 + parameters: + - name: messageId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "202": + description: Deleted message + content: + application/json: {} + "404": + description: Could not find message + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/image/{imageId}: + get: + tags: + - image-endpoint + summary: Find some image + operationId: findById + parameters: + - name: imageId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "404": + description: Image could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found image + content: + application/json: + schema: + $ref: '#/components/schemas/ImageDto' + put: + tags: + - image-endpoint + summary: Update some image + operationId: update_2 + parameters: + - name: imageId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ImageChangeDto' + required: true + responses: + "404": + description: Image could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Updated image successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ImageDto' + security: + - bearerAuth: [] + - basicAuth: [] + delete: + tags: + - image-endpoint + summary: Delete some image + operationId: delete_2 + parameters: + - name: imageId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "202": + description: Deleted image successfully + "404": + description: Image could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/identifier/{identifierId}: + get: + tags: + - identifier-endpoint + summary: Find some identifier + operationId: find_6 + parameters: + - name: identifierId + in: path + required: true + schema: + type: integer + format: int64 + - name: Accept + in: header + required: true + schema: + type: string + responses: + "406": + description: Failed to find acceptable representation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "422": + description: Failed to retrieve from database sidecar + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to find in data service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found identifier successfully + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierDto' + application/ld+json: + schema: + $ref: '#/components/schemas/LdDatasetDto' + text/csv: {} + text/xml: {} + text/bibliography: {} + text/bibliography; style=apa: {} + text/bibliography; style=ieee: {} + text/bibliography; style=bibtex: {} + "404": + description: Identifier could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to data service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: "Identifier could not be exported, the requested style is not known" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "410": + description: Failed to retrieve from S3 endpoint + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: Exported resource was not found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + put: + tags: + - identifier-endpoint + summary: Save identifier + operationId: save + parameters: + - name: identifierId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierSaveDto' + required: true + responses: + "403": + description: Insufficient access rights or authorities + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "405": + description: Creating identifier not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Identifier form contains invalid request data + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: "Failed to find database, table or view" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Saved identifier + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + delete: + tags: + - identifier-endpoint + summary: Delete some identifier + operationId: delete_3 + parameters: + - name: identifierId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Deleting identifier not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to delete in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Deleted identifier + content: + '*/*': + schema: + type: object + "404": + description: Identifier or database could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/identifier/{identifierId}/publish: + put: + tags: + - identifier-endpoint + summary: Publish identifier + operationId: publish + parameters: + - name: identifierId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "403": + description: Insufficient access rights or authorities + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "405": + description: Creating identifier not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Identifier form contains invalid request data + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: "Failed to find database, table or view" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Published identifier + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/visibility: + put: + tags: + - database-endpoint + summary: Update database visibility + operationId: visibility + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseModifyVisibilityDto' + required: true + responses: + "202": + description: Visibility modified successfully + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseDto' + "403": + description: Visibility modification is not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/table/{tableId}: + delete: + tags: + - table-endpoint + summary: Delete table + operationId: delete_1 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Deleted table + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Deletion query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + /api/database/{databaseId}/table/{tableId}/column/{columnId}: + put: + tags: + - table-endpoint + summary: Update a table column semantic mapping + operationId: update_3 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + - name: columnId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ColumnSemanticsUpdateDto' + required: true + responses: + "400": + description: Update semantic concept query is malformed or update unit of measurement query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Access to the database is forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Updated column semantics successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ColumnDto' + "404": + description: Failed to find user/table/database/ontology in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/owner: + put: + tags: + - database-endpoint + summary: Update database owner + operationId: transfer + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseTransferDto' + required: true + responses: + "403": + description: Transfer of ownership is not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Transfer of ownership was successful + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseDto' + "404": + description: Database or user could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/metadata/view: + put: + tags: + - database-endpoint + summary: Refresh database views metadata + operationId: refreshViewMetadata + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "403": + description: Refresh view metadata is not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Refreshed database views metadata + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseDto' + "404": + description: Failed to find database in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/metadata/table: + put: + tags: + - database-endpoint + summary: Refresh database tables metadata + operationId: refreshTableMetadata + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: Refreshed database tables metadata + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseDto' + "400": + description: Failed to parse payload at search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to refresh table metadata + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to fin user/database in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/image: + put: + tags: + - database-endpoint + summary: Update database image + operationId: modifyImage + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseModifyImageDto' + required: true + responses: + "404": + description: Database or user could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Modify of image was successful + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseDto' + "410": + description: File was not found in the Storage Service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Modify of image is not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/user: + get: + tags: + - user-endpoint + summary: Find all users + operationId: findAll + responses: + "200": + description: List users + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UserBriefDto' + post: + tags: + - user-endpoint + summary: Create user + operationId: create + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SignupRequestDto' + required: true + responses: + "503": + description: Failed to create in auth service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: User with e-mail already exists + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Failed to create in auth service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: default role not found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Parameters are not well-formed (likely email) + content: + application/json: {} + "201": + description: Created user + content: + application/json: + schema: + $ref: '#/components/schemas/UserBriefDto' + "409": + description: User with username already exists + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + /api/ontology: + get: + tags: + - ontology-endpoint + summary: List all ontologies + operationId: findAll_2 + responses: + "200": + description: List all ontologies + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OntologyDto' + post: + tags: + - ontology-endpoint + summary: Register a new ontology + operationId: create_1 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OntologyCreateDto' + required: true + responses: + "201": + description: Registered ontology successfully + content: + application/json: + schema: + $ref: '#/components/schemas/OntologyDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/message: + get: + tags: + - message-endpoint + summary: Find maintenance messages + operationId: list_2 + parameters: + - name: filter + in: query + required: false + schema: + type: string + responses: + "200": + description: List messages + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BannerMessageDto' + post: + tags: + - message-endpoint + summary: Create maintenance message + operationId: create_2 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BannerMessageCreateDto' + required: true + responses: + "201": + description: Created message + content: + application/json: + schema: + $ref: '#/components/schemas/BannerMessageBriefDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/image: + get: + tags: + - image-endpoint + summary: Find all images + operationId: findAll_3 + responses: + "200": + description: List images + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ContainerImage' + post: + tags: + - image-endpoint + summary: Create image + operationId: create_3 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ImageCreateDto' + required: true + responses: + "201": + description: Created image + content: + application/json: + schema: + $ref: '#/components/schemas/ImageDto' + "400": + description: Image specification is invalid + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: Image already exists + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/identifier: + get: + tags: + - identifier-endpoint + summary: Find all identifiers + operationId: findAll_4 + parameters: + - name: dbid + in: query + required: false + schema: + type: integer + format: int64 + - name: qid + in: query + required: false + schema: + type: integer + format: int64 + - name: vid + in: query + required: false + schema: + type: integer + format: int64 + - name: tid + in: query + required: false + schema: + type: integer + format: int64 + - name: Accept + in: header + required: true + schema: + type: string + responses: + "200": + description: Found identifiers successfully + content: + application/json: + schema: + type: string + application/ld+json: + schema: + type: string + "406": + description: "Identifier could not be exported, the requested style is not known" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + post: + tags: + - identifier-endpoint + summary: Draft identifier + operationId: create_4 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierCreateDto' + required: true + responses: + "403": + description: Insufficient access rights or authorities + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "405": + description: Creating identifier not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Identifier form contains invalid request data + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: "Failed to find database, table or view" + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "201": + description: Drafted identifier + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierDto' + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/view: + get: + tags: + - view-endpoint + summary: Find view schemas + operationId: getSchema + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "417": + description: View schema could not be retrieved + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: View schema could not be mapped to known columns + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database/view in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Database schema is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found view schemas + content: + application/json: + schema: + type: string + post: + tags: + - view-endpoint + summary: Create view + operationId: create_1 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ViewCreateDto' + required: true + responses: + "400": + description: View schema is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: View schema could not be mapped + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Created view + content: + application/json: + schema: + $ref: '#/components/schemas/ViewDto' + security: + - basicAuth: [] + - bearerAuth: [] + /api/database/{databaseId}/table: + get: + tags: + - table-endpoint + summary: Find table schemas + operationId: getSchema_1 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "403": + description: Find table schema not allowed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to parse table schema + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Got table schemas + content: + application/json: + schema: + type: string + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Schema data malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + post: + tags: + - table-endpoint + summary: Create table + operationId: create_2 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TableCreateDto' + required: true + responses: + "400": + description: Table schema or query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: Table name already exists in database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database or table in data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "201": + description: Created table + content: + application/json: + schema: + $ref: '#/components/schemas/TableDto' + security: + - basicAuth: [] + /api/container: + get: + tags: + - container-endpoint + summary: Find all containers + operationId: findAll_6 + parameters: + - name: limit + in: query + required: false + schema: + type: integer + format: int32 + responses: + "200": + description: List containers + content: + application/json: + schema: + type: array + items: + type: string + post: + tags: + - container-endpoint + summary: Create container + operationId: create_9 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ContainerCreateDto' + required: true + responses: + "404": + description: Container image or user could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: Container name already exists + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "201": + description: Created a new container + content: + application/json: + schema: + $ref: '#/components/schemas/ContainerBriefDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/unit: + get: + tags: + - unit-endpoint + summary: List semantic units + operationId: findAll_1 + responses: + "200": + description: Find all semantic units + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UnitDto' + /api/ontology/{ontologyId}/entity: + get: + tags: + - ontology-endpoint + summary: Find entities + operationId: find_4 + parameters: + - name: ontologyId + in: path + required: true + schema: + type: integer + format: int64 + - name: label + in: query + required: false + schema: + type: string + - name: uri + in: query + required: false + schema: + type: string + responses: + "404": + description: Could not find ontology + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "422": + description: Ontology does not have rdf or sparql endpoint + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found entities + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/EntityDto' + "400": + description: Filter params are invalid + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Generated query or uri is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/oai: + get: + tags: + - metadata-endpoint + summary: Get the record + operationId: identify_1_1_1_1 + parameters: + - name: verb + in: query + - name: parameters + in: query + required: true + schema: + $ref: '#/components/schemas/OaiListIdentifiersParameters' + responses: + "200": + description: List containers + content: + text/xml: {} + /api/message/message/{messageId}: + get: + tags: + - message-endpoint + summary: Find one maintenance message + operationId: find_5 + parameters: + - name: messageId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: Get messages + content: + application/json: + schema: + $ref: '#/components/schemas/BannerMessageDto' + "404": + description: Could not find message + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + /api/license: + get: + tags: + - license-endpoint + summary: Get all licenses + operationId: list_3 + responses: + "200": + description: List of licenses + content: + application/json: + schema: + type: array + items: + type: string + /api/identifier/retrieve: + get: + tags: + - identifier-endpoint + summary: Retrieve metadata from identifier + operationId: retrieve + parameters: + - name: url + in: query + required: true + schema: + type: string + responses: + "200": + description: Retrieved metadata from identifier + content: + application/json: + schema: + $ref: '#/components/schemas/IdentifierDto' + "404": + description: Failed to find metadata for identifier + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + /api/database/{databaseId}: + put: + tags: + - database-endpoint + summary: Update user password in database + operationId: update + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateUserPasswordDto' + required: true + responses: + "404": + description: Failed to find database in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Updated user password in database + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to update user password in database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + /api/database/{databaseId}/view/{viewId}: + delete: + tags: + - view-endpoint + summary: Delete view + operationId: delete + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: viewId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "202": + description: Deleted view + "409": + description: View schema could not be mapped + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find view in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Database schema is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + /api/database/{databaseId}/table/{tableId}/suggest: + get: + tags: + - table-endpoint + summary: Suggest table semantics + operationId: analyseTable + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: Suggested table semantics successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TableColumnEntityDto' + "400": + description: Failed to parse statistic in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "422": + description: Ontology does not have rdf or sparql endpoint + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database/table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Generated query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/table/{tableId}/column/{columnId}/suggest: + get: + tags: + - table-endpoint + summary: Suggest table column semantics + operationId: analyseTableColumn + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + - name: columnId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: Suggested table column semantics successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TableColumnEntityDto' + "422": + description: Ontology does not have rdf or sparql endpoint + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database/table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Generated query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/container/{containerId}: + get: + tags: + - container-endpoint + summary: Find some container + operationId: findById_3 + parameters: + - name: containerId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "200": + description: Found container + content: + application/json: + schema: + $ref: '#/components/schemas/ContainerDto' + "404": + description: Container image could not be found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + delete: + tags: + - container-endpoint + summary: Delete some container + operationId: delete_6 + parameters: + - name: containerId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "404": + description: Container not found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Deleted container successfully + content: + '*/*': + schema: + type: object + security: + - bearerAuth: [] + - basicAuth: [] + /api/concept: + get: + tags: + - concept-endpoint + summary: List semantic concepts + operationId: findAll_7 + responses: + "200": + description: Find all semantic concepts + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ConceptDto' + /api/database/{databaseId}/view/{viewId}/data: + get: + tags: + - view-endpoint + summary: Retrieve view data + operationId: getData + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: viewId + in: path + required: true + schema: + type: integer + format: int64 + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + responses: + "403": + description: Not allowed to retrieve view data + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: View schema could not be mapped + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find view in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Request pagination is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Retrieved view data + content: + application/json: + schema: + $ref: '#/components/schemas/QueryResultDto' + security: + - basicAuth: [] + - bearerAuth: [] + head: + tags: + - view-endpoint + summary: Retrieve view data + operationId: getData_1 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: viewId + in: path + required: true + schema: + type: integer + format: int64 + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + responses: + "403": + description: Not allowed to retrieve view data + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "409": + description: View schema could not be mapped + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find view in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Request pagination is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Retrieved view data + content: + application/json: + schema: + $ref: '#/components/schemas/QueryResultDto' + security: + - basicAuth: [] + - bearerAuth: [] + /api/database/{databaseId}/table/{tableId}/data: + get: + tags: + - table-endpoint + summary: Retrieve table data + operationId: getData_2 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + responses: + "200": + description: Retrieved table data + content: + application/json: + schema: + $ref: '#/components/schemas/QueryResultDto' + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Request pagination or table data select query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + put: + tags: + - table-endpoint + summary: Update table data + operationId: updateTuple + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TupleUpdateDto' + required: true + responses: + "403": + description: Update table data not allowed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Updated table data + "400": + description: Request pagination or table data select query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + post: + tags: + - table-endpoint + summary: Create table data + operationId: createTuple + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TupleDto' + required: true + responses: + "403": + description: Create table data not allowed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "201": + description: Created table data + "400": + description: Request pagination or table data select query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + delete: + tags: + - table-endpoint + summary: Delete table data + operationId: deleteTuple + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TupleDeleteDto' + required: true + responses: + "403": + description: Delete table data not allowed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Deleted table data + "400": + description: Request pagination or table data select query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + head: + tags: + - table-endpoint + summary: Retrieve table data + operationId: getData_3 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + responses: + "200": + description: Retrieved table data + content: + application/json: + schema: + $ref: '#/components/schemas/QueryResultDto' + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Request pagination or table data select query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + /api/database/{databaseId}/subset/{subsetId}/data: + get: + tags: + - subset-endpoint + summary: Retrieved subset data + operationId: getData_4 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: subsetId + in: path + required: true + schema: + type: integer + format: int64 + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + responses: + "400": + description: Malformed select query + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to retrieve subset data + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database or query in query store of the data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Retrieved subset data + content: + application/json: + schema: + $ref: '#/components/schemas/QueryResultDto' + security: + - bearerAuth: [] + - basicAuth: [] + head: + tags: + - subset-endpoint + summary: Retrieved subset data + operationId: getData_5 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: subsetId + in: path + required: true + schema: + type: integer + format: int64 + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + responses: + "400": + description: Malformed select query + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to retrieve subset data + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database or query in query store of the data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Retrieved subset data + content: + application/json: + schema: + $ref: '#/components/schemas/QueryResultDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/subset/{queryId}: + put: + tags: + - subset-endpoint + summary: Persist subset + operationId: persist + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: queryId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/QueryPersistDto' + required: true + responses: + "202": + description: Persisted subset + content: + application/json: + schema: + $ref: '#/components/schemas/QueryDto' + "400": + description: Malformed select query + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database or query in query store of the data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to persist subset + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "417": + description: Failed to persist subset + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + /api/database/{databaseId}/table/{tableId}/data/import: + post: + tags: + - table-endpoint + summary: Import dataset + operationId: importData + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ImportCsvDto' + required: true + responses: + "403": + description: Import table dataset not allowed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "400": + description: Import dataset query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "202": + description: Import dataset successfully + security: + - basicAuth: [] + - bearerAuth: [] + /api/database/{databaseId}/subset: + get: + tags: + - subset-endpoint + summary: Find subsets + operationId: list + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: persisted + in: query + required: false + schema: + type: boolean + responses: + "404": + description: Failed to find database in metadata database or query in query store of the data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to find subsets + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found subsets + content: + application/json: + schema: + type: string + security: + - basicAuth: [] + - bearerAuth: [] + post: + tags: + - subset-endpoint + summary: Create subset + operationId: create_3 + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: page + in: query + required: false + schema: + type: integer + format: int64 + - name: size + in: query + required: false + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ExecuteStatementDto' + required: true + responses: + "400": + description: Malformed select query + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database or query in query store of the data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to find subset + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "201": + description: Created subset + content: + application/json: + schema: + $ref: '#/components/schemas/QueryResultDto' + "417": + description: Failed to insert query into query store of data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "501": + description: Failed to execute query as it contains non-supported keywords + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + /api/database/{databaseId}/table/{tableId}/history: + get: + tags: + - table-endpoint + summary: Find table history + operationId: getHistory + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + responses: + "404": + description: Failed to find table history in data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found table history + content: + application/json: + schema: + type: string + "403": + description: Find table history not allowed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + /api/database/{databaseId}/table/{tableId}/export: + get: + tags: + - table-endpoint + summary: Export table data + operationId: exportData + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: tableId + in: path + required: true + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + responses: + "404": + description: Failed to find table in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Exported table data + content: + application/json: + schema: + type: string + format: binary + "400": + description: Request pagination or table data select query is malformed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Export table data not allowed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - basicAuth: [] + - bearerAuth: [] + /api/database/{databaseId}/subset/{subsetId}: + get: + tags: + - subset-endpoint + summary: Find subset + operationId: findById + parameters: + - name: databaseId + in: path + required: true + schema: + type: integer + format: int64 + - name: subsetId + in: path + required: true + schema: + type: integer + format: int64 + - name: timestamp + in: query + required: false + schema: + type: string + format: date-time + responses: + "400": + description: Malformed select query + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "404": + description: Failed to find database in metadata database or query in query store of the data database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "403": + description: Not allowed to find subset + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "406": + description: Failed to find acceptable representation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + "200": + description: Found subset + content: + application/json: + schema: + $ref: '#/components/schemas/QueryDto' + text/csv: {} + security: + - basicAuth: [] + - bearerAuth: [] + /api/search: + get: + consumes: + - application/json + description: Performs a fuzzy search + operationId: post_fuzzy_search + parameters: + - in: query + required: true + schema: + properties: + q: + example: air quality + type: string + type: string + produces: + - application/json + responses: + "200": + content: + application/json: + schema: + properties: + results: + items: + type: object + type: array + type: object + description: OK, contains the elements formatted as an array of JSON arrays + "415": + description: Wrong accept type + summary: Performs a fuzzy search + tags: + - search-endpoint + /api/search/database/{database_id}: + delete: + consumes: + - application/json + description: Deletes a database + operationId: delete_database + produces: + - application/json + responses: + "202": + content: + application/json: + schema: + properties: + id: + example: 1 + implementation: int64 + type: integer + required: + - id + type: object + description: Deleted database successfully + "404": + content: + application/json: + schema: + properties: + message: + example: Message + type: string + success: + example: false + type: boolean + required: + - success + - message + type: object + description: Database not found + security: + - bearerAuth: [] + - basicAuth: [] + summary: Deletes a database + tags: + - database-endpoint + put: + consumes: + - application/json + description: Updates a database + operationId: update_database + parameters: + - in: body + name: body + required: true + schema: + properties: + internal_name: + example: air_quality_abcd + type: string + name: + example: Air Quality + type: string + type: object + produces: + - application/json + responses: + "202": + content: + application/json: + schema: + properties: + id: + example: 1 + implementation: int64 + type: integer + required: + - id + type: object + description: Updated database successfully + "400": + content: + application/json: + schema: + properties: + message: + example: Message + type: string + success: + example: false + type: boolean + required: + - success + - message + type: object + description: Invalid schema + "404": + content: + application/json: + schema: + properties: + message: + example: Message + type: string + success: + example: false + type: boolean + required: + - success + - message + type: object + description: Database not found + security: + - bearerAuth: [] + - basicAuth: [] + summary: Updates a database + tags: + - database-endpoint + /api/search/{index}: + get: + consumes: + - application/json + description: Gets the index + operationId: get_index + parameters: + - description: The search type. + in: path + name: type + required: true + schema: + enum: + - database + - table + - view + - column + - user + - identifier + - concept + - unit + type: string + - in: body + name: body + required: true + schema: + properties: + field_value_pairs: + type: object + search_term: + example: air quality + type: string + t1: + example: 0 + type: integer + t2: + example: 100 + type: integer + type: object + produces: + - application/json + responses: + "200": + content: + application/json: + schema: + properties: + results: + items: + type: object + type: array + type: + description: Same as the requested type + enum: + - database + - table + - view + - column + - user + - identifier + - concept + - unit + type: string + type: object + description: OK, contains the elements formatted as an array of JSON arrays + summary: Gets the index + tags: + - search-endpoint + /api/search/{type}: + post: + consumes: + - application/json + description: Performs a general search + operationId: post_general_search + parameters: + - description: The search type. + in: path + name: type + required: true + schema: + enum: + - database + - table + - view + - column + - user + - identifier + - concept + - unit + type: string + - in: query + name: t1 + schema: + type: integer + - in: query + name: t2 + schema: + type: integer + - in: body + name: body + required: true + schema: + properties: + field_value_pairs: + type: object + search_term: + example: air quality + type: string + type: object + produces: + - application/json + responses: + "200": + content: + application/json: + schema: + properties: + results: + items: + type: object + type: array + type: + description: Same as the requested type + enum: + - database + - table + - view + - column + - user + - identifier + - concept + - unit + type: string + type: object + description: OK, contains the elements formatted as an array of JSON arrays + summary: Performs a general search + tags: + - search-endpoint + /api/search/{type}/fields: + get: + operationId: get_fields + parameters: + - description: The search type. + in: path + name: type + required: true + schema: + enum: + - database + - table + - view + - column + - user + - identifier + - concept + - unit + type: string + responses: + "200": + content: + application/json: + schema: + properties: + results: + items: + properties: + attr_friendly_name: + example: Name + type: string + attr_name: + example: name + type: string + type: + description: OpenSearch data types. + example: string + type: string + type: object + type: array + type: object + description: List of fields + "404": + description: Invalid type. + summary: Get searchable fields + tags: + - search-endpoint + /health: + get: + consumes: + - application/json + description: | + Return UP if the instance is ready to serve connections. + produces: + - application/json + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/Health' + description: OK, service is up and running + "404": + description: Service is not yet ready + summary: Return a healthcheck + tags: + - actuator + /api/analyse/database/{database_id}/table/{table_id}/statistics: + get: + operationId: analyse_table_stat + parameters: + - example: 1 + in: path + name: database_id + required: true + schema: + format: int64 + type: integer + - example: 1 + in: path + name: table_id + required: true + schema: + format: int64 + type: integer + responses: + "202": + content: + application/json: + schema: + $ref: '#/components/schemas/TableStats' + description: Determined statistics + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Missing parameters + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Table not found + security: + - bearerAuth: [] + - basicAuth: [] + summary: Determine table statistics + tags: + - analyse-endpoint + /api/analyse/datatypes: + get: + consumes: + - application/json + description: This is a simple API which returns the datatypes of a (path) csv file + operationId: analyse_datatypes + parameters: + - example: filename_s3_key + in: query + name: filename + required: true + schema: + type: string + - example: ',' + in: query + name: separator + required: true + schema: + type: string + - example: "false" + in: query + name: enum + required: false + schema: + type: boolean + - example: "2.5" + in: query + name: enum_tol + required: false + schema: + type: float + produces: + - application/json + responses: + "202": + content: + application/json: + schema: + $ref: '#/components/schemas/DataTypesDto' + description: Determined data types successfully + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Failed to determine data types + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Failed to find file in Storage Service + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Unexpected system error + summary: Determine datatypes + tags: + - analyse-endpoint + /api/analyse/keys: + get: + consumes: + - application/json + description: This is a simple API which returns the primary keys + ranking of a (path) csv file + operationId: analyse_keys + parameters: + - example: filename_s3_key + in: query + name: filename + required: true + schema: + type: string + - example: ',' + in: query + name: separator + required: true + schema: + type: string + produces: + - application/json + responses: + "202": + content: + application/json: + schema: + $ref: '#/components/schemas/KeysDto' + description: Determined keys successfully + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Failed to determine keys + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Failed to find file in Storage Service or is empty + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorDto' + description: Unexpected system error + summary: Determine primary keys + tags: + - analyse-endpoint + /sidecar/export/{filename}: + post: + consumes: + - application/json + description: | + Exports a specific .csv file to the Storage Service via S3 + parameters: + - description: Name of the object file to export to the Storage Service + in: path + name: filename + required: true + produces: + - application/json + responses: + "202": + content: {} + description: Exported the .csv + "400": + description: The Storage Service could not be contacted or .csv was not found. + security: + - bearerAuth: [] + - basicAuth: [] + summary: Exports a .csv to the Storage Service + tags: + - sidecar + /sidecar/import/{filename}: + post: + consumes: + - application/json + description: | + Imports a specific .csv file from the Storage Service via S3 + parameters: + - description: Name of the object file to import from the Storage Service + in: path + name: filename + required: true + produces: + - application/json + responses: + "202": + content: {} + description: Imported the .csv + "400": + description: The Storage Service could not be contacted or .csv was not found. + security: + - bearerAuth: [] + - basicAuth: [] + summary: Imports a .csv from the Storage Service + tags: + - sidecar diff --git a/.docs/.swagger/custom.css b/.docs/.swagger/custom.css index b4eb2af41ecae38ea62d2a693853ee79905985b8..c1056f453d6160e69be83e4bd4fef1a5964e2448 100644 --- a/.docs/.swagger/custom.css +++ b/.docs/.swagger/custom.css @@ -3,6 +3,10 @@ body { background: #eee; } +#logo { + margin-top: 1rem; +} + .scheme-container { background: none !important; box-shadow: none !important; diff --git a/.docs/.swagger/swagger-generate.sh b/.docs/.swagger/swagger-generate.sh index 1469a23bd056649994670c213782686898745abb..c293e6c5cf19a3b78b75de21e06faadbadeefdd4 100644 --- a/.docs/.swagger/swagger-generate.sh +++ b/.docs/.swagger/swagger-generate.sh @@ -9,7 +9,7 @@ services[3305]=sidecar function retrieve () { if [[ "$2" == analyse ]] || [[ "$2" == search ]] || [[ "$2" == sidecar ]]; then echo "... retrieve json api from localhost:$1" - curl -sSL "http://localhost:$1/api-$2.json" | yq -y > "./.docs/.swagger/api-$2.yaml" + curl -sSL "http://localhost:$1/api-$2.json" | yq -p=json > "./.docs/.swagger/api-$2.yaml" else echo "... retrieve yaml api from localhost:$1" curl -sSL "http://localhost:$1/v3/api-docs.yaml" > "./.docs/.swagger/api-$2.yaml" diff --git a/.docs/.swagger/swagger-site.sh b/.docs/.swagger/swagger-site.sh index f6f91bc9109786bf5c8341c548e49fca5ed59cf4..d8d91a73cb3dde9ad4d73b16aea193646e425683 100644 --- a/.docs/.swagger/swagger-site.sh +++ b/.docs/.swagger/swagger-site.sh @@ -1,23 +1,21 @@ #!/bin/bash declare -A services -services[1080]=upload +#services[1080]=upload services[4000]=search services[5000]=analyse services[9093]=data services[9099]=metadata services[3305]=sidecar -# ensure target directories are present -echo "ensure target directory ./site are present" -mkdir -p ./site +rm -f ./tmp.yaml +mkdir -p ./site/swagger +touch ./tmp.yaml -# extract static site -echo "extract static site .docs/.swagger/dist.tar.gz" +# -> build paths: map for key in "${!services[@]}"; do - mkdir -p ./site/${services[$key]} - echo "extract static site ./swagger-ui.html -> ./site/${services[$key]}" - cp .docs/.swagger/swagger-ui.html ./site/${services[$key]}/index.html - cp .docs/.swagger/custom.css ./site/${services[$key]}/custom.css - sed -i -e "s/__SERVICENAME__/${services[$key]^} Service/g" ./site/${services[$key]}/index.html - cp ".docs/.swagger/api-${services[$key]}.yaml" "./site/${services[$key]}/api.yaml" -done \ No newline at end of file + cat .docs/.swagger/api-${services[$key]}.yaml | yq .paths >> ./tmp.yaml +done + +# -> merge with api.base.yaml into final api.yaml +yq ".paths *= load(\"tmp.yaml\")" .docs/.swagger/api.base.yaml > .docs/.swagger/api.yaml + diff --git a/.docs/.swagger/swagger-ui.html b/.docs/.swagger/swagger-ui.html index ef3ce5574300058bb87b6b7d5c2dbbb56c9255d3..98f7cb441fb441c5b4f559e7f7820d112aed7982 100644 --- a/.docs/.swagger/swagger-ui.html +++ b/.docs/.swagger/swagger-ui.html @@ -3,16 +3,22 @@ <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> - <meta name="description" content="__SERVICENAME__ API description in OpenAPI 3.0"/> - <title>__SERVICENAME__ API</title> - <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.11.1/swagger-ui.css"/> + <meta name="description" content="DBRepo REST API description in OpenAPI 3.0"/> + <title>DBRepo REST API</title> + <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.17.12/swagger-ui.css"/> <link rel="stylesheet" href="./custom.css"/> <link rel="icon" href="https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/master/.docs/images/signet_white.png" /> </head> <body> +<div class="swagger-ui"> + <div class="wrapper"> + <img id="logo" width="300" alt="DBRepo Logo" + src="https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/master/dbrepo-ui/public/logo.png" /> + </div> +</div> <div id="swagger-ui"></div> -<script src="https://unpkg.com/swagger-ui-dist@5.11.1/swagger-ui-bundle.js" crossorigin></script> -<script src="https://unpkg.com/swagger-ui-dist@5.11.1/swagger-ui-standalone-preset.js" crossorigin></script> +<script src="https://unpkg.com/swagger-ui-dist@5.17.12/swagger-ui-bundle.js" crossorigin></script> +<script src="https://unpkg.com/swagger-ui-dist@5.17.12/swagger-ui-standalone-preset.js" crossorigin></script> <script> window.onload = () => { window.ui = SwaggerUIBundle({ diff --git a/.docs/concepts/databases.md b/.docs/concepts/databases.md new file mode 100644 index 0000000000000000000000000000000000000000..1076f775efe6b7730f843e5cb83581acc7721730 --- /dev/null +++ b/.docs/concepts/databases.md @@ -0,0 +1,33 @@ +--- +author: Martin Weise +--- + +## Relational Database + +TBD + +## Query + +TBD + +## System Versioning + +TBD + +## Data Ingest + +<figure markdown> + +<figcaption>Figure 1: Modes of data ingest</figcaption> +</figure> + +More [usage examples](../usage-overview/) include how to ingest datasets, data dumps, live data, etc. + +### Generation of Metadata in DBRepo + +You can generate metadata e.g. UI tbd + +!!! warning "Limitation" + + Only system-versioned tables are considered when generating metadata to tables. If your table is not system-versioned + e.g. a base table, it will not be visible in the UI. \ No newline at end of file diff --git a/.docs/concepts/dbms.md b/.docs/concepts/dbms.md deleted file mode 100644 index 5dc2e084357f4cadba08cb11a3b72d9a37d70594..0000000000000000000000000000000000000000 --- a/.docs/concepts/dbms.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -author: Martin Weise ---- - -## Relational Database - -TBD - -## Query - -TBD - -## System Versioning - -TBD \ No newline at end of file diff --git a/.docs/concepts/index.md b/.docs/concepts/index.md index a4cc85435ac313d355b8b03b753073502fa5eeff..8aa7e58597cac0a23dd1adba87227aea200649f2 100644 --- a/.docs/concepts/index.md +++ b/.docs/concepts/index.md @@ -3,13 +3,14 @@ author: Martin Weise --- This is the full system description from a technical/developer view and continuously being updated as the development -progresses. +progresses. -## Data Ingest - -<figure markdown> - -<figcaption>Figure 1: Modes of data ingest</figcaption> -</figure> - -More [usage examples](../usage-overview/) include how to ingest datasets, data dumps, live data, etc. +The remainder of this Sec. is organized as follows: in [Authentication](../concepts/authentication) +we describe how to to accessing important parts of DBRepo. Sec. [DBMS](../concepts/dbms) describes database management +systems on a high-level, Sec. [Messaging](../concepts/messaging) shows how data streams can be connected with DBRepo for +e.g. continuous sensor measurements. Sec. [(Meta-)Data](../concepts/metadata) describes the data derived from the +datasets, Sec. [Persistent Identifier](../concepts/pid) introduces how data is precisely identified for e.g. citation +using the DOI system. Sec. [Search](../concepts/search) describes how anything in DBRepo can be searched, Sec. +[Storage](../concepts/storage) shows how datasets can be uploaded/transferred between the services and Sec. +[User Interface](../concepts/ui) introduces the graphical interface for human interaction as part of virtual research +environments. \ No newline at end of file diff --git a/.docs/concepts/metadata.md b/.docs/concepts/metadata.md deleted file mode 100644 index 331a4bb98036a5db8769b097b895c73432cd01cc..0000000000000000000000000000000000000000 --- a/.docs/concepts/metadata.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -author: Martin Weise ---- - -TBD diff --git a/.docs/concepts/monitoring.md b/.docs/concepts/monitoring.md new file mode 100644 index 0000000000000000000000000000000000000000..10a1b331eb895d73368c17bd87e6d96340bcf011 --- /dev/null +++ b/.docs/concepts/monitoring.md @@ -0,0 +1,136 @@ +--- +author: Martin Weise +--- + +## Prometheus Metrics + +We expose Prometheus metrics on all endpoints of the REST API. [Prometheus](https://prometheus.io/) is a cloud-native +monitoring system using a time-series database. In the default deployment (Docker Compose / Kubernetes) no Prometheus +instance is started. + +You need can setup Prometheus in a few minutes using +a [Docker container](https://prometheus.io/docs/prometheus/latest/installation/). + +## Example + +## Analyse Service + +| **Metric** | **Description** | +|-----------------------------|---------------------------------------------| +| `dbrepo_analyse_datatypes` | Time needed to analyse datatypes of dataset | +| `dbrepo_analyse_keys` | Time needed to analyse keys of dataset | +| `dbrepo_analyse_table_stat` | Time needed to analyse table statistics | +| `dbrepo_analyse_table_stat` | Time needed to analyse table statistics | + +## Auth Service + +See [Keycloak documentation](https://www.keycloak.org/server/configuration-metrics). + +## Broker Service + +See [RabbitMQ documentation](https://www.rabbitmq.com/docs/prometheus). + +## Databases + +See [MariaDB Galera documentation](https://galeracluster.com/documentation/html_docs_20210213-1355-master/documentation/galera-manager-monitoring-clusters.html). + +The [Data Database Sidecar](#) metrics are: + +| **Metric** | **Description** | +|---------------------------------|---------------------------------------| +| `dbrepo_sidecar_import_dataset` | Time needed to import dataset from S3 | +| `dbrepo_sidecar_export_dataset` | Time needed to export dataset to S3 | + +## Data Service + +| **Metric** | **Description** | +|-----------------------------|-------------------------------------------| +| `dbrepo_message_receive` | Received AMQP message from Broker Service | +| `dbrepo_subset_create` | Create subset | +| `dbrepo_subset_data` | Retrieved subset data | +| `dbrepo_subset_find` | Find subset | +| `dbrepo_subset_list` | Find subsets | +| `dbrepo_subset_persist` | Persist subset | +| `dbrepo_table_data_create` | Create table data | +| `dbrepo_table_data_delete` | Delete table data | +| `dbrepo_table_data_export` | Export table data | +| `dbrepo_table_data_history` | Find table history | +| `dbrepo_table_data_import` | Import dataset | +| `dbrepo_table_data_list` | Retrieve table data | +| `dbrepo_table_data_update` | Update table data | +| `dbrepo_view_data` | Retrieve view data | +| `dbrepo_view_schema_list` | Find view schemas | + +## Metadata Service + +| **Metric** | **Description** | +|------------------------------------|-----------------------------------| +| `dbrepo_user_refresh_token` | Refresh user token | +| `dbrepo_identifier_save` | Save identifier | +| `dbrepo_oai_record_get` | Get the record | +| `dbrepo_access_give` | Give access to some database | +| `dbrepo_ontologies_find` | Find one ontology | +| `dbrepo_database_findall` | List databases | +| `dbrepo_tables_refresh` | Refresh database tables metadata | +| `dbrepo_license_findall` | Get all licenses | +| `dbrepo_user_modify` | Modify user information | +| `dbrepo_container_findall` | Find all containers | +| `dbrepo_maintenance_delete` | Delete maintenance message | +| `dbrepo_maintenance_update` | Update maintenance message | +| `dbrepo_ontologies_create` | Register a new ontology | +| `dbrepo_identifier_delete` | Delete some identifier | +| `dbrepo_oai_identify` | Identify the repository | +| `dbrepo_database_create` | Create database | +| `dbrepo_oai_metadataformats_list` | List the metadata formats | +| `dbrepo_user_password_modify` | Modify user password | +| `dbrepo_semantic_concepts_findall` | List semantic concepts | +| `dbrepo_identifier_retrieve` | Retrieve metadata from identifier | +| `dbrepo_identifier_list` | Find all identifiers | +| `dbrepo_views_findall` | Find all views | +| `dbrepo_identifier_create` | Draft identifier | +| `dbrepo_oai_identifiers_list` | List the identifiers | +| `dbrepo_image_findall` | Find all images | +| `dbrepo_database_visibility` | Update database visibility | +| `dbrepo_container_create` | Create container | +| `dbrepo_views_refresh` | Refresh database views metadata | +| `dbrepo_database_find` | Find some database | +| `dbrepo_access_get` | Check access to some database | +| `dbrepo_identifier_find` | Find some identifier | +| `dbrepo_maintenance_create` | Create maintenance message | +| `dbrepo_container_delete` | Delete some container | +| `dbrepo_ontologies_delete` | Delete an ontology | +| `dbrepo_ontologies_findall` | List all ontologies | +| `dbrepo_user_token` | Obtain user token | +| `dbrepo_view_find` | Find one view | +| `dbrepo_user_create` | Create user | +| `dbrepo_ontologies_update` | Update an ontology | +| `dbrepo_maintenance_findall` | Find maintenance messages | +| `dbrepo_users_list` | Find all users | +| `dbrepo_image_find` | Find some image | +| `dbrepo_user_find` | Get a user info | +| `dbrepo_image_delete` | Delete some image | +| `dbrepo_identifier_publish` | Publish identifier | +| `dbrepo_image_update` | Update some image | +| `dbrepo_view_create` | Create a view | +| `dbrepo_semantic_units_findall` | List semantic units | +| `dbrepo_image_create` | Create image | +| `dbrepo_database_image` | Update database image | +| `dbrepo_view_delete` | Delete one view | +| `dbrepo_database_transfer` | Update database owner | +| `dbrepo_maintenance_find` | Find one maintenance message | +| `dbrepo_access_modify` | Modify access to some database | +| `dbrepo_ontologies_entities_find` | Find entities | +| `dbrepo_access_delete` | Revoke access to some database | +| `dbrepo_container_find` | Find some container | + +## Search Service + +| **Metric** | **Description** | +|---------------------------------|---------------------------------------------------------| +| `dbrepo_search_index_list` | Time needed to list search index | +| `dbrepo_search_type_list` | Time needed to list search types | +| `dbrepo_search_fuzzy` | Time needed to search fuzzy | +| `dbrepo_search_type` | Time needed to search by type | +| `dbrepo_search_update_database` | Time needed to update a database in the search database | +| `dbrepo_search_delete_database` | Time needed to delete a database in the search database | + diff --git a/.docs/examples/covid19.md b/.docs/examples/covid19.md index 0aedca2e37ba1bd4b45c6a86398e06d0c568fe17..e5db773195075167bb353d473777fa56916ca52a 100644 --- a/.docs/examples/covid19.md +++ b/.docs/examples/covid19.md @@ -2,10 +2,20 @@ author: Martin Weise --- +## tl;dr + +tbd + ## Description TBD ## Solution -TBD \ No newline at end of file +TBD + +## DBRepo Features + +- [x] Large Dataset ≈15GiB +- [x] Subset Citation using PID +- [x] External access from Grafana Dashboard \ No newline at end of file diff --git a/.docs/examples/influenza.md b/.docs/examples/influenza.md index 0aedca2e37ba1bd4b45c6a86398e06d0c568fe17..074c413d31f3f5e1d590d2491c6562677ee75a39 100644 --- a/.docs/examples/influenza.md +++ b/.docs/examples/influenza.md @@ -2,10 +2,20 @@ author: Martin Weise --- +## tl;dr + +tbd + ## Description TBD ## Solution -TBD \ No newline at end of file +TBD + +## DBRepo Features + +- [x] Import through CSV-dataset upload +- [x] Data views implementing embargo period (24 hours) +- [x] External access from Grafana Dashboard diff --git a/.docs/examples/manufacturing.md b/.docs/examples/manufacturing.md index 0aedca2e37ba1bd4b45c6a86398e06d0c568fe17..f3eb32600f44a77f046865f6da212212a0bfdc08 100644 --- a/.docs/examples/manufacturing.md +++ b/.docs/examples/manufacturing.md @@ -2,10 +2,18 @@ author: Martin Weise --- +## tl;dr + +tbd + ## Description TBD ## Solution -TBD \ No newline at end of file +TBD + +## DBRepo Features + +- [x] TBD diff --git a/.docs/examples/power.md b/.docs/examples/power.md index 0aedca2e37ba1bd4b45c6a86398e06d0c568fe17..ea16727536bd48046e09d1a0fcdba5e5eaf95359 100644 --- a/.docs/examples/power.md +++ b/.docs/examples/power.md @@ -2,10 +2,20 @@ author: Martin Weise --- +## tl;dr + +tbd + ## Description TBD ## Solution -TBD \ No newline at end of file +TBD + +## DBRepo Features + +- [x] High-throughput real-time data import (MQTT) +- [x] Private database +- [x] Public embargoed data view diff --git a/.docs/index.md b/.docs/index.md index 8b7f397570856aac0cadf2c7aa7dfa26e5386fa4..49f9903b570e2c8b62cea772267708155c6f82a0 100644 --- a/.docs/index.md +++ b/.docs/index.md @@ -7,18 +7,18 @@ author: Martin Weise [](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services){ tabindex=-1 } [](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services){ tabindex=-1 } -Documentation for version: [v1.4.3](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/releases). +Documentation for version: [v1.4.4](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/releases). -DBRepo is a repository for data in databases that are used from the beginning of a research project supporting data -evolution, -citation and -versioning. It implements the -[RDA WGDC recommendations](https://doi.org/10.1162/99608f92.be565013) on precisely identifying arbitrary subsets of -data. +DBRepo is a repository for data in databases that are used from the beginning until the end of a research +project supporting data evolution, -citation and -versioning. It implements the query store of the +[RDA WGDC](https://doi.org/10.1162/99608f92.be565013) on precisely identifying arbitrary subsets of data. ## Why use DBRepo? * **aaa** bbbb -Installing DBRepo is very easy or just [give it a try online](https://test.dbrepo.tuwien.ac.at). +Installing DBRepo is very easy or +[give it a try online](https://test.dbrepo.tuwien.ac.at){ target="_blank" }. ## Who is using DBRepo? @@ -26,4 +26,4 @@ TBD ## How can I try DBRepo -[:fontawesome-solid-flask: Demonstration Instance](https://test.dbrepo.tuwien.ac.at){ .md-button .md-button--primary } \ No newline at end of file +[:fontawesome-solid-flask: Demonstration Instance](https://test.dbrepo.tuwien.ac.at){ .md-button .md-button--primary target="_blank" } \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9cf181a38e0d982c8da5a8dfab71c6257c6a1c28..908da84c1ecf2d8532bd8cf68f2708e6bf518b0e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,9 @@ ready schema.xsd final/ build/ -swagger/ *.tar +tmp.yaml +.docs/.swagger/api-* # docs .docs/.swagger/dist/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 10377b3fccd0d2aa2f947cb9b9ff680cc462c6e2..a3230d4e7c3cc3b0d5089e6143cc2cdd5ad768ad 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -267,7 +267,7 @@ scan-analyse-service: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-analyse-service-report.json dbrepo-analyse-service:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-analyse-service-report.json dbrepo-analyse-service:latest - trivy image --insecure --exit-code 0 dbrepo-analyse-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-analyse-service:latest cache: @@ -287,7 +287,7 @@ scan-auth-service: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-authentication-service-report.json dbrepo-auth-service:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-authentication-service-report.json dbrepo-auth-service:latest - trivy image --insecure --exit-code 0 dbrepo-auth-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-auth-service:latest cache: @@ -307,7 +307,7 @@ scan-broker-service: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-broker-service-report.json dbrepo-broker-service:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-broker-service-report.json dbrepo-broker-service:latest - trivy image --insecure --exit-code 0 dbrepo-broker-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-broker-service:latest cache: @@ -327,7 +327,7 @@ scan-data-db-sidecar: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-data-db-sidecar-report.json dbrepo-data-db-sidecar:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-data-db-sidecar-report.json dbrepo-data-db-sidecar:latest - trivy image --insecure --exit-code 0 data-db-sidecar:latest - trivy image --insecure --exit-code 1 --severity CRITICAL data-db-sidecar:latest cache: @@ -347,7 +347,7 @@ scan-gateway-service: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-gateway-service-report.json docker.io/nginx:1.25.0-alpine-slim + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-gateway-service-report.json docker.io/nginx:1.25.0-alpine-slim - trivy image --insecure --exit-code 0 docker.io/nginx:1.25.0-alpine-slim - trivy image --insecure --exit-code 1 --severity CRITICAL docker.io/nginx:1.25.0-alpine-slim cache: @@ -367,7 +367,7 @@ scan-metadata-service: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-metadata-service-report.json dbrepo-metadata-service:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-metadata-service-report.json dbrepo-metadata-service:latest - trivy image --insecure --exit-code 0 dbrepo-metadata-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-metadata-service:latest cache: @@ -387,7 +387,7 @@ scan-data-service: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-data-service-report.json dbrepo-data-service:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-data-service-report.json dbrepo-data-service:latest - trivy image --insecure --exit-code 0 dbrepo-data-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-data-service:latest cache: @@ -407,7 +407,7 @@ scan-search-db: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-search-db-report.json dbrepo-search-db:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-search-db-report.json dbrepo-search-db:latest - trivy image --insecure --exit-code 0 dbrepo-search-db:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-search-db:latest cache: @@ -427,7 +427,7 @@ scan-search-service-init: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-search-service-init-report.json dbrepo-search-service-init:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-search-service-init-report.json dbrepo-search-service-init:latest - trivy image --insecure --exit-code 0 dbrepo-search-service-init:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-search-service-init:latest cache: @@ -447,7 +447,7 @@ scan-data-db: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-data-db-report.json docker.io/bitnami/mariadb:11.2.2-debian-11-r0 + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-data-db-report.json docker.io/bitnami/mariadb:11.2.2-debian-11-r0 - trivy image --insecure --exit-code 0 docker.io/bitnami/mariadb:11.2.2-debian-11-r0 - trivy image --insecure --exit-code 1 --severity CRITICAL docker.io/bitnami/mariadb:11.2.2-debian-11-r0 cache: @@ -467,7 +467,7 @@ scan-metadata-db: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-metadata-db-report.json dbrepo-metadata-db:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-metadata-db-report.json dbrepo-metadata-db:latest - trivy image --insecure --exit-code 0 dbrepo-metadata-db:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-metadata-db:latest cache: @@ -487,7 +487,7 @@ scan-ui: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-ui-report.json dbrepo-ui:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-ui-report.json dbrepo-ui:latest - trivy image --insecure --exit-code 0 dbrepo-ui:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-ui:latest cache: @@ -507,7 +507,7 @@ scan-search-service: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-ui-report.json dbrepo-search-service:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-ui-report.json dbrepo-search-service:latest - trivy image --insecure --exit-code 0 dbrepo-search-service:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-search-service:latest cache: @@ -527,7 +527,7 @@ scan-storage-service: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-storage-service-report.json docker.io/chrislusf/seaweedfs:3.59 + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-storage-service-report.json docker.io/chrislusf/seaweedfs:3.59 - trivy image --insecure --exit-code 0 docker.io/chrislusf/seaweedfs:3.59 - trivy image --insecure --exit-code 1 --severity CRITICAL docker.io/chrislusf/seaweedfs:3.59 cache: @@ -547,7 +547,7 @@ scan-storage-service-init: - master allow_failure: true script: - - trivy image --insecure --exit-code 0 --format template --template "@.trivy/gitlab.tpl" -o ./.trivy/trivy-storage-service-init-report.json dbrepo-storage-service-init:latest + - trivy image --insecure --exit-code 0 --format template --template "@.gitlab/gitlab.tpl" -o ./.trivy/trivy-storage-service-init-report.json dbrepo-storage-service-init:latest - trivy image --insecure --exit-code 0 dbrepo-storage-service-init:latest - trivy image --insecure --exit-code 1 --severity CRITICAL dbrepo-storage-service-init:latest cache: @@ -609,13 +609,23 @@ release-chart: release-docs: stage: release image: docker.io/python:3.11-alpine + variables: + VERSION: "${CI_COMMIT_BRANCH:8:8}" only: refs: - /^release-.*/ before_script: + - "wget https://github.com/mikefarah/yq/releases/download/v4.2.0/yq_linux_amd64 -O /usr/bin/yq" + - "chmod +x /usr/bin/yq" - "apt-get update && apt-get install -y git make sed wget ssh" - script: - - make docs + - "mkdir -p ./final/${VERSION}/swagger" + script: + - "make gen-swagger-doc gen-lib-doc gen-docs-doc" + - "cp -r ./lib/python/docs/build/html ./final/${VERSION}/sphinx" # sphinx + - "cp .docs/.swagger/api.yaml ./final/${VERSION}/swagger/api.yaml" # swagger + - "cp .docs/.swagger/swagger-ui.html ./final/${VERSION}/swagger/index.html" # swagger + - "cp .docs/.swagger/custom.css ./final/${VERSION}/swagger/custom.css" # swagger + - "cp -r ./site ./final/${VERSION}" # mkdocs - eval $(ssh-agent -s) - echo "$CI_KEY_PRIVATE" > /root/.ssh/id_rsa && chmod 0600 /root/.ssh/id_rsa - echo "$CI_KEY_PUBLIC" > /root/.ssh/id_rsa.pub diff --git a/.trivy/gitlab.tpl b/.gitlab/gitlab.tpl similarity index 100% rename from .trivy/gitlab.tpl rename to .gitlab/gitlab.tpl diff --git a/bin/teardown.sh b/bin/teardown.sh deleted file mode 100755 index 9b7926d521d7c9c96eeb4689c86120b220f24775..0000000000000000000000000000000000000000 --- a/bin/teardown.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -echo "=== [ Stopping dbrepo-* ] ===" -docker container stop $(docker container ls -aq -f name=^/dbrepo-.*) || true -echo "=== [ Removing dbrepo-* ] ===" -docker container rm $(docker container ls -aq -f name=^/dbrepo-.*) || true -docker volume rm $(docker volume ls -q -f name=^dbrepo-.*) || true -docker network rm $(docker network ls -q -f name=^dbrepo-.*) || true -echo "=== [ Stopping * ] ===" -docker container stop $(docker container ls -aq -f name=.*-service) || true -docker container stop ui ui-proxy metadata-db || true -echo "=== [ Removing * ] ===" -docker container rm $(docker container ls -aq -f name=.*-service) || true -docker container rm ui ui-proxy metadata-db || true -docker volume rm $(docker volume ls -q) || true -echo "=== [ Stopping fda-* ] ===" -docker container stop $(docker container ls -aq -f name=^/fda-.*) || true -echo "=== [ Removing fda-* ] ===" -docker container rm $(docker container ls -aq -f name=^/fda-.*) || true -docker volume rm $(docker volume ls -q -f name=^fda-.*) || true -docker network rm $(docker network ls -q -f name=^fda-.*) || true -echo "=== [ Stopping tuw-* ] ===" -docker container stop $(docker container ls -aq -f name=^/tuw-.*) || true -echo "=== [ Removing tuw-* ] ===" -docker container rm $(docker container ls -aq -f name=^/tuw-.*) || true -docker volume rm $(docker volume ls -q -f name=^tuw-.*) || true -docker network rm $(docker network ls -q -f name=^tuw-.*) || true \ No newline at end of file diff --git a/dbrepo-analyse-service/Pipfile b/dbrepo-analyse-service/Pipfile index f9dc9086d5b98a69c8cfa652f9466e1f6e018cb8..98166931a4f958a9ea6a5c94187e5d02d2014b4c 100644 --- a/dbrepo-analyse-service/Pipfile +++ b/dbrepo-analyse-service/Pipfile @@ -21,7 +21,7 @@ numpy = "*" pandas = "*" minio = "*" pydantic = "*" -dbrepo = {path = "./lib/dbrepo-1.4.3.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.4.4.tar.gz"} opensearch-py = "*" [dev-packages] diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock index 93479ce06f5d816035e175f3ed7839ee998eb0ab..d1f47348f8d5aa0a9d78d9c8b28ebf7006197766 100644 --- a/dbrepo-analyse-service/Pipfile.lock +++ b/dbrepo-analyse-service/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "928e32d569e15d302ad2f00c83df5481e4bf1c54e502d2428e0da86865bcc11a" + "sha256": "f862bcd0c3285ad0a48d0d0f738bddf0f3c1d2c5d263af9e07994463e39e5610" }, "pipfile-spec": 6, "requires": { @@ -108,11 +108,11 @@ }, "annotated-types": { "hashes": [ - "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43", - "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d" + "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", + "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" ], "markers": "python_version >= '3.8'", - "version": "==0.6.0" + "version": "==0.7.0" }, "argon2-cffi": { "hashes": [ @@ -167,19 +167,19 @@ }, "boto3": { "hashes": [ - "sha256:5b37c8f4ea6f408147994a6e230c49ca755da57f5964ccea8b8fd4ff5f11759e", - "sha256:bec91a3bca63320e5f68a25b5eaa7bab65e35bb9253a544875c2e03679f1d5fb" + "sha256:009cd143509f2ff4c37582c3f45d50f28c95eed68e8a5c36641206bdb597a9ea", + "sha256:7e59f0a848be477a4c98a90e7a18a0e284adfb643f7879d2b303c5f493661b7a" ], "index": "pypi", - "version": "==1.34.104" + "version": "==1.34.113" }, "botocore": { "hashes": [ - "sha256:b68ed482e9b4c313129c9948af5a91d0e84840558e6d232a1a27ab0b9733e5b9", - "sha256:fe36dd3cea4160fbbe27dc1cf89cb7018234350555a26933b2977947052a346a" + "sha256:449912ba3c4ded64f21d09d428146dd9c05337b2a112e15511bf2c4888faae79", + "sha256:8ca87776450ef41dd25c327eb6e504294230a5756940d68bcfdedc4a7cdeca97" ], "markers": "python_version >= '3.8'", - "version": "==1.34.104" + "version": "==1.34.113" }, "certifi": { "hashes": [ @@ -391,10 +391,10 @@ }, "dbrepo": { "hashes": [ - "sha256:d3503b851d526b33cb795f247ec510911ae356e35efec7449863e9b6590283c1" + "sha256:ceab260cf76c050e118ce0f0589fec66059396751e03f2ec41fa489cfacc4e7b" ], - "path": "./lib/dbrepo-1.4.3.tar.gz", - "version": "==1.4.3" + "path": "./lib/dbrepo-1.4.4.tar.gz", + "version": "==1.4.4" }, "exceptiongroup": { "hashes": [ @@ -1224,11 +1224,11 @@ }, "requests": { "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289", + "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c" ], "index": "pypi", - "version": "==2.31.0" + "version": "==2.32.2" }, "rpds-py": { "hashes": [ @@ -1345,11 +1345,11 @@ }, "setuptools": { "hashes": [ - "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987", - "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32" + "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4", + "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0" ], "markers": "python_version >= '3.8'", - "version": "==69.5.1" + "version": "==70.0.0" }, "six": { "hashes": [ @@ -1377,11 +1377,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", - "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" + "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8", + "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594" ], "markers": "python_version >= '3.8'", - "version": "==4.11.0" + "version": "==4.12.0" }, "tzdata": { "hashes": [ @@ -1513,45 +1513,45 @@ }, "zope.interface": { "hashes": [ - "sha256:014bb94fe6bf1786da1aa044eadf65bc6437bcb81c451592987e5be91e70a91e", - "sha256:01a0b3dd012f584afcf03ed814bce0fc40ed10e47396578621509ac031be98bf", - "sha256:10cde8dc6b2fd6a1d0b5ca4be820063e46ddba417ab82bcf55afe2227337b130", - "sha256:187f7900b63845dcdef1be320a523dbbdba94d89cae570edc2781eb55f8c2f86", - "sha256:1b0c4c90e5eefca2c3e045d9f9ed9f1e2cdbe70eb906bff6b247e17119ad89a1", - "sha256:22e8a218e8e2d87d4d9342aa973b7915297a08efbebea5b25900c73e78ed468e", - "sha256:26c9a37fb395a703e39b11b00b9e921c48f82b6e32cc5851ad5d0618cd8876b5", - "sha256:2bb78c12c1ad3a20c0d981a043d133299117b6854f2e14893b156979ed4e1d2c", - "sha256:2c3cfb272bcb83650e6695d49ae0d14dd06dc694789a3d929f23758557a23d92", - "sha256:2f32010ffb87759c6a3ad1c65ed4d2e38e51f6b430a1ca11cee901ec2b42e021", - "sha256:3c8731596198198746f7ce2a4487a0edcbc9ea5e5918f0ab23c4859bce56055c", - "sha256:40aa8c8e964d47d713b226c5baf5f13cdf3a3169c7a2653163b17ff2e2334d10", - "sha256:4137025731e824eee8d263b20682b28a0bdc0508de9c11d6c6be54163e5b7c83", - "sha256:46034be614d1f75f06e7dcfefba21d609b16b38c21fc912b01a99cb29e58febb", - "sha256:483e118b1e075f1819b3c6ace082b9d7d3a6a5eb14b2b375f1b80a0868117920", - "sha256:4d6b229f5e1a6375f206455cc0a63a8e502ed190fe7eb15e94a312dc69d40299", - "sha256:567d54c06306f9c5b6826190628d66753b9f2b0422f4c02d7c6d2b97ebf0a24e", - "sha256:5683aa8f2639016fd2b421df44301f10820e28a9b96382a6e438e5c6427253af", - "sha256:600101f43a7582d5b9504a7c629a1185a849ce65e60fca0f6968dfc4b76b6d39", - "sha256:62e32f02b3f26204d9c02c3539c802afc3eefb19d601a0987836ed126efb1f21", - "sha256:69dedb790530c7ca5345899a1b4cb837cc53ba669051ea51e8c18f82f9389061", - "sha256:72d5efecad16c619a97744a4f0b67ce1bcc88115aa82fcf1dc5be9bb403bcc0b", - "sha256:8d407e0fd8015f6d5dfad481309638e1968d70e6644e0753f229154667dd6cd5", - "sha256:a058e6cf8d68a5a19cb5449f42a404f0d6c2778b897e6ce8fadda9cea308b1b0", - "sha256:a1adc14a2a9d5e95f76df625a9b39f4709267a483962a572e3f3001ef90ea6e6", - "sha256:a56fe1261230093bfeedc1c1a6cd6f3ec568f9b07f031c9a09f46b201f793a85", - "sha256:ad4524289d8dbd6fb5aa17aedb18f5643e7d48358f42c007a5ee51a2afc2a7c5", - "sha256:afa0491a9f154cf8519a02026dc85a416192f4cb1efbbf32db4a173ba28b289a", - "sha256:bf34840e102d1d0b2d39b1465918d90b312b1119552cebb61a242c42079817b9", - "sha256:c40df4aea777be321b7e68facb901bc67317e94b65d9ab20fb96e0eb3c0b60a1", - "sha256:d0e7321557c702bd92dac3c66a2f22b963155fdb4600133b6b29597f62b71b12", - "sha256:d165d7774d558ea971cb867739fb334faf68fc4756a784e689e11efa3becd59e", - "sha256:e78a183a3c2f555c2ad6aaa1ab572d1c435ba42f1dc3a7e8c82982306a19b785", - "sha256:e8fa0fb05083a1a4216b4b881fdefa71c5d9a106e9b094cd4399af6b52873e91", - "sha256:f83d6b4b22262d9a826c3bd4b2fbfafe1d0000f085ef8e44cd1328eea274ae6a", - "sha256:f95bebd0afe86b2adc074df29edb6848fc4d474ff24075e2c263d698774e108d" + "sha256:00b5c3e9744dcdc9e84c24ed6646d5cf0cf66551347b310b3ffd70f056535854", + "sha256:0e4fa5d34d7973e6b0efa46fe4405090f3b406f64b6290facbb19dcbf642ad6b", + "sha256:136cacdde1a2c5e5bc3d0b2a1beed733f97e2dad8c2ad3c2e17116f6590a3827", + "sha256:1730c93a38b5a18d24549bc81613223962a19d457cfda9bdc66e542f475a36f4", + "sha256:1a62fd6cd518693568e23e02f41816adedfca637f26716837681c90b36af3671", + "sha256:1c207e6f6dfd5749a26f5a5fd966602d6b824ec00d2df84a7e9a924e8933654e", + "sha256:2eccd5bef45883802848f821d940367c1d0ad588de71e5cabe3813175444202c", + "sha256:33ee982237cffaf946db365c3a6ebaa37855d8e3ca5800f6f48890209c1cfefc", + "sha256:3d136e5b8821073e1a09dde3eb076ea9988e7010c54ffe4d39701adf0c303438", + "sha256:47654177e675bafdf4e4738ce58cdc5c6d6ee2157ac0a78a3fa460942b9d64a8", + "sha256:47937cf2e7ed4e0e37f7851c76edeb8543ec9b0eae149b36ecd26176ff1ca874", + "sha256:4ac46298e0143d91e4644a27a769d1388d5d89e82ee0cf37bf2b0b001b9712a4", + "sha256:4c0b208a5d6c81434bdfa0f06d9b667e5de15af84d8cae5723c3a33ba6611b82", + "sha256:551db2fe892fcbefb38f6f81ffa62de11090c8119fd4e66a60f3adff70751ec7", + "sha256:599f3b07bde2627e163ce484d5497a54a0a8437779362395c6b25e68c6590ede", + "sha256:5ef8356f16b1a83609f7a992a6e33d792bb5eff2370712c9eaae0d02e1924341", + "sha256:5fe919027f29b12f7a2562ba0daf3e045cb388f844e022552a5674fcdf5d21f1", + "sha256:6f0a6be264afb094975b5ef55c911379d6989caa87c4e558814ec4f5125cfa2e", + "sha256:706efc19f9679a1b425d6fa2b4bc770d976d0984335eaea0869bd32f627591d2", + "sha256:73f9752cf3596771c7726f7eea5b9e634ad47c6d863043589a1c3bb31325c7eb", + "sha256:762e616199f6319bb98e7f4f27d254c84c5fb1c25c908c2a9d0f92b92fb27530", + "sha256:866a0f583be79f0def667a5d2c60b7b4cc68f0c0a470f227e1122691b443c934", + "sha256:86a94af4a88110ed4bb8961f5ac72edf782958e665d5bfceaab6bf388420a78b", + "sha256:8e0343a6e06d94f6b6ac52fbc75269b41dd3c57066541a6c76517f69fe67cb43", + "sha256:97e615eab34bd8477c3f34197a17ce08c648d38467489359cb9eb7394f1083f7", + "sha256:a96e6d4074db29b152222c34d7eec2e2db2f92638d2b2b2c704f9e8db3ae0edc", + "sha256:b912750b13d76af8aac45ddf4679535def304b2a48a07989ec736508d0bbfbde", + "sha256:bc2676312cc3468a25aac001ec727168994ea3b69b48914944a44c6a0b251e79", + "sha256:cebff2fe5dc82cb22122e4e1225e00a4a506b1a16fafa911142ee124febf2c9e", + "sha256:d22fce0b0f5715cdac082e35a9e735a1752dc8585f005d045abb1a7c20e197f9", + "sha256:d3f7e001328bd6466b3414215f66dde3c7c13d8025a9c160a75d7b2687090d15", + "sha256:d3fe667935e9562407c2511570dca14604a654988a13d8725667e95161d92e9b", + "sha256:dabb70a6e3d9c22df50e08dc55b14ca2a99da95a2d941954255ac76fd6982bc5", + "sha256:e2fb8e8158306567a3a9a41670c1ff99d0567d7fc96fa93b7abf8b519a46b250", + "sha256:e96ac6b3169940a8cd57b4f2b8edcad8f5213b60efcd197d59fbe52f0accd66e", + "sha256:fbf649bc77510ef2521cf797700b96167bb77838c40780da7ea3edd8b78044d1" ], "markers": "python_version >= '3.7'", - "version": "==6.3" + "version": "==6.4.post2" } }, "develop": { @@ -1754,69 +1754,69 @@ }, "coverage": { "hashes": [ - "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de", - "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661", - "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26", - "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41", - "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d", - "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981", - "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2", - "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34", - "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f", - "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a", - "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35", - "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223", - "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1", - "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746", - "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90", - "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c", - "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca", - "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8", - "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596", - "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e", - "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd", - "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e", - "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3", - "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e", - "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312", - "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7", - "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572", - "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428", - "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f", - "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07", - "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e", - "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4", - "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136", - "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5", - "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8", - "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d", - "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228", - "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206", - "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa", - "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e", - "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be", - "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5", - "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668", - "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601", - "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057", - "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146", - "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f", - "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8", - "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7", - "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987", - "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19", - "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece" + "sha256:06d96b9b19bbe7f049c2be3c4f9e06737ec6d8ef8933c7c3a4c557ef07936e46", + "sha256:13017a63b0e499c59b5ba94a8542fb62864ba3016127d1e4ef30d354fc2b00e9", + "sha256:1acc2e2ef098a1d4bf535758085f508097316d738101a97c3f996bccba963ea5", + "sha256:1aef719b6559b521ae913ddeb38f5048c6d1a3d366865e8b320270b7bc4693c2", + "sha256:1e4225990a87df898e40ca31c9e830c15c2c53b1d33df592bc8ef314d71f0281", + "sha256:1f11f98753800eb1ec872562a398081f6695f91cd01ce39819e36621003ec52a", + "sha256:1f29bf497d51a5077994b265e976d78b09d9d0dff6ca5763dbb4804534a5d380", + "sha256:1f96aa94739593ae0707eda9813ce363a0a0374a810ae0eced383340fc4a1f73", + "sha256:20e611fc36e1a0fc7bbf957ef9c635c8807d71fbe5643e51b2769b3cc0fb0b51", + "sha256:23f2f16958b16152b43a39a5ecf4705757ddd284b3b17a77da3a62aef9c057ef", + "sha256:24bb4c7859a3f757a116521d4d3a8a82befad56ea1bdacd17d6aafd113b0071e", + "sha256:26716a1118c6ce2188283b4b60a898c3be29b480acbd0a91446ced4fe4e780d8", + "sha256:29da75ce20cb0a26d60e22658dd3230713c6c05a3465dd8ad040ffc991aea318", + "sha256:2b144d142ec9987276aeff1326edbc0df8ba4afbd7232f0ca10ad57a115e95b6", + "sha256:2c79f058e7bec26b5295d53b8c39ecb623448c74ccc8378631f5cb5c16a7e02c", + "sha256:3bb5b92a0ab3d22dfdbfe845e2fef92717b067bdf41a5b68c7e3e857c0cff1a4", + "sha256:3d3f7744b8a8079d69af69d512e5abed4fb473057625588ce126088e50d05493", + "sha256:3d9c62cff2ffb4c2a95328488fd7aa96a7a4b34873150650fe76b19c08c9c792", + "sha256:3e12536446ad4527ac8ed91d8a607813085683bcce27af69e3b31cd72b3c5960", + "sha256:40dbb8e7727560fe8ab65efcddfec1ae25f30ef02e2f2e5d78cfb52a66781ec5", + "sha256:431a3917e32223fcdb90b79fe60185864a9109631ebc05f6c5aa03781a00b513", + "sha256:448ec61ea9ea7916d5579939362509145caaecf03161f6f13e366aebb692a631", + "sha256:482df956b055d3009d10fce81af6ffab28215d7ed6ad4a15e5c8e67cb7c5251c", + "sha256:4a00bd5ba8f1a4114720bef283cf31583d6cb1c510ce890a6da6c4268f0070b7", + "sha256:51b6cee539168a912b4b3b040e4042b9e2c9a7ad9c8546c09e4eaeff3eacba6b", + "sha256:554c7327bf0fd688050348e22db7c8e163fb7219f3ecdd4732d7ed606b417263", + "sha256:5662bf0f6fb6757f5c2d6279c541a5af55a39772c2362ed0920b27e3ce0e21f7", + "sha256:5997d418c219dcd4dcba64e50671cca849aaf0dac3d7a2eeeb7d651a5bd735b8", + "sha256:59a75e6aa5c25b50b5a1499f9718f2edff54257f545718c4fb100f48d570ead4", + "sha256:60b66b0363c5a2a79fba3d1cd7430c25bbd92c923d031cae906bdcb6e054d9a2", + "sha256:6e34680049eecb30b6498784c9637c1c74277dcb1db75649a152f8004fbd6646", + "sha256:74eeaa13e8200ad72fca9c5f37395fb310915cec6f1682b21375e84fd9770e84", + "sha256:7c5c5b7ae2763533152880d5b5b451acbc1089ade2336b710a24b2b0f5239d20", + "sha256:829fb55ad437d757c70d5b1c51cfda9377f31506a0a3f3ac282bc6a387d6a5f1", + "sha256:878243e1206828908a6b4a9ca7b1aa8bee9eb129bf7186fc381d2646f4524ce9", + "sha256:8809c0ea0e8454f756e3bd5c36d04dddf222989216788a25bfd6724bfcee342c", + "sha256:8941e35a0e991a7a20a1fa3e3182f82abe357211f2c335a9e6007067c3392fcf", + "sha256:894b1acded706f1407a662d08e026bfd0ff1e59e9bd32062fea9d862564cfb65", + "sha256:900532713115ac58bc3491b9d2b52704a05ed408ba0918d57fd72c94bc47fba1", + "sha256:976cd92d9420e6e2aa6ce6a9d61f2b490e07cb468968adf371546b33b829284b", + "sha256:97de509043d3f0f2b2cd171bdccf408f175c7f7a99d36d566b1ae4dd84107985", + "sha256:9a42970ce74c88bdf144df11c52c5cf4ad610d860de87c0883385a1c9d9fa4ab", + "sha256:9e41c94035e5cdb362beed681b58a707e8dc29ea446ea1713d92afeded9d1ddd", + "sha256:9f805481d5eff2a96bac4da1570ef662bf970f9a16580dc2c169c8c3183fa02b", + "sha256:a35c97af60a5492e9e89f8b7153fe24eadfd61cb3a2fb600df1a25b5dab34b7e", + "sha256:a7c6574225f34ce45466f04751d957b5c5e6b69fca9351db017c9249786172ce", + "sha256:c7ebf2a37e4f5fea3c1a11e1f47cea7d75d0f2d8ef69635ddbd5c927083211fc", + "sha256:d0305e02e40c7cfea5d08d6368576537a74c0eea62b77633179748d3519d6705", + "sha256:e1046aab24c48c694f0793f669ac49ea68acde6a0798ac5388abe0a5615b5ec8", + "sha256:e5d22eba19273b2069e4efeff88c897a26bdc64633cbe0357a198f92dca94268", + "sha256:ec27e93bbf5976f0465e8936f02eb5add99bbe4e4e7b233607e4d7622912d68d", + "sha256:fe76d6dee5e4febefa83998b17926df3a04e5089e3d2b1688c74a9157798d7a2" ], "index": "pypi", - "version": "==7.5.1" + "version": "==7.5.2" }, "docker": { "hashes": [ - "sha256:12ba681f2777a0ad28ffbcc846a69c31b4dfd9752b47eb425a274ee269c5e14b", - "sha256:323736fb92cd9418fc5e7133bc953e11a9da04f4483f828b527db553f1e7e5a3" + "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", + "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0" ], "markers": "python_version >= '3.8'", - "version": "==7.0.0" + "version": "==7.1.0" }, "idna": { "hashes": [ @@ -1914,11 +1914,11 @@ }, "pytest": { "hashes": [ - "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233", - "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f" + "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd", + "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1" ], "index": "pypi", - "version": "==8.2.0" + "version": "==8.2.1" }, "python-dateutil": { "hashes": [ @@ -1930,11 +1930,11 @@ }, "requests": { "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289", + "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c" ], "index": "pypi", - "version": "==2.31.0" + "version": "==2.32.2" }, "requests-mock": { "hashes": [ @@ -1975,11 +1975,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", - "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" + "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8", + "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594" ], "markers": "python_version >= '3.8'", - "version": "==4.11.0" + "version": "==4.12.0" }, "urllib3": { "hashes": [ diff --git a/dbrepo-analyse-service/app.py b/dbrepo-analyse-service/app.py index a02b3d5b859bfbe3eac11c4c7d7617ecc4390af5..de1ca37a4d5ac444ddb527a86e041d5868bf1e4b 100644 --- a/dbrepo-analyse-service/app.py +++ b/dbrepo-analyse-service/app.py @@ -187,6 +187,7 @@ def get_health(): @app.route("/api/analyse/datatypes", methods=["GET"], endpoint="analyse_analyse_datatypes") +@metrics.gauge(name='dbrepo_analyse_datatypes', description='Time needed to analyse datatypes of dataset') @swag_from("as-yml/analyse_datatypes.yml") def analyse_datatypes(): filename: str = request.args.get('filename') @@ -212,6 +213,7 @@ def analyse_datatypes(): @app.route("/api/analyse/keys", methods=["GET"], endpoint="analyse_analyse_keys") +@metrics.gauge(name='dbrepo_analyse_keys', description='Time needed to analyse keys of dataset') @swag_from("as-yml/analyse_keys.yml") def analyse_keys(): filename: str = request.args.get("filename") @@ -234,6 +236,7 @@ def analyse_keys(): @app.route("/api/analyse/database/<database_id>/table/<table_id>/statistics", methods=["GET"], endpoint="analyse_analyse_table_stat") @auth.login_required(role=['admin', 'export-query-data', 'export-table-data']) +@metrics.gauge(name='dbrepo_analyse_table_stat', description='Time needed to analyse table statistics') @swag_from("as-yml/analyse_table_stat.yml") def analyse_table_stat(database_id: int = None, table_id: int = None): if database_id is None: diff --git a/dbrepo-analyse-service/lib/dbrepo-1.4.3-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.4.3-py3-none-any.whl index bb0ce570729cffddbd0f77eb818fd40eb0a56195..2e19eddac149ac401c67a52ba56577132e32869a 100644 Binary files a/dbrepo-analyse-service/lib/dbrepo-1.4.3-py3-none-any.whl and b/dbrepo-analyse-service/lib/dbrepo-1.4.3-py3-none-any.whl differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.4.3.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.4.3.tar.gz index 04043f0f56105d80e7f2aaa5fe1598077184ef64..ffb89654bab83c6f72a9381825e41f0dbe7d37c9 100644 Binary files a/dbrepo-analyse-service/lib/dbrepo-1.4.3.tar.gz and b/dbrepo-analyse-service/lib/dbrepo-1.4.3.tar.gz differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.4.4-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.4.4-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..11873004972bb08703994ba1fb0ddf18f96f6a2c Binary files /dev/null and b/dbrepo-analyse-service/lib/dbrepo-1.4.4-py3-none-any.whl differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.4.4.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.4.4.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..f7452a0e12c9a2d44f663bc1f338204b7579144b Binary files /dev/null and b/dbrepo-analyse-service/lib/dbrepo-1.4.4.tar.gz differ diff --git a/dbrepo-analyse-service/metrics.md b/dbrepo-analyse-service/metrics.md new file mode 100644 index 0000000000000000000000000000000000000000..f0eaee535aeb5cc5e4432be59feb813da75b37d7 --- /dev/null +++ b/dbrepo-analyse-service/metrics.md @@ -0,0 +1,6 @@ +| **Metric** | **Description** | +|-----------------------------|---------------------------------------------| +| `dbrepo_analyse_datatypes` | Time needed to analyse datatypes of dataset | +| `dbrepo_analyse_keys` | Time needed to analyse keys of dataset | +| `dbrepo_analyse_table_stat` | Time needed to analyse table statistics | +| `dbrepo_analyse_table_stat` | Time needed to analyse table statistics | \ No newline at end of file diff --git a/dbrepo-auth-service/dbrepo-realm.json b/dbrepo-auth-service/dbrepo-realm.json index 1abee7076bb8926443a5998213c39b60a495a933..f5ced37ff24b995b58f2cbb16686269b9ad46056 100644 --- a/dbrepo-auth-service/dbrepo-realm.json +++ b/dbrepo-auth-service/dbrepo-realm.json @@ -1091,7 +1091,7 @@ "otpPolicyLookAheadWindow" : 1, "otpPolicyPeriod" : 30, "otpPolicyCodeReusable" : false, - "otpSupportedApplications" : [ "totpAppMicrosoftAuthenticatorName", "totpAppFreeOTPName", "totpAppGoogleName" ], + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], "webAuthnPolicyRpEntityName" : "keycloak", "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], "webAuthnPolicyRpId" : "", @@ -2110,7 +2110,7 @@ "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper" ] + "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper" ] } }, { "id" : "3ab11d74-5e76-408a-b85a-26bf8950f979", @@ -2119,7 +2119,7 @@ "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper" ] } } ], "org.keycloak.keys.KeyProvider" : [ { @@ -2171,7 +2171,7 @@ "internationalizationEnabled" : false, "supportedLocales" : [ ], "authenticationFlows" : [ { - "id" : "81aad346-5dea-4764-a97d-70fa27c7d4a0", + "id" : "fbce9485-c780-438c-bbe9-135352504aa7", "alias" : "Account verification options", "description" : "Method with which to verity the existing account", "providerId" : "basic-flow", @@ -2193,7 +2193,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "1677aaa5-9086-4d75-8f07-c76e25f90167", + "id" : "dce6a1a5-7099-4366-a644-79b08fd399fd", "alias" : "Authentication Options", "description" : "Authentication options.", "providerId" : "basic-flow", @@ -2222,7 +2222,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "04270a38-4dd9-4820-bccd-0eeab6d5e60b", + "id" : "ac79c3e5-8aa3-499c-ae23-1656ab67972c", "alias" : "Browser - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2244,7 +2244,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "82af3fdb-f93f-40cd-9a1b-5aaac3c99fc4", + "id" : "ecafaa7c-4a1f-4842-b8cd-6661fea1da33", "alias" : "Direct Grant - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2266,7 +2266,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "9f7a2dee-a00b-4ed0-a28d-aebd5b04c098", + "id" : "55d29fb3-07a8-47b7-a051-9176e404ab55", "alias" : "First broker login - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2288,7 +2288,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "8bb2d6f7-095f-4be5-844e-aa7351be07a3", + "id" : "23a6b3f9-d7dc-41f0-b9b0-917e64aa62ed", "alias" : "Handle Existing Account", "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", "providerId" : "basic-flow", @@ -2310,7 +2310,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "dc8b131c-6078-4730-9c89-0f6e523bd42e", + "id" : "ea03fe83-9a6c-47e0-85e9-94fb006bc504", "alias" : "Reset - Conditional OTP", "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "providerId" : "basic-flow", @@ -2332,7 +2332,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "f308ac01-8dfa-4593-b19f-562c26d95bbd", + "id" : "c2f4bb71-24a7-42a2-a870-d0485b6430f7", "alias" : "User creation or linking", "description" : "Flow for the existing/non-existing user alternatives", "providerId" : "basic-flow", @@ -2355,7 +2355,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "12fe4a00-c0ee-4a21-929f-c9e510f7edd4", + "id" : "08a0c43e-434c-4f9d-97d8-efcc697c0bdb", "alias" : "Verify Existing Account by Re-authentication", "description" : "Reauthentication of existing account", "providerId" : "basic-flow", @@ -2377,7 +2377,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "4add5b6a-55d9-4d95-8d24-00e508039883", + "id" : "9df5a633-532d-4da0-99ad-b60bac9a984b", "alias" : "browser", "description" : "browser based authentication", "providerId" : "basic-flow", @@ -2413,7 +2413,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "783c72d8-b771-45ff-9b94-facbc7fe7c33", + "id" : "cac0d15d-bba8-4731-a184-5711bfdc38d8", "alias" : "clients", "description" : "Base authentication for clients", "providerId" : "client-flow", @@ -2449,7 +2449,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "55bed153-d2e3-44fa-9a42-4fe971325112", + "id" : "5cb539c9-6124-4883-b058-e4b0062c8ed0", "alias" : "direct grant", "description" : "OpenID Connect Resource Owner Grant", "providerId" : "basic-flow", @@ -2478,7 +2478,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "8fc5834a-2853-47e5-9b0b-9af49ec8ae4f", + "id" : "610d7baf-f915-44e0-8617-8ae6309b1098", "alias" : "docker auth", "description" : "Used by Docker clients to authenticate against the IDP", "providerId" : "basic-flow", @@ -2493,7 +2493,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "34062276-646c-48d7-ab65-4f086c3575fb", + "id" : "d613df19-1185-4796-b1e9-9716f4b241c9", "alias" : "first broker login", "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "providerId" : "basic-flow", @@ -2516,7 +2516,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "47f8b7df-bc03-43cd-ab0b-be6ca3320f1c", + "id" : "7a475371-0966-4dff-9296-28790d5aa227", "alias" : "forms", "description" : "Username, password, otp and other auth forms.", "providerId" : "basic-flow", @@ -2538,7 +2538,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "e975f4cf-3cad-458a-b0c5-1f6c5bb14d1b", + "id" : "7d71011c-9828-495a-8fc6-82e88e308d26", "alias" : "http challenge", "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", "providerId" : "basic-flow", @@ -2560,7 +2560,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "5a570e5c-22aa-4cb9-ba03-9729876a0f14", + "id" : "0eb1b344-0a43-4ffa-8bf2-98560bd7471f", "alias" : "registration", "description" : "registration flow", "providerId" : "basic-flow", @@ -2576,7 +2576,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "2a50f240-7f9c-4663-b922-bf141d8cecea", + "id" : "fd2328ca-38ca-4dc9-b9e5-09790a3512c5", "alias" : "registration form", "description" : "registration form", "providerId" : "form-flow", @@ -2612,7 +2612,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "4136e336-cf46-444c-9aaa-77ec1b2eaec0", + "id" : "770cf19b-4bc2-4161-b156-161dc23eebaa", "alias" : "reset credentials", "description" : "Reset credentials for a user if they forgot their password or something", "providerId" : "basic-flow", @@ -2648,7 +2648,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "d1ba354a-8203-42d5-bf16-d850182f7336", + "id" : "ab251c63-6c1b-4d93-9f26-2f5d18c81832", "alias" : "saml ecp", "description" : "SAML ECP Profile Authentication Flow", "providerId" : "basic-flow", @@ -2664,13 +2664,13 @@ } ] } ], "authenticatorConfig" : [ { - "id" : "cea49223-ea27-4324-816c-b6a890548097", + "id" : "709dcd0e-a60b-4ae5-ac66-d15374b1562c", "alias" : "create unique user config", "config" : { "require.password.update.after.registration" : "false" } }, { - "id" : "3627d68d-6f05-45b2-835d-8127ab90a6b3", + "id" : "f80268b2-6944-4acd-b622-426369f8c44d", "alias" : "review profile config", "config" : { "update.profile.on.first.login" : "missing" diff --git a/dbrepo-data-db/sidecar/app.py b/dbrepo-data-db/sidecar/app.py index 1ddd181140353dbe20e2a9b54d404b22f9bcdc1b..f4342301dfed6a16dc21a60db21c1d0272b07061 100644 --- a/dbrepo-data-db/sidecar/app.py +++ b/dbrepo-data-db/sidecar/app.py @@ -130,6 +130,7 @@ app.config["S3_IMPORT_BUCKET"] = os.getenv('S3_IMPORT_BUCKET', 'dbrepo-upload') app.json_encoder = LazyJSONEncoder + @token_auth.verify_token def verify_token(token: str): if token is None or token == "": @@ -177,6 +178,7 @@ def health(): @app.route("/sidecar/import/<string:filename>", methods=["POST"], endpoint="sidecar_import") +@metrics.gauge(name='dbrepo_sidecar_import_dataset', description='Time needed to import dataset from S3') @auth.login_required(role=['admin', 'import-database-data']) @swag_from("ds-yml/import.yml") def import_csv(filename): @@ -190,6 +192,7 @@ def import_csv(filename): @app.route("/sidecar/export/<string:filename>", methods=["POST"], endpoint="sidecar_export") +@metrics.gauge(name='dbrepo_sidecar_export_dataset', description='Time needed to export dataset to S3') @auth.login_required(role=['admin', 'export-query-data', 'export-table-data']) @swag_from("ds-yml/export.yml") def import_csv(filename): diff --git a/dbrepo-data-db/sidecar/metrics.md b/dbrepo-data-db/sidecar/metrics.md new file mode 100644 index 0000000000000000000000000000000000000000..0aaa9e332bacdba4a977b0ed2bffab05b5d1eae6 --- /dev/null +++ b/dbrepo-data-db/sidecar/metrics.md @@ -0,0 +1,4 @@ +| **Metric** | **Description** | +|---------------------------------|---------------------------------------| +| `dbrepo_sidecar_import_dataset` | Time needed to import dataset from S3 | +| `dbrepo_sidecar_export_dataset` | Time needed to export dataset to S3 | \ No newline at end of file diff --git a/dbrepo-data-service/metrics.md b/dbrepo-data-service/metrics.md new file mode 100644 index 0000000000000000000000000000000000000000..5e0773ad8c40200051ba25a814268208c57e2e26 --- /dev/null +++ b/dbrepo-data-service/metrics.md @@ -0,0 +1,17 @@ +| **Metric** | **Description** | +|-----------------------------|-------------------------------------------| +| `dbrepo_message_receive` | Received AMQP message from Broker Service | +| `dbrepo_subset_create` | Create subset | +| `dbrepo_subset_data` | Retrieved subset data | +| `dbrepo_subset_find` | Find subset | +| `dbrepo_subset_list` | Find subsets | +| `dbrepo_subset_persist` | Persist subset | +| `dbrepo_table_data_create` | Create table data | +| `dbrepo_table_data_delete` | Delete table data | +| `dbrepo_table_data_export` | Export table data | +| `dbrepo_table_data_history` | Find table history | +| `dbrepo_table_data_import` | Import dataset | +| `dbrepo_table_data_list` | Retrieve table data | +| `dbrepo_table_data_update` | Update table data | +| `dbrepo_view_data` | Retrieve view data | +| `dbrepo_view_schema_list` | Find view schemas | diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index 811bd2057645caf5f0572574eac5475cd4d7197e..98ad4d797ce44b3e92a2644562e56118e9c7932b 100644 --- a/dbrepo-data-service/pom.xml +++ b/dbrepo-data-service/pom.xml @@ -11,7 +11,7 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> <name>dbrepo-data-service</name> - <version>1.4.3</version> + <version>1.4.4</version> <description>Service that manages the data</description> diff --git a/dbrepo-data-service/querystore/pom.xml b/dbrepo-data-service/querystore/pom.xml index e30f0c2956617ec2114a15c326e2e24b6f5ff387..4e08bccd72ee108c77bb795468a44eefed375073 100644 --- a/dbrepo-data-service/querystore/pom.xml +++ b/dbrepo-data-service/querystore/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-data-service-querystore</artifactId> <name>dbrepo-data-service-querystore</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies/> diff --git a/dbrepo-data-service/report/pom.xml b/dbrepo-data-service/report/pom.xml index 8a52a9d2ce78fcb2bdf38ed5fd5b9abd5b3b6141..9a46c8f2fbe3d5a4257835c1a6935d36e4376d36 100644 --- a/dbrepo-data-service/report/pom.xml +++ b/dbrepo-data-service/report/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>report</artifactId> <name>dbrepo-data-service-report</name> - <version>1.4.3</version> + <version>1.4.4</version> <description> This module is only intended for the pipeline coverage report. See the detailed report in the respective modules diff --git a/dbrepo-data-service/rest-service/pom.xml b/dbrepo-data-service/rest-service/pom.xml index 9175428c48c4bde9b4635bf456f76ab1c5142d88..72f1a8f5d927f7334692c032bc3169d2b83d2b60 100644 --- a/dbrepo-data-service/rest-service/pom.xml +++ b/dbrepo-data-service/rest-service/pom.xml @@ -6,18 +6,18 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>rest-service</artifactId> <name>dbrepo-data-service-rest-service</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies> <dependency> <groupId>at.tuwien</groupId> <artifactId>services</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </dependency> </dependencies> diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java index 452a1e6b466076b18904decf43885853aac15ee6..ea7b1b3677cea807fc3892b6835db60f58233b41 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java @@ -20,10 +20,8 @@ import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; -import java.security.Principal; import java.sql.SQLException; import java.util.UUID; @@ -43,36 +41,33 @@ public class AccessEndpoint { } @PostMapping("/{userId}") - @Transactional - @Observed(name = "dbrepo_database_access_create") @PreAuthorize("hasAuthority('admin')") @Operation(summary = "Give access to some database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", - description = "Granting access succeeded", - content = {@Content}), + description = "Granting access succeeded"), @ApiResponse(responseCode = "400", description = "Granting access query or database connection is malformed", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "403", - description = "Failed giving access", + description = "Not allowed to give access", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "Database or user not found", + description = "Failed to find database/user in metadata database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "405", - description = "Granting access not permitted", + @ApiResponse(responseCode = "417", + description = "Failed to give access in the database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Access could not be created in the data service", + description = "Failed to establish connection to metadata service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -99,40 +94,45 @@ public class AccessEndpoint { } @PutMapping("/{userId}") - @Transactional - @Observed(name = "dbrepo_database_access_update") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Modify access to some database", security = {@SecurityRequirement(name = "basicAuth")}) + @Operation(summary = "Update access to some database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", - description = "Modify access succeeded", + description = "Update access succeeded", content = {@Content}), @ApiResponse(responseCode = "400", - description = "Modify access query or database connection is malformed", + description = "Update access query or database connection is malformed", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "403", - description = "Modify access not permitted when no access is granted in the first place", + description = "Not allowed to update access", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "Database or user not found", + description = "Failed to find database/user in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "417", + description = "Failed to update access in database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Access could not be updated in the data service", + description = "Failed to establish connection with metadata service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<?> update(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("userId") UUID userId, - @Valid @RequestBody UpdateDatabaseAccessDto accessDto) throws NotAllowedException, QueryMalformedException, - DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseMalformedException { - log.debug("endpoint modify access to database, databaseId={}, userId={}, accessDto={}", databaseId, userId, accessDto); + @Valid @RequestBody UpdateDatabaseAccessDto access) throws NotAllowedException, + QueryMalformedException, DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, + DatabaseMalformedException { + log.debug("endpoint modify access to database, databaseId={}, userId={}, access.type={}", databaseId, userId, + access.getType()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); final PrivilegedUserDto user = metadataServiceGateway.getUserById(userId); if (database.getAccesses().stream().noneMatch(a -> a.getUser().getId().equals(userId))) { @@ -140,7 +140,7 @@ public class AccessEndpoint { throw new NotAllowedException("Failed to update access to user with id " + userId + ": no access"); } try { - accessService.update(database, user, accessDto.getType()); + accessService.update(database, user, access.getType()); return ResponseEntity.accepted() .build(); } catch (SQLException e) { @@ -149,31 +149,33 @@ public class AccessEndpoint { } @DeleteMapping("/{userId}") - @Transactional - @Observed(name = "dbrepo_database_access_revoke") @PreAuthorize("hasAuthority('admin')") @Operation(summary = "Revoke access to some database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", - description = "Revoked access successfully", - content = {@Content}), + description = "Revoked access successfully"), @ApiResponse(responseCode = "400", - description = "Modify access query or database connection is malformed", + description = "Revoke access query or database connection is malformed", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "403", - description = "Revoke of access not permitted as no access was found", + description = "Not allowed to revoke access", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "User, database with access was not found", + description = "Failed to find database/user in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "417", + description = "Failed to revoke access in database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Access could not be revoked in the data service", + description = "Failed to establish connection with the metadata service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index 21014faf4c4d18e233fb4e90f1147ea060a99fea..f69019e7178dd8631723d929747d8654d94881e4 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -13,7 +13,6 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.AccessService; import at.tuwien.service.DatabaseService; import at.tuwien.service.SubsetService; -import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -27,7 +26,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.sql.SQLException; @@ -55,12 +53,11 @@ public class DatabaseEndpoint { } @PostMapping - @Transactional(rollbackFor = Exception.class) @PreAuthorize("hasAuthority('admin')") @Operation(summary = "Create database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", - description = "Created a new database", + description = "Created a database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = DatabaseDto.class))}), @@ -69,10 +66,25 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find container in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "417", + description = "Failed to create query store in database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to communicate with database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<DatabaseDto> create(@Valid @RequestBody CreateDatabaseDto data) throws DatabaseUnavailableException, - RemoteUnavailableException, ContainerNotFoundException, DatabaseMalformedException, - QueryStoreCreateException { + public ResponseEntity<DatabaseDto> create(@Valid @RequestBody CreateDatabaseDto data) + throws DatabaseUnavailableException, RemoteUnavailableException, ContainerNotFoundException, + DatabaseMalformedException, QueryStoreCreateException { log.debug("endpoint create database, data.containerId={}, data.internalName={}, data.username={}", data.getContainerId(), data.getInternalName(), data.getUsername()); final PrivilegedContainerDto container = metadataServiceGateway.getContainerById(data.getContainerId()); @@ -94,17 +106,23 @@ public class DatabaseEndpoint { } @PutMapping("/{databaseId}") - @Transactional(rollbackFor = Exception.class) @PreAuthorize("hasAuthority('admin')") @Operation(summary = "Update user password in database", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", - description = "Created a new database", + description = "Updated user password in database"), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database", content = {@Content( mediaType = "application/json", - schema = @Schema(implementation = DatabaseDto.class))}), - @ApiResponse(responseCode = "400", - description = "Database create query is malformed or image is not supported", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "417", + description = "Failed to update user password in database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to communicate with database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java index 32c30d481c40d01a698d68cd633f4ada4ca38b41..b9a9ae442d8a34340237a9098e79b3a08baa95f8 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java @@ -6,6 +6,7 @@ import at.tuwien.api.database.query.ExecuteStatementDto; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.query.QueryPersistDto; import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.api.error.ApiErrorDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.SubsetService; @@ -25,6 +26,7 @@ import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -62,10 +64,25 @@ public class SubsetEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = QueryDto[].class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to find subsets", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database or query in query store of the data database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to communicate with database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<List<QueryDto>> findAllById(@NotNull @PathVariable("databaseId") Long databaseId, - @RequestParam(name = "persisted", required = false) Boolean filterPersisted, - Principal principal) + public ResponseEntity<List<QueryDto>> list(@NotNull @PathVariable("databaseId") Long databaseId, + @RequestParam(name = "persisted", required = false) Boolean filterPersisted, + Principal principal) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, QueryNotFoundException, NotAllowedException { log.debug("endpoint find subsets in database, databaseId={}, filterPersisted={}, principal.name={}", databaseId, @@ -94,7 +111,36 @@ public class SubsetEndpoint { @Operation(summary = "Find subset", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", - description = "Found subset") + description = "Found subset", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = QueryDto.class)), + @Content(mediaType = "text/csv")}), + @ApiResponse(responseCode = "400", + description = "Malformed select query", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to find subset", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database or query in query store of the data database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "406", + description = "Failed to find acceptable representation", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to communicate with database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<?> findById(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("subsetId") Long subsetId, @@ -165,6 +211,36 @@ public class SubsetEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = QueryResultDto.class))}), + @ApiResponse(responseCode = "400", + description = "Malformed select query", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to find subset", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database or query in query store of the data database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "417", + description = "Failed to insert query into query store of data database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "501", + description = "Failed to execute query as it contains non-supported keywords", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to communicate with database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<QueryResultDto> create(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody ExecuteStatementDto data, @@ -173,10 +249,10 @@ public class SubsetEndpoint { @RequestParam(required = false) Long size, @RequestParam(required = false) Instant timestamp) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, - QueryNotFoundException, FormatNotAvailableException, StorageUnavailableException, QueryMalformedException, - SidecarExportException, StorageNotFoundException, QueryStoreInsertException, TableMalformedException, - PaginationException, QueryNotSupportedException, NotAllowedException, UserNotFoundException { - log.debug("endpoint find subset in database, databaseId={}, data.statement={}, principal.name={}, page={}, size={}, timestamp={}", + QueryNotFoundException, StorageUnavailableException, QueryMalformedException, SidecarExportException, + StorageNotFoundException, QueryStoreInsertException, TableMalformedException, PaginationException, + QueryNotSupportedException, NotAllowedException, UserNotFoundException { + log.debug("endpoint create subset in database, databaseId={}, data.statement={}, principal.name={}, page={}, size={}, timestamp={}", databaseId, data.getStatement(), principal.getName(), page, size, timestamp); /* check */ endpointValidator.validateDataParams(page, size); @@ -206,18 +282,39 @@ public class SubsetEndpoint { throw new DatabaseUnavailableException("Failed to establish connection to database: " + e.getMessage(), e); } log.info("Created subset with id {} in data database", queryResult.getId()); - return ResponseEntity.ok(queryResult); + return ResponseEntity.status(HttpStatus.CREATED) + .body(queryResult); } @RequestMapping(value = "/{subsetId}/data", method = {RequestMethod.GET, RequestMethod.HEAD}) @Observed(name = "dbrepo_subset_data") - @Operation(summary = "Re-execute some query", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) + @Operation(summary = "Retrieved subset data", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", - description = "Get subset data", + description = "Retrieved subset data", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = QueryResultDto.class))}), + @ApiResponse(responseCode = "400", + description = "Malformed select query", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to retrieve subset data", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database or query in query store of the data database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to communicate with database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<QueryResultDto> getData(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("subsetId") Long subsetId, @@ -273,13 +370,38 @@ public class SubsetEndpoint { @PutMapping("/{queryId}") @PreAuthorize("hasAuthority('persist-query')") @Observed(name = "dbrepo_subset_persist") - @Operation(summary = "Persist some query", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) + @Operation(summary = "Persist subset", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", - description = "Persist query successful", + description = "Persisted subset", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = QueryDto.class))}), + @ApiResponse(responseCode = "400", + description = "Malformed select query", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to persist subset", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database or query in query store of the data database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "417", + description = "Failed to persist subset", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to communicate with database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<QueryDto> persist(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("queryId") Long queryId, diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 1a32663870bda03fee2d509d2ac4e2fef1e015ba..d00089687032e3ae0ccfd84309620b264438c0be 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -1,7 +1,6 @@ package at.tuwien.endpoints; import at.tuwien.ExportResourceDto; -import at.tuwien.api.database.AccessTypeDto; import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; @@ -10,6 +9,7 @@ import at.tuwien.api.database.query.QueryResultDto; import at.tuwien.api.database.table.*; import at.tuwien.api.database.table.internal.PrivilegedTableDto; import at.tuwien.api.database.table.internal.TableCreateDto; +import at.tuwien.api.error.ApiErrorDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.AnalyseService; @@ -64,37 +64,71 @@ public class TableEndpoint { @PreAuthorize("hasAuthority('admin')") @Operation(summary = "Create table", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { - @ApiResponse(responseCode = "202", - description = "Created a new table", + @ApiResponse(responseCode = "201", + description = "Created table", content = {@Content( mediaType = "application/json", - schema = @Schema(implementation = DatabaseDto.class))}), + schema = @Schema(implementation = TableDto.class))}), + @ApiResponse(responseCode = "400", + description = "Table schema or query is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database or table in data database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "409", + description = "Table name already exists in database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<Void> create(@NotNull @PathVariable("databaseId") Long databaseId, - @Valid @RequestBody TableCreateDto data) - throws DatabaseNotFoundException, RemoteUnavailableException, TableMalformedException, - DatabaseUnavailableException, TableExistsException { + public ResponseEntity<TableDto> create(@NotNull @PathVariable("databaseId") Long databaseId, + @Valid @RequestBody TableCreateDto data) throws DatabaseNotFoundException, + RemoteUnavailableException, TableMalformedException, DatabaseUnavailableException, TableExistsException, + TableNotFoundException, QueryMalformedException { log.debug("endpoint create table, databaseId={}, data.name={}", databaseId, data.getName()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { - tableService.createTable(database, data); + return ResponseEntity.status(HttpStatus.CREATED) + .body(tableService.createTable(database, data)); } catch (SQLException e) { log.error("Failed to establish connection to database: {}", e.getMessage()); throw new DatabaseUnavailableException("Failed to establish connection to database: " + e.getMessage(), e); } - return ResponseEntity.status(HttpStatus.CREATED) - .build(); } @DeleteMapping("/{tableId}") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Delete table in database", security = {@SecurityRequirement(name = "basicAuth")}) + @Operation(summary = "Delete table", security = {@SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { - @ApiResponse(responseCode = "201", + @ApiResponse(responseCode = "202", description = "Deleted table", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = DatabaseDto.class))}), + @ApiResponse(responseCode = "400", + description = "Deletion query is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find table in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> delete(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId) @@ -114,13 +148,28 @@ public class TableEndpoint { @RequestMapping(value = "/{tableId}/data", method = {RequestMethod.GET, RequestMethod.HEAD}) @Observed(name = "dbrepo_table_data_list") - @Operation(summary = "Find table data", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) + @Operation(summary = "Retrieve table data", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", - description = "Found table data", + description = "Retrieved table data", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = QueryResultDto.class))}), + @ApiResponse(responseCode = "400", + description = "Request pagination or table data select query is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find table in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<QueryResultDto> getData(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId, @@ -128,7 +177,7 @@ public class TableEndpoint { @RequestParam(required = false) Long page, @RequestParam(required = false) Long size) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, PaginationException, SQLException, QueryMalformedException { + TableMalformedException, PaginationException, QueryMalformedException { log.debug("endpoint find table data, databaseId={}, tableId={}, timestamp={}, page={}, size={}", databaseId, tableId, timestamp, page, size); endpointValidator.validateDataParams(page, size); @@ -147,11 +196,11 @@ public class TableEndpoint { } final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId); final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Count", "" + tableService.getCount(table, timestamp)); headers.set("Access-Control-Expose-Headers", "X-Count"); try { + headers.set("X-Count", "" + tableService.getCount(table, timestamp)); final QueryResultDto dto = tableService.getData(table, timestamp, page, size); - return ResponseEntity.status(HttpStatus.OK) + return ResponseEntity.ok() .headers(headers) .body(dto); } catch (SQLException e) { @@ -167,6 +216,26 @@ public class TableEndpoint { @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Created table data"), + @ApiResponse(responseCode = "400", + description = "Request pagination or table data select query is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Create table data not allowed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find table in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> createTuple(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId, @@ -197,6 +266,26 @@ public class TableEndpoint { @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Updated table data"), + @ApiResponse(responseCode = "400", + description = "Request pagination or table data select query is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Update table data not allowed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find table in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> updateTuple(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId, @@ -228,6 +317,26 @@ public class TableEndpoint { @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Deleted table data"), + @ApiResponse(responseCode = "400", + description = "Request pagination or table data select query is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Delete table data not allowed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find table in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> deleteTuple(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId, @@ -260,7 +369,22 @@ public class TableEndpoint { description = "Found table history", content = {@Content( mediaType = "application/json", - schema = @Schema(implementation = DatabaseDto.class))}), + schema = @Schema(implementation = TableHistoryDto[].class))}), + @ApiResponse(responseCode = "403", + description = "Find table history not allowed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find table history in data database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<List<TableHistoryDto>> getHistory(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId, @@ -283,6 +407,54 @@ public class TableEndpoint { } } + @GetMapping + @PreAuthorize("isAuthenticated()") + @Operation(summary = "Find table schemas") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "Got table schemas", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = TableDto[].class))}), + @ApiResponse(responseCode = "400", + description = "Schema data malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Find table schema not allowed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "417", + description = "Failed to parse table schema", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + }) + public ResponseEntity<List<TableDto>> getSchema(@NotBlank @PathVariable("databaseId") Long databaseId) + throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, + DatabaseMalformedException, TableNotFoundException, QueryMalformedException { + log.debug("endpoint inspect table schemas, databaseId={}", databaseId); + final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); + try { + return ResponseEntity.ok(tableService.getSchemas(database)); + } catch (SQLException e) { + log.error("Failed to establish connection to database: {}", e.getMessage()); + throw new DatabaseUnavailableException("Failed to establish connection to database: " + e.getMessage(), e); + } + } + @GetMapping("/{tableId}/export") @Observed(name = "dbrepo_table_data_export") @Operation(summary = "Export table data", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @@ -291,7 +463,27 @@ public class TableEndpoint { description = "Exported table data", content = {@Content( mediaType = "application/json", - schema = @Schema(implementation = DatabaseDto.class))}), + schema = @Schema(implementation = InputStreamResource.class))}), + @ApiResponse(responseCode = "400", + description = "Request pagination or table data select query is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Export table data not allowed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find table in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<InputStreamResource> exportData(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId, @@ -332,10 +524,30 @@ public class TableEndpoint { @PostMapping("/{tableId}/data/import") @Observed(name = "dbrepo_table_data_import") @PreAuthorize("hasAuthority('insert-table-data')") - @Operation(summary = "Insert data from csv", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) + @Operation(summary = "Import dataset", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", - description = "Import successfully"), + description = "Import dataset successfully"), + @ApiResponse(responseCode = "400", + description = "Import dataset query is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Import table dataset not allowed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find table in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> importData(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("tableId") Long tableId, diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 7fc146bbe2852b5732307068cceca7cd4ff1259c..91e5f7390dbe542e39bfa826981dae18574eb647 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -1,11 +1,11 @@ package at.tuwien.endpoints; -import at.tuwien.api.database.DatabaseAccessDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewCreateDto; +import at.tuwien.api.database.*; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.database.internal.PrivilegedViewDto; import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.error.ApiErrorDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.ViewService; @@ -33,6 +33,7 @@ import org.springframework.web.bind.annotation.*; import java.security.Principal; import java.sql.SQLException; import java.time.Instant; +import java.util.List; @Log4j2 @RestController @@ -52,40 +53,125 @@ public class ViewEndpoint { this.metadataServiceGateway = metadataServiceGateway; } + @GetMapping + @PreAuthorize("isAuthenticated()") + @Observed(name = "dbrepo_view_schema_list") + @Operation(summary = "Find view schemas") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "Found view schemas", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ViewDto[].class))}), + @ApiResponse(responseCode = "400", + description = "Database schema is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database/view in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "409", + description = "View schema could not be mapped to known columns", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "417", + description = "View schema could not be retrieved", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + }) + public ResponseEntity<List<ViewDto>> getSchema(@NotBlank @PathVariable("databaseId") Long databaseId) + throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, + ViewMalformedException, ViewNotFoundException, DatabaseMalformedException, ViewSchemaException { + log.debug("endpoint inspect view schemas, databaseId={}", databaseId); + final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); + try { + return ResponseEntity.ok(viewService.getSchemas(database)); + } catch (SQLException e) { + log.error("Failed to establish connection to database: {}", e.getMessage()); + throw new DatabaseUnavailableException("Failed to establish connection to database: " + e.getMessage(), e); + } + } + @PostMapping @PreAuthorize("hasAuthority('admin')") @Operation(summary = "Create view", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", - description = "Created a new view", + description = "Created view", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ViewDto.class))}), + @ApiResponse(responseCode = "400", + description = "View schema is malformed", content = {@Content( mediaType = "application/json", - schema = @Schema(implementation = DatabaseDto.class))}), + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "409", + description = "View schema could not be mapped", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<Void> create(@NotNull @PathVariable("databaseId") Long databaseId, - @Valid @RequestBody ViewCreateDto data) throws DatabaseUnavailableException, + public ResponseEntity<ViewDto> create(@NotNull @PathVariable("databaseId") Long databaseId, + @Valid @RequestBody ViewCreateDto data) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException { log.debug("endpoint create view, databaseId={}, data.name={}", databaseId, data.getName()); final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId); try { - viewService.create(database, data); + return ResponseEntity.status(HttpStatus.CREATED) + .body(viewService.create(database, data)); } catch (SQLException e) { log.error("Failed to establish connection to database: {}", e.getMessage()); throw new DatabaseUnavailableException("Failed to establish connection to database: " + e.getMessage(), e); } - return ResponseEntity.status(HttpStatus.CREATED) - .build(); } @DeleteMapping("/{viewId}") @PreAuthorize("hasAuthority('admin')") - @Operation(summary = "Delete view in database", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) + @Operation(summary = "Delete view", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { - @ApiResponse(responseCode = "201", - description = "Deleted table", + @ApiResponse(responseCode = "202", + description = "Deleted view"), + @ApiResponse(responseCode = "400", + description = "Database schema is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find view in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "409", + description = "View schema could not be mapped", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", content = {@Content( mediaType = "application/json", - schema = @Schema(implementation = DatabaseDto.class))}), + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> delete(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("viewId") Long viewId) @@ -104,15 +190,39 @@ public class ViewEndpoint { } @RequestMapping(value = "/{viewId}/data", method = {RequestMethod.GET, RequestMethod.HEAD}) - @PreAuthorize("hasAuthority('view-database-view-data')") @Observed(name = "dbrepo_view_data") - @Operation(summary = "Get view data", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) + @Operation(summary = "Retrieve view data", security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", - description = "Returned view data", + description = "Retrieved view data", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = QueryResultDto.class))}), + @ApiResponse(responseCode = "400", + description = "Request pagination is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to retrieve view data", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find view in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "409", + description = "View schema could not be mapped", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to establish connection with the metadata service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<QueryResultDto> getData(@NotBlank @PathVariable("databaseId") Long databaseId, @NotBlank @PathVariable("viewId") Long viewId, @@ -123,8 +233,8 @@ public class ViewEndpoint { Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, ViewNotFoundException, QueryMalformedException, ViewMalformedException, PaginationException, NotAllowedException { - log.debug("endpoint get view data, databaseId={}, viewId={}, page={}, size={}, timestamp={}", databaseId, viewId, - page, size, timestamp); + log.debug("endpoint get view data, databaseId={}, viewId={}, page={}, size={}, timestamp={}", databaseId, + viewId, page, size, timestamp); endpointValidator.validateDataParams(page, size); /* parameters */ if (page == null) { @@ -140,7 +250,9 @@ public class ViewEndpoint { timestamp = Instant.now(); } final PrivilegedViewDto view = metadataServiceGateway.getViewById(databaseId, viewId); - metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); + if (!view.getIsPublic()) { + metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal)); + } try { final Long count = viewService.count(view, timestamp); final HttpHeaders headers = new HttpHeaders(); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java index c3c95682bd80cd8c160b9f933a02e5411137e6e0..18373423c5dd58d5236670a63989134132e4685d 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java @@ -25,7 +25,7 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { } @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) + @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) @ExceptionHandler(DatabaseMalformedException.class) public ResponseEntity<ApiErrorDto> handle(DatabaseMalformedException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); @@ -88,7 +88,7 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { } @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) + @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) @ExceptionHandler(QueryStoreCreateException.class) public ResponseEntity<ApiErrorDto> handle(QueryStoreCreateException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); @@ -102,14 +102,14 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { } @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) + @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) @ExceptionHandler(QueryStoreInsertException.class) public ResponseEntity<ApiErrorDto> handle(QueryStoreInsertException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); } @Hidden - @ResponseStatus(code = HttpStatus.BAD_REQUEST) + @ResponseStatus(code = HttpStatus.EXPECTATION_FAILED) @ExceptionHandler(QueryStorePersistException.class) public ResponseEntity<ApiErrorDto> handle(QueryStorePersistException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); @@ -185,6 +185,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.CONFLICT) + @ExceptionHandler(TableSchemaException.class) + public ResponseEntity<ApiErrorDto> handle(TableSchemaException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.NOT_FOUND) @ExceptionHandler(UserNotFoundException.class) @@ -206,6 +213,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.CONFLICT) + @ExceptionHandler(ViewSchemaException.class) + public ResponseEntity<ApiErrorDto> handle(ViewSchemaException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + private ResponseEntity<ApiErrorDto> generic_handle(Class<?> exceptionClass, String message) { final HttpHeaders headers = new HttpHeaders(); headers.set("Content-Type", "application/problem+json"); diff --git a/dbrepo-data-service/rest-service/src/main/resources/application-local.yml b/dbrepo-data-service/rest-service/src/main/resources/application-local.yml index adee5bea5986e7714625bba6d6ea504ead1b3e6c..fda4447d0b66d22e95cdb1bd1c2525a9eb5f9a15 100644 --- a/dbrepo-data-service/rest-service/src/main/resources/application-local.yml +++ b/dbrepo-data-service/rest-service/src/main/resources/application-local.yml @@ -68,3 +68,6 @@ dbrepo: password: fda client: dbrepo-client clientSecret: MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG + defaultDateFormatId: 1 + defaultTimeFormatId: 4 + defaultTimestampFormatId: 3 diff --git a/dbrepo-data-service/rest-service/src/main/resources/application.yml b/dbrepo-data-service/rest-service/src/main/resources/application.yml index 056e2bd75063784619d0b3f0675821ff07324e81..44daf91e46c603ae27ee7780e4ecc62de90b5339 100644 --- a/dbrepo-data-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-data-service/rest-service/src/main/resources/application.yml @@ -81,4 +81,7 @@ dbrepo: queueName: "${BROKER_QUEUE_NAME:dbrepo}" exchangeName: "${BROKER_EXCHANGE_NAME:dbrepo}" routingKey: "${BROKER_ROUTING_KEY:#}" - connectionTimeout: ${CONNECTION_TIMEOUT:10000} \ No newline at end of file + connectionTimeout: ${CONNECTION_TIMEOUT:10000} + defaultDateFormatId: "${DEFAULT_DATE_FORMAT_ID:3}" + defaultTimeFormatId: "${DEFAULT_TIME_FORMAT_ID:4}" + defaultTimestampFormatId: "${DEFAULT_TIMESTAMP_FORMAT_ID:1}" diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java index 8792fc9fee1d48388c95117facc77f9910fa5532..d212bb3064252f2ab2317028224914e96bb85c5f 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java @@ -504,7 +504,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { } /* test */ - final ResponseEntity<List<QueryDto>> response = subsetEndpoint.findAllById(databaseId, null, principal); + final ResponseEntity<List<QueryDto>> response = subsetEndpoint.list(databaseId, null, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); return response.getBody(); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java index 9041e7a3a6e856f157d47e0323c5b5f4daf7eb35..fd93a3ae967be7290776b8d4d910c25a93f12c9a 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java @@ -3,10 +3,7 @@ package at.tuwien.endpoint; import at.tuwien.ExportResourceDto; import at.tuwien.api.database.query.ImportCsvDto; import at.tuwien.api.database.query.QueryResultDto; -import at.tuwien.api.database.table.TableHistoryDto; -import at.tuwien.api.database.table.TupleDeleteDto; -import at.tuwien.api.database.table.TupleDto; -import at.tuwien.api.database.table.TupleUpdateDto; +import at.tuwien.api.database.table.*; import at.tuwien.endpoints.TableEndpoint; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; @@ -61,17 +58,17 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) public void create_succeeds() throws DatabaseUnavailableException, TableMalformedException, - DatabaseNotFoundException, TableExistsException, RemoteUnavailableException, SQLException { + DatabaseNotFoundException, TableExistsException, RemoteUnavailableException, SQLException, + TableNotFoundException, QueryMalformedException { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - doNothing() - .when(tableService) - .createTable(DATABASE_1_PRIVILEGED_DTO, TABLE_4_CREATE_INTERNAL_DTO); + when(tableService.createTable(DATABASE_1_PRIVILEGED_DTO, TABLE_4_CREATE_INTERNAL_DTO)) + .thenReturn(TABLE_4_DTO); /* test */ - final ResponseEntity<Void> response = tableEndpoint.create(DATABASE_1_ID, TABLE_4_CREATE_INTERNAL_DTO); + final ResponseEntity<TableDto> response = tableEndpoint.create(DATABASE_1_ID, TABLE_4_CREATE_INTERNAL_DTO); assertEquals(HttpStatus.CREATED, response.getStatusCode()); } @@ -434,9 +431,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_3_USER_3_READ_ACCESS_DTO); /* test */ - assertThrows(NotAllowedException.class, () -> { - tableEndpoint.updateTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); - }); + assertThrows(NotAllowedException.class, () -> { + tableEndpoint.updateTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL); + }); } @Test diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java index fa4549fda46279349432ee0b35c2d6fb983d1642..de98f501d095dc637b1b21cd667459f65eb08ee8 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java @@ -1,5 +1,6 @@ package at.tuwien.endpoint; +import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.query.QueryResultDto; import at.tuwien.endpoints.ViewEndpoint; import at.tuwien.exception.*; @@ -16,6 +17,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -30,9 +32,6 @@ import static org.mockito.Mockito.*; @ExtendWith(SpringExtension.class) public class ViewEndpointUnitTest extends AbstractUnitTest { - @Autowired - private ViewEndpoint viewEndpoint; - @MockBean private ViewService viewService; @@ -42,6 +41,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @MockBean private HttpServletRequest httpServletRequest; + @Autowired + private ViewEndpoint viewEndpoint; + @BeforeEach public void beforeEach() { genesis(); @@ -55,12 +57,11 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - doNothing() - .when(viewService) - .create(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO); + when(viewService.create(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO)) + .thenReturn(VIEW_1_DTO); /* test */ - final ResponseEntity<Void> response = viewEndpoint.create(DATABASE_1_ID, VIEW_1_CREATE_DTO); + final ResponseEntity<ViewDto> response = viewEndpoint.create(DATABASE_1_ID, VIEW_1_CREATE_DTO); assertEquals(HttpStatus.CREATED, response.getStatusCode()); } @@ -72,9 +73,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - doNothing() - .when(viewService) - .create(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO); + when(viewService.create(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO)) + .thenReturn(VIEW_1_DTO); /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { @@ -205,16 +205,6 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { assertNull(response.getBody()); } - @Test - @WithMockUser(username = USER_4_USERNAME) - public void getData_noRole_fails() { - - /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - viewEndpoint.getData(DATABASE_1_ID, VIEW_1_ID, null, null, null, httpServletRequest, USER_4_PRINCIPAL); - }); - } - @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"}) public void getData_viewNotFound_fails() throws RemoteUnavailableException, ViewNotFoundException { @@ -236,15 +226,15 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { NotAllowedException { /* mock */ - when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_3_ID)) + .thenReturn(VIEW_3_PRIVILEGED_DTO); doThrow(NotAllowedException.class) .when(metadataServiceGateway) .getAccess(DATABASE_1_ID, USER_3_ID); /* test */ assertThrows(NotAllowedException.class, () -> { - viewEndpoint.getData(DATABASE_1_ID, VIEW_1_ID, null, null, null, httpServletRequest, USER_3_PRINCIPAL); + viewEndpoint.getData(DATABASE_1_ID, VIEW_3_ID, null, null, null, httpServletRequest, USER_3_PRINCIPAL); }); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java index 5d478c6953f3a6d2c2840f49053751410f7e7c91..d1426cdf69db414892baed59cd121087cea8cc1b 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java @@ -3,6 +3,7 @@ package at.tuwien.mvc; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.endpoints.*; import at.tuwien.test.AbstractUnitTest; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.log4j.Log4j2; @@ -69,9 +70,10 @@ public class OpenApiEndpointMvcTest extends AbstractUnitTest { private void generic_openApiDocs(Class<?> endpoint) { final List<Method> methods = Arrays.stream(endpoint.getMethods()) - .filter(m -> m.getDeclaringClass().equals(AccessEndpoint.class)) + .filter(m -> m.getDeclaringClass().equals(endpoint)) .toList(); methods.forEach(m -> { + assertNotNull(m.getDeclaredAnnotation(Operation.class).summary()); final List<Class<?>> exceptions = Arrays.stream(m.getExceptionTypes()) .toList(); final List<Class<?>> invalidExceptions = exceptions.stream() diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index a3fc0ec14be30060f37cbed9ad9a8aad4d4eea7c..1b51d3072c52398288c68725b6b020d08e66e622 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -1,6 +1,5 @@ package at.tuwien.mvc; -import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.api.database.query.ExecuteStatementDto; import at.tuwien.api.database.query.ImportCsvDto; import at.tuwien.api.database.query.QueryPersistDto; @@ -11,7 +10,9 @@ import at.tuwien.config.MetricsConfig; import at.tuwien.endpoints.*; import at.tuwien.listener.DefaultListener; import at.tuwien.test.AbstractUnitTest; +import io.micrometer.observation.annotation.Observed; import io.micrometer.observation.tck.TestObservationRegistry; +import io.swagger.v3.oas.annotations.Operation; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.log4j.Log4j2; import org.apache.commons.io.FileUtils; @@ -26,7 +27,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -34,15 +34,13 @@ import org.springframework.test.web.servlet.MockMvc; import java.io.File; import java.io.IOException; -import java.nio.charset.Charset; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.*; import static at.tuwien.utils.RabbitMqUtils.buildMessage; import static io.micrometer.observation.tck.TestObservationRegistryAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -68,10 +66,10 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { private HttpServletRequest httpServletRequest; @Autowired - private AccessEndpoint accessEndpoint; + private AccessEndpoint accessEndpoint; /* no metrics */ @Autowired - private DatabaseEndpoint databaseEndpoint; + private DatabaseEndpoint databaseEndpoint; /* no metrics */ @Autowired private SubsetEndpoint subsetEndpoint; @@ -82,7 +80,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { @Autowired private ViewEndpoint viewEndpoint; - private static final List<String> metrics = new LinkedList<>(); + private static final Map<String, String> metrics = new TreeMap<>(); /* sorted */ @TestConfiguration static class ObservationTestConfiguration { @@ -100,10 +98,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { @AfterAll public static void afterAll() throws IOException { - Collections.sort(metrics); - final StringBuilder content = new StringBuilder("# AUTOGENERATED FILE (DO NOT EDIT)\n") - .append(String.join("\n", metrics)); - FileUtils.writeStringToFile(new File("../metrics.txt"), content.toString(), Charset.defaultCharset()); + saveObservedMetrics(metrics); } @Test @@ -118,49 +113,17 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { @Test public void prometheusDefaultListener_succeeds() { - /* mock */ - defaultListener.onMessage(buildMessage("dbrepo.database", "{}", new HashMap<>())); - - /* test */ - metrics.add("dbrepo_message_receive"); - assertThat(registry) - .hasObservationWithNameEqualTo("dbrepo_message_receive"); - } - - @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void prometheusAccessEndpoint_succeeds() { - /* mock */ try { - accessEndpoint.create(DATABASE_1_ID, USER_1_ID, UPDATE_DATABASE_ACCESS_READ_DTO); - } catch (Exception e) { - /* ignore */ - } - try { - accessEndpoint.revoke(DATABASE_1_ID, USER_1_ID); - } catch (Exception e) { - /* ignore */ - } - try { - accessEndpoint.update(DATABASE_1_ID, USER_1_ID, UPDATE_DATABASE_ACCESS_READ_DTO); + defaultListener.onMessage(buildMessage("dbrepo.database", "{}", new HashMap<>())); } catch (Exception e) { /* ignore */ } /* test */ - for (String metric : List.of("dbrepo_database_access_create", "dbrepo_database_access_update", - "dbrepo_database_access_revoke")) { - metrics.add(metric); - assertThat(registry) - .hasObservationWithNameEqualTo(metric); - } - } - - @Test - @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"admin"}) - public void prometheusDatabaseEndpoint_succeeds() { - assertTrue(true); + assertThat(registry) + .hasObservationWithNameEqualTo("dbrepo_message_receive"); + generic_openApiDocs(DefaultListener.class); } @Test @@ -169,7 +132,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* mock */ try { - subsetEndpoint.findAllById(DATABASE_1_ID, null, USER_1_PRINCIPAL); + subsetEndpoint.list(DATABASE_1_ID, null, USER_1_PRINCIPAL); } catch (Exception e) { /* ignore */ } @@ -197,10 +160,10 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* test */ for (String metric : List.of("dbrepo_subset_list", "dbrepo_subset_create", "dbrepo_subset_data", "dbrepo_subset_persist", "dbrepo_subset_find")) { - metrics.add(metric); assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(SubsetEndpoint.class); } @Test @@ -253,10 +216,10 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { for (String metric : List.of("dbrepo_table_data_list", "dbrepo_table_data_create", "dbrepo_table_data_update", "dbrepo_table_data_delete", "dbrepo_table_data_history", "dbrepo_table_data_export", "dbrepo_table_data_import")) { - metrics.add(metric); assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(TableEndpoint.class); } @Test @@ -271,9 +234,23 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - metrics.add("dbrepo_view_data"); assertThat(registry) .hasObservationWithNameEqualTo("dbrepo_view_data"); + generic_openApiDocs(ViewEndpoint.class); + } + + private static void generic_openApiDocs(Class<?> endpoint) { + final List<Method> methods = Arrays.stream(endpoint.getMethods()) + .filter(m -> m.getDeclaringClass().equals(endpoint)) + .toList(); + methods.forEach(m -> { + final Observed observed = m.getDeclaredAnnotation(Observed.class); + final Operation operation = m.getDeclaredAnnotation(Operation.class); + if (observed != null) { + assertNotNull(operation); + metrics.put(observed.name(), operation.summary()); + } + }); } } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c9efad23f02b5ef280e8d9a55605d94e79a6b2fd --- /dev/null +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java @@ -0,0 +1,143 @@ +package at.tuwien.service; + +import at.tuwien.api.database.ViewColumnDto; +import at.tuwien.api.database.ViewDto; +import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.database.table.columns.ColumnDto; +import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.tuwien.api.database.table.constraints.ConstraintsDto; +import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; +import at.tuwien.api.database.table.constraints.unique.UniqueDto; +import at.tuwien.config.MariaDbConfig; +import at.tuwien.config.MariaDbContainerConfig; +import at.tuwien.exception.*; +import at.tuwien.test.AbstractUnitTest; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.testcontainers.containers.MariaDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.sql.SQLException; +import java.util.List; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +@Log4j2 +@SpringBootTest +@ExtendWith(SpringExtension.class) +@Testcontainers +public class SchemaServiceIntegrationTest extends AbstractUnitTest { + + @Autowired + private SchemaService schemaService; + + @Container + private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); + + @BeforeEach + public void beforeEach() throws SQLException { + genesis(); + /* metadata database */ + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_DTO); + } + + @Test + public void inspectTable_succeeds() throws TableNotFoundException, SQLException, QueryMalformedException { + + /* test */ + final TableDto response = schemaService.inspectTable(DATABASE_1_PRIVILEGED_DTO, "not_in_metadata_db"); + assertEquals("not_in_metadata_db", response.getInternalName()); + assertEquals("not_in_metadata_db", response.getName()); + assertEquals(DATABASE_1_ID, response.getTdbid()); + assertTrue(response.getIsVersioned()); + assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); + final List<ColumnDto> columns = response.getColumns(); + assertNotNull(columns); + assertEquals(5, columns.size()); + final ColumnDto column0 = columns.get(0); + assertEquals("id", column0.getName()); + assertEquals("id", column0.getInternalName()); + assertEquals(ColumnTypeDto.BIGINT, column0.getColumnType()); + assertFalse(column0.getIsNullAllowed()); + final ColumnDto column1 = columns.get(1); + assertEquals("given_name", column1.getName()); + assertEquals("given_name", column1.getInternalName()); + assertEquals(ColumnTypeDto.VARCHAR, column1.getColumnType()); + assertEquals(255, column1.getSize()); + assertFalse(column1.getIsNullAllowed()); + final ColumnDto column2 = columns.get(2); + assertEquals("middle_name", column2.getName()); + assertEquals("middle_name", column2.getInternalName()); + assertEquals(ColumnTypeDto.VARCHAR, column2.getColumnType()); + assertEquals(255, column2.getSize()); + assertTrue(column2.getIsNullAllowed()); + final ColumnDto column3 = columns.get(3); + assertEquals("family_name", column3.getName()); + assertEquals("family_name", column3.getInternalName()); + assertEquals(ColumnTypeDto.VARCHAR, column3.getColumnType()); + assertEquals(255, column3.getSize()); + assertFalse(column3.getIsNullAllowed()); + final ColumnDto column4 = columns.get(4); + assertEquals("age", column4.getName()); + assertEquals("age", column4.getInternalName()); + assertEquals(ColumnTypeDto.INT, column4.getColumnType()); + assertFalse(column4.getIsNullAllowed()); + final ConstraintsDto constraints = response.getConstraints(); + assertNotNull(constraints); + final Set<PrimaryKeyDto> primaryKey = constraints.getPrimaryKey(); + assertEquals(1, primaryKey.size()); + final Set<String> checks = constraints.getChecks(); + assertEquals(1, checks.size()); + assertEquals(Set.of("`age` > 0 and `age` < 120"), checks); + final List<UniqueDto> uniques = constraints.getUniques(); + assertEquals(1, uniques.size()); + assertEquals(2, uniques.get(0).getColumns().size()); + assertEquals("not_in_metadata_db", uniques.get(0).getTable().getInternalName()); + assertEquals("given_name", uniques.get(0).getColumns().get(0).getInternalName()); + assertEquals("family_name", uniques.get(0).getColumns().get(1).getInternalName()); + } + + @Test + public void inspectView_succeeds() throws ViewMalformedException, SQLException, ViewNotFoundException, + ViewSchemaException { + + /* test */ + final ViewDto response = schemaService.inspectView(DATABASE_1_PRIVILEGED_DTO, "not_in_metadata_db2"); + assertEquals("not_in_metadata_db2", response.getInternalName()); + assertEquals("not_in_metadata_db2", response.getName()); + assertEquals(DATABASE_1_ID, response.getVdbid()); + assertEquals(DATABASE_1_ID, response.getDatabase().getId()); + assertEquals(DATABASE_1_OWNER, response.getCreatedBy()); + assertEquals(DATABASE_1_OWNER, response.getCreator().getId()); + assertFalse(response.getIsInitialView()); + assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); + assertTrue(response.getQuery().length() >= 69); + assertNotNull(response.getQueryHash()); + assertEquals(4, response.getColumns().size()); + final ViewColumnDto column0 = response.getColumns().get(0); + assertNotNull(column0.getName()); + assertEquals("date", column0.getInternalName()); + assertEquals(DATABASE_1_ID, column0.getDatabaseId()); + final ViewColumnDto column1 = response.getColumns().get(1); + assertNotNull(column1.getName()); + assertEquals("location", column1.getInternalName()); + assertEquals(DATABASE_1_ID, column1.getDatabaseId()); + final ViewColumnDto column2 = response.getColumns().get(2); + assertNotNull(column2.getName()); + assertEquals("MinTemp", column2.getInternalName()); + assertEquals(DATABASE_1_ID, column2.getDatabaseId()); + final ViewColumnDto column3 = response.getColumns().get(3); + assertNotNull(column3.getName()); + assertEquals("Rainfall", column3.getInternalName()); + assertEquals(DATABASE_1_ID, column3.getDatabaseId()); + } + +} diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java index e688df184018cbfa5e69cfb0acbbfc19981ecce1..25144d827dabaaf1b88fc7ab4914ae2ccc1b3283 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java @@ -1,14 +1,21 @@ package at.tuwien.service; +import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.TupleDeleteDto; import at.tuwien.api.database.table.TupleDto; import at.tuwien.api.database.table.TupleUpdateDto; +import at.tuwien.api.database.table.columns.ColumnDto; +import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.tuwien.api.database.table.constraints.ConstraintsDto; +import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; +import at.tuwien.api.database.table.constraints.unique.UniqueDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -27,6 +34,7 @@ import java.util.Map; import java.util.Set; import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.when; @Log4j2 @@ -310,4 +318,62 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { assertEquals(0, result.size()); } + @Test + public void getSchemas_succeeds() throws TableNotFoundException, SQLException, QueryMalformedException, + DatabaseMalformedException { + + /* test */ + final List<TableDto> response = tableService.getSchemas(DATABASE_1_PRIVILEGED_DTO); + final TableDto table0 = response.get(0); + Assertions.assertEquals("not_in_metadata_db", table0.getInternalName()); + Assertions.assertEquals("not_in_metadata_db", table0.getName()); + Assertions.assertEquals(DATABASE_1_ID, table0.getTdbid()); + assertTrue(table0.getIsVersioned()); + Assertions.assertEquals(DATABASE_1_PUBLIC, table0.getIsPublic()); + final List<ColumnDto> columns = table0.getColumns(); + assertNotNull(columns); + Assertions.assertEquals(5, columns.size()); + final ColumnDto column0 = columns.get(0); + Assertions.assertEquals("id", column0.getName()); + Assertions.assertEquals("id", column0.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.BIGINT, column0.getColumnType()); + assertFalse(column0.getIsNullAllowed()); + final ColumnDto column1 = columns.get(1); + Assertions.assertEquals("given_name", column1.getName()); + Assertions.assertEquals("given_name", column1.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.VARCHAR, column1.getColumnType()); + Assertions.assertEquals(255, column1.getSize()); + assertFalse(column1.getIsNullAllowed()); + final ColumnDto column2 = columns.get(2); + Assertions.assertEquals("middle_name", column2.getName()); + Assertions.assertEquals("middle_name", column2.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.VARCHAR, column2.getColumnType()); + Assertions.assertEquals(255, column2.getSize()); + assertTrue(column2.getIsNullAllowed()); + final ColumnDto column3 = columns.get(3); + Assertions.assertEquals("family_name", column3.getName()); + Assertions.assertEquals("family_name", column3.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.VARCHAR, column3.getColumnType()); + Assertions.assertEquals(255, column3.getSize()); + assertFalse(column3.getIsNullAllowed()); + final ColumnDto column4 = columns.get(4); + Assertions.assertEquals("age", column4.getName()); + Assertions.assertEquals("age", column4.getInternalName()); + Assertions.assertEquals(ColumnTypeDto.INT, column4.getColumnType()); + assertFalse(column4.getIsNullAllowed()); + final ConstraintsDto constraints = table0.getConstraints(); + assertNotNull(constraints); + final Set<PrimaryKeyDto> primaryKey = constraints.getPrimaryKey(); + Assertions.assertEquals(1, primaryKey.size()); + final Set<String> checks = constraints.getChecks(); + Assertions.assertEquals(1, checks.size()); + Assertions.assertEquals(Set.of("`age` > 0 and `age` < 120"), checks); + final List<UniqueDto> uniques = constraints.getUniques(); + Assertions.assertEquals(1, uniques.size()); + Assertions.assertEquals(2, uniques.get(0).getColumns().size()); + Assertions.assertEquals("not_in_metadata_db", uniques.get(0).getTable().getInternalName()); + Assertions.assertEquals("given_name", uniques.get(0).getColumns().get(0).getInternalName()); + Assertions.assertEquals("family_name", uniques.get(0).getColumns().get(1).getInternalName()); + } + } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java index e30889840dd31650f34debdc55eafe06f67c157c..ba846f37cc1a4dd8de4c2e1927a9c1f2493f29f3 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java @@ -1,6 +1,9 @@ package at.tuwien.service; +import at.tuwien.api.database.ViewColumnDto; +import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; import at.tuwien.exception.*; @@ -21,8 +24,8 @@ import java.time.Instant; import java.util.List; import java.util.Map; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; @Log4j2 @SpringBootTest @@ -68,24 +71,49 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest { assertEquals(VIEW_2_ID, response.getId()); assertNotNull(response.getHeaders()); assertEquals(4, response.getHeaders().size()); - assertEquals(List.of(Map.of("date", 0), Map.of("location", 1), Map.of("rainfall", 2), Map.of("mintemp", 3)), response.getHeaders()); + assertEquals(List.of(Map.of("date", 0), Map.of("location", 1), Map.of("mintemp", 2), Map.of("location", 3)), response.getHeaders()); assertNotNull(response.getResult()); assertEquals(3, response.getResult().size()); /* row 0 */ assertEquals(Instant.ofEpochSecond(1228089600), response.getResult().get(0).get("date")); assertEquals("Albury", response.getResult().get(0).get("location")); assertEquals(13.4, response.getResult().get(0).get("mintemp")); - assertEquals(0.6, response.getResult().get(0).get("rainfall")); /* row 1 */ assertEquals(Instant.ofEpochSecond(1228176000), response.getResult().get(1).get("date")); assertEquals("Albury", response.getResult().get(1).get("location")); assertEquals(7.4, response.getResult().get(1).get("mintemp")); - assertEquals(0.0, response.getResult().get(1).get("rainfall")); /* row 2 */ assertEquals(Instant.ofEpochSecond(1228262400), response.getResult().get(2).get("date")); assertEquals("Albury", response.getResult().get(2).get("location")); assertEquals(12.9, response.getResult().get(2).get("mintemp")); - assertEquals(0.0, response.getResult().get(2).get("rainfall")); + } + + @Test + public void getSchemas_succeeds() throws ViewMalformedException, SQLException, ViewNotFoundException, + DatabaseMalformedException, ViewSchemaException { + + /* test */ + final List<ViewDto> response = viewService.getSchemas(DATABASE_1_PRIVILEGED_DTO); + final ViewDto view0 = response.get(0); + assertEquals("not_in_metadata_db2", view0.getName()); + assertEquals("not_in_metadata_db2", view0.getInternalName()); + assertEquals(DATABASE_1_ID, view0.getVdbid()); + assertEquals(DATABASE_1_ID, view0.getDatabase().getId()); + assertEquals(DATABASE_1_OWNER, view0.getCreatedBy()); + assertEquals(DATABASE_1_OWNER, view0.getCreator().getId()); + assertFalse(view0.getIsInitialView()); + assertEquals(DATABASE_1_PUBLIC, view0.getIsPublic()); + assertTrue(view0.getQuery().length() >= 69); + assertNotNull(view0.getQueryHash()); + assertEquals(4, view0.getColumns().size()); + final ViewColumnDto column0a = view0.getColumns().get(0); + assertEquals("date", column0a.getInternalName()); + final ViewColumnDto column1a = view0.getColumns().get(1); + assertEquals("location", column1a.getInternalName()); + final ViewColumnDto column2a = view0.getColumns().get(2); + assertEquals("MinTemp", column2a.getInternalName()); + final ViewColumnDto column3a = view0.getColumns().get(3); + assertEquals("Rainfall", column3a.getInternalName()); } } diff --git a/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql b/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql index 6c1b14187daafdbe0022548c445e86688ea9f5d3..2eef31b4752b03ed0b1ccad1cc2d93a56e44f1ae 100644 --- a/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql +++ b/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql @@ -55,11 +55,18 @@ select `date`, `location`, `mintemp`, `rainfall` from `weather_aus` where `location` = 'Albury'); -CREATE VIEW `hs_weather_aus` AS -SELECT * -FROM (SELECT `id`, ROW_START AS inserted_at, IF(ROW_END > NOW(), NULL, ROW_END) AS deleted_at, COUNT(*) as total - FROM `weather_aus` FOR SYSTEM_TIME ALL - GROUP BY inserted_at, deleted_at - ORDER BY deleted_at DESC - LIMIT 50) AS v -ORDER BY v.inserted_at, v.deleted_at ASC; +CREATE TABLE not_in_metadata_db +( + id BIGINT NOT NULL PRIMARY KEY, + given_name VARCHAR(255) NOT NULL, + middle_name VARCHAR(255) NULL, + family_name VARCHAR(255) NOT NULL, + age INT NOT NULL CHECK ( age > 0 AND age < 120 ), + UNIQUE (given_name, family_name) +) WITH SYSTEM VERSIONING; + +CREATE VIEW not_in_metadata_db2 AS +( +select `date`, `location`, `mintemp` as `MinTemp`, `rainfall` as `Rainfall` +from `weather_aus` +where `location` = 'Vienna'); \ No newline at end of file diff --git a/dbrepo-data-service/services/pom.xml b/dbrepo-data-service/services/pom.xml index 760173af8f1c854fb9c8b48050460c3d96bd84c9..d5f6be25c8c35716eb34186b20d5711210e6f923 100644 --- a/dbrepo-data-service/services/pom.xml +++ b/dbrepo-data-service/services/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>services</artifactId> <name>dbrepo-data-service-services</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies> <dependency> @@ -22,7 +22,7 @@ <dependency> <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service-querystore</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </dependency> </dependencies> diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/QueryConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/QueryConfig.java index b6363911705d4778111879d8cce3dc30a0475992..55888bda1ad9789cfca1eb097fb2d7716bdb555a 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/QueryConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/QueryConfig.java @@ -13,4 +13,13 @@ public class QueryConfig { @Value("${dbrepo.sql.forbidden}") private String[] forbiddenKeywords; + @Value("${dbrepo.defaultDateFormatId}") + private Long defaultDateFormatId; + + @Value("${dbrepo.defaultTimeFormatId}") + private Long defaultTimeFormatId; + + @Value("${dbrepo.defaultTimestampFormatId}") + private Long defaultTimestampFormatId; + } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseMalformedException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseMalformedException.java index 5a0ff612f8e6fdb8dbf048c439cc2d3940455d25..4bdc362256cc6a8778649a3a22f0aa2ca72761ae 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseMalformedException.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/DatabaseMalformedException.java @@ -3,7 +3,7 @@ package at.tuwien.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; -@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "error.database.invalid") +@ResponseStatus(code = HttpStatus.EXPECTATION_FAILED, reason = "error.database.invalid") public class DatabaseMalformedException extends Exception { public DatabaseMalformedException(String message) { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreCreateException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreCreateException.java index a7bcaf2a15acd080d894026da39e14aacc463e18..27ddb85e2c7eb6746eedf3e6e4e0c137a5a55227 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreCreateException.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreCreateException.java @@ -3,7 +3,7 @@ package at.tuwien.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; -@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "error.store.invalid") +@ResponseStatus(code = HttpStatus.EXPECTATION_FAILED, reason = "error.store.invalid") public class QueryStoreCreateException extends Exception { public QueryStoreCreateException(String message) { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreInsertException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreInsertException.java index 4b10a9891c913e28a9eca7a5d2c96b11b10a67e5..564383c844ee31ad55f383df81e5c1c783dc310f 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreInsertException.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStoreInsertException.java @@ -3,7 +3,7 @@ package at.tuwien.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; -@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "error.store.insert") +@ResponseStatus(code = HttpStatus.EXPECTATION_FAILED, reason = "error.store.insert") public class QueryStoreInsertException extends Exception { public QueryStoreInsertException(String message) { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStorePersistException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStorePersistException.java index 339bdc2f7508a48c4c7b7ca26dc8771d8931f261..5b17442a3a804504755a9c16675b3f30258d0ea2 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStorePersistException.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/QueryStorePersistException.java @@ -3,7 +3,7 @@ package at.tuwien.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; -@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "error.store.persist") +@ResponseStatus(code = HttpStatus.EXPECTATION_FAILED, reason = "error.store.persist") public class QueryStorePersistException extends Exception { public QueryStorePersistException(String message) { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableSchemaException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableSchemaException.java new file mode 100644 index 0000000000000000000000000000000000000000..539e39897e52c3447378aa46112b96d654cdb7d1 --- /dev/null +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/TableSchemaException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.CONFLICT, reason = "error.schema.table") +public class TableSchemaException extends Exception { + + public TableSchemaException(String message) { + super(message); + } + + public TableSchemaException(String message, Throwable thr) { + super(message, thr); + } + + public TableSchemaException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewSchemaException.java b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewSchemaException.java new file mode 100644 index 0000000000000000000000000000000000000000..4761b6e964a1db84de55fbd2a70006c1cc15a54c --- /dev/null +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/exception/ViewSchemaException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.CONFLICT, reason = "error.schema.view") +public class ViewSchemaException extends Exception { + + public ViewSchemaException(String message) { + super(message); + } + + public ViewSchemaException(String message, Throwable thr) { + super(message, thr); + } + + public ViewSchemaException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java b/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java index 47121c458e9f16f48e7409d24d02b2b3af376ef8..c9e5bda2705d1d6822c1fbffe9fae167a2468858 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java @@ -7,6 +7,7 @@ import at.tuwien.service.QueueService; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import io.micrometer.observation.annotation.Observed; +import io.swagger.v3.oas.annotations.Operation; import lombok.extern.log4j.Log4j2; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageListener; @@ -39,6 +40,7 @@ public class DefaultListener implements MessageListener { @Override @Observed(name = "dbrepo_message_receive") + @Operation(summary = "Received AMQP message from Broker Service") public void onMessage(Message message) { final MessageProperties properties = message.getMessageProperties(); final TypeReference<HashMap<String, Object>> typeRef = new TypeReference<>() { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java index 9372f5f6ac32fb3289efdfe74de7a5826a74ea9c..d1b033fe5bf3bb237adc09f6ab541f3260cc11b1 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java @@ -2,6 +2,7 @@ package at.tuwien.mapper; import at.tuwien.api.container.image.ImageDateDto; import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.query.ImportCsvDto; import at.tuwien.api.database.query.QueryDto; @@ -11,11 +12,13 @@ import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; +import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; +import at.tuwien.api.database.table.constraints.unique.UniqueDto; import at.tuwien.api.database.table.internal.PrivilegedTableDto; -import at.tuwien.exception.QueryMalformedException; -import at.tuwien.exception.QueryNotFoundException; -import at.tuwien.exception.TableMalformedException; +import at.tuwien.config.QueryConfig; +import at.tuwien.exception.*; import com.github.dockerjava.zerodep.shaded.org.apache.commons.codec.binary.Hex; +import com.google.common.hash.Hashing; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserManager; import net.sf.jsqlparser.schema.Column; @@ -26,6 +29,7 @@ import org.mapstruct.Named; import java.io.*; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.sql.*; import java.sql.Date; import java.text.Normalizer; @@ -37,7 +41,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -@Mapper(componentModel = "spring") +@Mapper(componentModel = "spring", uses = {MetadataMapper.class}) public interface MariaDbMapper { org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MariaDbMapper.class); @@ -102,6 +106,54 @@ public interface MariaDbMapper { .build(); } + default String databaseTablesSelectRawQuery() { + final String statement = "SELECT DISTINCT t.`TABLE_NAME` FROM information_schema.TABLES t WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'SYSTEM VERSIONED' AND t.`TABLE_NAME` != 'qs_queries'"; + log.trace("mapped select tables statement: {}", statement); + return statement; + } + + default String databaseTableSelectRawQuery() { + final String statement = "SELECT t.`TABLE_NAME`, t.`TABLE_TYPE`, t.`TABLE_ROWS`, t.`AVG_ROW_LENGTH`, t.`DATA_LENGTH`, t.`MAX_DATA_LENGTH`, COALESCE(t.`CREATE_TIME`, NOW()) as `CREATE_TIME`, t.`UPDATE_TIME`, v.`VIEW_DEFINITION` FROM information_schema.TABLES t LEFT JOIN information_schema.VIEWS v ON t.`TABLE_NAME` = v.`TABLE_NAME` WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'SYSTEM VERSIONED' AND t.`TABLE_NAME` != 'qs_queries' AND t.`TABLE_NAME` = ?"; + log.trace("mapped select table statement: {}", statement); + return statement; + } + + default String databaseViewSelectRawQuery() { + final String statement = "SELECT t.`TABLE_NAME`, t.`TABLE_TYPE`, t.`TABLE_ROWS`, t.`AVG_ROW_LENGTH`, t.`DATA_LENGTH`, t.`MAX_DATA_LENGTH`, COALESCE(t.`CREATE_TIME`, NOW()) as `CREATE_TIME`, t.`UPDATE_TIME`, v.`VIEW_DEFINITION` FROM information_schema.TABLES t LEFT JOIN information_schema.VIEWS v ON t.`TABLE_NAME` = v.`TABLE_NAME` WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'VIEW' AND t.`TABLE_NAME` != 'qs_queries' AND t.`TABLE_NAME` = ?"; + log.trace("mapped select view statement: {}", statement); + return statement; + } + + default String columnsCheckConstraintSelectRawQuery() { + final String statement = "SELECT DISTINCT c.`CHECK_CLAUSE` FROM information_schema.COLUMNS k JOIN information_schema.CHECK_CONSTRAINTS c ON k.TABLE_NAME = c.TABLE_NAME WHERE k.TABLE_SCHEMA = ? AND k.TABLE_NAME = ?"; + log.trace("mapped select column constraint statement: {}", statement); + return statement; + } + + default String databaseTableColumnsSelectRawQuery() { + final String statement = "SELECT `ORDINAL_POSITION`, `COLUMN_DEFAULT`, `IS_NULLABLE`, `DATA_TYPE`, `CHARACTER_MAXIMUM_LENGTH`, `NUMERIC_PRECISION`, `NUMERIC_SCALE`, `COLUMN_TYPE`, `COLUMN_KEY`, `COLUMN_NAME`, `COLUMN_COMMENT` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?;"; + log.trace("mapped select columns statement: {}", statement); + return statement; + } + + default String databaseTableConstraintsSelectRawQuery() { + final String statement = "SELECT k.`ORDINAL_POSITION`, c.`CONSTRAINT_TYPE`, k.`CONSTRAINT_NAME`, k.`COLUMN_NAME` FROM information_schema.TABLE_CONSTRAINTS c JOIN information_schema.KEY_COLUMN_USAGE k ON c.`TABLE_NAME` = k.`TABLE_NAME` AND c.`CONSTRAINT_NAME` = k.`CONSTRAINT_NAME`WHERE c.`CONSTRAINT_TYPE` = 'UNIQUE' AND LOWER(k.`COLUMN_NAME`) != 'row_end' AND c.`TABLE_SCHEMA` = ? AND c.`TABLE_NAME` = ? ORDER BY k.`ORDINAL_POSITION` ASC;"; + log.trace("mapped select table constraints statement: {}", statement); + return statement; + } + + default String viewCreateRawQuery(String viewName, String query) { + final String statement = "CREATE VIEW IF NOT EXISTS `" + viewName + "` AS (" + query + ")"; + log.trace("mapped create view statement: {}", statement); + return statement; + } + + default String databaseViewsSelectRawQuery() { + final String statement = "SELECT DISTINCT t.`TABLE_NAME` FROM information_schema.TABLES t WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` = 'VIEW'"; + log.trace("mapped select views statement: {}", statement); + return statement; + } + default String tableCreateDtoToCreateSequenceRawQuery(at.tuwien.api.database.table.internal.TableCreateDto data) { return "CREATE SEQUENCE IF NOT EXISTS `" + tableCreateDtoToSequenceName(data) + "` NOCACHE"; } @@ -174,7 +226,9 @@ public interface MariaDbMapper { /* null expressions */ .append(column.getNullAllowed() != null && column.getNullAllowed() ? " NULL" : " NOT NULL") /* default expressions */ - .append(data.getNeedSequence() && column.getName().equals("id") ? " DEFAULT NEXTVAL(`" + tableCreateDtoToSequenceName(data) + "`)" : ""); + .append(data.getNeedSequence() && column.getName().equals("id") ? " DEFAULT NEXTVAL(`" + tableCreateDtoToSequenceName(data) + "`)" : "") + /* comments */ + .append(!column.getDescription().isEmpty() ? (" COMMENT \"" + column.getDescription() + "\"") : ""); } /* create primary key index */ stringBuilder.append(", PRIMARY KEY (") @@ -228,6 +282,12 @@ public interface MariaDbMapper { .append(ck) .append(")")); } + if (!data.getDescription().isBlank()) { + /* create table comments */ + stringBuilder.append(" COMMENT \"") + .append(data.getDescription()) + .append("\""); + } } stringBuilder.append(") WITH SYSTEM VERSIONING;"); log.trace("mapped create table query: {}", stringBuilder); @@ -419,10 +479,40 @@ public interface MariaDbMapper { return statement.toString(); } - default TableDto resultSetToTable(DatabaseDto database, ResultSet resultSet) throws SQLException, - QueryMalformedException { + /** + * Map the inspected schema to either an existing view/table and append e.g. column or (if not existing) create a new view/table. + * @param database The database. + * @param resultSet The inspected schema. + * @return The database containing the updated view/table. + * @throws SQLException + */ + default ViewDto schemaResultSetToView(DatabaseDto database, ResultSet resultSet) throws SQLException { + return ViewDto.builder() + .name(resultSet.getString(1)) + .internalName(resultSet.getString(1)) + .vdbid(database.getId()) + .database(database) + .isInitialView(false) + .isPublic(database.getIsPublic()) + .query(resultSet.getString(9)) + .queryHash(Hashing.sha256() + .hashString(resultSet.getString(9), StandardCharsets.UTF_8) + .toString()) + .columns(new LinkedList<>()) + .identifiers(new LinkedList<>()) + .creator(database.getOwner()) + .createdBy(database.getOwner().getId()) + .build(); + } + + ViewColumnDto columnDtoToViewColumnDto(ColumnDto data); + + ColumnDto viewColumnDtoToColumnDto(ViewColumnDto data); + + default TableDto schemaResultSetToTable(DatabaseDto database, ResultSet resultSet) throws SQLException, + TableNotFoundException { if (!resultSet.next()) { - throw new QueryMalformedException("Failed to map table"); + throw new TableNotFoundException("Failed to find table in the information schema"); } final TableDto table = TableDto.builder() .name(resultSet.getString(1)) @@ -434,7 +524,9 @@ public interface MariaDbMapper { .maxDataLength(resultSet.getLong(6)) .tdbid(database.getId()) .queueName("dbrepo") - .routingKey("dbrepo." + database.getInternalName() + "." + resultSet.getString(1)) + .routingKey("dbrepo") + .columns(new LinkedList<>()) + .identifiers(new LinkedList<>()) .creator(database.getOwner()) .createdBy(database.getOwner().getId()) .owner(database.getOwner()) @@ -444,6 +536,7 @@ public interface MariaDbMapper { .uniques(new LinkedList<>()) .checks(new LinkedHashSet<>()) .build()) + .isPublic(database.getIsPublic()) .build(); if (resultSet.getString(7) != null && !resultSet.getString(7).isEmpty()) { table.setCreated(Timestamp.valueOf(resultSet.getString(7)) @@ -452,44 +545,123 @@ public interface MariaDbMapper { return table; } - default TableDto resultSetToTable(ResultSet resultSet, TableDto table, ImageDateDto defaultDateFormat, - ImageDateDto defaultTimestampFormat) throws SQLException { - /* columns */ - final List<ColumnDto> columns = new LinkedList<>(); - while (resultSet.next()) { - /* constraints */ - if (resultSet.getString(9) != null && resultSet.getString(9).equals("PRI")) { - table.getConstraints().getPrimaryKey().add(resultSet.getString(10)); - } - final ColumnDto column = ColumnDto.builder() - .ordinalPosition(resultSet.getInt(1) - 1) /* start at zero */ - .autoGenerated(resultSet.getString(2) != null && resultSet.getString(2).startsWith("nextval")) - .isNullAllowed(resultSet.getString(3).equals("YES")) - .columnType(ColumnTypeDto.valueOf(resultSet.getString(4).toUpperCase())) - .d(resultSet.getString(7) != null ? resultSet.getLong(7) : null) - .name(resultSet.getString(10)) - .internalName(resultSet.getString(10)) - .build(); - /* fix boolean and set size for others */ - if (resultSet.getString(8).equalsIgnoreCase("tinyint(1)")) { - column.setColumnType(ColumnTypeDto.BOOL); - } else if (resultSet.getString(5) != null) { - column.setSize(resultSet.getLong(5)); - } else if (resultSet.getString(6) != null) { - column.setSize(resultSet.getLong(6)); - } - if (column.getColumnType().equals(ColumnTypeDto.TIMESTAMP) || column.getColumnType().equals(ColumnTypeDto.DATETIME)) { - column.setDateFormat(defaultTimestampFormat); - } else if (column.getColumnType().equals(ColumnTypeDto.DATE)) { - column.setDateFormat(defaultDateFormat); + default TableDto resultSetToConstraint(ResultSet resultSet, TableDto table) throws SQLException { + final String type = resultSet.getString(2); + final String name = resultSet.getString(3); + final String columnName = resultSet.getString(4); + final Optional<ColumnDto> optional = table.getColumns().stream() + .filter(c -> c.getInternalName().equals(columnName)) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find table column: {}", columnName); + throw new IllegalArgumentException("Failed to find table column"); + } + final ColumnDto column = optional.get(); + if (type.equals("UNIQUE")) { + final Optional<UniqueDto> optional2 = table.getConstraints().getUniques().stream().filter(u -> u.getName().equals(name)).findFirst(); + if (optional2.isPresent()) { + optional2.get() + .getColumns() + .add(column); + return table; } - log.trace("mapped result set to column {}", column); - columns.add(column); + table.getConstraints() + .getUniques() + .add(UniqueDto.builder() + .name(name) + .columns(new LinkedList<>(List.of(column))) + .build()); + return table; + } + return table; + } + + TableBriefDto tableDtoToTableBriefDto(TableDto data); + + default TableDto resultSetToTable(ResultSet resultSet, TableDto table, QueryConfig queryConfig) throws SQLException { + final ColumnDto column = ColumnDto.builder() + .ordinalPosition(resultSet.getInt(1) - 1) /* start at zero */ + .autoGenerated(resultSet.getString(2) != null && resultSet.getString(2).startsWith("nextval")) + .isNullAllowed(resultSet.getString(3).equals("YES")) + .columnType(ColumnTypeDto.valueOf(resultSet.getString(4).toUpperCase())) + .d(resultSet.getString(7) != null ? resultSet.getLong(7) : null) + .name(resultSet.getString(10)) + .internalName(resultSet.getString(10)) + .table(table) + .tableId(table.getId()) + .databaseId(table.getTdbid()) + .description(resultSet.getString(11)) + .build(); + /* constraints */ + if (resultSet.getString(9) != null && resultSet.getString(9).equals("PRI")) { + table.getConstraints().getPrimaryKey().add(PrimaryKeyDto.builder() + .table(tableDtoToTableBriefDto(table)) + .column(column) + .build()); + } + /* fix boolean and set size for others */ + if (resultSet.getString(8).equalsIgnoreCase("tinyint(1)")) { + column.setColumnType(ColumnTypeDto.BOOL); + } else if (resultSet.getString(5) != null) { + column.setSize(resultSet.getLong(5)); + } else if (resultSet.getString(6) != null) { + column.setSize(resultSet.getLong(6)); + } + if (column.getColumnType().equals(ColumnTypeDto.TIMESTAMP) || column.getColumnType().equals(ColumnTypeDto.DATETIME)) { + column.setDateFormat(ImageDateDto.builder() + .id(queryConfig.getDefaultTimestampFormatId()) + .build()); + } else if (column.getColumnType().equals(ColumnTypeDto.DATE)) { + column.setDateFormat(ImageDateDto.builder() + .id(queryConfig.getDefaultDateFormatId()) + .build()); + } else if (column.getColumnType().equals(ColumnTypeDto.TIME)) { + column.setDateFormat(ImageDateDto.builder() + .id(queryConfig.getDefaultTimeFormatId()) + .build()); } - table.setColumns(columns); + table.getColumns() + .add(column); return table; } + default ViewDto resultSetToTable(ResultSet resultSet, ViewDto view, QueryConfig queryConfig) throws SQLException { + final ViewColumnDto column = ViewColumnDto.builder() + .ordinalPosition(resultSet.getInt(1) - 1) /* start at zero */ + .autoGenerated(resultSet.getString(2) != null && resultSet.getString(2).startsWith("nextval")) + .isNullAllowed(resultSet.getString(3).equals("YES")) + .columnType(ColumnTypeDto.valueOf(resultSet.getString(4).toUpperCase())) + .d(resultSet.getString(7) != null ? resultSet.getLong(7) : null) + .name(resultSet.getString(10)) + .internalName(resultSet.getString(10)) + .databaseId(view.getDatabase().getId()) + .build(); + /* fix boolean and set size for others */ + if (resultSet.getString(8).equalsIgnoreCase("tinyint(1)")) { + column.setColumnType(ColumnTypeDto.BOOL); + } else if (resultSet.getString(5) != null) { + column.setSize(resultSet.getLong(5)); + } else if (resultSet.getString(6) != null) { + column.setSize(resultSet.getLong(6)); + } + if (column.getColumnType().equals(ColumnTypeDto.TIMESTAMP) || column.getColumnType().equals(ColumnTypeDto.DATETIME)) { + column.setDateFormat(ImageDateDto.builder() + .id(queryConfig.getDefaultTimestampFormatId()) + .build()); + } else if (column.getColumnType().equals(ColumnTypeDto.DATE)) { + column.setDateFormat(ImageDateDto.builder() + .id(queryConfig.getDefaultDateFormatId()) + .build()); + } else if (column.getColumnType().equals(ColumnTypeDto.TIME)) { + column.setDateFormat(ImageDateDto.builder() + .id(queryConfig.getDefaultTimeFormatId()) + .build()); + } + view.getColumns() + .add(column); + return view; + } + default List<TableHistoryDto> resultSetToTableHistory(ResultSet resultSet) throws SQLException { /* columns */ final List<TableHistoryDto> history = new LinkedList<>(); @@ -672,7 +844,7 @@ public interface MariaDbMapper { default void columnToDateSet(ImportCsvDto data, ColumnDto column, StringBuilder set) { log.trace("mapping column to date set"); - set.append(set.length() != 0 ? ", " : "") + set.append(!set.isEmpty() ? ", " : "") .append("`") .append(column.getInternalName()) .append("` = STR_TO_DATE("); @@ -702,7 +874,7 @@ public interface MariaDbMapper { default void columnToBoolSet(ImportCsvDto data, ColumnDto column, StringBuilder set) { log.trace("mapping column to bool set, data={}, column={}, set=(generated)", data, column); - set.append(set.length() != 0 ? ", " : "") + set.append(!set.isEmpty() ? ", " : "") .append("`") .append(column.getInternalName()) .append("` = "); @@ -1021,22 +1193,28 @@ public interface MariaDbMapper { throw new IllegalArgumentException("Column type not known"); } + /** + * Parse columns from a SQL statement of a known database. + * @param database The database. + * @param query The SQL statement. + * @return The list of columns. + * @throws JSQLParserException The table/view or column was not found in the database. + */ default List<ColumnDto> parseColumns(DatabaseDto database, String query) throws JSQLParserException { final List<ColumnDto> columns = new ArrayList<>(); final CCJSqlParserManager parserRealSql = new CCJSqlParserManager(); final net.sf.jsqlparser.statement.Statement statement = parserRealSql.parse(new StringReader(query)); - log.debug("parse columns from query: {}", query); + log.trace("parse columns from query: {}", query); /* bi-directional mapping */ database.getTables() .forEach(table -> table.getColumns() .forEach(column -> column.setTable(table))); /* check */ - if (!(statement instanceof Select)) { + if (!(statement instanceof Select selectStatement)) { log.error("Query attempts to update the dataset, not a SELECT statement"); throw new JSQLParserException("Query attempts to update the dataset"); } /* start parsing */ - final Select selectStatement = (Select) statement; final PlainSelect ps = (PlainSelect) selectStatement.getSelectBody(); final List<SelectItem> clauses = ps.getSelectItems(); log.trace("columns referenced in the from-clause: {}", clauses); @@ -1053,7 +1231,8 @@ public interface MariaDbMapper { final List<ColumnDto> allColumns = Stream.of(database.getViews() .stream() .map(ViewDto::getColumns) - .flatMap(List::stream), + .flatMap(List::stream) + .map(this::viewColumnDtoToColumnDto), database.getTables() .stream() .map(TableDto::getColumns) @@ -1061,8 +1240,6 @@ public interface MariaDbMapper { .flatMap(i -> i) .toList(); log.trace("columns referenced in the from-clause and join-clause(s): {}", clauses); - /* Checking if all tables or views exist */ - log.trace("table/view/join referenced in the statement: {}", fromItems.stream().map(this::fromItemToFromItems).flatMap(List::stream).collect(Collectors.toList())); /* Checking if all columns exist */ for (SelectItem clause : clauses) { final SelectExpressionItem item = (SelectExpressionItem) clause; @@ -1099,6 +1276,9 @@ public interface MariaDbMapper { if (item.getAlias() != null) { resultColumn.setAlias(item.getAlias().getName().replace("`", "")); } + resultColumn.setDatabaseId(database.getId()); + resultColumn.setTable(resultColumn.getTable()); + resultColumn.setTableId(resultColumn.getTable().getId()); log.trace("found column with internal name {} and alias {}", resultColumn.getInternalName(), resultColumn.getAlias()); columns.add(resultColumn); } @@ -1142,11 +1322,11 @@ public interface MariaDbMapper { return found; } - default List<FromItem> fromItemToFromItems(FromItem data) { + default List<FromItem> fromItemToFromItems(FromItem data) throws JSQLParserException { return fromItemToFromItems(data, 0); } - default List<FromItem> fromItemToFromItems(FromItem data, Integer level) { + default List<FromItem> fromItemToFromItems(FromItem data, Integer level) throws JSQLParserException { final List<FromItem> fromItems = new LinkedList<>(); if (data instanceof net.sf.jsqlparser.schema.Table table) { fromItems.add(data); @@ -1156,9 +1336,19 @@ public interface MariaDbMapper { if (data instanceof SubJoin subJoin) { log.trace("from-item is of type sub-join: level ~> {}", level); for (Join join : subJoin.getJoinList()) { - fromItems.addAll(fromItemToFromItems(join.getRightItem(), level + 1)); + final List<FromItem> tmp = fromItemToFromItems(join.getRightItem(), level + 1); + if (tmp == null) { + log.error("Failed to find right sub-join table: {}", join.getRightItem()); + throw new JSQLParserException("Failed to find right sub-join table"); + } + fromItems.addAll(tmp); + } + final List<FromItem> tmp = fromItemToFromItems(subJoin.getLeft(), level + 1); + if (tmp == null) { + log.error("Failed to find left sub-join table: {}", subJoin.getLeft()); + throw new JSQLParserException("Failed to find left sub-join table"); } - fromItems.addAll(fromItemToFromItems(((SubJoin) data).getLeft(), level + 1)); + fromItems.addAll(tmp); return fromItems; } log.warn("unknown from-item {}", data); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java index c4de9ec6df53c1cf275d4bda0a8c53adfceaf755..67633ba1757897a4a0f5619670e7990d9cd1559a 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -4,10 +4,13 @@ import at.tuwien.api.container.ContainerDto; import at.tuwien.api.container.image.ImageDto; import at.tuwien.api.container.internal.PrivilegedContainerDto; import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.database.internal.PrivilegedViewDto; +import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.internal.PrivilegedTableDto; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -24,6 +27,13 @@ public interface MetadataMapper { TableDto privilegedTableDtoToTableDto(PrivilegedTableDto data); + ColumnDto viewColumnDtoToColumnDto(ViewColumnDto data); + + ViewColumnDto columnDtoToViewColumnDto(ColumnDto data); + + /* keep */ + TableBriefDto tableDtoToTableBriefDto(TableDto data); + @Mappings({ @Mapping(target = "database", expression = "java(PrivilegedDatabaseDto.builder().container(PrivilegedContainerDto.builder().image(new ImageDto()).build()).build())") }) diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java index 92c46b64ce0da763308d6d329b26105c01f903ee..6c99910e67067502070d307fc55cb22b905b377e 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java @@ -1,10 +1,11 @@ package at.tuwien.service; import at.tuwien.api.container.internal.PrivilegedContainerDto; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.internal.CreateDatabaseDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; -import at.tuwien.exception.DatabaseMalformedException; +import at.tuwien.exception.*; import java.sql.SQLException; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SchemaService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SchemaService.java index eb5428b2613961b56eee6be02329136c99f5c8db..2319d16b3974feaa206ab99235c3cc43b92579c8 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SchemaService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SchemaService.java @@ -1,13 +1,16 @@ package at.tuwien.service; +import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.database.table.TableDto; -import at.tuwien.exception.QueryMalformedException; +import at.tuwien.exception.*; import java.sql.SQLException; public interface SchemaService { - TableDto obtainTableMetadata(PrivilegedDatabaseDto database, String tableName) throws SQLException, - QueryMalformedException; + TableDto inspectTable(PrivilegedDatabaseDto database, String tableName) throws SQLException, + QueryMalformedException, TableNotFoundException; + + ViewDto inspectView(PrivilegedDatabaseDto database, String viewName) throws SQLException, ViewMalformedException, ViewNotFoundException, ViewSchemaException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java index 66bdd3fb1d54e6a9ebb5aa561a73c5faf3592dd3..b8d2f393902545b1931a6927bc318cb606be92f6 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java @@ -14,8 +14,13 @@ import java.time.Instant; import java.util.List; public interface TableService { - void createTable(PrivilegedDatabaseDto database, TableCreateDto data) throws SQLException, - TableMalformedException, TableExistsException; + + List<TableDto> getSchemas(PrivilegedDatabaseDto database) throws SQLException, TableNotFoundException, QueryMalformedException, DatabaseMalformedException; + + TableDto find(PrivilegedDatabaseDto database, String tableName) throws TableNotFoundException, SQLException, QueryMalformedException; + + TableDto createTable(PrivilegedDatabaseDto database, TableCreateDto data) throws SQLException, + TableMalformedException, TableExistsException, TableNotFoundException, QueryMalformedException; void delete(PrivilegedTableDto table) throws SQLException, QueryMalformedException; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java index e8ac39f9012c3e849b3a64cc952714ed2cd5ae54..4dcd96ed535971d7b32507f998535544b0a27317 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java @@ -10,9 +10,23 @@ import at.tuwien.exception.*; import java.sql.SQLException; import java.time.Instant; +import java.util.List; public interface ViewService { + /** + * + * @param database + * @return The list of view metadata. + * @throws SQLException + * @throws DatabaseMalformedException + * @throws ViewMalformedException + * @throws ViewNotFoundException + * @throws ViewSchemaException + */ + List<ViewDto> getSchemas(PrivilegedDatabaseDto database) throws SQLException, DatabaseMalformedException, + ViewMalformedException, ViewNotFoundException, ViewSchemaException; + /** * Creates a view in the given data database. * @@ -21,7 +35,7 @@ public interface ViewService { * @throws SQLException The connection to the data database was unsuccessful. * @throws ViewMalformedException The query is malformed and was rejected by the data database. */ - void create(PrivilegedDatabaseDto database, ViewCreateDto data) throws SQLException, + ViewDto create(PrivilegedDatabaseDto database, ViewCreateDto data) throws SQLException, ViewMalformedException; /** diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java index 632015d025fe884af31bda725a7f44bd8c95cd68..7bd233371e5b42ea8085c58ca5cae06b03af4aa7 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java @@ -1,19 +1,27 @@ package at.tuwien.service.impl; import at.tuwien.api.container.internal.PrivilegedContainerDto; +import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.CreateDatabaseDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; +import at.tuwien.api.database.table.TableDto; import at.tuwien.api.user.UserDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.config.RabbitConfig; -import at.tuwien.exception.DatabaseMalformedException; +import at.tuwien.exception.*; +import at.tuwien.mapper.MariaDbMapper; +import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.DatabaseService; +import at.tuwien.service.SchemaService; import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; @Log4j2 diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java index 83222dfe44f955f7be689aae3e6b4c8a9b51e799..6a583b274affc20d6871e7358e842d77a88f2c4c 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java @@ -42,7 +42,6 @@ public abstract class HibernateConnector { .append("?currentSchema=") .append(databaseName); } - log.debug("connecting via jdbc, url={}", stringBuilder); return stringBuilder.toString(); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/QueueServiceRabbitMqImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/QueueServiceRabbitMqImpl.java index fe733a22aa84af46b686814ffac548595f359099..fd7966e0bebe65df727b903452d792ac59625a77 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/QueueServiceRabbitMqImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/QueueServiceRabbitMqImpl.java @@ -9,7 +9,6 @@ import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.sql.Connection; import java.sql.PreparedStatement; @@ -31,7 +30,6 @@ public class QueueServiceRabbitMqImpl extends HibernateConnector implements Queu } @Override - @Transactional(readOnly = true) public void insert(PrivilegedTableDto table, Map<String, Object> data) throws SQLException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase()); final Connection connection = dataSource.getConnection(); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java index 9cd87fafc890331facd039f75f28248a8d430588..c2c53c7830730ce548ea9d16afb66ef4f9bfba22 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SchemaServiceMariaDbImpl.java @@ -1,8 +1,17 @@ package at.tuwien.service.impl; +import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewColumnDto; +import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.database.table.TableDto; -import at.tuwien.exception.QueryMalformedException; +import at.tuwien.api.database.table.columns.ColumnDto; +import at.tuwien.api.database.table.constraints.unique.UniqueDto; +import at.tuwien.config.QueryConfig; +import at.tuwien.exception.TableNotFoundException; +import at.tuwien.exception.ViewMalformedException; +import at.tuwien.exception.ViewNotFoundException; +import at.tuwien.exception.ViewSchemaException; import at.tuwien.mapper.MariaDbMapper; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.SchemaService; @@ -13,45 +22,144 @@ import org.springframework.stereotype.Service; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; @Log4j2 @Service public class SchemaServiceMariaDbImpl extends HibernateConnector implements SchemaService { + private final QueryConfig queryConfig; private final MariaDbMapper mariaDbMapper; private final MetadataMapper metadataMapper; @Autowired - public SchemaServiceMariaDbImpl(MariaDbMapper mariaDbMapper, MetadataMapper metadataMapper) { + public SchemaServiceMariaDbImpl(QueryConfig queryConfig, MariaDbMapper mariaDbMapper, + MetadataMapper metadataMapper) { + this.queryConfig = queryConfig; this.mariaDbMapper = mariaDbMapper; this.metadataMapper = metadataMapper; } @Override - public TableDto obtainTableMetadata(PrivilegedDatabaseDto database, String tableName) throws SQLException, - QueryMalformedException { + public TableDto inspectTable(PrivilegedDatabaseDto database, String tableName) throws SQLException, + TableNotFoundException { + log.trace("inspecting table: {}.{}", database.getInternalName(), tableName); final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); - TableDto table; try { - /* obtain basic table metadata */ - connection.commit(); - final PreparedStatement basicMetadataStatement = connection.prepareStatement("SELECT t.`TABLE_NAME`, t.`TABLE_TYPE`, t.`TABLE_ROWS`, t.`AVG_ROW_LENGTH`, t.`DATA_LENGTH`, t.`MAX_DATA_LENGTH`, COALESCE(t.`CREATE_TIME`, NOW()) as `CREATE_TIME`, t.`UPDATE_TIME`, v.`VIEW_DEFINITION` FROM information_schema.TABLES t LEFT JOIN information_schema.VIEWS v ON t.`TABLE_NAME` = v.`TABLE_NAME` WHERE t.`TABLE_SCHEMA` = ? AND t.`TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED', 'VIEW') AND t.`TABLE_NAME` = ?"); - basicMetadataStatement.setString(1, database.getInternalName()); - basicMetadataStatement.setString(2, tableName); - final TableDto tmp = mariaDbMapper.resultSetToTable(metadataMapper.privilegedDatabaseDtoToDatabaseDto(database), basicMetadataStatement.getResultSet()); - /* obtain table constraints metadata */ - final PreparedStatement constraintMetadataStatement = connection.prepareStatement("SELECT `ORDINAL_POSITION`, `COLUMN_DEFAULT`, `IS_NULLABLE`, `DATA_TYPE`, `CHARACTER_MAXIMUM_LENGTH`, `NUMERIC_PRECISION`, `NUMERIC_SCALE`, `COLUMN_TYPE`, `COLUMN_KEY`, `COLUMN_NAME` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?;"); - constraintMetadataStatement.setString(1, database.getInternalName()); - constraintMetadataStatement.setString(2, tableName); - table = mariaDbMapper.resultSetToTable(constraintMetadataStatement.getResultSet(), tmp, - database.getContainer().getDefaultDateFormat(), database.getContainer().getDefaultTimestampFormat()); + /* obtain only table metadata */ + final PreparedStatement statement1 = connection.prepareStatement(mariaDbMapper.databaseTableSelectRawQuery()); + statement1.setString(1, database.getInternalName()); + statement1.setString(2, tableName); + log.trace("1={}, 2={}", database.getInternalName(), tableName); + TableDto table = mariaDbMapper.schemaResultSetToTable(metadataMapper.privilegedDatabaseDtoToDatabaseDto(database), statement1.executeQuery()); + /* obtain columns metadata */ + final PreparedStatement statement2 = connection.prepareStatement(mariaDbMapper.databaseTableColumnsSelectRawQuery()); + statement2.setString(1, database.getInternalName()); + statement2.setString(2, tableName); + log.trace("1={}, 2={}", database.getInternalName(), tableName); + final ResultSet resultSet2 = statement2.executeQuery(); + while (resultSet2.next()) { + table = mariaDbMapper.resultSetToTable(resultSet2, table, queryConfig); + } + /* obtain check constraints metadata */ + final PreparedStatement statement3 = connection.prepareStatement(mariaDbMapper.columnsCheckConstraintSelectRawQuery()); + statement3.setString(1, database.getInternalName()); + statement3.setString(2, tableName); + log.trace("1={}, 2={}", database.getInternalName(), tableName); + final ResultSet resultSet3 = statement3.executeQuery(); + while (resultSet3.next()) { + final String clause = resultSet3.getString(1); + table.getConstraints() + .getChecks() + .add(clause); + log.trace("found check clause: {}", clause); + } + /* obtain column constraints metadata */ + final PreparedStatement statement4 = connection.prepareStatement(mariaDbMapper.databaseTableConstraintsSelectRawQuery()); + statement4.setString(1, database.getInternalName()); + statement4.setString(2, tableName); + log.trace("1={}, 2={}", database.getInternalName(), tableName); + final ResultSet resultSet4 = statement4.executeQuery(); + while (resultSet4.next()) { + table = mariaDbMapper.resultSetToConstraint(resultSet4, table); + for (UniqueDto uk : table.getConstraints().getUniques()) { + uk.setTable(metadataMapper.tableDtoToTableBriefDto(table)); + final TableDto tmpTable = table; + uk.getColumns() + .forEach(column -> { + column.setTable(tmpTable); + column.setTableId(tmpTable.getId()); + column.setDatabaseId(database.getId()); + column.setIsPublic(database.getIsPublic()); + }); + } + } + table.setTdbid(database.getId()); + table.setCreator(database.getCreator()); + table.setCreatedBy(database.getCreator().getId()); + final TableDto tmpTable = table; + tmpTable.getColumns() + .forEach(column -> { + column.setTable(tmpTable); + column.setTableId(tmpTable.getId()); + column.setDatabaseId(database.getId()); + }); + log.debug("obtained metadata for table {}.{}", database.getInternalName(), tableName); + return tmpTable; + } finally { + dataSource.close(); + } + } + + @Override + public ViewDto inspectView(PrivilegedDatabaseDto privilegedDatabase, String viewName) throws SQLException, + ViewNotFoundException { + final ComboPooledDataSource dataSource = getPrivilegedDataSource(privilegedDatabase); + final Connection connection = dataSource.getConnection(); + final DatabaseDto database = metadataMapper.privilegedDatabaseDtoToDatabaseDto(privilegedDatabase); + try { + /* obtain only view metadata */ + final PreparedStatement statement1 = connection.prepareStatement(mariaDbMapper.databaseViewSelectRawQuery()); + statement1.setString(1, database.getInternalName()); + statement1.setString(2, viewName); + log.trace("1={}, 2={}", database.getInternalName(), viewName); + final ResultSet resultSet1 = statement1.executeQuery(); + if (!resultSet1.next()) { + throw new ViewNotFoundException("Failed to find view in the information schema"); + } + ViewDto view = mariaDbMapper.schemaResultSetToView(metadataMapper.privilegedDatabaseDtoToDatabaseDto(privilegedDatabase), resultSet1); + view.setDatabase(database); + view.setVdbid(database.getId()); + view.setCreator(database.getCreator()); + view.setCreatedBy(database.getCreator().getId()); + /* obtain view columns */ + final PreparedStatement statement2 = connection.prepareStatement(mariaDbMapper.databaseTableColumnsSelectRawQuery()); + statement2.setString(1, database.getInternalName()); + statement2.setString(2, viewName); + log.trace("1={}, 2={}", database.getInternalName(), viewName); + final ResultSet resultSet2 = statement2.executeQuery(); + TableDto tmp = TableDto.builder() + .columns(new LinkedList<>()) + .build(); + while (resultSet2.next()) { + tmp = mariaDbMapper.resultSetToTable(resultSet2, tmp, queryConfig); + } + view.setColumns(tmp.getColumns() + .stream() + .map(metadataMapper::columnDtoToViewColumnDto) + .toList()); + view.getColumns() + .forEach(column -> column.setDatabaseId(database.getId())); + log.debug("obtained metadata for view {}.{}", database.getInternalName(), viewName); + return view; } finally { dataSource.close(); } - log.info("Obtained table metadata for table {}{}", database.getInternalName(), tableName); - return table; } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java index 2e0952d0f828a7d45c6821565383035167e08ddb..92e369e0afd2d0d24509ab3691cc32d40702de55 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java @@ -13,6 +13,7 @@ import at.tuwien.config.S3Config; import at.tuwien.exception.*; import at.tuwien.gateway.DataDatabaseSidecarGateway; import at.tuwien.mapper.MariaDbMapper; +import at.tuwien.service.SchemaService; import at.tuwien.service.StorageService; import at.tuwien.service.TableService; import com.mchange.v2.c3p0.ComboPooledDataSource; @@ -31,21 +32,62 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table private final S3Config s3Config; private final MariaDbMapper mariaDbMapper; + private final SchemaService schemaService; private final StorageService storageService; private final DataDatabaseSidecarGateway dataDatabaseSidecarGateway; @Autowired - public TableServiceMariaDbImpl(S3Config s3Config, MariaDbMapper mariaDbMapper, StorageService storageService, + public TableServiceMariaDbImpl(S3Config s3Config, MariaDbMapper mariaDbMapper, SchemaService schemaService, + StorageService storageService, DataDatabaseSidecarGateway dataDatabaseSidecarGateway) { this.s3Config = s3Config; this.mariaDbMapper = mariaDbMapper; + this.schemaService = schemaService; this.storageService = storageService; this.dataDatabaseSidecarGateway = dataDatabaseSidecarGateway; } @Override - public void createTable(PrivilegedDatabaseDto database, TableCreateDto data) throws SQLException, - TableMalformedException, TableExistsException { + public List<TableDto> getSchemas(PrivilegedDatabaseDto database) throws SQLException, TableNotFoundException, + QueryMalformedException, DatabaseMalformedException { + final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); + final Connection connection = dataSource.getConnection(); + final List<TableDto> tables = new LinkedList<>(); + try { + /* inspect tables before views */ + final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.databaseTablesSelectRawQuery()); + statement.setString(1, database.getInternalName()); + final ResultSet resultSet1 = statement.executeQuery(); + while (resultSet1.next()) { + final String tableName = resultSet1.getString(1); + if (database.getTables().stream().anyMatch(t -> t.getInternalName().equals(tableName))) { + log.trace("view {}.{} already known to metadata database, skip.", database.getInternalName(), tableName); + continue; + } + final TableDto table = schemaService.inspectTable(database, tableName); + if (database.getTables().stream().noneMatch(t -> t.getInternalName().equals(table.getInternalName()))) { + tables.add(table); + } + } + } catch (SQLException e) { + log.error("Failed to get table schemas: {}", e.getMessage()); + throw new DatabaseMalformedException("Failed to get table schemas: " + e.getMessage(), e); + } finally { + dataSource.close(); + } + log.info("Found {} table schema(s)", tables.size()); + return tables; + } + + @Override + public TableDto find(PrivilegedDatabaseDto database, String tableName) throws TableNotFoundException, SQLException, + QueryMalformedException { + return schemaService.inspectTable(database, tableName); + } + + @Override + public TableDto createTable(PrivilegedDatabaseDto database, TableCreateDto data) throws SQLException, + TableMalformedException, TableExistsException, TableNotFoundException, QueryMalformedException { final String tableName = mariaDbMapper.nameToInternalName(data.getName()); final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); @@ -72,6 +114,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table dataSource.close(); } log.info("Created table with name {}", tableName); + return find(database, tableName); } @Override diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java index 1c245e9e54604472f1543ed8f4c51f96ac71933e..b28e2a1dc4f0e4530b8a4a9235b7cdc4819ee0fe 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java @@ -6,10 +6,14 @@ import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.PrivilegedDatabaseDto; import at.tuwien.api.database.internal.PrivilegedViewDto; import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.api.database.table.columns.ColumnDto; +import at.tuwien.config.QueryConfig; import at.tuwien.config.S3Config; import at.tuwien.exception.*; import at.tuwien.gateway.DataDatabaseSidecarGateway; import at.tuwien.mapper.MariaDbMapper; +import at.tuwien.mapper.MetadataMapper; +import at.tuwien.service.SchemaService; import at.tuwien.service.StorageService; import at.tuwien.service.ViewService; import com.mchange.v2.c3p0.ComboPooledDataSource; @@ -17,40 +21,103 @@ import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.time.Instant; +import java.util.LinkedList; +import java.util.List; @Log4j2 @Service public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewService { private final S3Config s3Config; + private final QueryConfig queryConfig; private final MariaDbMapper mariaDbMapper; + private final SchemaService schemaService; private final StorageService storageService; + private final MetadataMapper metadataMapper; private final DataDatabaseSidecarGateway dataDatabaseSidecarGateway; @Autowired - public ViewServiceMariaDbImpl(S3Config s3Config, MariaDbMapper mariaDbMapper, StorageService storageService, + public ViewServiceMariaDbImpl(S3Config s3Config, QueryConfig queryConfig, MariaDbMapper mariaDbMapper, + SchemaService schemaService, StorageService storageService, + MetadataMapper metadataMapper, DataDatabaseSidecarGateway dataDatabaseSidecarGateway) { this.s3Config = s3Config; + this.queryConfig = queryConfig; this.mariaDbMapper = mariaDbMapper; + this.schemaService = schemaService; this.storageService = storageService; + this.metadataMapper = metadataMapper; this.dataDatabaseSidecarGateway = dataDatabaseSidecarGateway; } @Override - public void create(PrivilegedDatabaseDto database, ViewCreateDto data) throws SQLException, + public List<ViewDto> getSchemas(PrivilegedDatabaseDto database) throws SQLException, DatabaseMalformedException, + ViewMalformedException, ViewNotFoundException, ViewSchemaException { + final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); + final Connection connection = dataSource.getConnection(); + final List<ViewDto> views = new LinkedList<>(); + try { + /* inspect tables before views */ + final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.databaseViewsSelectRawQuery()); + statement.setString(1, database.getInternalName()); + final ResultSet resultSet1 = statement.executeQuery(); + while (resultSet1.next()) { + final String viewName = resultSet1.getString(1); + if (database.getViews().stream().anyMatch(v -> v.getInternalName().equals(viewName))) { + log.trace("view {}.{} already known to metadata database, skip.", database.getInternalName(), viewName); + continue; + } + final ViewDto view; + view = schemaService.inspectView(database, viewName); + if (database.getTables().stream().noneMatch(t -> t.getInternalName().equals(view.getInternalName()))) { + views.add(view); + } + } + } catch (SQLException e) { + log.error("Failed to get view schemas: {}", e.getMessage()); + throw new DatabaseMalformedException("Failed to get view schemas: " + e.getMessage(), e); + } finally { + dataSource.close(); + } + log.info("Found {} view schema(s)", views.size()); + return views; + } + + @Override + public ViewDto create(PrivilegedDatabaseDto database, ViewCreateDto data) throws SQLException, ViewMalformedException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(database); final Connection connection = dataSource.getConnection(); + ViewDto view = ViewDto.builder() + .name(data.getName()) + .internalName(data.getName()) + .isPublic(database.getIsPublic()) + .creator(database.getOwner()) + .createdBy(database.getOwner().getId()) + .identifiers(new LinkedList<>()) + .isInitialView(false) + .vdbid(database.getId()) + .database(metadataMapper.privilegedDatabaseDtoToDatabaseDto(database)) + .columns(new LinkedList<>()) + .build(); try { /* create view if not exists */ - connection.prepareStatement("CREATE VIEW IF NOT EXISTS `" + data.getName() + "` AS (" + data.getQuery() + ")") + connection.prepareStatement(mariaDbMapper.viewCreateRawQuery(data.getName(), data.getQuery())) .execute(); + /* select view columns */ + final PreparedStatement statement2 = connection.prepareStatement(mariaDbMapper.databaseTableColumnsSelectRawQuery()); + statement2.setString(1, database.getInternalName()); + statement2.setString(2, data.getName()); + final ResultSet resultSet2 = statement2.executeQuery(); + while (resultSet2.next()) { + view = mariaDbMapper.resultSetToTable(resultSet2, view, queryConfig); + } connection.commit(); } catch (SQLException e) { connection.rollback(); @@ -59,7 +126,8 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe } finally { dataSource.close(); } - log.info("Created view with name {}", data.getName()); + log.info("Created view with name {}", view.getName()); + return view; } @Override @@ -70,11 +138,15 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe final QueryResultDto queryResult; try { /* find table data */ + final List<ColumnDto> mappedColumns = view.getColumns() + .stream() + .map(metadataMapper::viewColumnDtoToColumnDto) + .toList(); final ResultSet resultSet = connection.prepareStatement( - mariaDbMapper.selectDatasetRawQuery(view.getDatabase().getInternalName(), view.getInternalName(), - view.getColumns(), timestamp, size, page)) + mariaDbMapper.selectDatasetRawQuery(view.getDatabase().getInternalName(), + view.getInternalName(), mappedColumns, timestamp, size, page)) .executeQuery(); - queryResult = mariaDbMapper.resultListToQueryResultDto(view.getColumns(), resultSet); + queryResult = mariaDbMapper.resultListToQueryResultDto(mappedColumns, resultSet); queryResult.setId(view.getId()); connection.commit(); } catch (SQLException e) { @@ -108,7 +180,6 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe @Override - @Transactional public Long count(PrivilegedViewDto view, Instant timestamp) throws SQLException, QueryMalformedException { final ComboPooledDataSource dataSource = getPrivilegedDataSource(view.getDatabase()); @@ -142,8 +213,12 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe final Connection connection = dataSource.getConnection(); try { /* export to data database sidecar */ + final List<ColumnDto> columns = view.getColumns() + .stream() + .map(metadataMapper::viewColumnDtoToColumnDto) + .toList(); connection.prepareStatement(mariaDbMapper.tableOrViewToRawExportQuery(database.getInternalName(), - view.getInternalName(), view.getColumns(), timestamp, filePath)) + view.getInternalName(), columns, timestamp, filePath)) .executeUpdate(); connection.commit(); } catch (SQLException e) { diff --git a/dbrepo-metadata-db/setup-schema.sql b/dbrepo-metadata-db/setup-schema.sql index 85be688437146429e3359532236c701cc98601c0..7a12ed5e828f489ce4c04e81ebe7faed0dadf57a 100644 --- a/dbrepo-metadata-db/setup-schema.sql +++ b/dbrepo-metadata-db/setup-schema.sql @@ -120,13 +120,13 @@ CREATE TABLE IF NOT EXISTS `mdb_databases_subjects` CREATE TABLE IF NOT EXISTS `mdb_tables` ( - ID bigint NOT NULL AUTO_INCREMENT, - tDBID bigint NOT NULL, - internal_name character varying(255) NOT NULL, - queue_name character varying(255) NOT NULL, - routing_key character varying(255), - tName VARCHAR(50), - tDescription TEXT, + ID bigint NOT NULL AUTO_INCREMENT, + tDBID bigint NOT NULL, + tName VARCHAR(64) NOT NULL, + internal_name VARCHAR(64) NOT NULL, + queue_name VARCHAR(255) NOT NULL, + routing_key VARCHAR(255), + tDescription VARCHAR(2048), num_rows BIGINT, data_length BIGINT, max_data_length BIGINT, @@ -138,12 +138,13 @@ CREATE TABLE IF NOT EXISTS `mdb_tables` element_true VARCHAR(50), element_false VARCHAR(50), Version TEXT, - created timestamp NOT NULL DEFAULT NOW(), - versioned boolean not null default true, - created_by character varying(36) NOT NULL, - owned_by character varying(36) NOT NULL, + created timestamp NOT NULL DEFAULT NOW(), + versioned boolean not null default true, + created_by character varying(36) NOT NULL, + owned_by character varying(36) NOT NULL, last_modified timestamp, PRIMARY KEY (ID), + UNIQUE (tDBID, internal_name), FOREIGN KEY (tDBID) REFERENCES mdb_databases (id), FOREIGN KEY (created_by) REFERENCES mdb_users (id), FOREIGN KEY (owned_by) REFERENCES mdb_users (id) @@ -151,25 +152,26 @@ CREATE TABLE IF NOT EXISTS `mdb_tables` CREATE TABLE IF NOT EXISTS `mdb_columns` ( - ID BIGINT NOT NULL AUTO_INCREMENT, - tID BIGINT NOT NULL, + ID BIGINT NOT NULL AUTO_INCREMENT, + tID BIGINT NOT NULL, dfID BIGINT, - cName VARCHAR(100), - internal_name VARCHAR(100) NOT NULL, + cName VARCHAR(64), + internal_name VARCHAR(64) NOT NULL, Datatype ENUM ('CHAR','VARCHAR','BINARY','VARBINARY','TINYBLOB','TINYTEXT','TEXT','BLOB','MEDIUMTEXT','MEDIUMBLOB','LONGTEXT','LONGBLOB','ENUM','SET','BIT','TINYINT','BOOL','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL','DATE','DATETIME','TIMESTAMP','TIME','YEAR'), - length BIGINT NULL, - ordinal_position INTEGER NOT NULL, - index_length BIGINT NULL, + length BIGINT NULL, + ordinal_position INTEGER NOT NULL, + index_length BIGINT NULL, + description VARCHAR(2048), size BIGINT, d BIGINT, - auto_generated BOOLEAN DEFAULT false, - is_null_allowed BOOLEAN NOT NULL DEFAULT true, - val_min NUMERIC NULL, - val_max NUMERIC NULL, - mean NUMERIC NULL, - median NUMERIC NULL, - std_dev Numeric NULL, - created timestamp NOT NULL DEFAULT NOW(), + auto_generated BOOLEAN DEFAULT false, + is_null_allowed BOOLEAN NOT NULL DEFAULT true, + val_min NUMERIC NULL, + val_max NUMERIC NULL, + mean NUMERIC NULL, + median NUMERIC NULL, + std_dev Numeric NULL, + created timestamp NOT NULL DEFAULT NOW(), last_modified timestamp, FOREIGN KEY (tID) REFERENCES mdb_tables (ID) ON DELETE CASCADE, PRIMARY KEY (ID) @@ -326,8 +328,8 @@ CREATE TABLE IF NOT EXISTS `mdb_view` ( id bigint NOT NULL AUTO_INCREMENT, vdbid bigint NOT NULL, - vName VARCHAR(255) NOT NULL, - internal_name VARCHAR(255) NOT NULL, + vName VARCHAR(64) NOT NULL, + internal_name VARCHAR(64) NOT NULL, Query TEXT NOT NULL, query_hash VARCHAR(255) NOT NULL, Public BOOLEAN NOT NULL, @@ -369,14 +371,19 @@ CREATE TABLE IF NOT EXISTS `mdb_ontologies` CREATE TABLE IF NOT EXISTS `mdb_view_columns` ( - id BIGINT NOT NULL AUTO_INCREMENT, - cid BIGINT NOT NULL, - vid BIGINT NOT NULL, - alias VARCHAR(100), - ordinal_position INTEGER, + id BIGINT NOT NULL AUTO_INCREMENT, + view_id BIGINT NOT NULL, + dfID BIGINT, + name VARCHAR(64), + internal_name VARCHAR(64) NOT NULL, + column_type ENUM ('CHAR','VARCHAR','BINARY','VARBINARY','TINYBLOB','TINYTEXT','TEXT','BLOB','MEDIUMTEXT','MEDIUMBLOB','LONGTEXT','LONGBLOB','ENUM','SET','BIT','TINYINT','BOOL','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL','DATE','DATETIME','TIMESTAMP','TIME','YEAR'), + ordinal_position INTEGER NOT NULL, + size BIGINT, + d BIGINT, + auto_generated BOOLEAN DEFAULT false, + is_null_allowed BOOLEAN NOT NULL DEFAULT true, PRIMARY KEY (id), - FOREIGN KEY (vid) REFERENCES mdb_view (id), - FOREIGN KEY (cid) REFERENCES mdb_columns (ID) + FOREIGN KEY (view_id) REFERENCES mdb_view (id) ) WITH SYSTEM VERSIONING; CREATE TABLE IF NOT EXISTS `mdb_identifiers` @@ -485,18 +492,6 @@ CREATE TABLE IF NOT EXISTS `mdb_identifier_creators` FOREIGN KEY (pid) REFERENCES mdb_identifiers (id) ) WITH SYSTEM VERSIONING; -CREATE TABLE IF NOT EXISTS `mdb_feed` -( - fDBID bigint, - fID bigint, - fUserId character varying(36) not null, - fDataID bigint REFERENCES mdb_data (ID), - created timestamp NOT NULL DEFAULT NOW(), - PRIMARY KEY (fDBID, fID, fUserId, fDataID), - FOREIGN KEY (fDBID, fID) REFERENCES mdb_tables (tDBID, ID), - FOREIGN KEY (fUserId) REFERENCES mdb_users (id) -) WITH SYSTEM VERSIONING; - CREATE TABLE IF NOT EXISTS `mdb_update` ( uUserID character varying(255) NOT NULL, diff --git a/dbrepo-metadata-service/api/pom.xml b/dbrepo-metadata-service/api/pom.xml index 8aebde719ae0f41da0d97e0888faa2a1e46464db..6815b5f9e6139001d2908d339a254e1424d21732 100644 --- a/dbrepo-metadata-service/api/pom.xml +++ b/dbrepo-metadata-service/api/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-metadata-service-api</artifactId> <name>dbrepo-metadata-service-api</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies/> diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/internal/PrivilegedContainerDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/internal/PrivilegedContainerDto.java index 8bfe3824960496c6b24cc980fd7f56cff0f7af8c..8de17a48f3221ed4ace1d837ec67183186731381 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/internal/PrivilegedContainerDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/internal/PrivilegedContainerDto.java @@ -66,10 +66,8 @@ public class PrivilegedContainerDto { @ToString.Exclude private String password; - @JsonProperty("default_timestamp_format") - private ImageDateDto defaultTimestampFormat; + private Long defaultTimestampFormatId; - @JsonProperty("default_date_format") - private ImageDateDto defaultDateFormat; + private Long defaultDateFormatId; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java new file mode 100644 index 0000000000000000000000000000000000000000..49c7c58e8a1dfb00bd89dafca87afa74effbeea9 --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java @@ -0,0 +1,59 @@ +package at.tuwien.api.database; + +import at.tuwien.api.identifier.IdentifierDto; +import at.tuwien.api.user.UserBriefDto; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +import java.time.Instant; +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class DatabaseBriefDto { + + @NotNull + private Long id; + + @NotBlank + @Schema(example = "Air Quality") + private String name; + + @NotBlank + @JsonProperty("internal_name") + @Schema(example = "air_quality") + private String internalName; + + @Schema(example = "Air Quality") + private String description; + + @NotNull + @JsonProperty("is_public") + @Schema(example = "true") + private Boolean isPublic; + + private List<IdentifierDto> identifiers; + + @ToString.Exclude + @NotNull + private UserBriefDto contact; + + @NotNull + private UserBriefDto owner; + + @NotNull + @Schema(example = "2021-03-12T15:26:21Z") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") + private Instant created; + +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java new file mode 100644 index 0000000000000000000000000000000000000000..35edfc6d8410c2eedbad2c9118fcad494cd01f73 --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewColumnDto.java @@ -0,0 +1,89 @@ +package at.tuwien.api.database; + +import at.tuwien.api.container.image.ImageDateDto; +import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.tuwien.api.database.table.columns.concepts.ConceptDto; +import at.tuwien.api.database.table.columns.concepts.UnitDto; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class ViewColumnDto { + + @NotNull + private Long id; + + @NotNull + @JsonProperty("database_id") + private Long databaseId; + + @NotNull + @Schema(example = "0") + @JsonProperty("ordinal_position") + private Integer ordinalPosition; + + @NotBlank + @Size(max = 64) + @Schema(example = "Date") + private String name; + + @NotBlank + @Size(max = 64) + @JsonProperty("internal_name") + @Schema(example = "mdb_date") + private String internalName; + + @Schema + private String alias; + + @JsonProperty("date_format") + private ImageDateDto dateFormat; + + @NotNull + @JsonProperty("auto_generated") + @Schema(example = "false") + private Boolean autoGenerated; + + @JsonProperty("index_length") + private Long indexLength; + + @JsonProperty("length") + private Long length; + + @NotNull + @JsonProperty("column_type") + @Schema(example = "string") + private ColumnTypeDto columnType; + + @Schema(example = "255") + private Long size; + + @Schema(example = "0") + private Long d; + + private ConceptDto concept; + + private UnitDto unit; + + @NotNull + @JsonProperty("is_public") + @Schema(example = "true") + private Boolean isPublic; + + @NotNull + @JsonProperty("is_null_allowed") + @Schema(example = "false") + private Boolean isNullAllowed; + +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewCreateDto.java index ca02de1b42faf916d6daf899a690d40416560ffd..583b5f0d81aab8f8af7ca71efcd743ac8a079b27 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewCreateDto.java @@ -2,6 +2,7 @@ package at.tuwien.api.database; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; import lombok.*; import jakarta.validation.constraints.NotBlank; @@ -17,15 +18,16 @@ import lombok.extern.jackson.Jacksonized; @ToString public class ViewCreateDto { - @NotBlank(message = "name is required") + @NotBlank + @Size(min = 1, max = 64) @Schema(example = "Air Quality") private String name; - @NotBlank(message = "query is required") + @NotBlank @Schema(example = "SELECT `id` FROM `air_quality`") private String query; - @NotNull(message = "public attribute is required") + @NotNull @JsonProperty("is_public") @Schema(example = "true") private Boolean isPublic; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java index 1aa92a11c0b2c69809ec5a7a16a9573683fa55cd..30f16448d36462da23dc27ba38512f61dab58b25 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java @@ -1,6 +1,5 @@ package at.tuwien.api.database; -import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.api.user.UserDto; import com.fasterxml.jackson.annotation.JsonFormat; @@ -12,7 +11,6 @@ import lombok.extern.jackson.Jacksonized; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; -import org.springframework.data.annotation.Id; import java.time.Instant; import java.util.List; @@ -35,6 +33,7 @@ public class ViewDto { private Long vdbid; @NotNull + @ToString.Exclude private DatabaseDto database; @NotBlank @@ -77,7 +76,7 @@ public class ViewDto { private UserDto creator; @NotNull - private List<ColumnDto> columns; + private List<ViewColumnDto> columns; @JsonProperty("last_modified") @Schema(example = "2021-03-12T15:26:21Z") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedViewDto.java index ff15b7b9e83c30c3f725450912cbbd3b142bd58e..5053f8c5d6330834acf382435218353841be4c8b 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/internal/PrivilegedViewDto.java @@ -1,6 +1,7 @@ package at.tuwien.api.database.internal; import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.api.user.UserDto; @@ -78,7 +79,7 @@ public class PrivilegedViewDto { private UserDto creator; @NotNull(message = "columns are required") - private List<ColumnDto> columns; + private List<ViewColumnDto> columns; @JsonProperty("last_modified") @Schema(example = "2021-03-12T15:26:21Z") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java index db6179edf3d684a06ed9a4f0f3c739cae12a2b58..aa566a495c6ea05a5a1d1259f0577ccf37cf1d0c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableBriefDto.java @@ -2,6 +2,7 @@ package at.tuwien.api.database.table; import at.tuwien.api.database.table.columns.ColumnBriefDto; import at.tuwien.api.user.UserBriefDto; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; @@ -21,18 +22,22 @@ import java.util.List; @ToString public class TableBriefDto { - @NotNull(message = "id is required") + @NotNull private Long id; - @NotBlank(message = "name is required") + @NotNull + @JsonProperty("database_id") + private Long databaseId; + + @NotBlank @Schema(example = "Air Quality") private String name; - @NotBlank(message = "description is required") + @NotBlank @Schema(example = "Air Quality in Austria") private String description; - @NotBlank(message = "internal name is required") + @NotBlank @JsonProperty("internal_name") @Schema(example = "air_quality") private String internalName; @@ -42,9 +47,11 @@ public class TableBriefDto { @Schema(example = "true") private Boolean isVersioned; - @NotNull(message = "owner is required") + @NotNull private UserBriefDto owner; - @NotNull(message = "columns are required") + @ToString.Exclude + @JsonIgnore + @NotNull private List<ColumnBriefDto> columns; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java index eff91d877a1ea1b6a8894cf1c0712b8d5a66e2ad..5764b311cacdd773e1e071718c2caf6db65977a7 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java @@ -7,6 +7,7 @@ import at.tuwien.api.user.UserDto; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; import lombok.*; import lombok.extern.jackson.Jacksonized; @@ -76,6 +77,7 @@ public class TableDto { @Schema(example = "dbrepo.1.2") private String routingKey; + @Size(max = 2048) @Schema(example = "Air Quality in Austria") private String description; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java index 44f6ed8315786d7caef12f059fa729220c72245f..78fb7fb84e5f0f8f171a97cafe63e68f32c47e35 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java @@ -2,6 +2,7 @@ package at.tuwien.api.database.table.columns; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; import lombok.*; import jakarta.validation.constraints.NotBlank; @@ -36,6 +37,10 @@ public class ColumnCreateDto { @Schema(example = "0") private Long d; + @Size(max = 2048) + @Schema(example = "Formatted as YYYY-MM-dd") + private String description; + @NotNull @JsonProperty("null_allowed") @Schema(example = "true") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java index f03ee60d7115028f6c6066805178cb224e757cf7..430bdba2704561274afbeeebcf56679e1ec7a10c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnDto.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.*; import lombok.extern.jackson.Jacksonized; @@ -43,10 +44,12 @@ public class ColumnDto { private Integer ordinalPosition; @NotBlank + @Size(max = 64) @Schema(example = "Date") private String name; @NotBlank + @Size(max = 64) @JsonProperty("internal_name") @Schema(example = "mdb_date") private String internalName; @@ -113,10 +116,16 @@ public class ColumnDto { private UnitDto unit; + @Size(max = 2048) + @Schema(example = "Formatted as YYYY-MM-dd") + private String description; + @ToString.Exclude + @JsonIgnore private transient TableDto table; @ToString.Exclude + @JsonIgnore private transient List<ViewDto> views; @NotNull diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsCreateDto.java index ccb00d23a00a1b33f3e064acb9a9f3115ae2eacd..a317b08b8afb1a5f69d30aa69ff5d68ddbce14d6 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsCreateDto.java @@ -1,6 +1,6 @@ package at.tuwien.api.database.table.constraints; -import at.tuwien.api.database.table.constraints.foreignKey.ForeignKeyCreateDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyCreateDto; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; import lombok.*; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsDto.java index 409878292adaf95f05fd09db2d3ccb3fe02ffdd3..3cd36f6d687892224e668100e6171552c090b449 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/ConstraintsDto.java @@ -1,6 +1,7 @@ package at.tuwien.api.database.table.constraints; -import at.tuwien.api.database.table.constraints.foreignKey.ForeignKeyDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; +import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; @@ -26,5 +27,5 @@ public class ConstraintsDto { private Set<String> checks; @JsonProperty("primary_key") - private Set<String> primaryKey; + private Set<PrimaryKeyDto> primaryKey; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ForeignKeyCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyCreateDto.java similarity index 91% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ForeignKeyCreateDto.java rename to dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyCreateDto.java index e6758b36eff367491a20c7f8022b28ecf8d4fde1..8e2a110997bb257b9414a9780fb29751265cce76 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ForeignKeyCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyCreateDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.constraints.foreignKey; +package at.tuwien.api.database.table.constraints.foreign; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ForeignKeyDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java similarity index 54% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ForeignKeyDto.java rename to dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java index 1c4acfc5caf386592b47f86b03f7ddd70ab94032..68ee2e56da310d8ab6b4ffa8e154ec6906c05135 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ForeignKeyDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyDto.java @@ -1,8 +1,9 @@ -package at.tuwien.api.database.table.constraints.foreignKey; +package at.tuwien.api.database.table.constraints.foreign; -import at.tuwien.api.database.table.TableBriefDto; +import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; @@ -17,19 +18,25 @@ import java.util.List; @ToString public class ForeignKeyDto { - @NonNull + private Long id; + + @NotNull private String name; - @NonNull - private List<ColumnDto> columns; + @NotNull + private ColumnDto column; - @NonNull - @JsonProperty("referenced_table") - private TableBriefDto referencedTable; + @NotNull + private List<ForeignKeyReferenceDto> references; - @NonNull - @JsonProperty("referenced_columns") - private List<ColumnDto> referencedColumns; + @NotNull + @ToString.Exclude + private TableDto table; + + @NotNull + @ToString.Exclude + @JsonProperty("referenced_table") + private TableDto referencedTable; @JsonProperty("on_update") private ReferenceTypeDto onUpdate; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java new file mode 100644 index 0000000000000000000000000000000000000000..fb978671bc9a2b8d9f647b5c537762977c628229 --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ForeignKeyReferenceDto.java @@ -0,0 +1,32 @@ +package at.tuwien.api.database.table.constraints.foreign; + +import at.tuwien.api.database.table.columns.ColumnDto; +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class ForeignKeyReferenceDto { + + private Long id; + + @NotNull + @JsonProperty("foreign_key") + private ForeignKeyDto foreignKey; + + @NotNull + @ToString.Exclude + private ColumnDto column; + + @NotNull + @ToString.Exclude + @JsonProperty("referenced_column") + private ColumnDto referencedColumn; +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ReferenceTypeDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java similarity index 90% rename from dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ReferenceTypeDto.java rename to dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java index cec40a76a808198e75439e00db58fd6999906894..ebd2d5688764c85dffa273a88bb05d42ad8a9f28 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreignKey/ReferenceTypeDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/ReferenceTypeDto.java @@ -1,4 +1,4 @@ -package at.tuwien.api.database.table.constraints.foreignKey; +package at.tuwien.api.database.table.constraints.foreign; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java new file mode 100644 index 0000000000000000000000000000000000000000..19c25371b2c67204a48728c705d550c8c8feec9e --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/primary/PrimaryKeyDto.java @@ -0,0 +1,27 @@ +package at.tuwien.api.database.table.constraints.primary; + +import at.tuwien.api.database.table.TableBriefDto; +import at.tuwien.api.database.table.columns.ColumnDto; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class PrimaryKeyDto { + + private Long pkid; + + @NotNull + @ToString.Exclude + private TableBriefDto table; + + @NotNull + @ToString.Exclude + private ColumnDto column; +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java index 44b94f63f46fdd95a107b285fce1d76416134866..10f97e83904a4af1e6bcbba0d24e4e038edec573 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/unique/UniqueDto.java @@ -1,6 +1,7 @@ package at.tuwien.api.database.table.constraints.unique; +import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; import jakarta.validation.constraints.NotNull; @@ -23,8 +24,13 @@ public class UniqueDto { private Long uid; @NotNull - private TableDto table; + private String name; @NotNull + @ToString.Exclude + private TableBriefDto table; + + @NotNull + @ToString.Exclude private List<ColumnDto> columns; } diff --git a/dbrepo-metadata-service/entities/pom.xml b/dbrepo-metadata-service/entities/pom.xml index 2bac9671301ee19f98169f079dc3bda968db0934..62dec0e318ee6dc3f660220db1d4f233a2b7a7e0 100644 --- a/dbrepo-metadata-service/entities/pom.xml +++ b/dbrepo-metadata-service/entities/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-metadata-service-entities</artifactId> <name>dbrepo-metadata-service-entity</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies/> diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java index 937b9a3ba121d262e60e125bbdae8196c3cd4b93..302046d035813aa42f43fe211bcafb6a4ca18eed 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java @@ -22,10 +22,6 @@ import java.util.List; @EntityListeners(AuditingEntityListener.class) @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Table(name = "mdb_containers") -@NamedQueries({ - @NamedQuery(name = "Container.findDefaultTimestampFormat", query = "select d from ContainerImageDate d where d.hasTime = true order by d.id limit 1"), - @NamedQuery(name = "Container.findDefaultDateFormat", query = "select d from ContainerImageDate d where d.hasTime = false order by d.id limit 1"), -}) public class Container { @Id @@ -69,7 +65,7 @@ public class Container { }) private List<Database> databases; - @ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}) @JoinColumns({ @JoinColumn(name = "image_id", referencedColumnName = "id") }) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java index 40849fe4efcb68779c40e126ae7cde09aebe090f..b315c7e81daf711103ab063ca2b4d9a8b438c1a9 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImage.java @@ -53,7 +53,7 @@ public class ContainerImage { @Column(nullable = false) private Integer defaultPort; - @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.ALL}, mappedBy = "image") // ALL = cascade save + delete + @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "image") private List<ContainerImageDate> dateFormats; @ToString.Exclude diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImageDate.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImageDate.java index c40da7b077d1443c2e9c4bf22bc60ea27ded28dc..5b370ecc0664fa438e34511d606c75d0219ceb9f 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImageDate.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/image/ContainerImageDate.java @@ -7,6 +7,7 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import jakarta.persistence.*; + import java.time.Instant; @Data @@ -27,12 +28,15 @@ public class ContainerImageDate { @Column(updatable = false, nullable = false) private Long id; + @EqualsAndHashCode.Include @Column(name = "iid") private Long iid; @ToString.Exclude - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "iid", insertable = false, updatable = false) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) + @JoinColumns({ + @JoinColumn(name = "iid", insertable = false, updatable = false) + }) private ContainerImage image; @Column(name = "example", nullable = false) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java index bf5904f4addb669df4044d09d3498aea352b223e..f463370e4d252f87cdaf11266e3497a4af4c2c36 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java @@ -23,7 +23,7 @@ import java.util.UUID; @Data @Entity -@Builder +@Builder(toBuilder = true) @ToString @AllArgsConstructor @NoArgsConstructor diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java index f2104863474599c931acfa98165b64fe884b0e26..44ffab29592243bc605083aa993e0215ac95475a 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java @@ -10,7 +10,6 @@ import jakarta.persistence.NamedQuery; import jakarta.persistence.OrderBy; import jakarta.persistence.Table; import lombok.*; -import net.sf.jsqlparser.statement.select.FromItem; import org.hibernate.annotations.*; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -58,10 +57,10 @@ public class View { }) private User creator; - @Column(name = "vname", nullable = false) + @Column(name = "vname", nullable = false, columnDefinition = "VARCHAR(64)") private String name; - @Column(nullable = false) + @Column(nullable = false, columnDefinition = "VARCHAR(64)") private String internalName; @Column(name = "public", nullable = false) @@ -95,27 +94,9 @@ public class View { }) private Database database; - /** - * KEEP THIS FUNCTION HERE! IT WILL BREAK CODE! - * Custom equality function implementation. - * - * @param other The other view - * @return True if views are equal, false otherwise - */ - public boolean equals(FromItem other) { - if (other == null) { - return false; - } - final net.sf.jsqlparser.schema.Table table = (net.sf.jsqlparser.schema.Table) other; - return this.internalName.equals(table.getName().replace("`", "")); - } - @ToString.Exclude -// @OnDelete(action = OnDeleteAction.CASCADE) - @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) - @JoinColumns({ - @JoinColumn(name = "vid", referencedColumnName = "id", updatable = false) - }) + @OnDelete(action = OnDeleteAction.CASCADE) + @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}, mappedBy = "view") @OrderColumn(name = "ordinalPosition") private List<ViewColumn> columns; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/ViewColumn.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/ViewColumn.java index a74bde27fe3afd1f4ae2d1878541efdf4759773a..eb9b352095bfd1c875cde9fac6db5d45ad8d5e6d 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/ViewColumn.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/ViewColumn.java @@ -1,6 +1,7 @@ package at.tuwien.entities.database; -import at.tuwien.entities.database.table.columns.TableColumn; +import at.tuwien.entities.container.image.ContainerImageDate; +import at.tuwien.entities.database.table.columns.TableColumnType; import lombok.*; import org.hibernate.annotations.GenericGenerator; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -15,7 +16,7 @@ import jakarta.persistence.*; @NoArgsConstructor @EntityListeners(AuditingEntityListener.class) @jakarta.persistence.Table(name = "mdb_view_columns", uniqueConstraints = { - @UniqueConstraint(columnNames = {"cid", "vid"}) + @UniqueConstraint(columnNames = {"view_id", "internalName"}) }) public class ViewColumn implements Comparable<ViewColumn> { @@ -26,28 +27,45 @@ public class ViewColumn implements Comparable<ViewColumn> { @Column(updatable = false, nullable = false) private Long id; - @Column(updatable = false) - private String alias; - - @Column(nullable = false) - private Integer ordinalPosition; + @ToString.Exclude + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "dfid", referencedColumnName = "id") + private ContainerImageDate dateFormat; @ToString.Exclude @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinColumns({ - @JoinColumn(name = "vid", referencedColumnName = "id", updatable = false) + @JoinColumn(name = "view_id", referencedColumnName = "id", nullable = false) }) private View view; - @ToString.Exclude - @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) - @JoinColumns({ - @JoinColumn(name = "cid", referencedColumnName = "id", updatable = false) - }) - private TableColumn column; + @Column(nullable = false, columnDefinition = "VARCHAR(64)") + private String name; + + @Column(name = "auto_generated", columnDefinition = "BOOLEAN default false") + private Boolean autoGenerated; + + @Column(nullable = false, columnDefinition = "VARCHAR(64)") + private String internalName; + + @Column(nullable = false, columnDefinition = "ENUM('CHAR','VARCHAR','BINARY','VARBINARY','TINYBLOB','TINYTEXT','TEXT','BLOB','MEDIUMTEXT','MEDIUMBLOB','LONGTEXT','LONGBLOB','ENUM','SET','BIT','TINYINT','BOOL','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL','DATE','DATETIME','TIMESTAMP','TIME','YEAR')") + @Enumerated(EnumType.STRING) + private TableColumnType columnType; + + @Column(nullable = false, columnDefinition = "BOOLEAN default true") + private Boolean isNullAllowed; + + @Column(nullable = false) + private Integer ordinalPosition; + + @Column + private Long size; + + @Column + private Long d; @Override - public int compareTo(ViewColumn tableColumn) { - return Integer.compare(this.ordinalPosition, tableColumn.getOrdinalPosition()); + public int compareTo(ViewColumn viewColumn) { + return Integer.compare(this.ordinalPosition, viewColumn.getOrdinalPosition()); } } diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java index 3dc5b9bdea799fd964e1d7d9f83e920d37e5c45d..57d9dbab1b9b95b143fde6752384457d99653857 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java @@ -10,7 +10,6 @@ import jakarta.persistence.CascadeType; import jakarta.persistence.OrderBy; import lombok.*; import lombok.extern.log4j.Log4j2; -import net.sf.jsqlparser.statement.select.FromItem; import org.hibernate.annotations.*; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -29,8 +28,11 @@ import java.util.UUID; @ToString @AllArgsConstructor @NoArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true) @EntityListeners(AuditingEntityListener.class) -@jakarta.persistence.Table(name = "mdb_tables") +@jakarta.persistence.Table(name = "mdb_tables", uniqueConstraints = { + @UniqueConstraint(columnNames = {"tdbid", "internalName"}) +}) public class Table { @Id @@ -48,7 +50,7 @@ public class Table { private UUID createdBy; @ToString.Exclude - @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "created_by", referencedColumnName = "ID", insertable = false, updatable = false) }) @@ -60,27 +62,27 @@ public class Table { private UUID ownedBy; @ToString.Exclude - @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "owned_by", referencedColumnName = "ID", insertable = false, updatable = false) }) private User owner; - @Column(name = "tname", nullable = false) + @Column(name = "tname", nullable = false, columnDefinition = "VARCHAR(64)") private String name; - @Column(nullable = false) + @Column(nullable = false, columnDefinition = "VARCHAR(64)") private String internalName; @Column(name = "queue_name", nullable = false, updatable = false) private String queueName; - @Column(name = "tdescription", columnDefinition = "TEXT") + @Column(name = "tdescription", columnDefinition = "VARCHAR(2048)") private String description; @ToString.Exclude @org.springframework.data.annotation.Transient - @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "tdbid", referencedColumnName = "id", insertable = false, updatable = false) }) @@ -129,31 +131,5 @@ public class Table { @Column(columnDefinition = "TIMESTAMP") private Instant lastModified; - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof Table other)) { - return false; - } - return this.id.equals(other.getId()); - } - - /** - * KEEP THIS FUNCTION HERE! IT WILL BREAK CODE! - * Custom equality function implementation. - * - * @param other The other table - * @return True if tables are equal, false otherwise - */ - public boolean equals(FromItem other) { - if (other == null) { - return false; - } - final net.sf.jsqlparser.schema.Table table = (net.sf.jsqlparser.schema.Table) other; - return this.internalName.equals(table.getName().replace("`", "")); - } - } diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java index f5b955dd5920e8bdb7fcf42cd36e96c60336c221..9a50f5c0545c8351b5fae16157b171d2f52dd870 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java @@ -1,7 +1,6 @@ package at.tuwien.entities.database.table.columns; import at.tuwien.entities.container.image.ContainerImageDate; -import at.tuwien.entities.database.View; import at.tuwien.entities.database.table.Table; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.*; @@ -40,32 +39,29 @@ public class TableColumn implements Comparable<TableColumn> { private Long id; @ToString.Exclude - @OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) + @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dfid", referencedColumnName = "id") private ContainerImageDate dateFormat; @ToString.Exclude - @org.springframework.data.annotation.Transient @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinColumns({ @JoinColumn(name = "tID", referencedColumnName = "id", nullable = false) }) private Table table; - @ToString.Exclude - @org.springframework.data.annotation.Transient - @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE, mappedBy = "columns") - private List<View> views; - - @Column(name = "cname", nullable = false) + @Column(name = "cname", nullable = false, columnDefinition = "VARCHAR(64)") private String name; @Column(name = "auto_generated", columnDefinition = "BOOLEAN default false") private Boolean autoGenerated; - @Column(nullable = false) + @Column(nullable = false, columnDefinition = "VARCHAR(64)") private String internalName; + @Column(columnDefinition = "VARCHAR(2048)") + private String description; + @Column private Long indexLength; @@ -90,13 +86,13 @@ public class TableColumn implements Comparable<TableColumn> { @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") private Instant created; - @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}) @JoinTable(name = "mdb_columns_concepts", joinColumns = @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false), inverseJoinColumns = @JoinColumn(name = "id", referencedColumnName = "id")) private TableColumnConcept concept; - @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}) @JoinTable(name = "mdb_columns_units", joinColumns = @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false), inverseJoinColumns = @JoinColumn(name = "id", referencedColumnName = "id")) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKey.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKey.java index 92050024e5c0d24dde314a915c4746dc315c99ef..83e0d356561c0ea47f1c6278680571e8c27bf17b 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKey.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKey.java @@ -30,7 +30,6 @@ public class ForeignKey { private String name; @ToString.Exclude - @org.springframework.data.annotation.Transient @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) @JoinColumns({ @JoinColumn(name = "tid", referencedColumnName = "id", nullable = false) @@ -38,7 +37,6 @@ public class ForeignKey { private Table table; @ToString.Exclude - @org.springframework.data.annotation.Transient @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) @JoinColumns({ @JoinColumn(name = "rtid", referencedColumnName = "id", nullable = false) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java index 88a1ce77a10231fa70fe96df23454a5b4bffd418..89f52c6cb2d2b199e5b1883d10b4969fad3ec612 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java @@ -26,17 +26,17 @@ public class ForeignKeyReference { private Long id; @ToString.Exclude - @ManyToOne(fetch = FetchType.LAZY, optional = false) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "fkid", referencedColumnName = "fkid", nullable = false) private ForeignKey foreignKey; - @ManyToOne(fetch = FetchType.LAZY, optional = false) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false) }) private TableColumn column; - @ManyToOne(fetch = FetchType.LAZY, optional = false) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "rcid", referencedColumnName = "id", nullable = false) }) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java index d373339f2d0ac4e3a70344a914882087de907119..269410a8c88f3197db69c706b933ca2667d62911 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java @@ -7,6 +7,7 @@ import org.hibernate.annotations.GenericGenerator; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import jakarta.persistence.*; + import java.util.List; @Data diff --git a/dbrepo-metadata-service/metrics.md b/dbrepo-metadata-service/metrics.md new file mode 100644 index 0000000000000000000000000000000000000000..976bacc4aaf07d381b939b457d9af19f5417de41 --- /dev/null +++ b/dbrepo-metadata-service/metrics.md @@ -0,0 +1,67 @@ +| **Metric** | **Description** | +|------------------------------------|----------------------------------------| +| `dbrepo_access_delete` | Revoke access to some database | +| `dbrepo_access_get` | Check access to some database | +| `dbrepo_access_give` | Give access to some database | +| `dbrepo_access_modify` | Modify access to some database | +| `dbrepo_container_create` | Create container | +| `dbrepo_container_delete` | Delete some container | +| `dbrepo_container_find` | Find some container | +| `dbrepo_container_findall` | Find all containers | +| `dbrepo_database_create` | Create database | +| `dbrepo_database_find` | Find some database | +| `dbrepo_database_findall` | List databases | +| `dbrepo_database_image` | Update database image | +| `dbrepo_database_transfer` | Update database owner | +| `dbrepo_database_visibility` | Update database visibility | +| `dbrepo_identifier_create` | Draft identifier | +| `dbrepo_identifier_delete` | Delete some identifier | +| `dbrepo_identifier_find` | Find some identifier | +| `dbrepo_identifier_list` | Find all identifiers | +| `dbrepo_identifier_publish` | Publish identifier | +| `dbrepo_identifier_retrieve` | Retrieve metadata from identifier | +| `dbrepo_identifier_save` | Save identifier | +| `dbrepo_image_create` | Create image | +| `dbrepo_image_delete` | Delete some image | +| `dbrepo_image_find` | Find some image | +| `dbrepo_image_findall` | Find all images | +| `dbrepo_image_update` | Update some image | +| `dbrepo_license_findall` | Get all licenses | +| `dbrepo_maintenance_create` | Create maintenance message | +| `dbrepo_maintenance_delete` | Delete maintenance message | +| `dbrepo_maintenance_find` | Find one maintenance message | +| `dbrepo_maintenance_findall` | Find maintenance messages | +| `dbrepo_maintenance_update` | Update maintenance message | +| `dbrepo_oai_identifiers_list` | List the identifiers | +| `dbrepo_oai_identify` | Identify the repository | +| `dbrepo_oai_metadataformats_list` | List the metadata formats | +| `dbrepo_oai_record_get` | Get the record | +| `dbrepo_ontologies_create` | Register a new ontology | +| `dbrepo_ontologies_delete` | Delete an ontology | +| `dbrepo_ontologies_entities_find` | Find entities | +| `dbrepo_ontologies_find` | Find one ontology | +| `dbrepo_ontologies_findall` | List all ontologies | +| `dbrepo_ontologies_update` | Update an ontology | +| `dbrepo_semantic_column_analyse` | Suggest table column semantics | +| `dbrepo_semantic_concepts_findall` | List semantic concepts | +| `dbrepo_semantic_table_analyse` | Suggest table semantics | +| `dbrepo_semantic_units_findall` | List semantic units | +| `dbrepo_semantics_column_save` | Update a table column semantic mapping | +| `dbrepo_statistic_table_update` | Update table statistics | +| `dbrepo_table_create` | Create a table | +| `dbrepo_table_delete` | Delete a table | +| `dbrepo_tables_find` | Get information about table | +| `dbrepo_tables_findall` | List all tables | +| `dbrepo_tables_refresh` | Refresh database tables metadata | +| `dbrepo_user_create` | Create user | +| `dbrepo_user_find` | Get a user info | +| `dbrepo_user_modify` | Modify user information | +| `dbrepo_user_password_modify` | Modify user password | +| `dbrepo_user_refresh_token` | Refresh user token | +| `dbrepo_user_token` | Obtain user token | +| `dbrepo_users_list` | Find all users | +| `dbrepo_view_create` | Create a view | +| `dbrepo_view_delete` | Delete one view | +| `dbrepo_view_find` | Find one view | +| `dbrepo_views_findall` | Find all views | +| `dbrepo_views_refresh` | Refresh database views metadata | diff --git a/dbrepo-metadata-service/oai/pom.xml b/dbrepo-metadata-service/oai/pom.xml index 591462a4e8f542cb2b8d9937828c0fa9aaf1fa93..e432736721cba310f5a48416beeeb9ed3196774e 100644 --- a/dbrepo-metadata-service/oai/pom.xml +++ b/dbrepo-metadata-service/oai/pom.xml @@ -6,33 +6,13 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-metadata-service-oai</artifactId> <name>dbrepo-metadata-service-oai</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies/> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <source>${java.version}</source> - <target>${java.version}</target> - <annotationProcessorPaths> - <path> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> - </path> - </annotationProcessorPaths> - </configuration> - </plugin> - </plugins> - </build> - </project> \ No newline at end of file diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index e770adf57f167d0f7c476fbeac67044af64ce708..2e6651d9cfac0e2e7a20b403886ca18e752da2d6 100644 --- a/dbrepo-metadata-service/pom.xml +++ b/dbrepo-metadata-service/pom.xml @@ -11,7 +11,7 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> <name>dbrepo-metadata-service</name> - <version>1.4.3</version> + <version>1.4.4</version> <description>Service that manages the metadata</description> @@ -72,7 +72,6 @@ <apache-jena.version>4.10.0</apache-jena.version> <opencsv.version>5.7.1</opencsv.version> <super-csv.version>2.4.0</super-csv.version> - <jsql.version>4.6</jsql.version> <keycloak.version>21.0.2</keycloak.version> <springdoc-openapi.version>2.3.0</springdoc-openapi.version> <testcontainers.version>1.19.1</testcontainers.version> @@ -232,11 +231,6 @@ <version>${rabbitmq.version}</version> </dependency> <!-- Testing --> - <dependency> - <groupId>com.github.jsqlparser</groupId> - <artifactId>jsqlparser</artifactId> - <version>${jsql.version}</version> - </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> diff --git a/dbrepo-metadata-service/report/pom.xml b/dbrepo-metadata-service/report/pom.xml index 21d50f9082333dc1f87ea87705ad520b0a6d644d..9012f19379811a0fec2a80cdb869ec0720ce98e1 100644 --- a/dbrepo-metadata-service/report/pom.xml +++ b/dbrepo-metadata-service/report/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-metadata-service-report</artifactId> <name>dbrepo-metadata-service-report</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/repositories/pom.xml b/dbrepo-metadata-service/repositories/pom.xml index 7bee38495ad5875d10a74731b1f101045aee82f1..1fa4ba34e789e6d9f12a45e756b7e7d481309baa 100644 --- a/dbrepo-metadata-service/repositories/pom.xml +++ b/dbrepo-metadata-service/repositories/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-metadata-service-repositories</artifactId> <name>dbrepo-metadata-service-repositories</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/CredentialsInvalidException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/CredentialsInvalidException.java index b7c6b8d03beb4c65e99179c10c20b5954bc86dd6..984c70f4857262c158a7fc15075376aa8e425186 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/CredentialsInvalidException.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/CredentialsInvalidException.java @@ -3,7 +3,7 @@ package at.tuwien.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; -@ResponseStatus(code = HttpStatus.UNAUTHORIZED, reason = "error.user.credentials") +@ResponseStatus(code = HttpStatus.FORBIDDEN, reason = "error.user.credentials") public class CredentialsInvalidException extends Exception { public CredentialsInvalidException(String msg) { diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/DatabaseMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/DatabaseMapper.java index ce89fc93c602f5a1e136b50404fc2e5f21f7167a..c2428f5f2aaa7ffd7eef9f413a6f23e633ed5be2 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/DatabaseMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/DatabaseMapper.java @@ -44,11 +44,15 @@ public interface DatabaseMapper { } @Mappings({ - @Mapping(target = "id", source = "id"), @Mapping(target = "created", source = "created", dateFormat = "dd-MM-yyyy HH:mm"), }) DatabaseDto databaseToDatabaseDto(Database data); + @Mappings({ + @Mapping(target = "created", source = "created", dateFormat = "dd-MM-yyyy HH:mm"), + }) + DatabaseBriefDto databaseToDatabaseBriefDto(Database data); + AccessType accessTypeDtoToAccessType(AccessTypeDto data); AccessTypeDto accessTypeToAccessTypeDto(AccessType data); diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java deleted file mode 100644 index f5b74f4b282608eb62bf694eed9f4dad21038fd3..0000000000000000000000000000000000000000 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java +++ /dev/null @@ -1,196 +0,0 @@ -package at.tuwien.mapper; - -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.View; -import at.tuwien.entities.database.ViewColumn; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.database.table.columns.TableColumnType; -import net.sf.jsqlparser.JSQLParserException; -import net.sf.jsqlparser.parser.CCJSqlParserManager; -import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.statement.select.*; -import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.SelectItem; -import org.mapstruct.Mapper; -import org.springframework.transaction.annotation.Transactional; - -import java.io.*; -import java.math.BigInteger; -import java.sql.*; -import java.time.*; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Mapper(componentModel = "spring", imports = {LinkedList.class}) -public interface QueryMapper { - - org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(QueryMapper.class); - - /** - * Parses the stored columns from a given query. - * - * @param query The query. - * @param database The database that contains the list of tables with list of columns. - * @return List of columns in the order they are referenced in the query. - * @throws JSQLParserException The columns could not be extracted from the query. - */ - @Transactional(readOnly = true) - default List<TableColumn> parseColumns(String query, Database database) throws JSQLParserException { - final List<TableColumn> columns = new ArrayList<>(); - final CCJSqlParserManager parserRealSql = new CCJSqlParserManager(); - final net.sf.jsqlparser.statement.Statement statement = parserRealSql.parse(new StringReader(query)); - log.debug("parse columns from query: {}", query); - /* check */ - if (!(statement instanceof Select)) { - log.error("Query attempts to update the dataset, not a SELECT statement"); - throw new JSQLParserException("Query attempts to update the dataset"); - } - /* start parsing */ - final Select selectStatement = (Select) statement; - final PlainSelect ps = (PlainSelect) selectStatement.getSelectBody(); - final List<SelectItem> clauses = ps.getSelectItems(); - log.trace("columns referenced in the from-clause: {}", clauses); - /* Parse all tables */ - final List<FromItem> fromItems = new ArrayList<>(fromItemToFromItems(ps.getFromItem())); - if (ps.getJoins() != null && !ps.getJoins().isEmpty()) { - log.trace("query contains join items: {}", ps.getJoins()); - for (net.sf.jsqlparser.statement.select.Join j : ps.getJoins()) { - if (j.getRightItem() != null) { - fromItems.add(j.getRightItem()); - } - } - } - final List<ViewColumn> allColumns = Stream.of(database.getViews() - .stream() - .map(View::getColumns) - .flatMap(List::stream), - database.getTables() - .stream() - .map(Table::getColumns) - .flatMap(List::stream) - .map(c -> ViewColumn.builder() - .column(c) - .alias(c.getAlias()) - .ordinalPosition(c.getOrdinalPosition()) - .build()) - ) - .flatMap(i -> i) - .toList(); - log.trace("columns referenced in the from-clause and join-clause(s): {}", clauses); - /* Checking if all tables or views exist */ - log.trace("table/view/join referenced in the statement: {}", fromItems.stream().map(this::fromItemToFromItems).flatMap(List::stream).collect(Collectors.toList())); - /* Checking if all columns exist */ - for (SelectItem clause : clauses) { - final SelectExpressionItem item = (SelectExpressionItem) clause; - final Column column = (Column) item.getExpression(); - final Optional<net.sf.jsqlparser.schema.Table> optional = fromItems.stream() - .map(t -> (net.sf.jsqlparser.schema.Table) t) - .filter(t -> { - if (column.getTable() == null) { - /* column does not reference a specific table, so there is only one table */ - final String tableName = ((net.sf.jsqlparser.schema.Table) fromItems.get(0)).getName().replace("`", ""); - return tableMatches(t, tableName); - } - final String tableName = column.getTable().getName().replace("`", ""); - return tableMatches(t, tableName); - }) - .findFirst(); - if (optional.isEmpty()) { - log.error("Failed to find table/view {} (with designator {})", column.getTable().getName(), column.getTable().getAlias()); - throw new JSQLParserException("Failed to find table/view " + column.getTable().getName() + " (with alias " + column.getTable().getAlias() + ")"); - } - final String columnName = column.getColumnName().replace("`", ""); - final String tableOrView = optional.get().getName().replace("`", ""); - final List<ViewColumn> filteredColumns = allColumns.stream() - .filter(c -> (c.getAlias() != null && c.getAlias().equals(columnName)) || c.getColumn().getInternalName().equals(columnName)) - .toList(); - final Optional<ViewColumn> optionalColumn = filteredColumns.stream() - .filter(c -> columnMatches(c, tableOrView)) - .findFirst(); - if (optionalColumn.isEmpty()) { - log.error("Failed to find column with name {} of table/view {} in {}", columnName, tableOrView, filteredColumns.stream().map(c -> c.getColumn().getTable().getInternalName() + "." + c.getColumn().getInternalName()).toList()); - throw new JSQLParserException("Failed to find column with name " + columnName + " of table/view " + tableOrView); - } - final ViewColumn resultColumn = optionalColumn.get(); - if (item.getAlias() != null) { - resultColumn.getColumn().setAlias(item.getAlias().getName().replace("`", "")); - } - log.trace("found column with internal name {} and alias {}", resultColumn.getColumn().getInternalName(), resultColumn.getAlias()); - columns.add(resultColumn.getColumn()); - } - return columns; - } - - default List<FromItem> fromItemToFromItems(FromItem data) { - return fromItemToFromItems(data, 0); - } - - default List<FromItem> fromItemToFromItems(FromItem data, Integer level) { - final List<FromItem> fromItems = new LinkedList<>(); - if (data instanceof net.sf.jsqlparser.schema.Table table) { - fromItems.add(data); - log.trace("from-item {} is of type table: level ~> {}", table.getName(), level); - return fromItems; - } - if (data instanceof SubJoin subJoin) { - log.trace("from-item is of type sub-join: level ~> {}", level); - for (Join join : subJoin.getJoinList()) { - fromItems.addAll(fromItemToFromItems(join.getRightItem(), level + 1)); - } - fromItems.addAll(fromItemToFromItems(((SubJoin) data).getLeft(), level + 1)); - return fromItems; - } - log.warn("unknown from-item {}", data); - return null; - } - - default boolean tableMatches(net.sf.jsqlparser.schema.Table table, String otherTableName) { - final String tableName = table.getName() - .trim() - .replace("`", ""); - if (table.getAlias() == null) { - /* table does not have designator */ - log.trace("table {} has no designator", tableName); - return tableName.equals(otherTableName); - } - /* has designator */ - final String designator = table.getAlias() - .getName() - .trim() - .replace("`", ""); - log.trace("table {} has designator {}", tableName, designator); - return designator.equals(otherTableName); - } - - @Transactional(readOnly = true) - default boolean columnMatches(ViewColumn column, String tableOrView) { - if (column.getView() != null && column.getView().getInternalName().equals(tableOrView)) { - log.trace("view {} found in column table", tableOrView); - return true; - } - if (column.getColumn().getTable().getInternalName().equals(tableOrView)) { - log.trace("table {} found in column table", tableOrView); - return true; - } - if (column.getColumn().getViews() == null) { - log.trace("table/view {} not found among column views: empty list", tableOrView); - return false; - } - /* maybe matches one of the other views */ - final boolean found = column.getColumn() - .getViews() - .stream() - .anyMatch(v -> v.getInternalName().equals(tableOrView)); - if (!found) { - log.trace("table/view {} not found among column views: {}", tableOrView, column.getColumn().getViews().stream().map(View::getInternalName).toList()); - } - return found; - } - - -} diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/TableMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/TableMapper.java index 62d05fcbba5f69ad6795f86c76d2db71b5e3f9cd..a63bc5c9459270a0c20df9e57387c91e267d5fb1 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/TableMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/TableMapper.java @@ -1,16 +1,16 @@ package at.tuwien.mapper; -import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; import at.tuwien.entities.container.image.ContainerImage; import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.View; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; import at.tuwien.entities.database.table.constraints.Constraints; @@ -26,7 +26,7 @@ import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; -@Mapper(componentModel = "spring", uses = {IdentifierMapper.class, UserMapper.class}, imports = {Collectors.class}) +@Mapper(componentModel = "spring", uses = {IdentifierMapper.class, UserMapper.class}, imports = {Collectors.class, LinkedList.class}) public interface TableMapper { org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TableMapper.class); @@ -38,25 +38,53 @@ public interface TableMapper { }) TableBriefDto tableToTableBriefDto(Table data); - @Mappings({ - @Mapping(target = "table.constraints", ignore = true), - }) - UniqueDto uniqueToUniqueDto(Unique data); + TableBriefDto tableDtoToTableBriefDto(TableDto data); + + /* keep */ + default UniqueDto uniqueToUniqueDto(Unique data) { + return UniqueDto.builder() + .uid(data.getUid()) + .name("uk") + .columns(data.getColumns().stream().map(this::tableColumnToColumnDto).toList()) + .table(tableToTableBriefDto(data.getTable())) + .build(); + } @Mappings({ @Mapping(target = "name", expression = "java(data.getName())"), @Mapping(target = "internalName", expression = "java(data.getInternalName())"), @Mapping(target = "queueName", expression = "java(data.getQueueName())"), @Mapping(target = "routingKey", expression = "java(\"dbrepo.\" + data.getTdbid() + \".\" + data.getId())"), - @Mapping(target = "isPublic", source = "database.isPublic") + @Mapping(target = "isPublic", source = "database.isPublic"), }) TableDto tableToTableDto(Table data); - /* keep */ @Mappings({ - @Mapping(target = "primaryKey", expression = "java(data.getPrimaryKey().stream().map(pk -> pk.getColumn().getInternalName()).collect(Collectors.toSet()))") + @Mapping(target = "table", ignore = true), + @Mapping(target = "referencedTable", ignore = true), + }) + ForeignKeyDto foreignKeyToForeignKeyDto(ForeignKey foreignKey); + + @Mappings({ + @Mapping(target = "foreignKey", ignore = true), }) - ConstraintsDto constraintsToConstraintsDto(Constraints data); + ForeignKeyReferenceDto foreignKeyReferenceToForeignKeyReferenceDto(ForeignKeyReference foreignKeyReference); + + @Mappings({ + @Mapping(target = "table", ignore = true) + }) + TableColumn columnDtoToTableColumn(ColumnDto columnDto); + + @Mappings({ + @Mapping(target = "table", ignore = true) + }) + Unique uniqueDtoToUnique(UniqueDto data); + + @Mappings({ + @Mapping(target = "constraints.primaryKey", expression = "java(new LinkedList<>())"), + @Mapping(target = "ownedBy", source = "owner.id"), + }) + Table tableDtoToTable(TableDto data); /* keep */ default Constraints constraintsCreateDtoToConstraints(ConstraintsCreateDto data, Database database, Table table) { @@ -151,13 +179,13 @@ public interface TableMapper { @Mapping(target = "tableId", source = "table.id"), @Mapping(target = "databaseId", source = "table.database.id"), @Mapping(target = "isPublic", source = "table.database.isPublic"), + @Mapping(target = "description", source = "description"), @Mapping(target = "table.columns", ignore = true), @Mapping(target = "table.constraints", ignore = true), @Mapping(target = "views", ignore = true) }) ColumnDto tableColumnToColumnDto(TableColumn data); - @Named("internalMapping") default String nameToInternalName(String data) { if (data == null || data.isEmpty()) { diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/ViewMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/ViewMapper.java index 7333639371a877d508c515da91f1f6642418d4e3..7d8f2416b1896cb39cc7641208b75845754108bb 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/ViewMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/ViewMapper.java @@ -3,16 +3,12 @@ package at.tuwien.mapper; import at.tuwien.api.database.ViewBriefDto; import at.tuwien.api.database.ViewDto; import at.tuwien.entities.database.View; -import at.tuwien.entities.database.ViewColumn; -import at.tuwien.entities.database.table.columns.TableColumn; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.Named; -import org.springframework.transaction.annotation.Transactional; import java.text.Normalizer; -import java.util.List; import java.util.Locale; import java.util.regex.Pattern; @@ -44,24 +40,9 @@ public interface ViewMapper { ViewBriefDto viewToViewBriefDto(View data); - @Transactional(readOnly = true) - default TableColumn viewColumnToTableColumn(ViewColumn data) { - return data.getColumn() - .toBuilder() - .alias(data.getAlias()) - .build(); - } - - default List<ViewColumn> tableColumnsToViewColumns(View view, List<TableColumn> data) { - final int[] idx = new int[]{0}; - return data.stream() - .map(c -> ViewColumn.builder() - .ordinalPosition(idx[0]++) - .column(c) - .view(view) - .alias(c.getAlias()) - .build()) - .toList(); - } + @Mappings({ + @Mapping(target = "createdBy", source = "creator.id"), + }) + View viewDtoToView(ViewDto data); } diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ContainerRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ContainerRepository.java index 8155aef9cc3f67eb83c52ed5bb15c4a67c50c208..e1a1f209e3adf49d1d85ce2ced2779857da16a38 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ContainerRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/ContainerRepository.java @@ -1,6 +1,7 @@ package at.tuwien.repository; import at.tuwien.entities.container.Container; +import at.tuwien.entities.container.image.ContainerImageDate; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/dbrepo-metadata-service/rest-service/pom.xml b/dbrepo-metadata-service/rest-service/pom.xml index ba715899b7ab9cf08a2bc6e8d464d6bfde997329..97e108fa0d55fb1b46c9220ab6368a61fb5c123b 100644 --- a/dbrepo-metadata-service/rest-service/pom.xml +++ b/dbrepo-metadata-service/rest-service/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-metadata-service-rest-service</artifactId> <name>dbrepo-metadata-service-rest</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java index 3fe8d96df605166c49d581955e6a3f8ebf348ed3..ea66257cc19860534fc73d1e72630ddbb71e12f5 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java @@ -54,7 +54,7 @@ public class AccessEndpoint { @PostMapping("/{userId}") @Transactional - @Observed(name = "dbrepo_metadata_access_give") + @Observed(name = "dbrepo_access_give") @PreAuthorize("hasAuthority('create-database-access')") @Operation(summary = "Give access to some database", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -120,7 +120,7 @@ public class AccessEndpoint { @PutMapping("/{userId}") @Transactional - @Observed(name = "dbrepo_metadata_access_modify") + @Observed(name = "dbrepo_access_modify") @PreAuthorize("hasAuthority('update-database-access')") @Operation(summary = "Modify access to some database", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -175,7 +175,7 @@ public class AccessEndpoint { @RequestMapping(value = "/{userId}", method = {RequestMethod.GET, RequestMethod.HEAD}) @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_access_get") + @Observed(name = "dbrepo_access_get") @PreAuthorize("hasAuthority('check-database-access') or hasAuthority('admin')") @Operation(summary = "Check access to some database", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -218,7 +218,7 @@ public class AccessEndpoint { @DeleteMapping("/{userId}") @Transactional - @Observed(name = "dbrepo_metadata_access_delete") + @Observed(name = "dbrepo_access_delete") @PreAuthorize("hasAuthority('delete-database-access')") @Operation(summary = "Revoke access to some database", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java index 8cdc6f25137699629b436f5b9289b6f085d3f116..2d002e844930f7d249549dd843e8bc987658448e 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java @@ -36,7 +36,7 @@ public class ConceptEndpoint { @GetMapping @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_semantic_concepts_findall") + @Observed(name = "dbrepo_semantic_concepts_findall") @Operation(summary = "List semantic concepts") @ApiResponses(value = { @ApiResponse(responseCode = "200", diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java index 45c45a816f00f48edbeec45f0d1ed368df04c4b6..02f5a00f2bc33a7d73f9518a755fc3b0f5133d89 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java @@ -53,7 +53,7 @@ public class ContainerEndpoint { @GetMapping @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_container_findall") + @Observed(name = "dbrepo_container_findall") @Operation(summary = "Find all containers") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -75,7 +75,7 @@ public class ContainerEndpoint { @PostMapping @Transactional - @Observed(name = "dbrepo_metadata_container_create") + @Observed(name = "dbrepo_container_create") @PreAuthorize("hasAuthority('create-container')") @Operation(summary = "Create container", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -107,7 +107,7 @@ public class ContainerEndpoint { @GetMapping("/{containerId}") @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_container_find") + @Observed(name = "dbrepo_container_find") @Operation(summary = "Find some container") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -135,6 +135,7 @@ public class ContainerEndpoint { log.trace("attach privileged credential information"); headers.set("X-Username", container.getPrivilegedUsername()); headers.set("X-Password", container.getPrivilegedPassword()); + headers.set("Access-Control-Expose-Headers", "X-Username X-Password"); } } return ResponseEntity.ok() @@ -144,7 +145,7 @@ public class ContainerEndpoint { @DeleteMapping("/{containerId}") @Transactional - @Observed(name = "dbrepo_metadata_container_delete") + @Observed(name = "dbrepo_container_delete") @PreAuthorize("hasAuthority('delete-container')") @Operation(summary = "Delete some container", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index 1cbf31337842d6c095bbf866b8c5914529ec37d5..b364e2dcfc6f7abc89ffc7d1a5dc2b1e521836f2 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -1,7 +1,6 @@ package at.tuwien.endpoints; import at.tuwien.api.amqp.ExchangeDto; -import at.tuwien.api.auth.LoginRequestDto; import at.tuwien.api.database.*; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.config.RabbitConfig; @@ -45,29 +44,27 @@ public class DatabaseEndpoint { private final UserService userService; private final RabbitConfig rabbitConfig; private final AccessService accessService; - private final BrokerService messageQueueService; + private final BrokerService brokerService; private final DatabaseMapper databaseMapper; private final StorageService storageService; private final DatabaseService databaseService; - private final AuthenticationService authenticationService; @Autowired public DatabaseEndpoint(UserService userService, RabbitConfig rabbitConfig, AccessService accessService, - BrokerService messageQueueService, DatabaseMapper databaseMapper, - StorageService storageService, DatabaseService databaseService, AuthenticationService authenticationService) { + BrokerService brokerService, DatabaseMapper databaseMapper, + StorageService storageService, DatabaseService databaseService) { this.userService = userService; this.rabbitConfig = rabbitConfig; this.accessService = accessService; - this.messageQueueService = messageQueueService; + this.brokerService = brokerService; this.databaseMapper = databaseMapper; this.storageService = storageService; this.databaseService = databaseService; - this.authenticationService = authenticationService; } @RequestMapping(method = {RequestMethod.GET, RequestMethod.HEAD}) @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_database_findall") + @Observed(name = "dbrepo_database_findall") @Operation(summary = "List databases") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -76,19 +73,19 @@ public class DatabaseEndpoint { mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = DatabaseDto.class)))}), }) - public ResponseEntity<List<DatabaseDto>> list(@RequestParam(name = "internal_name", required = false) String internalName) { + public ResponseEntity<List<DatabaseBriefDto>> list(@RequestParam(name = "internal_name", required = false) String internalName) { log.debug("endpoint list databases, internalName={}", internalName); - List<DatabaseDto> dtos = new LinkedList<>(); + List<DatabaseBriefDto> dtos = new LinkedList<>(); if (internalName != null) { try { - dtos = List.of(databaseMapper.databaseToDatabaseDto(databaseService.findByInternalName(internalName))); + dtos = List.of(databaseMapper.databaseToDatabaseBriefDto(databaseService.findByInternalName(internalName))); } catch (DatabaseNotFoundException e) { /* ignore */ } } else { dtos = databaseService.findAll() .stream() - .map(databaseMapper::databaseToDatabaseDto) + .map(databaseMapper::databaseToDatabaseBriefDto) .toList(); } log.trace("list databases resulted in {} database(s)", dtos.size()); @@ -103,7 +100,7 @@ public class DatabaseEndpoint { @PostMapping @Transactional(rollbackFor = Exception.class) @PreAuthorize("hasAuthority('create-database')") - @Observed(name = "dbrepo_metadata_database_create") + @Observed(name = "dbrepo_database_create") @Operation(summary = "Create database", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -122,7 +119,7 @@ public class DatabaseEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "Container, user or database could not be found", + description = "Failed to fin container/user/database in metadata database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -131,8 +128,13 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Connection to the database failed", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -149,10 +151,107 @@ public class DatabaseEndpoint { .body(dto); } + @PutMapping("/{databaseId}/metadata/table") + @Transactional(rollbackFor = {SearchServiceException.class, SearchServiceConnectionException.class, DatabaseNotFoundException.class}) + @PreAuthorize("hasAuthority('find-database')") + @Observed(name = "dbrepo_tables_refresh") + @Operation(summary = "Refresh database tables metadata", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "Refreshed database tables metadata", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = DatabaseDto.class))}), + @ApiResponse(responseCode = "400", + description = "Failed to parse payload at search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to refresh table metadata", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to fin user/database in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + }) + public ResponseEntity<DatabaseDto> refreshTableMetadata(@NotNull @PathVariable("databaseId") Long databaseId, + @NotNull Principal principal) throws ServiceException, + ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException, NotAllowedException, QueryNotFoundException, MalformedException { + log.debug("endpoint refresh database metadata, databaseId={}", databaseId); + Database database = databaseService.findById(databaseId); + if (!database.getOwner().equals(principal)) { + log.error("Failed to refresh database tables metadata: not owner"); + throw new NotAllowedException("Failed to refresh tables metadata: not owner"); + } + final DatabaseDto dto = databaseMapper.databaseToDatabaseDto(databaseService.updateTableMetadata(database)); + return ResponseEntity.ok(dto); + } + + @PutMapping("/{databaseId}/metadata/view") + @Transactional(rollbackFor = {SearchServiceException.class, SearchServiceConnectionException.class, DatabaseNotFoundException.class}) + @PreAuthorize("hasAuthority('find-database')") + @Observed(name = "dbrepo_views_refresh") + @Operation(summary = "Refresh database views metadata", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "Refreshed database views metadata", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = DatabaseDto.class))}), + @ApiResponse(responseCode = "403", + description = "Refresh view metadata is not permitted", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + }) + public ResponseEntity<DatabaseDto> refreshViewMetadata(@NotNull @PathVariable("databaseId") Long databaseId, + @NotNull Principal principal) throws ServiceException, + ServiceConnectionException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException, NotAllowedException, QueryNotFoundException { + log.debug("endpoint refresh database metadata, databaseId={}", databaseId); + Database database = databaseService.findById(databaseId); + if (!database.getOwner().equals(principal)) { + log.error("Failed to refresh database views metadata: not owner"); + throw new NotAllowedException("Failed to refresh database views metadata: not owner"); + } + final DatabaseDto dto = databaseMapper.databaseToDatabaseDto(databaseService.updateViewMetadata(database)); + return ResponseEntity.ok(dto); + } + @PutMapping("/{databaseId}/visibility") @Transactional @PreAuthorize("hasAuthority('modify-database-visibility')") - @Observed(name = "dbrepo_metadata_database_visibility") + @Observed(name = "dbrepo_database_visibility") @Operation(summary = "Update database visibility", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -160,13 +259,23 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = DatabaseDto.class))}), + @ApiResponse(responseCode = "403", + description = "Visibility modification is not permitted", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "Database could not be found", + description = "Failed to find database in metadata database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "403", - description = "Visibility modification is not permitted", + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -189,7 +298,7 @@ public class DatabaseEndpoint { @PutMapping("/{databaseId}/owner") @Transactional @PreAuthorize("hasAuthority('modify-database-owner')") - @Observed(name = "dbrepo_metadata_database_transfer") + @Observed(name = "dbrepo_database_transfer") @Operation(summary = "Update database owner", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -207,6 +316,16 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<DatabaseDto> transfer(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody DatabaseTransferDto data, @@ -229,7 +348,7 @@ public class DatabaseEndpoint { @PutMapping("/{databaseId}/image") @Transactional @PreAuthorize("hasAuthority('modify-database-image')") - @Observed(name = "dbrepo_metadata_database_image") + @Observed(name = "dbrepo_database_image") @Operation(summary = "Update database image", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -252,6 +371,16 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<DatabaseDto> modifyImage(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody DatabaseModifyImageDto data, @@ -277,7 +406,7 @@ public class DatabaseEndpoint { @GetMapping("/{databaseId}") @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_database_find") + @Observed(name = "dbrepo_database_find") @Operation(summary = "Find some database", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -290,11 +419,16 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "503", + @ApiResponse(responseCode = "502", description = "Connection to the broker service could not be established", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to find queue information in broker service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<DatabaseDto> findById(@NotNull @PathVariable("databaseId") Long databaseId, Principal principal) throws ServiceException, @@ -314,7 +448,7 @@ public class DatabaseEndpoint { final HttpHeaders headers = new HttpHeaders(); if (principal != null) { /* extra effort only when having access */ - final ExchangeDto exchange = messageQueueService.findExchange(rabbitConfig.getExchangeName()); + final ExchangeDto exchange = brokerService.findExchange(rabbitConfig.getExchangeName()); dto.setExchangeType(exchange.getType()); final Authentication authentication = (Authentication) principal; if (authentication.isAuthenticated() && authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("admin"))) { diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java index c5af4657ba3883c9ed469c31562223f112ee946c..726d118f1302ccb784e6ab440a24b6f0ea19bd1a 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java @@ -85,7 +85,7 @@ public class IdentifierEndpoint { @GetMapping(produces = {MediaType.APPLICATION_JSON_VALUE, "application/ld+json"}) @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_identifier_list") + @Observed(name = "dbrepo_identifier_list") @Operation(summary = "Find all identifiers") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -140,7 +140,7 @@ public class IdentifierEndpoint { MediaType.TEXT_XML_VALUE, "text/csv", "text/bibliography", "text/bibliography; style=apa", "text/bibliography; style=ieee", "text/bibliography; style=bibtex"}) @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_identifier_find") + @Observed(name = "dbrepo_identifier_find") @Operation(summary = "Find some identifier") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -158,37 +158,48 @@ public class IdentifierEndpoint { @ApiResponse(responseCode = "400", description = "Identifier could not be exported, the requested style is not known", content = {@Content( - mediaType = "text/bibliography", + mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", description = "Identifier could not be found", content = {@Content( - mediaType = "text/csv", + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "406", + description = "Failed to find acceptable representation", + content = {@Content( + mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "409", description = "Exported resource was not found", content = {@Content( - mediaType = "text/csv", + mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "410", description = "Failed to retrieve from S3 endpoint", content = {@Content( - mediaType = "text/csv", + mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "422", description = "Failed to retrieve from database sidecar", content = {@Content( - mediaType = "text/csv", + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to data service failed", + content = {@Content( + mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Identifier could not exported from database as it is not reachable", + description = "Failed to find in data service", content = {@Content( - mediaType = "text/csv", + mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<?> find(@Valid @PathVariable("identifierId") Long identifierId, @RequestHeader(HttpHeaders.ACCEPT) String accept) throws IdentifierNotFoundException, - ServiceException, ServiceConnectionException, MalformedException, FormatNotAvailableException, QueryNotFoundException { + ServiceException, ServiceConnectionException, MalformedException, FormatNotAvailableException, + QueryNotFoundException { log.debug("endpoint find identifier, identifierId={}, accept={}", identifierId, accept); final Identifier identifier = identifierService.find(identifierId); log.info("Found persistent identifier with id {}", identifier.getId()); @@ -252,7 +263,7 @@ public class IdentifierEndpoint { @DeleteMapping("/{identifierId}") @Transactional - @Observed(name = "dbrepo_metadata_identifier_delete") + @Observed(name = "dbrepo_identifier_delete") @PreAuthorize("hasAuthority('delete-identifier')") @Operation(summary = "Delete some identifier", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -267,7 +278,17 @@ public class IdentifierEndpoint { description = "Identifier or database could not be found", content = {@Content( mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}) + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to delete in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<?> delete(@NotNull @PathVariable("identifierId") Long identifierId) throws IdentifierNotFoundException, NotAllowedException, ServiceException, ServiceConnectionException, @@ -286,7 +307,7 @@ public class IdentifierEndpoint { @PutMapping("/{identifierId}/publish") @Transactional - @Observed(name = "dbrepo_metadata_identifier_publish") + @Observed(name = "dbrepo_identifier_publish") @PreAuthorize("hasAuthority('publish-identifier')") @Operation(summary = "Publish identifier", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -315,8 +336,13 @@ public class IdentifierEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "DataCite system did not respond", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -332,7 +358,7 @@ public class IdentifierEndpoint { @PutMapping("/{identifierId}") @Transactional(rollbackFor = {Exception.class}) - @Observed(name = "dbrepo_metadata_identifier_save") + @Observed(name = "dbrepo_identifier_save") @PreAuthorize("hasAuthority('create-identifier') or hasAuthority('create-foreign-identifier')") @Operation(summary = "Save identifier", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -361,8 +387,13 @@ public class IdentifierEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "DataCite system did not respond", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -452,7 +483,7 @@ public class IdentifierEndpoint { @PostMapping @Transactional(rollbackFor = {Exception.class}) - @Observed(name = "dbrepo_metadata_identifier_create") + @Observed(name = "dbrepo_identifier_create") @PreAuthorize("hasAuthority('create-identifier') or hasAuthority('create-foreign-identifier')") @Operation(summary = "Draft identifier", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -481,8 +512,13 @@ public class IdentifierEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "DataCite system did not respond", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -492,7 +528,7 @@ public class IdentifierEndpoint { UserNotFoundException, NotAllowedException, MalformedException, ServiceConnectionException, SearchServiceException, ServiceException, QueryNotFoundException, SearchServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { - log.debug("endpoint create identifier"); + log.debug("endpoint create identifier, data.databaseId={}", data.getDatabaseId()); final Database database = databaseService.findById(data.getDatabaseId()); final User user = userService.findByUsername(principal.getName()); /* check access */ @@ -512,7 +548,7 @@ public class IdentifierEndpoint { } @GetMapping("/retrieve") - @Observed(name = "dbrepo_metadata_identifier_retrieve") + @Observed(name = "dbrepo_identifier_retrieve") @Operation(summary = "Retrieve metadata from identifier") @ApiResponses(value = { @ApiResponse(responseCode = "200", diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java index 52428de24be047e9551928bfecac33212849c883..44b25250a882d0b094c0ee4a801bf2e8cbd2fb23 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java @@ -51,7 +51,7 @@ public class ImageEndpoint { @GetMapping @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_image_findall") + @Observed(name = "dbrepo_image_findall") @Operation(summary = "Find all images") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -71,7 +71,7 @@ public class ImageEndpoint { @PostMapping @Transactional - @Observed(name = "dbrepo_metadata_image_create") + @Observed(name = "dbrepo_image_create") @PreAuthorize("hasAuthority('create-image')") @Operation(summary = "Create image", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -108,7 +108,7 @@ public class ImageEndpoint { @GetMapping("/{imageId}") @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_image_find") + @Observed(name = "dbrepo_image_find") @Operation(summary = "Find some image") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -133,7 +133,7 @@ public class ImageEndpoint { @PutMapping("/{imageId}") @Transactional - @Observed(name = "dbrepo_metadata_image_update") + @Observed(name = "dbrepo_image_update") @PreAuthorize("hasAuthority('modify-image')") @Operation(summary = "Update some image", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @@ -162,7 +162,7 @@ public class ImageEndpoint { @DeleteMapping("/{imageId}") @Transactional - @Observed(name = "dbrepo_metadata_image_delete") + @Observed(name = "dbrepo_image_delete") @PreAuthorize("hasAuthority('delete-image')") @Operation(summary = "Delete some image", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java index 3763e9943c99ce84e26644b7fd494041ac1a418d..dd81274a29ffecdab3c7fdbed2dcb023d2a1a6eb 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java @@ -40,7 +40,7 @@ public class LicenseEndpoint { @GetMapping @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_license_findall") + @Observed(name = "dbrepo_license_findall") @Operation(summary = "Get all licenses") @ApiResponses(value = { @ApiResponse(responseCode = "200", diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java index ec7675b0d2616bf0bc45cc0efb2114ba219bcd81..bcff92bc49b00e61e9bdbea9fc4aff9435f06189 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java @@ -44,7 +44,7 @@ public class MessageEndpoint { } @GetMapping - @Observed(name = "dbrepo_metadata_maintenance_findall") + @Observed(name = "dbrepo_maintenance_findall") @Operation(summary = "Find maintenance messages") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -72,7 +72,7 @@ public class MessageEndpoint { } @GetMapping("/message/{messageId}") - @Observed(name = "dbrepo_metadata_maintenance_find") + @Observed(name = "dbrepo_maintenance_find") @Operation(summary = "Find one maintenance message") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -95,7 +95,7 @@ public class MessageEndpoint { } @PostMapping - @Observed(name = "dbrepo_metadata_maintenance_create") + @Observed(name = "dbrepo_maintenance_create") @Operation(summary = "Create maintenance message", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @PreAuthorize("hasAuthority('create-maintenance-message')") @ApiResponses(value = { @@ -114,7 +114,7 @@ public class MessageEndpoint { } @PutMapping("/{messageId}") - @Observed(name = "dbrepo_metadata_maintenance_update") + @Observed(name = "dbrepo_maintenance_update") @Operation(summary = "Update maintenance message", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @PreAuthorize("hasAuthority('update-maintenance-message')") @ApiResponses(value = { @@ -141,7 +141,7 @@ public class MessageEndpoint { } @DeleteMapping("/{messageId}") - @Observed(name = "dbrepo_metadata_maintenance_delete") + @Observed(name = "dbrepo_maintenance_delete") @Operation(summary = "Delete maintenance message", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @PreAuthorize("hasAuthority('delete-maintenance-message')") @ApiResponses(value = { diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java index c144511fda32956380f80a5392c53fd253ca5c72..18bf1c3e62b0302cb3fda314570cb00adfb2d040 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java @@ -43,7 +43,7 @@ public class MetadataEndpoint { @ExampleObject(value = "GetRecord"), @ExampleObject(value = "ListMetadataFormats"), }) - @Observed(name = "dbrepo_metadata_oai_identify") + @Observed(name = "dbrepo_oai_identify") @Operation(summary = "Identify the repository") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -56,7 +56,7 @@ public class MetadataEndpoint { } @GetMapping(params = "verb=Identify", produces = MediaType.TEXT_XML_VALUE) - @Observed(name = "dbrepo_metadata_oai_identify") + @Observed(name = "dbrepo_oai_identify") @Operation(summary = "Identify the repository") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -71,7 +71,7 @@ public class MetadataEndpoint { } @GetMapping(params = "verb=ListIdentifiers", produces = MediaType.TEXT_XML_VALUE) - @Observed(name = "dbrepo_metadata_oai_identifiers_list") + @Observed(name = "dbrepo_oai_identifiers_list") @Operation(summary = "List the identifiers") public ResponseEntity<String> listIdentifiers(OaiListIdentifiersParameters parameters) { log.debug("endpoint list identifiers, verb=ListIdentifiers, parameters={}", parameters); @@ -81,7 +81,7 @@ public class MetadataEndpoint { } @GetMapping(params = "verb=GetRecord", produces = MediaType.TEXT_XML_VALUE) - @Observed(name = "dbrepo_metadata_oai_record_get") + @Observed(name = "dbrepo_oai_record_get") @Operation(summary = "Get the record") public ResponseEntity<String> getRecord(OaiRecordParameters parameters) { log.debug("endpoint get record, verb=GetRecord, parameters={}", parameters); @@ -116,7 +116,7 @@ public class MetadataEndpoint { } @GetMapping(params = "verb=ListMetadataFormats", produces = MediaType.TEXT_XML_VALUE) - @Observed(name = "dbrepo_metadata_oai_metadataformats_list") + @Observed(name = "dbrepo_oai_metadataformats_list") @Operation(summary = "List the metadata formats") public ResponseEntity<String> listMetadataFormats() { log.debug("endpoint list metadata formats, verb=ListMetadataFormats"); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java index 80b646ed5fea2389db901bd24eb954bd5889beb8..d9a1b2c50b7014b30b581ecf8c5541c2a10892ba 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java @@ -45,7 +45,7 @@ public class OntologyEndpoint { } @GetMapping - @Observed(name = "dbrepo_metadata_ontologies_findall") + @Observed(name = "dbrepo_ontologies_findall") @Operation(summary = "List all ontologies") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -65,7 +65,7 @@ public class OntologyEndpoint { } @GetMapping("/{ontologyId}") - @Observed(name = "dbrepo_metadata_ontologies_find") + @Observed(name = "dbrepo_ontologies_find") @Operation(summary = "Find one ontology") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -79,7 +79,8 @@ public class OntologyEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<OntologyDto> find(@NotNull @PathVariable("ontologyId") Long ontologyId) throws OntologyNotFoundException { + public ResponseEntity<OntologyDto> find(@NotNull @PathVariable("ontologyId") Long ontologyId) + throws OntologyNotFoundException { log.debug("endpoint find all ontologies, ontologyId={}", ontologyId); final OntologyDto dto = ontologyMapper.ontologyToOntologyDto(ontologyService.find(ontologyId)); log.trace("create ontology resulted in dto {}", dto); @@ -88,7 +89,7 @@ public class OntologyEndpoint { @PostMapping @PreAuthorize("hasAuthority('create-ontology')") - @Observed(name = "dbrepo_metadata_ontologies_create") + @Observed(name = "dbrepo_ontologies_create") @Operation(summary = "Register a new ontology", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -108,7 +109,7 @@ public class OntologyEndpoint { @PutMapping("/{ontologyId}") @PreAuthorize("hasAuthority('update-ontology')") - @Observed(name = "dbrepo_metadata_ontologies_update") + @Observed(name = "dbrepo_ontologies_update") @Operation(summary = "Update an ontology", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -123,7 +124,8 @@ public class OntologyEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<OntologyDto> update(@NotNull @PathVariable("ontologyId") Long ontologyId, - @NotNull @Valid @RequestBody OntologyModifyDto data) throws OntologyNotFoundException { + @NotNull @Valid @RequestBody OntologyModifyDto data) + throws OntologyNotFoundException { log.debug("endpoint update ontology, data={}", data); final Ontology ontology = ontologyService.find(ontologyId); final OntologyDto dto = ontologyMapper.ontologyToOntologyDto(ontologyService.update(ontology, data)); @@ -134,7 +136,7 @@ public class OntologyEndpoint { @DeleteMapping("/{ontologyId}") @PreAuthorize("hasAuthority('delete-ontology')") - @Observed(name = "dbrepo_metadata_ontologies_delete") + @Observed(name = "dbrepo_ontologies_delete") @Operation(summary = "Delete an ontology", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -147,7 +149,8 @@ public class OntologyEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<?> delete(@NotNull @PathVariable("ontologyId") Long ontologyId) throws OntologyNotFoundException { + public ResponseEntity<?> delete(@NotNull @PathVariable("ontologyId") Long ontologyId) + throws OntologyNotFoundException { log.debug("endpoint delete ontology, ontologyId={}", ontologyId); final Ontology ontology = ontologyService.find(ontologyId); ontologyService.delete(ontology); @@ -157,7 +160,7 @@ public class OntologyEndpoint { @GetMapping("/{ontologyId}/entity") @PreAuthorize("hasAuthority('execute-semantic-query')") - @Observed(name = "dbrepo_metadata_ontologies_entities_find") + @Observed(name = "dbrepo_ontologies_entities_find") @Operation(summary = "Find entities", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 687e986acde08bef428f442f66e42c093f441a7d..6e008287baeba357273319a8263a06843f012049 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -77,7 +77,7 @@ public class TableEndpoint { @GetMapping @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_tables_findall") + @Observed(name = "dbrepo_tables_findall") @Operation(summary = "List all tables", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -114,7 +114,7 @@ public class TableEndpoint { @GetMapping("/{tableId}/suggest") @Transactional(readOnly = true) @PreAuthorize("hasAuthority('table-semantic-analyse')") - @Observed(name = "dbrepo_metadata_semantic_table_analyse") + @Observed(name = "dbrepo_semantic_table_analyse") @Operation(summary = "Suggest table semantics", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -122,8 +122,13 @@ public class TableEndpoint { content = {@Content( mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = TableColumnEntityDto.class)))}), + @ApiResponse(responseCode = "400", + description = "Failed to parse statistic in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "Could not find the table", + description = "Failed to find database/table in metadata database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -152,11 +157,31 @@ public class TableEndpoint { @PutMapping("/{tableId}") @Transactional @PreAuthorize("hasAuthority('admin')") - @Observed(name = "dbrepo_metadata_statistic_table_update") + @Observed(name = "dbrepo_statistic_table_update") @Operation(summary = "Update table statistics", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Updated table statistics successfully"), + @ApiResponse(responseCode = "400", + description = "Payload malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database/table in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> updateStatistic(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, @@ -174,7 +199,7 @@ public class TableEndpoint { @PutMapping("/{tableId}/column/{columnId}") @Transactional @PreAuthorize("hasAuthority('modify-table-column-semantics') or hasAuthority('modify-foreign-table-column-semantics')") - @Observed(name = "dbrepo_metadata_semantics_column_save") + @Observed(name = "dbrepo_semantics_column_save") @Operation(summary = "Update a table column semantic mapping", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -193,7 +218,17 @@ public class TableEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "Table or database could not be found", + description = "Failed to find user/table/database/ontology in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -225,7 +260,7 @@ public class TableEndpoint { @GetMapping("/{tableId}/column/{columnId}/suggest") @Transactional(readOnly = true) @PreAuthorize("hasAuthority('table-semantic-analyse')") - @Observed(name = "dbrepo_metadata_semantic_column_analyse") + @Observed(name = "dbrepo_semantic_column_analyse") @Operation(summary = "Suggest table column semantics", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -233,13 +268,13 @@ public class TableEndpoint { content = {@Content( mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = TableColumnEntityDto.class)))}), - @ApiResponse(responseCode = "404", - description = "Could not find the table column", + @ApiResponse(responseCode = "400", + description = "Generated query is malformed", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "417", - description = "Generated query is malformed", + @ApiResponse(responseCode = "404", + description = "Failed to find database/table in metadata database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -265,7 +300,7 @@ public class TableEndpoint { @PostMapping @Transactional(rollbackFor = {ServiceConnectionException.class, DatabaseNotFoundException.class, ServiceException.class}) @PreAuthorize("hasAuthority('create-table')") - @Observed(name = "dbrepo_metadata_table_create") + @Observed(name = "dbrepo_table_create") @Operation(summary = "Create a table", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -293,6 +328,16 @@ public class TableEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<TableDto> create(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @Valid @RequestBody TableCreateDto data, @@ -322,7 +367,7 @@ public class TableEndpoint { @GetMapping("/{tableId}") @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_tables_find") + @Observed(name = "dbrepo_tables_find") @Operation(summary = "Get information about table", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -340,8 +385,13 @@ public class TableEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Could not communicate with the broker service", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -380,7 +430,7 @@ public class TableEndpoint { @DeleteMapping("/{tableId}") @Transactional @PreAuthorize("hasAuthority('delete-table') or hasAuthority('delete-foreign-table')") - @Observed(name = "dbrepo_metadata_table_delete") + @Observed(name = "dbrepo_table_delete") @Operation(summary = "Delete a table", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -400,7 +450,17 @@ public class TableEndpoint { description = "Table, database or container could not be found", content = {@Content( mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}) + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<?> delete(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java index 79d0b4079bce7a67aeb00698fa5cdb780c064082..7808b1b2918eb55a901335f119e14d2dc9deb284 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java @@ -36,7 +36,7 @@ public class UnitEndpoint { @GetMapping @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_semantic_units_findall") + @Observed(name = "dbrepo_semantic_units_findall") @Operation(summary = "List semantic units") @ApiResponses(value = { @ApiResponse(responseCode = "200", diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java index 102b4670bccaf2516542d5df97e08f1bd3ff1135..4d5ad8164b97934f6d2b511266ca8a78d998614d 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java @@ -59,7 +59,7 @@ public class UserEndpoint { @GetMapping @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_users_list") + @Observed(name = "dbrepo_users_list") @Operation(summary = "Find all users") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -81,7 +81,7 @@ public class UserEndpoint { @PostMapping @Transactional(rollbackFor = {ServiceException.class, ServiceConnectionException.class}) @PreAuthorize("!isAuthenticated()") - @Observed(name = "dbrepo_metadata_user_create") + @Observed(name = "dbrepo_user_create") @Operation(summary = "Create user") @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -107,6 +107,16 @@ public class UserEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Failed to create in auth service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to create in auth service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<UserBriefDto> create(@NotNull @Valid @RequestBody SignupRequestDto data) throws UserExistsException, EmailExistsException, ServiceException, ServiceConnectionException, @@ -124,7 +134,7 @@ public class UserEndpoint { } @PostMapping("/token") - @Observed(name = "dbrepo_metadata_user_token") + @Observed(name = "dbrepo_user_token") @Operation(summary = "Obtain user token") @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -132,6 +142,31 @@ public class UserEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = TokenDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to get token", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find user in auth database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "428", + description = "Account is not fully setup in auth service (requires password change?)", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to auth service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to get user in auth service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<TokenDto> getToken(@NotNull @Valid @RequestBody LoginRequestDto data) throws ServiceException, ServiceConnectionException, UserNotFoundException, CredentialsInvalidException, @@ -157,7 +192,7 @@ public class UserEndpoint { } @PutMapping("/token") - @Observed(name = "dbrepo_metadata_user_refresh_token") + @Observed(name = "dbrepo_user_refresh_token") @Operation(summary = "Refresh user token") @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -165,6 +200,16 @@ public class UserEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = TokenDto.class))}), + @ApiResponse(responseCode = "403", + description = "Invalid refresh token", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to auth service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<TokenDto> refreshToken(@NotNull @Valid @RequestBody RefreshTokenRequestDto data) throws ServiceConnectionException, CredentialsInvalidException { @@ -178,7 +223,7 @@ public class UserEndpoint { @GetMapping("/{userId}") @Transactional(readOnly = true) @PreAuthorize("isAuthenticated()") - @Observed(name = "dbrepo_metadata_user_find") + @Observed(name = "dbrepo_user_find") @Operation(summary = "Get a user info", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -217,7 +262,7 @@ public class UserEndpoint { @PutMapping("/{userId}") @Transactional @PreAuthorize("hasAuthority('modify-user-information')") - @Observed(name = "dbrepo_metadata_user_modify") + @Observed(name = "dbrepo_user_modify") @Operation(summary = "Modify user information", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -230,11 +275,21 @@ public class UserEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to modify user metadata", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database/user in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<UserDto> modify(@NotNull @PathVariable("userId") UUID userId, @NotNull @Valid @RequestBody UserUpdateDto data, - @NotNull Principal principal) throws ServiceException, - ServiceConnectionException, NotAllowedException, UserNotFoundException, DatabaseNotFoundException { + @NotNull Principal principal) throws NotAllowedException, + UserNotFoundException, DatabaseNotFoundException { log.debug("endpoint modify a user, userId={}, data={}", userId, data); User user = userService.findById(userId); if (!user.equals(principal)) { @@ -250,7 +305,7 @@ public class UserEndpoint { @PutMapping("/{userId}/password") @Transactional @PreAuthorize("isAuthenticated()") - @Observed(name = "dbrepo_metadata_user_password_modify") + @Observed(name = "dbrepo_user_password_modify") @Operation(summary = "Modify user password", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -258,6 +313,26 @@ public class UserEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = UserDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to change foreign user password", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database/user in metadata database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to auth service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to get user in auth service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<?> password(@NotNull @PathVariable("userId") UUID userId, @NotNull @Valid @RequestBody UserPasswordDto data, diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 767d6f74eae2aebdcc80f06bd7c4fd9996dd4d52..a6627689aa3f4c52098b90271b77aa64881bd90b 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -58,7 +58,7 @@ public class ViewEndpoint { @GetMapping @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_views_findall") + @Observed(name = "dbrepo_views_findall") @Operation(summary = "Find all views", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -89,7 +89,7 @@ public class ViewEndpoint { @PostMapping @Transactional @PreAuthorize("hasAuthority('create-database-view')") - @Observed(name = "dbrepo_metadata_view_create") + @Observed(name = "dbrepo_view_create") @Operation(summary = "Create a view", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -113,7 +113,7 @@ public class ViewEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", - description = "Database or user could not be found", + description = "Failed to find database/user in metadata database.", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -127,8 +127,13 @@ public class ViewEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Connection to the database failed", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -155,7 +160,7 @@ public class ViewEndpoint { @GetMapping("/{viewId}") @Transactional(readOnly = true) - @Observed(name = "dbrepo_metadata_view_find") + @Observed(name = "dbrepo_view_find") @Operation(summary = "Find one view", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -202,7 +207,7 @@ public class ViewEndpoint { @DeleteMapping("/{viewId}") @Transactional @PreAuthorize("hasAuthority('delete-database-view')") - @Observed(name = "dbrepo_metadata_view_delete") + @Observed(name = "dbrepo_view_delete") @Operation(summary = "Delete one view", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -233,8 +238,13 @@ public class ViewEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "503", - description = "Connection to the database failed", + description = "Failed to save in search service", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java index e1cad8fbb68d47c90b0730c3bdcf2b92e7f2229e..bca87e510e1d849c371f76d79f39b7471d9413d2 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java @@ -53,7 +53,7 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { } @Hidden - @ResponseStatus(code = HttpStatus.UNAUTHORIZED) + @ResponseStatus(code = HttpStatus.FORBIDDEN) @ExceptionHandler(CredentialsInvalidException.class) public ResponseEntity<ApiErrorDto> handle(CredentialsInvalidException e) { return generic_handle(e.getClass(), e.getLocalizedMessage()); diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml b/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml index 3cf8b37d3167d287f8580d1f8e857e533324f65e..6f69d7737cb69c1aab6d3af2b8f3bf0082e6c4ee 100644 --- a/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml +++ b/dbrepo-metadata-service/rest-service/src/main/resources/application-local.yml @@ -1,6 +1,6 @@ spring: datasource: - url: jdbc:mariadb://localhost:3306/fda + url: jdbc:mariadb://localhost:3306/dbrepo driver-class-name: org.mariadb.jdbc.Driver username: root password: dbrepo @@ -62,7 +62,7 @@ dbrepo: username: admin password: admin endpoints: - searchService: http://localhost:5000 + searchService: http://localhost:4000 dataService: http://localhost:9093 brokerService: http://localhost/admin/broker authService: http://localhost:8080 diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java index ac5963a12529c13d37da89f51d6021450314e38c..08233dfd4478321c77b5662d02f7dd4d6bc053b2 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java @@ -420,10 +420,10 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } /* test */ - final ResponseEntity<List<DatabaseDto>> response = databaseEndpoint.list(internalName); + final ResponseEntity<List<DatabaseBriefDto>> response = databaseEndpoint.list(internalName); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); - final List<DatabaseDto> body = response.getBody(); + final List<DatabaseBriefDto> body = response.getBody(); assertEquals(databases.size(), body.size()); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java index 799fdee0053dd706caafe144469f810b6eea766f..d685ca65cd0478aa06ec8c9a2aa7bcfdcc61a804 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/OpenApiEndpointMvcTest.java @@ -3,6 +3,7 @@ package at.tuwien.mvc; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.endpoints.*; import at.tuwien.test.AbstractUnitTest; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.log4j.Log4j2; @@ -11,7 +12,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; @@ -19,9 +19,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; import java.lang.reflect.Method; import java.util.Arrays; -import java.util.LinkedList; import java.util.List; -import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -116,7 +114,7 @@ public class OpenApiEndpointMvcTest extends AbstractUnitTest { private void generic_openApiDocs(Class<?> endpoint) { final List<Method> methods = Arrays.stream(endpoint.getMethods()) - .filter(m -> m.getDeclaringClass().equals(AccessEndpoint.class)) + .filter(m -> m.getDeclaringClass().equals(endpoint)) .toList(); methods.forEach(m -> { final List<Class<?>> exceptions = Arrays.stream(m.getExceptionTypes()) @@ -126,6 +124,7 @@ public class OpenApiEndpointMvcTest extends AbstractUnitTest { .toList(); assertTrue(invalidExceptions.isEmpty(), "method '" + m.getName() + "' throws exception(s) outside package scope at.tuwien: " + invalidExceptions.stream().map(Class::getName).toList()); exceptions.forEach(exception -> { + assertNotNull(m.getDeclaredAnnotation(Operation.class).summary()); final int status = exception.getAnnotation(ResponseStatus.class) .code() .value(); @@ -143,7 +142,7 @@ public class OpenApiEndpointMvcTest extends AbstractUnitTest { assertNotNull(response.content()); assertTrue(response.content().length > 0); final Content content0 = response.content()[0]; - assertEquals(MediaType.APPLICATION_JSON_VALUE, content0.mediaType()); + assertEquals(MediaType.APPLICATION_JSON_VALUE, content0.mediaType(), "method " + m.getName() + " and status " + status + " should return JSON"); assertEquals(ApiErrorDto.class, content0.schema().implementation()); }); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index 8b479cabf3e4e308dc79c8b5587c4e2aa735eaf8..76678a1fe376b77926d1929b5888a649e2c9d512 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -2,15 +2,20 @@ package at.tuwien.mvc; import at.tuwien.api.auth.RefreshTokenRequestDto; import at.tuwien.api.database.table.TableStatisticDto; +import at.tuwien.api.database.table.columns.ColumnStatisticDto; +import at.tuwien.api.semantics.TableColumnEntityDto; import at.tuwien.test.AbstractUnitTest; import at.tuwien.api.container.ContainerCreateDto; import at.tuwien.api.database.*; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.config.MetricsConfig; import at.tuwien.endpoints.*; +import io.micrometer.observation.annotation.Observed; import io.micrometer.observation.tck.TestObservationRegistry; +import io.swagger.v3.oas.annotations.Operation; import lombok.extern.log4j.Log4j2; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -30,11 +35,10 @@ import org.springframework.test.web.servlet.MockMvc; import java.io.File; import java.io.IOException; +import java.lang.reflect.Method; +import java.math.BigDecimal; import java.nio.charset.Charset; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import static io.micrometer.observation.tck.TestObservationRegistryAssert.assertThat; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -80,7 +84,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { private LicenseEndpoint licenseEndpoint; @Autowired - private MessageEndpoint maintenanceEndpoint; + private MessageEndpoint messageEndpoint; @Autowired private MetadataEndpoint metadataEndpoint; @@ -97,7 +101,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { @Autowired private ViewEndpoint viewEndpoint; - private static final List<String> metrics = new LinkedList<>(); + private static final Map<String, String> metrics = new TreeMap<>(); /* sorted */ @TestConfiguration static class ObservationTestConfiguration { @@ -110,15 +114,12 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { @BeforeAll public static void beforeAll() { - FileUtils.deleteQuietly(new File("../metrics.txt")); + FileUtils.deleteQuietly(new File("../metrics.md")); } @AfterAll public static void afterAll() throws IOException { - Collections.sort(metrics); - final StringBuilder content = new StringBuilder("# AUTOGENERATED FILE (DO NOT EDIT)\n") - .append(String.join("\n", metrics)); - FileUtils.writeStringToFile(new File("../metrics.txt"), content.toString(), Charset.defaultCharset()); + saveObservedMetrics(metrics); } @Test @@ -157,11 +158,11 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_access_give", "dbrepo_metadata_access_get", "dbrepo_metadata_access_modify", "dbrepo_metadata_access_get", "dbrepo_metadata_access_delete")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_access_give", "dbrepo_access_get", "dbrepo_access_modify", "dbrepo_access_get", "dbrepo_access_delete")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(AccessEndpoint.class); } @Test @@ -191,11 +192,11 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_container_findall", "dbrepo_metadata_container_create", "dbrepo_metadata_container_find", "dbrepo_metadata_container_delete")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_container_findall", "dbrepo_container_create", "dbrepo_container_find", "dbrepo_container_delete")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(ContainerEndpoint.class); } @Test @@ -235,11 +236,11 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_database_findall", "dbrepo_metadata_database_create", "dbrepo_metadata_database_visibility", "dbrepo_metadata_database_transfer", "dbrepo_metadata_database_find", "dbrepo_metadata_database_image")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_database_findall", "dbrepo_database_create", "dbrepo_database_visibility", "dbrepo_database_transfer", "dbrepo_database_find", "dbrepo_database_image")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(DatabaseEndpoint.class); } @Test @@ -279,13 +280,13 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_identifier_create", "dbrepo_metadata_identifier_retrieve", - "dbrepo_metadata_identifier_list", "dbrepo_metadata_identifier_save", - "dbrepo_metadata_identifier_publish")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_identifier_create", "dbrepo_identifier_retrieve", + "dbrepo_identifier_list", "dbrepo_identifier_save", + "dbrepo_identifier_publish")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(IdentifierEndpoint.class); } @Test @@ -320,12 +321,12 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_image_findall", "dbrepo_metadata_image_create", - "dbrepo_metadata_image_find", "dbrepo_metadata_image_update", "dbrepo_metadata_image_delete")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_image_findall", "dbrepo_image_create", + "dbrepo_image_find", "dbrepo_image_update", "dbrepo_image_delete")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(ImageEndpoint.class); } @Test @@ -340,9 +341,9 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - metrics.add("dbrepo_metadata_license_findall"); assertThat(registry) - .hasObservationWithNameEqualTo("dbrepo_metadata_license_findall"); + .hasObservationWithNameEqualTo("dbrepo_license_findall"); + generic_openApiDocs(LicenseEndpoint.class); } @Test @@ -351,37 +352,37 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* mock */ try { - maintenanceEndpoint.list(""); + messageEndpoint.list(""); } catch (Exception e) { /* ignore */ } try { - maintenanceEndpoint.find(BANNER_MESSAGE_1_ID); + messageEndpoint.find(BANNER_MESSAGE_1_ID); } catch (Exception e) { /* ignore */ } try { - maintenanceEndpoint.create(BANNER_MESSAGE_1_CREATE_DTO); + messageEndpoint.create(BANNER_MESSAGE_1_CREATE_DTO); } catch (Exception e) { /* ignore */ } try { - maintenanceEndpoint.update(BANNER_MESSAGE_1_ID, BANNER_MESSAGE_1_UPDATE_DTO); + messageEndpoint.update(BANNER_MESSAGE_1_ID, BANNER_MESSAGE_1_UPDATE_DTO); } catch (Exception e) { /* ignore */ } try { - maintenanceEndpoint.delete(BANNER_MESSAGE_1_ID); + messageEndpoint.delete(BANNER_MESSAGE_1_ID); } catch (Exception e) { /* ignore */ } /* test */ - for (String metric : List.of("dbrepo_metadata_maintenance_findall", "dbrepo_metadata_maintenance_find", "dbrepo_metadata_maintenance_create", "dbrepo_metadata_maintenance_update", "dbrepo_metadata_maintenance_delete")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_maintenance_findall", "dbrepo_maintenance_find", "dbrepo_maintenance_create", "dbrepo_maintenance_update", "dbrepo_maintenance_delete")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(MessageEndpoint.class); } @Test @@ -411,11 +412,11 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_oai_identify", "dbrepo_metadata_oai_identifiers_list", "dbrepo_metadata_oai_record_get", "dbrepo_metadata_oai_metadataformats_list")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_oai_identify", "dbrepo_oai_identifiers_list", "dbrepo_oai_record_get", "dbrepo_oai_metadataformats_list")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(MetadataEndpoint.class); } @Test @@ -455,105 +456,61 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_ontologies_findall", "dbrepo_metadata_ontologies_find", "dbrepo_metadata_ontologies_create", "dbrepo_metadata_ontologies_update", "dbrepo_metadata_ontologies_delete", "dbrepo_metadata_ontologies_entities_find")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_ontologies_findall", "dbrepo_ontologies_find", "dbrepo_ontologies_create", "dbrepo_ontologies_update", "dbrepo_ontologies_delete", "dbrepo_ontologies_entities_find")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(OntologyEndpoint.class); } @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-identifier-metadata", "delete-identifier"}) - public void prometheusPersistenceEndpoint_succeeds() { + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-semantic-concept", "admin"}) + public void prometheusConceptEndpoint_succeeds() { /* mock */ try { - identifierEndpoint.find(IDENTIFIER_1_ID, null); - } catch (Exception e) { - /* ignore */ - } - try { - identifierEndpoint.delete(IDENTIFIER_1_ID); + conceptEndpoint.findAll(); } catch (Exception e) { /* ignore */ } /* test */ - for (String metric : List.of("dbrepo_metadata_identifier_find", "dbrepo_metadata_identifier_delete")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_semantic_concepts_findall")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(ConceptEndpoint.class); } @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"create-semantic-concept", "create-semantic-unit", "table-semantic-analyse", "admin"}) - public void prometheusSemanticsEndpoint_succeeds() { + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-semantic-unit", "admin"}) + public void prometheusUnitEndpoint_succeeds() { /* mock */ - try { - conceptEndpoint.findAll(); - } catch (Exception e) { - /* ignore */ - } try { unitEndpoint.findAll(); } catch (Exception e) { /* ignore */ } - try { - tableEndpoint.analyseTable(DATABASE_1_ID, TABLE_1_ID); - } catch (Exception e) { - /* ignore */ - } - try { - tableEndpoint.updateStatistic(DATABASE_1_ID, TABLE_1_ID, TableStatisticDto.builder() - .columns(new HashMap<>()) - .build()); - } catch (Exception e) { - /* ignore */ - } - try { - tableEndpoint.analyseTableColumn(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId()); - } catch (Exception e) { - /* ignore */ - } /* test */ - for (String metric : List.of("dbrepo_metadata_semantic_concepts_findall", - "dbrepo_metadata_statistic_table_update", "dbrepo_metadata_semantic_units_findall", - "dbrepo_metadata_semantic_table_analyse", "dbrepo_metadata_semantic_column_analyse")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_semantic_units_findall")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(UnitEndpoint.class); } @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics", "modify-foreign-table-column-semantics"}) - public void prometheusTableColumnEndpoint_succeeds() { + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-table", "delete-table", + "modify-table-column-semantics", "modify-foreign-table-column-semantics", "admin", + "table-semantic-analyse"}) + public void prometheusTableEndpoint_succeeds() { final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() .unitUri(UNIT_1_URI) .conceptUri(CONCEPT_1_URI) .build(); - /* mock */ - try { - tableEndpoint.update(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(3).getId(), request, USER_1_PRINCIPAL); - } catch (Exception e) { - /* ignore */ - } - - /* test */ - metrics.add("dbrepo_metadata_semantics_column_save"); - assertThat(registry) - .hasObservationWithNameEqualTo("dbrepo_metadata_semantics_column_save"); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"create-table", "delete-table"}) - public void prometheusTableEndpoint_succeeds() { - /* mock */ try { tableEndpoint.list(DATABASE_1_ID, USER_1_PRINCIPAL); @@ -575,14 +532,35 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } catch (Exception e) { /* ignore */ } + try { + tableEndpoint.analyseTable(DATABASE_1_ID, TABLE_1_ID); + } catch (Exception e) { + /* ignore */ + } + try { + tableEndpoint.updateStatistic(DATABASE_1_ID, TABLE_1_ID, TableStatisticDto.builder().build()); + } catch (Exception e) { + /* ignore */ + } + try { + tableEndpoint.analyseTableColumn(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId()); + } catch (Exception e) { + /* ignore */ + } + try { + tableEndpoint.update(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(3).getId(), request, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } /* test */ - for (String metric : List.of("dbrepo_metadata_tables_findall", "dbrepo_metadata_table_create", - "dbrepo_metadata_tables_find", "dbrepo_metadata_table_delete")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_tables_findall", "dbrepo_table_create", "dbrepo_tables_find", + "dbrepo_table_delete", "dbrepo_statistic_table_update", "dbrepo_semantic_table_analyse", + "dbrepo_semantic_column_analyse", "dbrepo_semantics_column_save")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(TableEndpoint.class); } @Test @@ -617,12 +595,12 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_user_refresh_token", "dbrepo_metadata_users_list", - "dbrepo_metadata_user_find", "dbrepo_metadata_user_modify", "dbrepo_metadata_user_password_modify")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_user_refresh_token", "dbrepo_users_list", + "dbrepo_user_find", "dbrepo_user_modify", "dbrepo_user_password_modify")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(UserEndpoint.class); } @Test @@ -642,11 +620,11 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_user_create", "dbrepo_metadata_user_token")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_user_create", "dbrepo_user_token")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + // already done above } @Test @@ -676,12 +654,21 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } /* test */ - for (String metric : List.of("dbrepo_metadata_views_findall", "dbrepo_metadata_view_create", - "dbrepo_metadata_view_find", "dbrepo_metadata_view_delete")) { - metrics.add(metric); + for (String metric : List.of("dbrepo_views_findall", "dbrepo_view_create", + "dbrepo_view_find", "dbrepo_view_delete")) { assertThat(registry) .hasObservationWithNameEqualTo(metric); } + generic_openApiDocs(ViewEndpoint.class); + } + + private static void generic_openApiDocs(Class<?> endpoint) { + final List<Method> methods = Arrays.stream(endpoint.getMethods()) + .filter(m -> m.getDeclaringClass().equals(endpoint)) + .toList(); + methods.forEach(m -> { + metrics.put(m.getDeclaredAnnotation(Observed.class).name(), m.getDeclaredAnnotation(Operation.class).summary()); + }); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java index 602c46fee55e0be90906095919d07325061c011e..d0323941dfbd61bd9460082e6d7f0c21a3e2ecf6 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ConceptServiceUnitTest.java @@ -12,7 +12,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; @@ -27,7 +26,7 @@ import static org.mockito.Mockito.when; public class ConceptServiceUnitTest extends AbstractUnitTest { @MockBean - private ConceptRepository conceptRepository;; + private ConceptRepository conceptRepository; @Autowired private ConceptService conceptService; @@ -38,7 +37,6 @@ public class ConceptServiceUnitTest extends AbstractUnitTest { } @Test - @Transactional public void findAll_succeeds() { /* mock */ @@ -52,7 +50,6 @@ public class ConceptServiceUnitTest extends AbstractUnitTest { } @Test - @Transactional public void find_succeeds() throws ConceptNotFoundException { /* mock */ @@ -67,7 +64,6 @@ public class ConceptServiceUnitTest extends AbstractUnitTest { } @Test - @Transactional public void findConcept_fails() { /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java index 2968c6f80d9955780ddaece852e850c95400d1ed..f28cc0b9b105f81feee49aabd9647af2cdf9624f 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java @@ -61,12 +61,6 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { @Autowired private DatabaseRepository databaseRepository; - @Autowired - private ConceptRepository conceptRepository; - - @Autowired - private UnitRepository unitRepository; - private final ParameterizedTypeReference<DataCiteBody<DataCiteDoi>> dataCiteBodyParameterizedTypeReference = new ParameterizedTypeReference<>() { }; @@ -76,8 +70,6 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { /* metadata database */ licenseRepository.save(LICENSE_1); containerRepository.save(CONTAINER_1); - conceptRepository.save(CONCEPT_1); - unitRepository.save(UNIT_1); userRepository.saveAll(List.of(USER_1, USER_2, USER_3, USER_4)); databaseRepository.save(DATABASE_1); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java index b9072ac7c73ae4a132685410997c31be52e0c5ec..ed5f21281d71961317a4779aa67b38d0d9b9dca1 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java @@ -2,6 +2,8 @@ package at.tuwien.service; import at.tuwien.entities.database.Database; import at.tuwien.exception.*; +import at.tuwien.gateway.DataServiceGateway; +import at.tuwien.gateway.SearchServiceGateway; import at.tuwien.repository.*; import at.tuwien.service.impl.DatabaseServiceImpl; import at.tuwien.test.AbstractUnitTest; @@ -12,21 +14,32 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; import java.util.List; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; @Log4j2 @SpringBootTest -@Disabled("keep failing on CI but works locally") +@Disabled("CI/CD") +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @ExtendWith(SpringExtension.class) public class DatabaseServicePersistenceTest extends AbstractUnitTest { + @MockBean + private DataServiceGateway dataServiceGateway; + + @MockBean + private SearchServiceGateway searchServiceGateway; + @Autowired - private DatabaseServiceImpl databaseService; + private DatabaseService databaseService; @Autowired private UserRepository userRepository; @@ -92,4 +105,20 @@ public class DatabaseServicePersistenceTest extends AbstractUnitTest { assertNotNull(response.getCreator().getAccesses()); } + @Test + public void updateTableMetadata_succeeds() throws SearchServiceException, MalformedException, ServiceException, + QueryNotFoundException, DatabaseNotFoundException, ServiceConnectionException, + SearchServiceConnectionException { + + /* mock */ + when(dataServiceGateway.getTableSchemas(DATABASE_1_ID)) + .thenReturn(List.of(TABLE_5_DTO)); + when(searchServiceGateway.update(any(Database.class))) + .thenReturn(DATABASE_1_DTO); /* ignored */ + + /* test */ + final Database response = databaseService.updateTableMetadata(DATABASE_1); + log.debug(""); + } + } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java index e50276d77da7980d8a94a2a0f84eda12c3da70f1..6c6357aaf63aeed98a6649f68c47bb63ae62946d 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java @@ -48,7 +48,7 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { private ContainerRepository containerRepository; @Autowired - private DatabaseServiceImpl databaseService; + private DatabaseService databaseService; @BeforeEach public void beforeEach() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServicePersistenceTest.java similarity index 92% rename from dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceIntegrationTest.java rename to dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServicePersistenceTest.java index cc79e0ca4c63004041b2bcaeb54203efecfcf8dc..50e0dc08f657fb5230838397c90a21a619d8bd8b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceIntegrationTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServicePersistenceTest.java @@ -5,7 +5,6 @@ import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.exception.ImageAlreadyExistsException; import at.tuwien.repository.ContainerRepository; import at.tuwien.repository.ImageRepository; -import at.tuwien.service.impl.ImageServiceImpl; import lombok.extern.log4j.Log4j2; import org.apache.http.auth.BasicUserPrincipal; import org.junit.jupiter.api.BeforeEach; @@ -24,10 +23,10 @@ import static org.junit.jupiter.api.Assertions.*; @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @ExtendWith(SpringExtension.class) @SpringBootTest -public class ImageServiceIntegrationTest extends AbstractUnitTest { +public class ImageServicePersistenceTest extends AbstractUnitTest { @Autowired - private ImageServiceImpl imageService; + private ImageService imageService; @Autowired private ImageRepository imageRepository; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java index f486f5db11c006374d7fdf4185a5536d155f876c..bce3c7bc125636591d86a83311a4315ab677fba3 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java @@ -31,7 +31,7 @@ public class ImageServiceUnitTest extends AbstractUnitTest { private ImageRepository imageRepository; @Autowired - private ImageServiceImpl imageService; + private ImageService imageService; @Test public void getAll_succeeds() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java index 6db5522dccd87fe8008c453accc960d5ca190337..91b64ef93c52e38a83a42fb4d39cd0c966f2ce67 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java @@ -3,13 +3,10 @@ package at.tuwien.service; import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; -import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; -import at.tuwien.api.database.table.constraints.foreignKey.ForeignKeyCreateDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.database.table.columns.TableColumnConcept; import at.tuwien.entities.database.table.columns.TableColumnType; import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey; import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; @@ -21,17 +18,17 @@ import at.tuwien.repository.*; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; @@ -40,6 +37,8 @@ import static org.mockito.Mockito.*; @Log4j2 @SpringBootTest +@Disabled("CI/CD") +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @ExtendWith(SpringExtension.class) public class TableServicePersistenceTest extends AbstractUnitTest { @@ -64,12 +63,6 @@ public class TableServicePersistenceTest extends AbstractUnitTest { @Autowired private DatabaseRepository databaseRepository; - @Autowired - private ConceptRepository conceptRepository; - - @Autowired - private UnitRepository unitRepository; - @Autowired private TableService tableService; @@ -80,8 +73,6 @@ public class TableServicePersistenceTest extends AbstractUnitTest { licenseRepository.save(LICENSE_1); containerRepository.save(CONTAINER_1); userRepository.saveAll(List.of(USER_1, USER_2, USER_3)); - conceptRepository.save(CONCEPT_1); - unitRepository.save(UNIT_1); databaseRepository.saveAll(List.of(DATABASE_1)); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java index c57c7e59345a4d90b9fc0a516bfe0cdc20a96b1f..0e74c54947e0693090f43a3a25809473c6c6a609 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java @@ -4,11 +4,9 @@ import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; -import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.foreignKey.ForeignKeyCreateDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyCreateDto; import at.tuwien.entities.database.table.columns.TableColumnType; import at.tuwien.entities.database.table.constraints.Constraints; -import at.tuwien.repository.OntologyRepository; import at.tuwien.test.AbstractUnitTest; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.entities.database.Database; diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f686a1c23a15b4728395ee3ca0c0ec0353071a45 --- /dev/null +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java @@ -0,0 +1,68 @@ +package at.tuwien.service; + +import at.tuwien.entities.database.View; +import at.tuwien.exception.*; +import at.tuwien.repository.ContainerRepository; +import at.tuwien.repository.DatabaseRepository; +import at.tuwien.repository.LicenseRepository; +import at.tuwien.repository.UserRepository; +import at.tuwien.test.AbstractUnitTest; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@Log4j2 +@SpringBootTest +@Disabled("CI/CD") +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@ExtendWith(SpringExtension.class) +public class ViewServicePersistenceTest extends AbstractUnitTest { + + @Autowired + private UserRepository userRepository; + + @Autowired + private LicenseRepository licenseRepository; + + @Autowired + private ContainerRepository containerRepository; + + @Autowired + private DatabaseRepository databaseRepository; + + @Autowired + private ViewService viewService; + + @BeforeEach + public void beforeEach() { + genesis(); + /* metadata database */ + licenseRepository.save(LICENSE_1); + containerRepository.save(CONTAINER_1); + userRepository.saveAll(List.of(USER_1, USER_2, USER_3)); + databaseRepository.save(DATABASE_1); + } + + @Test + public void findById_succeeds() throws ViewNotFoundException { + + /* test */ + final View response = viewService.findById(DATABASE_1, VIEW_1_ID); + assertEquals(VIEW_1_ID, response.getId()); + assertEquals(VIEW_1_NAME, response.getName()); + assertEquals(VIEW_1_INTERNAL_NAME, response.getInternalName()); + assertEquals(VIEW_1_QUERY, response.getQuery()); + assertEquals(VIEW_1_COLUMNS.size(), response.getColumns().size()); + } + +} diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java index f3987fc93be59b74e79caf2aa9e655b48fb82b14..da345658ef9897deba1486fc4b9d009823c3e459 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java @@ -57,9 +57,8 @@ public class ViewServiceUnitTest extends AbstractUnitTest { .build(); /* mock */ - doNothing() - .when(dataServiceGateway) - .createView(DATABASE_1_ID, request); + when(dataServiceGateway.createView(DATABASE_1_ID, request)) + .thenReturn(VIEW_1_DTO); when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(searchServiceGateway.update(any(Database.class))) diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/init/weather.sql b/dbrepo-metadata-service/rest-service/src/test/resources/init/weather.sql index b6dd8cff4cd1dabf0848697cb8db26db4e798601..19033d25486a4360bedbd9731437bc3809aa4180 100644 --- a/dbrepo-metadata-service/rest-service/src/test/resources/init/weather.sql +++ b/dbrepo-metadata-service/rest-service/src/test/resources/init/weather.sql @@ -9,15 +9,7 @@ CREATE TABLE weather_location location VARCHAR(255) PRIMARY KEY, lat DOUBLE PRECISION NULL, lng DOUBLE PRECISION NULL -) WITH SYSTEM VERSIONING; - -CREATE VIEW `hs_weather_location` AS -SELECT * -FROM (SELECT ROW_START AS inserted_at, IF(ROW_END > NOW(), NULL, ROW_END) AS deleted_at, COUNT(*) as total - FROM `weather_location` FOR SYSTEM_TIME ALL - GROUP BY inserted_at, deleted_at - ORDER BY deleted_at DESC LIMIT 50) AS v -ORDER BY v.inserted_at, v.deleted_at ASC; +) WITH SYSTEM VERSIONING COMMENT 'Weather location'; CREATE TABLE weather_aus ( @@ -29,29 +21,19 @@ CREATE TABLE weather_aus FOREIGN KEY (location) REFERENCES weather_location (location), UNIQUE (`date`), CHECK (`mintemp` > 0) -) WITH SYSTEM VERSIONING; - -CREATE VIEW `hs_weather_aus` AS -SELECT * -FROM (SELECT ROW_START AS inserted_at, IF(ROW_END > NOW(), NULL, ROW_END) AS deleted_at, COUNT(*) as total - FROM `weather_aus` FOR SYSTEM_TIME ALL - GROUP BY inserted_at, deleted_at - ORDER BY deleted_at DESC LIMIT 50) AS v -ORDER BY v.inserted_at, v.deleted_at ASC; +) WITH SYSTEM VERSIONING COMMENT 'Weather in the world'; CREATE TABLE sensor ( `timestamp` TIMESTAMP NOT NULL PRIMARY KEY, `value` DECIMAL -) WITH SYSTEM VERSIONING; +) WITH SYSTEM VERSIONING COMMENT 'Some sensor data'; -CREATE VIEW `hs_sensor` AS -SELECT * -FROM (SELECT ROW_START AS inserted_at, IF(ROW_END > NOW(), NULL, ROW_END) AS deleted_at, COUNT(*) as total - FROM `sensor` FOR SYSTEM_TIME ALL - GROUP BY inserted_at, deleted_at - ORDER BY deleted_at DESC LIMIT 50) AS v -ORDER BY v.inserted_at, v.deleted_at ASC; +CREATE TABLE sensor_2 +( + `timestamp` TIMESTAMP NOT NULL PRIMARY KEY, + `value` DECIMAL +) WITH SYSTEM VERSIONING COMMENT 'Hello sensor'; -- sequence not in metadata on purpose CREATE SEQUENCE weather_aut_seq NOCACHE; @@ -69,8 +51,6 @@ CREATE TABLE weather_aut CHECK (`mintemp` > 0) ) WITH SYSTEM VERSIONING; --- no history view in data database on purpose - -- table not in metadata on purpose CREATE TABLE weather_aut_without_versioning ( @@ -84,8 +64,6 @@ CREATE TABLE weather_aut_without_versioning CHECK (`mintemp` > 0) ); --- no history view in data database on purpose - -- view not in metadata on purpose CREATE VIEW weather_aut_merge AS ( diff --git a/dbrepo-metadata-service/services/pom.xml b/dbrepo-metadata-service/services/pom.xml index 7451e000154dc735a09357978f46198b7b6590a4..a66dfb7c87ea86057a39fdba40902bb784457e11 100644 --- a/dbrepo-metadata-service/services/pom.xml +++ b/dbrepo-metadata-service/services/pom.xml @@ -6,12 +6,12 @@ <parent> <artifactId>dbrepo-metadata-service</artifactId> <groupId>at.tuwien</groupId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-metadata-service-services</artifactId> <name>dbrepo-metadata-service-services</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java index 77dd5588adfa099b13fe18c49f46c43d666403ad..d8ba8a490fc41d3bff8234a1d2ea6e0fd9c42951 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java @@ -4,12 +4,15 @@ import at.tuwien.ExportResourceDto; import at.tuwien.api.database.AccessTypeDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewCreateDto; +import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.CreateDatabaseDto; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.table.TableCreateDto; +import at.tuwien.api.database.table.TableDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.exception.*; +import java.util.List; import java.util.UUID; public interface DataServiceGateway { @@ -27,11 +30,15 @@ public interface DataServiceGateway { void deleteTable(Long databaseId, Long tableId) throws ServiceConnectionException, ServiceException, TableNotFoundException; - void createView(Long databaseId, ViewCreateDto data) throws ServiceConnectionException, ServiceException; + ViewDto createView(Long databaseId, ViewCreateDto data) throws ServiceConnectionException, ServiceException; void deleteView(Long databaseId, Long viewId) throws ServiceConnectionException, ServiceException, ViewNotFoundException; QueryDto findQuery(Long databaseId, Long queryId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; ExportResourceDto exportQuery(Long databaseId, Long queryId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; + + List<TableDto> getTableSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; + + List<ViewDto> getViewSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java index b8e4d48d8d8c06aa563771cc29f5ef59fe750384..8ab7c8a7309d319949f3abde033534e5fb76f5a7 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java @@ -126,8 +126,6 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { final String url = "/api/exchanges/" + rabbitConfig.getVirtualHost() + "/" + name; final HttpHeaders headers = new HttpHeaders(); headers.set("Accept", "application/json"); - log.trace("gateway broker find exchange, virtual host={}, exchange={}", rabbitConfig.getVirtualHost(), name); - log.debug("find exchange from url {}{}", gatewayConfig.getBrokerEndpoint(), url); final ResponseEntity<ExchangeDto> response; try { response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers), ExchangeDto.class); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java index 4635ffbbb262829b1070dcffed4a83bc219f073f..a278fc60b97ecfa0bc58aa771965ddf6b60f8f91 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java @@ -1,13 +1,11 @@ package at.tuwien.gateway.impl; import at.tuwien.ExportResourceDto; -import at.tuwien.api.database.AccessTypeDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.UpdateDatabaseAccessDto; -import at.tuwien.api.database.ViewCreateDto; +import at.tuwien.api.database.*; import at.tuwien.api.database.internal.CreateDatabaseDto; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.table.TableCreateDto; +import at.tuwien.api.database.table.TableDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.exception.*; import at.tuwien.gateway.DataServiceGateway; @@ -20,6 +18,7 @@ import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; +import java.util.Arrays; import java.util.List; import java.util.UUID; @@ -211,12 +210,12 @@ public class DataServiceGatewayImpl implements DataServiceGateway { } @Override - public void createView(Long databaseId, ViewCreateDto data) throws ServiceConnectionException, ServiceException { - final ResponseEntity<Void> response; + public ViewDto createView(Long databaseId, ViewCreateDto data) throws ServiceConnectionException, ServiceException { + final ResponseEntity<ViewDto> response; final String url = "/api/database/" + databaseId + "/view"; log.debug("create view in data service"); try { - response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data), Void.class); + response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(data), ViewDto.class); } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | HttpServerErrorException.InternalServerError e) { log.error("Failed to create view: {}", e.getMessage()); @@ -229,6 +228,11 @@ public class DataServiceGatewayImpl implements DataServiceGateway { log.error("Failed to create view: wrong http code: {}", response.getStatusCode()); throw new ServiceException("Failed to create view: wrong http code: " + response.getStatusCode()); } + if (response.getBody() == null) { + log.error("Failed to create view: empty body: {}", response.getStatusCode()); + throw new ServiceException("Failed to create view: empty body: " + response.getStatusCode()); + } + return response.getBody(); } @Override @@ -267,7 +271,7 @@ public class DataServiceGatewayImpl implements DataServiceGateway { } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | HttpServerErrorException.InternalServerError e) { log.error("Failed to find query: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to delete table", e); + throw new ServiceConnectionException("Failed to find query", e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to find query: not found: {}", e.getMessage()); throw new QueryNotFoundException("Failed to find query: not found", e); @@ -296,7 +300,7 @@ public class DataServiceGatewayImpl implements DataServiceGateway { } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | HttpServerErrorException.InternalServerError e) { log.error("Failed to export query: {}", e.getMessage()); - throw new ServiceConnectionException("Failed to delete table: " + e.getMessage(), e); + throw new ServiceConnectionException("Failed to export query: " + e.getMessage(), e); } catch (HttpClientErrorException.NotFound e) { log.error("Failed to export query: not found: {}", e.getMessage()); throw new QueryNotFoundException("Failed to export query: not found: " + e.getMessage(), e); @@ -311,4 +315,65 @@ public class DataServiceGatewayImpl implements DataServiceGateway { return response.getBody(); } + @Override + public List<TableDto> getTableSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException { + final ResponseEntity<TableDto[]> response; + final String url = "/api/database/" + databaseId + "/table"; + log.debug("retrieve table schema metadata in data service"); + try { + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), TableDto[].class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { + log.error("Failed to get table schemas: {}", e.getMessage()); + throw new ServiceConnectionException("Failed to get table schemas: " + e.getMessage(), e); + } catch (HttpClientErrorException.NotFound e) { + log.error("Failed to get table schemas: not found: {}", e.getMessage()); + throw new QueryNotFoundException("Failed to get table schemas: not found: " + e.getMessage(), e); + } catch (HttpClientErrorException.Unauthorized e) { + log.error("Failed to get table schemas: {}", e.getMessage()); + throw new ServiceException("Failed to get table schemas: " + e.getMessage(), e); + } + if (!response.getStatusCode().equals(HttpStatus.OK)) { + log.error("Failed to get table schemas: wrong http code: {}", response.getStatusCode()); + throw new ServiceException("Failed to get table schemas: wrong http code: " + response.getStatusCode()); + } + if (response.getBody() == null) { + log.error("Failed to get table schemas: empty body: {}", response.getStatusCode()); + throw new ServiceException("Failed to get table schemas: empty body: " + response.getStatusCode()); + } + final List<TableDto> tables = Arrays.asList(response.getBody()); + log.debug("found {} table(s) in data service", tables.size()); + return tables; + } + + @Override + public List<ViewDto> getViewSchemas(Long databaseId) throws ServiceConnectionException, ServiceException, QueryNotFoundException { + final ResponseEntity<ViewDto[]> response; + final String url = "/api/database/" + databaseId + "/view"; + try { + response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null), ViewDto[].class); + } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | + HttpServerErrorException.InternalServerError e) { + log.error("Failed to get view schemas: {}", e.getMessage()); + throw new ServiceConnectionException("Failed to get view schemas: " + e.getMessage(), e); + } catch (HttpClientErrorException.NotFound e) { + log.error("Failed to get view schemas: not found: {}", e.getMessage()); + throw new QueryNotFoundException("Failed to get view schemas: not found: " + e.getMessage(), e); + } catch (HttpClientErrorException.Unauthorized e) { + log.error("Failed to get view schemas: {}", e.getMessage()); + throw new ServiceException("Failed to get view schemas: " + e.getMessage(), e); + } + if (!response.getStatusCode().equals(HttpStatus.OK)) { + log.error("Failed to get view schemas: wrong http code: {}", response.getStatusCode()); + throw new ServiceException("Failed to get view schemas: wrong http code: " + response.getStatusCode()); + } + if (response.getBody() == null) { + log.error("Failed to get view schemas: empty body: {}", response.getStatusCode()); + throw new ServiceException("Failed to get view schemas: empty body: " + response.getStatusCode()); + } + final List<ViewDto> views = Arrays.asList(response.getBody()); + log.debug("found {} view(s) in data service", views.size()); + return views; + } + } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java index 8b87a1bfad0c2490a44f778be3cef1d56b79f0db..487e088062fc7ccef2c830b857f721026337d1ea 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java @@ -1,10 +1,13 @@ package at.tuwien.gateway.impl; import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.table.constraints.unique.UniqueDto; import at.tuwien.entities.database.Database; +import at.tuwien.entities.database.View; import at.tuwien.exception.*; import at.tuwien.gateway.SearchServiceGateway; import at.tuwien.mapper.DatabaseMapper; +import at.tuwien.mapper.TableMapper; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -15,16 +18,22 @@ import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; +import java.util.LinkedList; +import java.util.List; + @Log4j2 @Service public class SearchServiceGatewayImpl implements SearchServiceGateway { + private final TableMapper tableMapper; private final RestTemplate restTemplate; private final DatabaseMapper databaseMapper; @Autowired - public SearchServiceGatewayImpl(@Qualifier("searchServiceRestTemplate") RestTemplate restTemplate, + public SearchServiceGatewayImpl(TableMapper tableMapper, + @Qualifier("searchServiceRestTemplate") RestTemplate restTemplate, DatabaseMapper databaseMapper) { + this.tableMapper = tableMapper; this.restTemplate = restTemplate; this.databaseMapper = databaseMapper; } @@ -33,6 +42,31 @@ public class SearchServiceGatewayImpl implements SearchServiceGateway { public DatabaseDto update(Database database) throws SearchServiceConnectionException, SearchServiceException, DatabaseNotFoundException { final ResponseEntity<DatabaseDto> response; final DatabaseDto payload = databaseMapper.databaseToDatabaseDto(database); + payload.getTables() + .forEach(table -> { + table.setIsPublic(database.getIsPublic()); + table.getColumns() + .forEach(column -> { + column.setTable(table); + column.setTableId(table.getId()); + column.setDatabaseId(payload.getId()); + column.setIsPublic(payload.getIsPublic()); + }); + table.getConstraints() + .getUniques() + .forEach(uk -> { + uk.setTable(tableMapper.tableDtoToTableBriefDto(table)); + uk.getTable().setDatabaseId(database.getId()); + uk.setColumns(new LinkedList<>()); +// uk.getColumns() +// .forEach(column -> { +// column.setTable(table); +// column.setTableId(table.getId()); +// column.setDatabaseId(database.getId()); +// column.setIsPublic(database.getIsPublic()); +// }); + }); + }); final HttpHeaders headers = new HttpHeaders(); headers.set("Accept", "application/json"); headers.set("Content-Type", "application/json"); @@ -48,8 +82,8 @@ public class SearchServiceGatewayImpl implements SearchServiceGateway { log.error("Failed to update database: not found"); throw new DatabaseNotFoundException("Failed to update database: not found", e); } catch (HttpClientErrorException.BadRequest | HttpClientErrorException.Unauthorized e) { - log.error("Failed to update database: body is null"); - throw new SearchServiceException("Failed to update database: body is null", e); + log.error("Failed to update database: malformed payload: {}", e.getMessage()); + throw new SearchServiceException("Failed to update database: malformed payload", e); } if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) { log.error("Failed to update database: response code is not 202"); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java index 8faa87017fcf95c732e88595105c93f58f7d0f3e..32291c8755e56c2a59409f8e4da79c292e85d8c5 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java @@ -7,6 +7,8 @@ import at.tuwien.entities.database.Database; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import java.security.Principal; import java.util.List; @@ -99,5 +101,11 @@ public interface DatabaseService { */ Database modifyImage(Database database, byte[] image) throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException; + Database updateTableMetadata(Database database) throws DatabaseNotFoundException, ServiceException, + SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, + ServiceConnectionException, MalformedException; + Database updateViewMetadata(Database database) throws DatabaseNotFoundException, ServiceException, + SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, + ServiceConnectionException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java index 7d92eb7ff669596d7bda775998c808647458b42a..f695267a4a5c089be5f8235e3cd8abd59d81f826 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java @@ -3,17 +3,24 @@ package at.tuwien.service.impl; import at.tuwien.api.database.DatabaseCreateDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.DatabaseModifyVisibilityDto; +import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.internal.CreateDatabaseDto; +import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.database.table.columns.ColumnDto; +import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.entities.container.Container; -import at.tuwien.entities.database.AccessType; -import at.tuwien.entities.database.Database; -import at.tuwien.entities.database.DatabaseAccess; +import at.tuwien.entities.database.*; +import at.tuwien.entities.database.table.Table; +import at.tuwien.entities.database.table.columns.TableColumn; +import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.gateway.DataServiceGateway; import at.tuwien.gateway.SearchServiceGateway; import at.tuwien.mapper.DatabaseMapper; +import at.tuwien.mapper.TableMapper; +import at.tuwien.mapper.ViewMapper; import at.tuwien.repository.DatabaseRepository; import at.tuwien.service.*; import lombok.extern.log4j.Log4j2; @@ -28,6 +35,8 @@ import java.util.*; @Service public class DatabaseServiceImpl implements DatabaseService { + private final ViewMapper viewMapper; + private final TableMapper tableMapper; private final DatabaseMapper databaseMapper; private final ContainerService containerService; private final DatabaseRepository databaseRepository; @@ -35,9 +44,11 @@ public class DatabaseServiceImpl implements DatabaseService { private final SearchServiceGateway searchServiceGateway; @Autowired - public DatabaseServiceImpl(DatabaseMapper databaseMapper, ContainerService containerService, - DatabaseRepository databaseRepository, DataServiceGateway dataServiceGateway, - SearchServiceGateway searchServiceGateway) { + public DatabaseServiceImpl(ViewMapper viewMapper, TableMapper tableMapper, DatabaseMapper databaseMapper, + ContainerService containerService, DatabaseRepository databaseRepository, + DataServiceGateway dataServiceGateway, SearchServiceGateway searchServiceGateway) { + this.viewMapper = viewMapper; + this.tableMapper = tableMapper; this.databaseMapper = databaseMapper; this.containerService = containerService; this.databaseRepository = databaseRepository; @@ -184,4 +195,92 @@ public class DatabaseServiceImpl implements DatabaseService { return database; } + @Override + @Transactional(rollbackFor = {SearchServiceException.class, SearchServiceConnectionException.class, DatabaseNotFoundException.class}) + public Database updateTableMetadata(Database database) throws DatabaseNotFoundException, ServiceException, + SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, + ServiceConnectionException, MalformedException { + for (TableDto table : dataServiceGateway.getTableSchemas(database.getId())) { + if (database.getTables().stream().anyMatch(t -> t.getInternalName().equals(table.getInternalName()))) { + log.debug("fetched known table from data service: {}.{}", database.getInternalName(), table.getInternalName()); + continue; + } + log.debug("fetched unknown table from data service: {}.{}", database.getInternalName(), table.getInternalName()); + final Table tableEntity = tableMapper.tableDtoToTable(table); + tableEntity.setDatabase(database); + tableEntity.getColumns() + .forEach(column -> { + column.setTable(tableEntity); + }); + /* map unique constraint(s) */ + tableEntity.getConstraints() + .getUniques() + .forEach(uk -> { + uk.setTable(tableEntity); + uk.getColumns() + .forEach(column -> { + column.setTable(tableEntity); + }); + }); + /* map foreign key constraint(s) */ + tableEntity.getConstraints() + .getForeignKeys() + .forEach(fk -> { + fk.setTable(tableEntity); + }); + /* map primary key constraint */ + for (PrimaryKeyDto key : table.getConstraints().getPrimaryKey()) { + final Optional<TableColumn> optional = tableEntity.getColumns() + .stream() + .filter(c -> c.getInternalName().equals(key.getColumn().getInternalName())) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find primary key column {} in table {}.{}", key.getColumn().getInternalName(), database.getInternalName(), table.getInternalName()); + throw new MalformedException("Failed to find primary key column: " + key.getColumn().getInternalName()); + } + tableEntity.getConstraints() + .getPrimaryKey() + .add(PrimaryKey.builder() + .table(tableEntity) + .column(optional.get()) + .build()); + } + database.getTables() + .add(tableEntity); + } + /* update in metadata database */ + database = databaseRepository.save(database); + /* save in search service */ + searchServiceGateway.update(database); + log.info("Updated table metadata of database with id {} & search database", database.getId()); + return database; + } + + @Override + @Transactional(rollbackFor = {SearchServiceException.class, SearchServiceConnectionException.class, DatabaseNotFoundException.class}) + public Database updateViewMetadata(Database database) throws DatabaseNotFoundException, ServiceException, + SearchServiceException, SearchServiceConnectionException, QueryNotFoundException, + ServiceConnectionException { + for (ViewDto view : dataServiceGateway.getViewSchemas(database.getId())) { + if (database.getViews().stream().anyMatch(v -> v.getInternalName().equals(view.getInternalName()))) { + log.debug("fetched known view from data service: {}.{}", database.getInternalName(), view.getInternalName()); + continue; + } + log.debug("fetched unknown view from data service: {}.{}", database.getInternalName(), view.getInternalName()); + final View viewEntity = viewMapper.viewDtoToView(view); + viewEntity.setDatabase(database); + for (ViewColumn column : viewEntity.getColumns()) { + column.setView(viewEntity); + } + database.getViews() + .add(viewEntity); + } + /* update in metadata database */ + database = databaseRepository.save(database); + /* save in search service */ + searchServiceGateway.update(database); + log.info("Updated view metadata of database with id {} & search database", database.getId()); + return database; + } + } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java index 54705186faabdc7ba000d5c8347ffe3d64bd5c87..ec269391996948f47ad0a3b55c7996eb73a3b9f2 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java @@ -1,19 +1,18 @@ package at.tuwien.service.impl; import at.tuwien.api.database.ViewCreateDto; +import at.tuwien.api.database.ViewDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.View; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.gateway.DataServiceGateway; import at.tuwien.gateway.SearchServiceGateway; -import at.tuwien.mapper.QueryMapper; import at.tuwien.mapper.ViewMapper; import at.tuwien.repository.DatabaseRepository; import at.tuwien.service.ViewService; import com.google.common.hash.Hashing; import lombok.extern.log4j.Log4j2; -import net.sf.jsqlparser.JSQLParserException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -28,16 +27,14 @@ import java.util.Optional; public class ViewServiceImpl implements ViewService { private final ViewMapper viewMapper; - private final QueryMapper queryMapper; private final DataServiceGateway dataServiceGateway; private final DatabaseRepository databaseRepository; private final SearchServiceGateway searchServiceGateway; @Autowired - public ViewServiceImpl(ViewMapper viewMapper, QueryMapper queryMapper, DataServiceGateway dataServiceGateway, + public ViewServiceImpl(ViewMapper viewMapper, DataServiceGateway dataServiceGateway, DatabaseRepository databaseRepository, SearchServiceGateway searchServiceGateway) { this.viewMapper = viewMapper; - this.queryMapper = queryMapper; this.dataServiceGateway = dataServiceGateway; this.databaseRepository = databaseRepository; this.searchServiceGateway = searchServiceGateway; @@ -102,17 +99,13 @@ public class ViewServiceImpl implements ViewService { .queryHash(Hashing.sha256() .hashString(data.getQuery(), StandardCharsets.UTF_8) .toString()) + .columns(new LinkedList<>()) .isInitialView(false) .isPublic(data.getIsPublic()) .build(); /* create in data service */ data.setName(view.getInternalName()); - dataServiceGateway.createView(database.getId(), data); - try { - view.setColumns(viewMapper.tableColumnsToViewColumns(view, queryMapper.parseColumns(data.getQuery(), database))); - } catch (JSQLParserException e) { - throw new MalformedException("Failed to parse columns from view: " + e.getMessage(), e); - } + final ViewDto dto = dataServiceGateway.createView(database.getId(), data); database.getViews() .add(view); database = databaseRepository.save(database); diff --git a/dbrepo-metadata-service/test/pom.xml b/dbrepo-metadata-service/test/pom.xml index 303ea6133e1f288274ae45bc391f20da742d9bd4..902e9efdda890936801911f8d2a63e7d2a47980b 100644 --- a/dbrepo-metadata-service/test/pom.xml +++ b/dbrepo-metadata-service/test/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> - <version>1.4.3</version> + <version>1.4.4</version> </parent> <artifactId>dbrepo-metadata-service-test</artifactId> <name>dbrepo-metadata-service-test</name> - <version>1.4.3</version> + <version>1.4.4</version> <dependencies> <dependency> diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java index 326437195d2a50657719c707e38c3ae08b76339c..a7808196311e875f354a997d364e160d510a9f81 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java @@ -24,6 +24,7 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_1_PRIVILEGED_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_1_USER_1_READ_ACCESS_DTO, DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO, DATABASE_1_USER_3_WRITE_ALL_ACCESS_DTO))); TABLE_1.setDatabase(DATABASE_1); TABLE_1.setColumns(new LinkedList<>(TABLE_1_COLUMNS)); + TABLE_1.setConstraints(TABLE_1_CONSTRAINTS); TABLE_1_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_1_COLUMNS_DTO)); TABLE_1_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); DATABASE_1.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4))); @@ -33,16 +34,24 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_1_PRIVILEGED_DTO.setTables(new LinkedList<>(List.of(TABLE_1_DTO, TABLE_2_DTO, TABLE_3_DTO, TABLE_4_DTO))); DATABASE_1_PRIVILEGED_DTO.setViews(new LinkedList<>(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO))); TABLE_1_DTO.setColumns(TABLE_1_COLUMNS_DTO); + TABLE_1_DTO.setConstraints(TABLE_1_CONSTRAINTS_DTO); TABLE_2.setDatabase(DATABASE_1); TABLE_2.setColumns(new LinkedList<>(TABLE_2_COLUMNS)); + TABLE_2_CONSTRAINTS.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_2_CONSTRAINTS.getForeignKeys().get(0)); + TABLE_2.setConstraints(TABLE_2_CONSTRAINTS); TABLE_2_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_2_COLUMNS_DTO)); TABLE_2_DTO.setColumns(TABLE_2_COLUMNS_DTO); + TABLE_2_DTO.setConstraints(TABLE_2_CONSTRAINTS_DTO); TABLE_3.setDatabase(DATABASE_1); TABLE_3.setColumns(new LinkedList<>(TABLE_3_COLUMNS)); + TABLE_3.setConstraints(TABLE_3_CONSTRAINTS); TABLE_3_DTO.setColumns(TABLE_3_COLUMNS_DTO); + TABLE_3_DTO.setConstraints(TABLE_3_CONSTRAINTS_DTO); TABLE_4.setDatabase(DATABASE_1); TABLE_4.setColumns(new LinkedList<>(TABLE_4_COLUMNS)); + TABLE_4.setConstraints(TABLE_4_CONSTRAINTS); TABLE_4_DTO.setColumns(TABLE_4_COLUMNS_DTO); + TABLE_4_DTO.setConstraints(TABLE_4_CONSTRAINTS_DTO); VIEW_1.setDatabase(DATABASE_1); VIEW_1.setColumns(VIEW_1_COLUMNS); VIEW_1.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_3))); @@ -52,6 +61,7 @@ public abstract class AbstractUnitTest extends BaseTest { VIEW_2_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); VIEW_3.setDatabase(DATABASE_1); VIEW_3.setColumns(VIEW_3_COLUMNS); + VIEW_3_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); IDENTIFIER_1.setDatabase(DATABASE_1); IDENTIFIER_2.setDatabase(DATABASE_1); IDENTIFIER_3.setDatabase(DATABASE_1); @@ -63,13 +73,22 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_2.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_5))); TABLE_5.setDatabase(DATABASE_2); TABLE_5.setColumns(new LinkedList<>(TABLE_5_COLUMNS)); + TABLE_5.setConstraints(TABLE_5_CONSTRAINTS); TABLE_5_DTO.setColumns(TABLE_5_COLUMNS_DTO); + TABLE_5_DTO.setConstraints(TABLE_5_CONSTRAINTS_DTO); TABLE_6.setDatabase(DATABASE_2); TABLE_6.setColumns(new LinkedList<>(TABLE_6_COLUMNS)); + TABLE_6.setConstraints(TABLE_6_CONSTRAINTS); TABLE_7.setDatabase(DATABASE_2); TABLE_7.setColumns(new LinkedList<>(TABLE_7_COLUMNS)); + TABLE_7.setConstraints(TABLE_7_CONSTRAINTS); + TABLE_7_CONSTRAINTS.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS.getForeignKeys().get(0)); + TABLE_7_CONSTRAINTS.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS.getForeignKeys().get(1)); + TABLE_7_DTO.setColumns(TABLE_7_COLUMNS_DTO); + TABLE_7_DTO.setConstraints(TABLE_7_CONSTRAINTS_DTO); + TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(0)); + TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(1).getReferences().get(0).setForeignKey(TABLE_7_CONSTRAINTS_DTO.getForeignKeys().get(1)); VIEW_4.setDatabase(DATABASE_2); - VIEW_4.setColumns(VIEW_4_COLUMNS); IDENTIFIER_5.setDatabase(DATABASE_2); /* DATABASE 3 */ DATABASE_3.setAccesses(new LinkedList<>(List.of(DATABASE_3_USER_1_WRITE_ALL_ACCESS))); @@ -78,8 +97,11 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_3.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_6))); TABLE_8.setDatabase(DATABASE_3); TABLE_8.setColumns(new LinkedList<>(TABLE_8_COLUMNS)); + TABLE_8.setConstraints(TABLE_8_CONSTRAINTS); TABLE_8_DTO.setColumns(new LinkedList<>(TABLE_8_COLUMNS_DTO)); + TABLE_8_DTO.setConstraints(TABLE_8_CONSTRAINTS_DTO); TABLE_8_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_8_COLUMNS_DTO)); + TABLE_8_PRIVILEGED_DTO.setConstraints(TABLE_8_CONSTRAINTS_DTO); VIEW_5.setDatabase(DATABASE_3); VIEW_5.setColumns(VIEW_5_COLUMNS); IDENTIFIER_6.setDatabase(DATABASE_3); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index 251191c5fb4d83e2199b479e222f17e335ec5704..e0275f5d6eb97dd096b8ad4143b1f085c4955c7a 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -25,12 +25,17 @@ import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.columns.concepts.*; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; -import at.tuwien.api.database.table.constraints.foreignKey.ForeignKeyCreateDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyCreateDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyDto; +import at.tuwien.api.database.table.constraints.foreign.ForeignKeyReferenceDto; +import at.tuwien.api.database.table.constraints.foreign.ReferenceTypeDto; +import at.tuwien.api.database.table.constraints.primary.PrimaryKeyDto; import at.tuwien.api.database.table.constraints.unique.UniqueDto; import at.tuwien.api.database.table.internal.PrivilegedTableDto; import at.tuwien.api.datacite.DataCiteBody; import at.tuwien.api.datacite.DataCiteData; import at.tuwien.api.datacite.doi.DataCiteDoi; +import at.tuwien.api.error.ApiErrorDto; import at.tuwien.api.identifier.*; import at.tuwien.api.keycloak.CredentialDto; import at.tuwien.api.keycloak.CredentialTypeDto; @@ -63,19 +68,36 @@ import at.tuwien.entities.database.table.columns.TableColumn; import at.tuwien.entities.database.table.columns.TableColumnConcept; import at.tuwien.entities.database.table.columns.TableColumnType; import at.tuwien.entities.database.table.columns.TableColumnUnit; +import at.tuwien.entities.database.table.constraints.Constraints; +import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey; +import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKeyReference; +import at.tuwien.entities.database.table.constraints.foreignKey.ReferenceType; +import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; +import at.tuwien.entities.database.table.constraints.unique.Unique; import at.tuwien.entities.identifier.*; import at.tuwien.entities.maintenance.BannerMessage; import at.tuwien.entities.maintenance.BannerMessageType; import at.tuwien.entities.semantics.Ontology; import at.tuwien.entities.user.User; import at.tuwien.test.utils.ArrayUtils; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.MediaType; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.web.bind.annotation.ResponseStatus; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; +import java.nio.charset.Charset; import java.security.Principal; import java.time.Instant; import java.util.*; @@ -995,7 +1017,7 @@ public abstract class BaseTest { .jdbcMethod(IMAGE_1_JDBC) .driverClass(IMAGE_1_DRIVER) .defaultPort(IMAGE_1_PORT) - .dateFormats(List.of(IMAGE_DATE_1, IMAGE_DATE_2, IMAGE_DATE_3, IMAGE_DATE_4)) + .dateFormats(new LinkedList<>(List.of(IMAGE_DATE_1, IMAGE_DATE_2, IMAGE_DATE_3, IMAGE_DATE_4))) .build(); public final static ImageDto IMAGE_1_DTO = ImageDto.builder() @@ -1498,13 +1520,6 @@ public abstract class BaseTest { public final static Instant TABLE_1_CREATED = Instant.ofEpochSecond(1677399975L) /* 2023-02-26 08:26:15 (UTC) */; public final static Instant TABLE_1_LAST_MODIFIED = Instant.ofEpochSecond(1677399975L) /* 2023-02-26 08:26:15 (UTC) */; - public final static ConstraintsDto TABLE_1_CONSTRAINT_DTO = ConstraintsDto.builder() - .checks(new LinkedHashSet<>()) - .primaryKey(new LinkedHashSet<>(Set.of("id"))) - .foreignKeys(new LinkedList<>()) - .uniques(new LinkedList<>()) - .build(); - public final static PrivilegedTableDto TABLE_1_PRIVILEGED_DTO = PrivilegedTableDto.builder() .id(TABLE_1_ID) .tdbid(DATABASE_1_ID) @@ -1518,7 +1533,7 @@ public abstract class BaseTest { .routingKey(TABLE_1_ROUTING_KEY) .identifiers(new LinkedList<>()) .columns(new LinkedList<>() /* TABLE_1_COLUMNS_DTO */) - .constraints(TABLE_1_CONSTRAINT_DTO) + .constraints(null) /* TABLE_1_CONSTRAINTS_DTO */ .createdBy(USER_1_ID) .owner(USER_1_DTO) .isPublic(DATABASE_1_PUBLIC) @@ -1536,6 +1551,7 @@ public abstract class BaseTest { .queueName(TABLE_1_QUEUE_NAME) .identifiers(new LinkedList<>()) .columns(new LinkedList<>() /* TABLE_1_COLUMNS */) + .constraints(null) /* TABLE_1_CONSTRAINTS */ .createdBy(USER_1_ID) .creator(USER_1) .ownedBy(USER_1_ID) @@ -1555,7 +1571,7 @@ public abstract class BaseTest { .routingKey(TABLE_1_ROUTING_KEY) .identifiers(new LinkedList<>()) .columns(new LinkedList<>() /* TABLE_1_COLUMNS_DTO */) - .constraints(TABLE_1_CONSTRAINT_DTO) + .constraints(null) /* TABLE_1_CONSTRAINT_DTO */ .createdBy(USER_1_ID) .owner(USER_1_DTO) .build(); @@ -1650,13 +1666,6 @@ public abstract class BaseTest { public final static Instant TABLE_2_CREATED = Instant.ofEpochSecond(1677400007L) /* 2023-02-26 08:26:47 (UTC) */; public final static Instant TABLE_2_LAST_MODIFIED = Instant.ofEpochSecond(1677400007L) /* 2023-02-26 08:26:47 (UTC) */; - public final static ConstraintsDto TABLE_2_CONSTRAINT_DTO = ConstraintsDto.builder() - .checks(new LinkedHashSet<>()) - .primaryKey(new LinkedHashSet<>(Set.of("location"))) - .foreignKeys(new LinkedList<>()) - .uniques(new LinkedList<>()) - .build(); - public final static Table TABLE_2 = Table.builder() .id(TABLE_2_ID) .tdbid(DATABASE_1_ID) @@ -1669,6 +1678,7 @@ public abstract class BaseTest { .lastModified(TABLE_2_LAST_MODIFIED) .queueName(TABLE_2_QUEUE_NAME) .columns(new LinkedList<>() /* TABLE_2_COLUMNS */) + .constraints(null) /* TABLE_2_CONSTRAINTS */ .createdBy(USER_2_ID) .ownedBy(USER_2_ID) .owner(USER_2) @@ -1687,7 +1697,7 @@ public abstract class BaseTest { .routingKey(TABLE_2_ROUTING_KEY) .identifiers(new LinkedList<>()) .columns(new LinkedList<>() /* TABLE_2_COLUMNS_DTO */) - .constraints(TABLE_2_CONSTRAINT_DTO) + .constraints(null) /* TABLE_2_CONSTRAINTS_DTO */ .createdBy(USER_1_ID) .owner(USER_1_DTO) .build(); @@ -1703,7 +1713,7 @@ public abstract class BaseTest { .queueName(TABLE_2_QUEUE_NAME) .routingKey(TABLE_2_ROUTING_KEY) .columns(new LinkedList<>() /* TABLE_2_COLUMNS_DTO */) - .constraints(ConstraintsDto.builder().build()) + .constraints(null) /* TABLE_2_CONSTRAINTS_DTO */ .createdBy(USER_2_ID) .owner(USER_2_DTO) .build(); @@ -1741,6 +1751,7 @@ public abstract class BaseTest { .lastModified(TABLE_3_LAST_MODIFIED) .queueName(TABLE_3_QUEUE_NAME) .columns(new LinkedList<>() /* TABLE_3_COLUMNS */) + .constraints(null) /* TABLE_3_CONSTRAINTS */ .createdBy(USER_3_ID) .ownedBy(USER_3_ID) .owner(USER_3) @@ -1757,7 +1768,7 @@ public abstract class BaseTest { .queueName(TABLE_3_QUEUE_NAME) .routingKey(TABLE_3_ROUTING_KEY) .columns(new LinkedList<>() /* TABLE_3_COLUMNS_DTO */) - .constraints(ConstraintsDto.builder().build()) + .constraints(null) /* TABLE_3_CONSTRAINTS_DTO */ .createdBy(USER_3_ID) .owner(USER_3_DTO) .build(); @@ -1822,7 +1833,8 @@ public abstract class BaseTest { .name(TABLE_5_NAME) .lastModified(TABLE_5_LAST_MODIFIED) .queueName(TABLE_5_QUEUE_NAME) - .columns(new LinkedList<>() /* needs to be set in the junit tests */) + .columns(new LinkedList<>()) /* TABLE_5_COLUMNS */ + .constraints(null) /* TABLE_5_CONSTRAINTS */ .createdBy(USER_1_ID) .ownedBy(USER_1_ID) .owner(USER_1) @@ -1838,12 +1850,22 @@ public abstract class BaseTest { .name(TABLE_5_NAME) .queueName(TABLE_5_QUEUE_NAME) .routingKey(TABLE_5_ROUTING_KEY) - .columns(new LinkedList<>() /* TABLE_5_COLUMNS_DTO */) - .constraints(ConstraintsDto.builder().build()) + .columns(new LinkedList<>()) /* TABLE_5_COLUMNS_DTO */ + .constraints(null) /* TABLE_5_CONSTRAINTS_DTO */ .createdBy(USER_1_ID) .owner(USER_1_DTO) .build(); + public final static TableBriefDto TABLE_5_BRIEF_DTO = TableBriefDto.builder() + .id(TABLE_5_ID) + .internalName(TABLE_5_INTERNALNAME) + .isVersioned(TABLE_5_VERSIONED) + .description(TABLE_5_DESCRIPTION) + .name(TABLE_5_NAME) + .columns(new LinkedList<>() /* TABLE_5_COLUMNS_DTO */) + .owner(USER_1_BRIEF_DTO) + .build(); + public final static Long TABLE_6_ID = 6L; public final static String TABLE_6_NAME = "names"; public final static String TABLE_6_INTERNALNAME = "names"; @@ -1865,7 +1887,8 @@ public abstract class BaseTest { .name(TABLE_6_NAME) .lastModified(TABLE_6_LAST_MODIFIED) .queueName(TABLE_6_QUEUE_NAME) - .columns(new LinkedList<>() /* needs to be set in the junit tests */) + .columns(new LinkedList<>()) /* TABLE_6_COLUMNS */ + .constraints(null) /* TABLE_6_CONSTRAINTS */ .createdBy(USER_1_ID) .ownedBy(USER_1_ID) .owner(USER_1) @@ -1882,13 +1905,23 @@ public abstract class BaseTest { .name(TABLE_6_NAME) .queueName(TABLE_6_QUEUE_NAME) .routingKey(TABLE_6_ROUTING_KEY) - .columns(new LinkedList<>() /* TABLE_6_COLUMNS_DTO */) - .constraints(ConstraintsDto.builder().build()) + .columns(new LinkedList<>()) /* TABLE_6_COLUMNS_DTO */ + .constraints(null) /* TABLE_6_CONSTRAINTS_DTO */ .createdBy(USER_1_ID) .owner(USER_1_DTO) .created(TABLE_6_CREATED) .build(); + public final static TableBriefDto TABLE_6_BRIEF_DTO = TableBriefDto.builder() + .id(TABLE_6_ID) + .internalName(TABLE_6_INTERNALNAME) + .isVersioned(TABLE_6_VERSIONED) + .description(TABLE_6_DESCRIPTION) + .name(TABLE_6_NAME) + .columns(new LinkedList<>()) /* TABLE_6_COLUMNS_DTO */ + .owner(USER_1_BRIEF_DTO) + .build(); + public final static Long TABLE_7_ID = 7L; public final static String TABLE_7_NAME = "likes"; public final static String TABLE_7_INTERNAL_NAME = "likes"; @@ -1910,7 +1943,8 @@ public abstract class BaseTest { .name(TABLE_7_NAME) .lastModified(TABLE_7_LAST_MODIFIED) .queueName(TABLE_7_QUEUE_NAME) - .columns(new LinkedList<>() /* TABLE_7_COLUMNS */) + .columns(new LinkedList<>()) /* TABLE_7_COLUMNS */ + .constraints(null) /* TABLE_7_CONSTRAINTS */ .createdBy(USER_1_ID) .ownedBy(USER_1_ID) .owner(USER_1) @@ -1927,16 +1961,26 @@ public abstract class BaseTest { .name(TABLE_7_NAME) .queueName(TABLE_7_QUEUE_NAME) .routingKey(TABLE_7_ROUTING_KEY) - .columns(new LinkedList<>() /* TABLE_7_COLUMNS_DTO */) - .constraints(ConstraintsDto.builder().build()) + .columns(new LinkedList<>()) /* TABLE_7_COLUMNS_DTO */ + .constraints(null) /* TABLE_7_CONSTRAINTS_DTO */ .createdBy(USER_1_ID) .owner(USER_1_DTO) .created(TABLE_7_CREATED) .build(); + public final static TableBriefDto TABLE_7_BRIEF_DTO = TableBriefDto.builder() + .id(TABLE_7_ID) + .internalName(TABLE_7_INTERNAL_NAME) + .isVersioned(TABLE_7_VERSIONED) + .description(TABLE_7_DESCRIPTION) + .name(TABLE_7_NAME) + .columns(new LinkedList<>()) /* TABLE_7_COLUMNS_DTO */ + .owner(USER_1_BRIEF_DTO) + .build(); + public final static Long TABLE_4_ID = 4L; - public final static String TABLE_4_NAME = "Sensor"; - public final static String TABLE_4_INTERNAL_NAME = "sensor"; + public final static String TABLE_4_NAME = "Sensor 2"; + public final static String TABLE_4_INTERNAL_NAME = "sensor_2"; public final static Boolean TABLE_4_VERSIONED = true; public final static Boolean TABLE_4_PROCESSED_CONSTRAINTS = true; public final static String TABLE_4_DESCRIPTION = "Hello sensor"; @@ -1953,7 +1997,8 @@ public abstract class BaseTest { .database(null /* DATABASE_1 */) .name(TABLE_4_NAME) .queueName(TABLE_4_QUEUE_NAME) - .columns(new LinkedList<>() /* TABLE_4_COLUMNS */) + .columns(new LinkedList<>()) /* TABLE_4_COLUMNS */ + .constraints(null) /* TABLE_4_CONSTRAINTS */ .isVersioned(TABLE_4_VERSIONED) .createdBy(USER_1_ID) .ownedBy(USER_1_ID) @@ -1970,8 +2015,8 @@ public abstract class BaseTest { .name(TABLE_4_NAME) .queueName(TABLE_4_QUEUE_NAME) .routingKey(TABLE_4_ROUTING_KEY) - .columns(new LinkedList<>() /* TABLE_4_COLUMNS_DTO */) - .constraints(ConstraintsDto.builder().build()) + .columns(new LinkedList<>()) /* TABLE_4_COLUMNS_DTO */ + .constraints(null) /* TABLE_4_CONSTRAINTS_DTO */ .isVersioned(TABLE_4_VERSIONED) .createdBy(USER_1_ID) .owner(USER_1_DTO) @@ -2089,7 +2134,8 @@ public abstract class BaseTest { .database(null /* DATABASE_1 */) .name(TABLE_8_NAME) .queueName(TABLE_8_QUEUE_NAME) - .columns(new LinkedList<>() /* TABLE_8_COLUMNS */) + .columns(new LinkedList<>()) /* TABLE_8_COLUMNS */ + .constraints(null) /* TABLE_8_CONSTRAINTS */ .createdBy(USER_1_ID) .ownedBy(USER_1_ID) .owner(USER_1) @@ -2105,13 +2151,24 @@ public abstract class BaseTest { .isVersioned(TABLE_8_VERSIONED) .name(TABLE_8_NAME) .queueName(TABLE_8_QUEUE_NAME) - .columns(new LinkedList<>() /* TABLE_8_COLUMNS */) + .columns(new LinkedList<>()) /* TABLE_8_COLUMNS_DTO */ + .constraints(null) /* TABLE_8_CONSTRAINTS_DTO */ .createdBy(USER_1_ID) .creator(USER_1_DTO) .owner(USER_1_DTO) .created(TABLE_8_CREATED) .build(); + public final static TableBriefDto TABLE_8_BRIEF_DTO = TableBriefDto.builder() + .id(TABLE_8_ID) + .internalName(TABLE_8_INTERNAL_NAME) + .description(TABLE_8_DESCRIPTION) + .isVersioned(TABLE_8_VERSIONED) + .name(TABLE_8_NAME) + .columns(new LinkedList<>()) /* TABLE_8_COLUMNS_DTO */ + .owner(USER_1_BRIEF_DTO) + .build(); + public final static PrivilegedTableDto TABLE_8_PRIVILEGED_DTO = PrivilegedTableDto.builder() .id(TABLE_8_ID) .tdbid(TABLE_8_DATABASE_ID) @@ -2120,7 +2177,7 @@ public abstract class BaseTest { .isVersioned(TABLE_8_VERSIONED) .name(TABLE_8_NAME) .queueName(TABLE_8_QUEUE_NAME) - .columns(new LinkedList<>() /* TABLE_8_COLUMNS */) + .columns(new LinkedList<>()) /* TABLE_8_COLUMNS_DTO */ .createdBy(USER_1_ID) .creator(USER_1_DTO) .owner(USER_1_DTO) @@ -2248,509 +2305,6 @@ public abstract class BaseTest { .sparqlEndpoint(ONTOLOGY_5_SPARQL_ENDPOINT) .build(); - public final static Long COLUMN_4_1_ID = 45L; - public final static Integer COLUMN_4_1_ORDINALPOS = 0; - public final static Boolean COLUMN_4_1_PRIMARY = true; - public final static String COLUMN_4_1_NAME = "id"; - public final static String COLUMN_4_1_INTERNAL_NAME = "id"; - public final static TableColumnType COLUMN_4_1_TYPE = TableColumnType.BIGINT; - public final static ColumnTypeDto COLUMN_4_1_TYPE_DTO = ColumnTypeDto.BIGINT; - public final static Long COLUMN_4_1_DATE_FORMAT = null; - public final static Boolean COLUMN_4_1_NULL = false; - public final static Boolean COLUMN_4_1_AUTO_GENERATED = true; - public final static String COLUMN_4_1_FOREIGN_KEY = null; - public final static String COLUMN_4_1_CHECK = null; - public final static List<String> COLUMN_4_1_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_1_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_1_ENUM_VALUES = null; - public final static List<String> COLUMN_4_1_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_1_SET_VALUES = null; - public final static List<String> COLUMN_4_1_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_2_ID = 46L; - public final static Integer COLUMN_4_2_ORDINALPOS = 1; - public final static Boolean COLUMN_4_2_PRIMARY = false; - public final static String COLUMN_4_2_NAME = "Animal Name"; - public final static String COLUMN_4_2_INTERNAL_NAME = "animal_name"; - public final static TableColumnType COLUMN_4_2_TYPE = TableColumnType.VARCHAR; - public final static ColumnTypeDto COLUMN_4_2_TYPE_DTO = ColumnTypeDto.VARCHAR; - public final static Long COLUMN_4_2_DATE_FORMAT = null; - public final static Boolean COLUMN_4_2_NULL = true; - public final static Boolean COLUMN_4_2_AUTO_GENERATED = false; - public final static String COLUMN_4_2_FOREIGN_KEY = null; - public final static String COLUMN_4_2_CHECK = null; - public final static List<String> COLUMN_4_2_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_2_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_2_ENUM_VALUES = null; - public final static List<String> COLUMN_4_2_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_2_SET_VALUES = null; - public final static List<String> COLUMN_4_2_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_3_ID = 47L; - public final static Integer COLUMN_4_3_ORDINALPOS = 2; - public final static Boolean COLUMN_4_3_PRIMARY = false; - public final static String COLUMN_4_3_NAME = "Hair"; - public final static String COLUMN_4_3_INTERNAL_NAME = "hair"; - public final static TableColumnType COLUMN_4_3_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_3_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_3_DATE_FORMAT = null; - public final static Boolean COLUMN_4_3_NULL = true; - public final static Boolean COLUMN_4_3_AUTO_GENERATED = false; - public final static String COLUMN_4_3_FOREIGN_KEY = null; - public final static String COLUMN_4_3_CHECK = null; - public final static List<String> COLUMN_4_3_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_3_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_3_ENUM_VALUES = null; - public final static List<String> COLUMN_4_3_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_3_SET_VALUES = null; - public final static List<String> COLUMN_4_3_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_4_ID = 48L; - public final static Integer COLUMN_4_4_ORDINALPOS = 3; - public final static Boolean COLUMN_4_4_PRIMARY = false; - public final static String COLUMN_4_4_NAME = "Feathers"; - public final static String COLUMN_4_4_INTERNAL_NAME = "feathers"; - public final static TableColumnType COLUMN_4_4_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_4_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_4_DATE_FORMAT = null; - public final static Boolean COLUMN_4_4_NULL = true; - public final static Boolean COLUMN_4_4_AUTO_GENERATED = false; - public final static String COLUMN_4_4_FOREIGN_KEY = null; - public final static String COLUMN_4_4_CHECK = null; - public final static List<String> COLUMN_4_4_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_4_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_4_ENUM_VALUES = null; - public final static List<String> COLUMN_4_4_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_4_SET_VALUES = null; - public final static List<String> COLUMN_4_4_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_5_ID = 49L; - public final static Integer COLUMN_4_5_ORDINALPOS = 4; - public final static Boolean COLUMN_4_5_PRIMARY = false; - public final static String COLUMN_4_5_NAME = "Bread"; - public final static String COLUMN_4_5_INTERNAL_NAME = "bread"; - public final static TableColumnType COLUMN_4_5_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_5_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_5_DATE_FORMAT = null; - public final static Boolean COLUMN_4_5_NULL = true; - public final static Boolean COLUMN_4_5_AUTO_GENERATED = false; - public final static String COLUMN_4_5_FOREIGN_KEY = null; - public final static String COLUMN_4_5_CHECK = null; - public final static List<String> COLUMN_4_5_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_5_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_5_ENUM_VALUES = null; - public final static List<String> COLUMN_4_5_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_5_SET_VALUES = null; - public final static List<String> COLUMN_4_5_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_6_ID = 50L; - public final static Integer COLUMN_4_6_ORDINALPOS = 5; - public final static Boolean COLUMN_4_6_PRIMARY = false; - public final static String COLUMN_4_6_NAME = "Eggs"; - public final static String COLUMN_4_6_INTERNAL_NAME = "eggs"; - public final static TableColumnType COLUMN_4_6_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_6_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_6_DATE_FORMAT = null; - public final static Boolean COLUMN_4_6_NULL = true; - public final static Boolean COLUMN_4_6_AUTO_GENERATED = false; - public final static String COLUMN_4_6_FOREIGN_KEY = null; - public final static String COLUMN_4_6_CHECK = null; - public final static List<String> COLUMN_4_6_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_6_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_6_ENUM_VALUES = null; - public final static List<String> COLUMN_4_6_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_6_SET_VALUES = null; - public final static List<String> COLUMN_4_6_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_7_ID = 51L; - public final static Integer COLUMN_4_7_ORDINALPOS = 6; - public final static Boolean COLUMN_4_7_PRIMARY = false; - public final static String COLUMN_4_7_NAME = "Milk"; - public final static String COLUMN_4_7_INTERNAL_NAME = "milk"; - public final static TableColumnType COLUMN_4_7_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_7_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_7_DATE_FORMAT = null; - public final static Boolean COLUMN_4_7_NULL = true; - public final static Boolean COLUMN_4_7_AUTO_GENERATED = false; - public final static String COLUMN_4_7_FOREIGN_KEY = null; - public final static String COLUMN_4_7_CHECK = null; - public final static List<String> COLUMN_4_7_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_7_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_7_ENUM_VALUES = null; - public final static List<String> COLUMN_4_7_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_7_SET_VALUES = null; - public final static List<String> COLUMN_4_7_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_8_ID = 52L; - public final static Integer COLUMN_4_8_ORDINALPOS = 7; - public final static Boolean COLUMN_4_8_PRIMARY = false; - public final static String COLUMN_4_8_NAME = "Water"; - public final static String COLUMN_4_8_INTERNAL_NAME = "water"; - public final static TableColumnType COLUMN_4_8_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_8_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_8_DATE_FORMAT = null; - public final static Boolean COLUMN_4_8_NULL = true; - public final static Boolean COLUMN_4_8_AUTO_GENERATED = false; - public final static String COLUMN_4_8_FOREIGN_KEY = null; - public final static String COLUMN_4_8_CHECK = null; - public final static List<String> COLUMN_4_8_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_8_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_8_ENUM_VALUES = null; - public final static List<String> COLUMN_4_8_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_8_SET_VALUES = null; - public final static List<String> COLUMN_4_8_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_9_ID = 53L; - public final static Integer COLUMN_4_9_ORDINALPOS = 8; - public final static Boolean COLUMN_4_9_PRIMARY = false; - public final static String COLUMN_4_9_NAME = "Airborne"; - public final static String COLUMN_4_9_INTERNAL_NAME = "airborne"; - public final static TableColumnType COLUMN_4_9_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_9_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_9_DATE_FORMAT = null; - public final static Boolean COLUMN_4_9_NULL = true; - public final static Boolean COLUMN_4_9_AUTO_GENERATED = false; - public final static String COLUMN_4_9_FOREIGN_KEY = null; - public final static String COLUMN_4_9_CHECK = null; - public final static List<String> COLUMN_4_9_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_9_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_9_ENUM_VALUES = null; - public final static List<String> COLUMN_4_9_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_9_SET_VALUES = null; - public final static List<String> COLUMN_4_9_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_10_ID = 54L; - public final static Integer COLUMN_4_10_ORDINALPOS = 9; - public final static Boolean COLUMN_4_10_PRIMARY = false; - public final static String COLUMN_4_10_NAME = "Waterborne"; - public final static String COLUMN_4_10_INTERNAL_NAME = "waterborne"; - public final static TableColumnType COLUMN_4_10_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_10_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_10_DATE_FORMAT = null; - public final static Boolean COLUMN_4_10_NULL = true; - public final static Boolean COLUMN_4_10_AUTO_GENERATED = false; - public final static String COLUMN_4_10_FOREIGN_KEY = null; - public final static String COLUMN_4_10_CHECK = null; - public final static List<String> COLUMN_4_10_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_10_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_10_ENUM_VALUES = null; - public final static List<String> COLUMN_4_10_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_10_SET_VALUES = null; - public final static List<String> COLUMN_4_10_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_11_ID = 55L; - public final static Integer COLUMN_4_11_ORDINALPOS = 10; - public final static Boolean COLUMN_4_11_PRIMARY = false; - public final static String COLUMN_4_11_NAME = "Aquantic"; - public final static String COLUMN_4_11_INTERNAL_NAME = "aquatic"; - public final static TableColumnType COLUMN_4_11_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_11_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_11_DATE_FORMAT = null; - public final static Boolean COLUMN_4_11_NULL = true; - public final static Boolean COLUMN_4_11_AUTO_GENERATED = false; - public final static String COLUMN_4_11_FOREIGN_KEY = null; - public final static String COLUMN_4_11_CHECK = null; - public final static List<String> COLUMN_4_11_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_11_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_11_ENUM_VALUES = null; - public final static List<String> COLUMN_4_11_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_11_SET_VALUES = null; - public final static List<String> COLUMN_4_11_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_12_ID = 56L; - public final static Integer COLUMN_4_12_ORDINALPOS = 11; - public final static Boolean COLUMN_4_12_PRIMARY = false; - public final static String COLUMN_4_12_NAME = "Predator"; - public final static String COLUMN_4_12_INTERNAL_NAME = "predator"; - public final static TableColumnType COLUMN_4_12_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_12_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_12_DATE_FORMAT = null; - public final static Boolean COLUMN_4_12_NULL = true; - public final static Boolean COLUMN_4_12_AUTO_GENERATED = false; - public final static String COLUMN_4_12_FOREIGN_KEY = null; - public final static String COLUMN_4_12_CHECK = null; - public final static List<String> COLUMN_4_12_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_12_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_12_ENUM_VALUES = null; - public final static List<String> COLUMN_4_12_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_12_SET_VALUES = null; - public final static List<String> COLUMN_4_12_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_13_ID = 57L; - public final static Integer COLUMN_4_13_ORDINALPOS = 12; - public final static Boolean COLUMN_4_13_PRIMARY = false; - public final static String COLUMN_4_13_NAME = "Backbone"; - public final static String COLUMN_4_13_INTERNAL_NAME = "backbone"; - public final static TableColumnType COLUMN_4_13_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_13_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_13_DATE_FORMAT = null; - public final static Boolean COLUMN_4_13_NULL = true; - public final static Boolean COLUMN_4_13_AUTO_GENERATED = false; - public final static String COLUMN_4_13_FOREIGN_KEY = null; - public final static String COLUMN_4_13_CHECK = null; - public final static List<String> COLUMN_4_13_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_13_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_13_ENUM_VALUES = null; - public final static List<String> COLUMN_4_13_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_13_SET_VALUES = null; - public final static List<String> COLUMN_4_13_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_14_ID = 58L; - public final static Integer COLUMN_4_14_ORDINALPOS = 13; - public final static Boolean COLUMN_4_14_PRIMARY = false; - public final static String COLUMN_4_14_NAME = "Breathes"; - public final static String COLUMN_4_14_INTERNAL_NAME = "breathes"; - public final static TableColumnType COLUMN_4_14_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_14_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_14_DATE_FORMAT = null; - public final static Boolean COLUMN_4_14_NULL = true; - public final static Boolean COLUMN_4_14_AUTO_GENERATED = false; - public final static String COLUMN_4_14_FOREIGN_KEY = null; - public final static String COLUMN_4_14_CHECK = null; - public final static List<String> COLUMN_4_14_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_14_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_14_ENUM_VALUES = null; - public final static List<String> COLUMN_4_14_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_14_SET_VALUES = null; - public final static List<String> COLUMN_4_14_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_15_ID = 59L; - public final static Integer COLUMN_4_15_ORDINALPOS = 14; - public final static Boolean COLUMN_4_15_PRIMARY = false; - public final static String COLUMN_4_15_NAME = "Venomous"; - public final static String COLUMN_4_15_INTERNAL_NAME = "venomous"; - public final static TableColumnType COLUMN_4_15_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_15_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_15_DATE_FORMAT = null; - public final static Boolean COLUMN_4_15_NULL = true; - public final static Boolean COLUMN_4_15_AUTO_GENERATED = false; - public final static String COLUMN_4_15_FOREIGN_KEY = null; - public final static String COLUMN_4_15_CHECK = null; - public final static List<String> COLUMN_4_15_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_15_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_15_ENUM_VALUES = null; - public final static List<String> COLUMN_4_15_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_15_SET_VALUES = null; - public final static List<String> COLUMN_4_15_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_16_ID = 60L; - public final static Integer COLUMN_4_16_ORDINALPOS = 15; - public final static Boolean COLUMN_4_16_PRIMARY = false; - public final static String COLUMN_4_16_NAME = "Fin"; - public final static String COLUMN_4_16_INTERNAL_NAME = "fins"; - public final static TableColumnType COLUMN_4_16_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_16_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_16_DATE_FORMAT = null; - public final static Boolean COLUMN_4_16_NULL = true; - public final static Boolean COLUMN_4_16_AUTO_GENERATED = false; - public final static String COLUMN_4_16_FOREIGN_KEY = null; - public final static String COLUMN_4_16_CHECK = null; - public final static List<String> COLUMN_4_16_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_16_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_16_ENUM_VALUES = null; - public final static List<String> COLUMN_4_16_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_16_SET_VALUES = null; - public final static List<String> COLUMN_4_16_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_17_ID = 61L; - public final static Integer COLUMN_4_17_ORDINALPOS = 16; - public final static Boolean COLUMN_4_17_PRIMARY = false; - public final static String COLUMN_4_17_NAME = "Legs"; - public final static String COLUMN_4_17_INTERNAL_NAME = "legs"; - public final static TableColumnType COLUMN_4_17_TYPE = TableColumnType.INT; - public final static ColumnTypeDto COLUMN_4_17_TYPE_DTO = ColumnTypeDto.INT; - public final static Long COLUMN_4_17_DATE_FORMAT = null; - public final static Boolean COLUMN_4_17_NULL = true; - public final static Boolean COLUMN_4_17_AUTO_GENERATED = false; - public final static String COLUMN_4_17_FOREIGN_KEY = null; - public final static String COLUMN_4_17_CHECK = null; - public final static List<String> COLUMN_4_17_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_17_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_17_ENUM_VALUES = null; - public final static List<String> COLUMN_4_17_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_17_SET_VALUES = null; - public final static List<String> COLUMN_4_17_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_18_ID = 62L; - public final static Integer COLUMN_4_18_ORDINALPOS = 17; - public final static Boolean COLUMN_4_18_PRIMARY = false; - public final static String COLUMN_4_18_NAME = "Tail"; - public final static String COLUMN_4_18_INTERNAL_NAME = "tail"; - public final static TableColumnType COLUMN_4_18_TYPE = TableColumnType.DECIMAL; - public final static ColumnTypeDto COLUMN_4_18_TYPE_DTO = ColumnTypeDto.DECIMAL; - public final static Long COLUMN_4_18_DATE_FORMAT = null; - public final static Boolean COLUMN_4_18_NULL = true; - public final static Boolean COLUMN_4_18_AUTO_GENERATED = false; - public final static String COLUMN_4_18_FOREIGN_KEY = null; - public final static String COLUMN_4_18_CHECK = null; - public final static List<String> COLUMN_4_18_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_18_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_18_ENUM_VALUES = null; - public final static List<String> COLUMN_4_18_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_18_SET_VALUES = null; - public final static List<String> COLUMN_4_18_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_19_ID = 63L; - public final static Integer COLUMN_4_19_ORDINALPOS = 18; - public final static Boolean COLUMN_4_19_PRIMARY = false; - public final static String COLUMN_4_19_NAME = "Domestic"; - public final static String COLUMN_4_19_INTERNAL_NAME = "domestic"; - public final static TableColumnType COLUMN_4_19_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_19_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_19_DATE_FORMAT = null; - public final static Boolean COLUMN_4_19_NULL = true; - public final static Boolean COLUMN_4_19_AUTO_GENERATED = false; - public final static String COLUMN_4_19_FOREIGN_KEY = null; - public final static String COLUMN_4_19_CHECK = null; - public final static List<String> COLUMN_4_19_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_19_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_19_ENUM_VALUES = null; - public final static List<String> COLUMN_4_19_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_19_SET_VALUES = null; - public final static List<String> COLUMN_4_19_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_20_ID = 64L; - public final static Integer COLUMN_4_20_ORDINALPOS = 19; - public final static Boolean COLUMN_4_20_PRIMARY = false; - public final static String COLUMN_4_20_NAME = "Cat Size"; - public final static String COLUMN_4_20_INTERNAL_NAME = "catsize"; - public final static TableColumnType COLUMN_4_20_TYPE = TableColumnType.BOOL; - public final static ColumnTypeDto COLUMN_4_20_TYPE_DTO = ColumnTypeDto.BOOL; - public final static Long COLUMN_4_20_DATE_FORMAT = null; - public final static Boolean COLUMN_4_20_NULL = true; - public final static Boolean COLUMN_4_20_AUTO_GENERATED = false; - public final static String COLUMN_4_20_FOREIGN_KEY = null; - public final static String COLUMN_4_20_CHECK = null; - public final static List<String> COLUMN_4_20_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_20_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_20_ENUM_VALUES = null; - public final static List<String> COLUMN_4_20_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_20_SET_VALUES = null; - public final static List<String> COLUMN_4_20_SET_VALUES_DTO = null; - - public final static Long COLUMN_4_21_ID = 65L; - public final static Integer COLUMN_4_21_ORDINALPOS = 20; - public final static Boolean COLUMN_4_21_PRIMARY = false; - public final static String COLUMN_4_21_NAME = "Class Type"; - public final static String COLUMN_4_21_INTERNAL_NAME = "class_type"; - public final static TableColumnType COLUMN_4_21_TYPE = TableColumnType.DECIMAL; - public final static ColumnTypeDto COLUMN_4_21_TYPE_DTO = ColumnTypeDto.DECIMAL; - public final static Long COLUMN_4_21_DATE_FORMAT = null; - public final static Boolean COLUMN_4_21_NULL = true; - public final static Boolean COLUMN_4_21_AUTO_GENERATED = false; - public final static String COLUMN_4_21_FOREIGN_KEY = null; - public final static String COLUMN_4_21_CHECK = null; - public final static List<String> COLUMN_4_21_ENUM_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_21_SET_VALUES_ARR = new LinkedList<>(); - public final static List<String> COLUMN_4_21_ENUM_VALUES = null; - public final static List<String> COLUMN_4_21_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_4_21_SET_VALUES = null; - public final static List<String> COLUMN_4_21_SET_VALUES_DTO = null; - - public final static Long COLUMN_5_1_ID = 66L; - public final static Integer COLUMN_5_1_ORDINALPOS = 0; - public final static Boolean COLUMN_5_1_PRIMARY = true; - public final static String COLUMN_5_1_NAME = "id"; - public final static String COLUMN_5_1_INTERNAL_NAME = "id"; - public final static TableColumnType COLUMN_5_1_TYPE = TableColumnType.BIGINT; - public final static ColumnTypeDto COLUMN_5_1_TYPE_DTO = ColumnTypeDto.BIGINT; - public final static Long COLUMN_5_1_DATE_FORMAT = null; - public final static Boolean COLUMN_5_1_NULL = false; - public final static Boolean COLUMN_5_1_AUTO_GENERATED = true; - public final static String COLUMN_5_1_FOREIGN_KEY = null; - public final static String COLUMN_5_1_CHECK = null; - public final static List<String> COLUMN_5_1_ENUM_VALUES = null; - public final static List<String> COLUMN_5_1_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_5_1_SET_VALUES = null; - public final static List<String> COLUMN_5_1_SET_VALUES_DTO = null; - - public final static Long COLUMN_5_2_ID = 67L; - public final static Integer COLUMN_5_2_ORDINALPOS = 1; - public final static Boolean COLUMN_5_2_PRIMARY = false; - public final static String COLUMN_5_2_NAME = "firstname"; - public final static String COLUMN_5_2_INTERNAL_NAME = "firstname"; - public final static TableColumnType COLUMN_5_2_TYPE = TableColumnType.VARCHAR; - public final static ColumnTypeDto COLUMN_5_2_TYPE_DTO = ColumnTypeDto.VARCHAR; - public final static Long COLUMN_5_2_SIZE = 20L; - public final static Long COLUMN_5_2_DATE_FORMAT = null; - public final static Boolean COLUMN_5_2_NULL = false; - public final static Boolean COLUMN_5_2_AUTO_GENERATED = false; - public final static String COLUMN_5_2_FOREIGN_KEY = null; - public final static String COLUMN_5_2_CHECK = null; - public final static List<String> COLUMN_5_2_ENUM_VALUES = null; - public final static List<String> COLUMN_5_2_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_5_2_SET_VALUES = null; - public final static List<String> COLUMN_5_2_SET_VALUES_DTO = null; - - public final static Long COLUMN_5_3_ID = 68L; - public final static Integer COLUMN_5_3_ORDINALPOS = 2; - public final static Boolean COLUMN_5_3_PRIMARY = false; - public final static String COLUMN_5_3_NAME = "lastname"; - public final static String COLUMN_5_3_INTERNAL_NAME = "lastname"; - public final static TableColumnType COLUMN_5_3_TYPE = TableColumnType.VARCHAR; - public final static ColumnTypeDto COLUMN_5_3_TYPE_DTO = ColumnTypeDto.VARCHAR; - public final static Long COLUMN_5_3_SIZE = 40L; - public final static Long COLUMN_5_3_DATE_FORMAT = null; - public final static Boolean COLUMN_5_3_NULL = false; - public final static Boolean COLUMN_5_3_AUTO_GENERATED = false; - public final static String COLUMN_5_3_FOREIGN_KEY = null; - public final static String COLUMN_5_3_CHECK = null; - public final static List<String> COLUMN_5_3_ENUM_VALUES = null; - public final static List<String> COLUMN_5_3_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_5_3_SET_VALUES = null; - public final static List<String> COLUMN_5_3_SET_VALUES_DTO = null; - - public final static Long COLUMN_5_4_ID = 69L; - public final static Integer COLUMN_5_4_ORDINALPOS = 3; - public final static Boolean COLUMN_5_4_PRIMARY = false; - public final static String COLUMN_5_4_NAME = "birth"; - public final static String COLUMN_5_4_INTERNAL_NAME = "birth"; - public final static TableColumnType COLUMN_5_4_TYPE = TableColumnType.YEAR; - public final static ColumnTypeDto COLUMN_5_4_TYPE_DTO = ColumnTypeDto.YEAR; - public final static Long COLUMN_5_4_DATE_FORMAT = null; - public final static Boolean COLUMN_5_4_NULL = true; - public final static Boolean COLUMN_5_4_AUTO_GENERATED = false; - public final static String COLUMN_5_4_FOREIGN_KEY = null; - public final static String COLUMN_5_4_CHECK = null; - public final static List<String> COLUMN_5_4_ENUM_VALUES = null; - public final static List<String> COLUMN_5_4_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_5_4_SET_VALUES = null; - public final static List<String> COLUMN_5_4_SET_VALUES_DTO = null; - - public final static Long COLUMN_5_5_ID = 70L; - public final static Integer COLUMN_5_5_ORDINALPOS = 4; - public final static Boolean COLUMN_5_5_PRIMARY = false; - public final static String COLUMN_5_5_NAME = "reminder"; - public final static String COLUMN_5_5_INTERNAL_NAME = "reminder"; - public final static TableColumnType COLUMN_5_5_TYPE = TableColumnType.TIME; - public final static ColumnTypeDto COLUMN_5_5_TYPE_DTO = ColumnTypeDto.TIME; - public final static Long COLUMN_5_5_DATE_FORMAT = IMAGE_DATE_4_ID; - public final static Boolean COLUMN_5_5_NULL = true; - public final static Boolean COLUMN_5_5_AUTO_GENERATED = false; - public final static String COLUMN_5_5_FOREIGN_KEY = null; - public final static String COLUMN_5_5_CHECK = null; - public final static List<String> COLUMN_5_5_ENUM_VALUES = null; - public final static List<String> COLUMN_5_5_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_5_5_SET_VALUES = null; - public final static List<String> COLUMN_5_5_SET_VALUES_DTO = null; - - public final static Long COLUMN_5_6_ID = 71L; - public final static Integer COLUMN_5_6_ORDINALPOS = 5; - public final static Boolean COLUMN_5_6_PRIMARY = false; - public final static String COLUMN_5_6_NAME = "ref_id"; - public final static String COLUMN_5_6_INTERNAL_NAME = "ref_id"; - public final static TableColumnType COLUMN_5_6_TYPE = TableColumnType.BIGINT; - public final static ColumnTypeDto COLUMN_5_6_TYPE_DTO = ColumnTypeDto.BIGINT; - public final static Long COLUMN_5_6_DATE_FORMAT = null; - public final static Boolean COLUMN_5_6_NULL = true; - public final static Boolean COLUMN_5_6_AUTO_GENERATED = false; - public final static String COLUMN_5_6_FOREIGN_KEY = null; - public final static String COLUMN_5_6_CHECK = null; - public final static List<String> COLUMN_5_6_ENUM_VALUES = null; - public final static List<String> COLUMN_5_6_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_5_6_SET_VALUES = null; - public final static List<String> COLUMN_5_6_SET_VALUES_DTO = null; - public final static Long COLUMN_8_1_ID = 72L; public final static Integer COLUMN_8_1_ORDINALPOS = 0; public final static Boolean COLUMN_8_1_PRIMARY = true; @@ -4169,474 +3723,426 @@ public abstract class BaseTest { .sets(new LinkedList<>()) .build()); - public final static ConstraintsDto TABLE_3_CONSTRAINTS_DTO = ConstraintsDto.builder() - .uniques(List.of(UniqueDto.builder().columns(List.of(TABLE_3_COLUMNS_DTO.get(0))).build())) - .foreignKeys(new LinkedList<>()) - .checks(Set.of()) - .build(); - public final static List<TableColumn> TABLE_5_COLUMNS = List.of(TableColumn.builder() - .id(COLUMN_4_1_ID) - .ordinalPosition(COLUMN_4_1_ORDINALPOS) + .id(45L) + .ordinalPosition(0) .table(TABLE_5) - .name(COLUMN_4_1_NAME) - .internalName(COLUMN_4_1_INTERNAL_NAME) - .columnType(COLUMN_4_1_TYPE) - .isNullAllowed(COLUMN_4_1_NULL) - .autoGenerated(COLUMN_4_1_AUTO_GENERATED) - .enums(COLUMN_4_1_ENUM_VALUES) - .sets(COLUMN_4_1_SET_VALUES) + .name("id") + .internalName("id") + .columnType(TableColumnType.BIGINT) + .isNullAllowed(false) + .autoGenerated(true) .build(), TableColumn.builder() - .id(COLUMN_4_2_ID) - .ordinalPosition(COLUMN_4_2_ORDINALPOS) + .id(46L) + .ordinalPosition(1) .table(TABLE_5) - .name(COLUMN_4_2_NAME) - .internalName(COLUMN_4_2_INTERNAL_NAME) - .columnType(COLUMN_4_2_TYPE) - .isNullAllowed(COLUMN_4_2_NULL) - .autoGenerated(COLUMN_4_2_AUTO_GENERATED) - .enums(COLUMN_4_2_ENUM_VALUES) - .sets(COLUMN_4_2_SET_VALUES) + .name("Animal Name") + .internalName("animal_name") + .columnType(TableColumnType.VARCHAR) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_3_ID) - .ordinalPosition(COLUMN_4_3_ORDINALPOS) + .id(47L) + .ordinalPosition(2) .table(TABLE_5) - .name(COLUMN_4_3_NAME) - .internalName(COLUMN_4_3_INTERNAL_NAME) - .columnType(COLUMN_4_3_TYPE) - .isNullAllowed(COLUMN_4_3_NULL) - .autoGenerated(COLUMN_4_3_AUTO_GENERATED) - .enums(COLUMN_4_3_ENUM_VALUES) - .sets(COLUMN_4_3_SET_VALUES) + .name("Hair") + .internalName("hair") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_4_ID) - .ordinalPosition(COLUMN_4_4_ORDINALPOS) + .id(48L) + .ordinalPosition(3) .table(TABLE_5) - .name(COLUMN_4_4_NAME) - .internalName(COLUMN_4_4_INTERNAL_NAME) - .columnType(COLUMN_4_4_TYPE) - .isNullAllowed(COLUMN_4_4_NULL) - .autoGenerated(COLUMN_4_4_AUTO_GENERATED) - .enums(COLUMN_4_4_ENUM_VALUES) - .sets(COLUMN_4_4_SET_VALUES) + .name("Feathers") + .internalName("feathers") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_5_ID) - .ordinalPosition(COLUMN_4_5_ORDINALPOS) + .id(49L) + .ordinalPosition(4) .table(TABLE_5) - .name(COLUMN_4_5_NAME) - .internalName(COLUMN_4_5_INTERNAL_NAME) - .columnType(COLUMN_4_5_TYPE) - .isNullAllowed(COLUMN_4_5_NULL) - .autoGenerated(COLUMN_4_5_AUTO_GENERATED) - .enums(COLUMN_4_5_ENUM_VALUES) - .sets(COLUMN_4_5_SET_VALUES) + .name("Bread") + .internalName("bread") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_6_ID) - .ordinalPosition(COLUMN_4_6_ORDINALPOS) + .id(50L) + .ordinalPosition(5) .table(TABLE_5) - .name(COLUMN_4_6_NAME) - .internalName(COLUMN_4_6_INTERNAL_NAME) - .columnType(COLUMN_4_6_TYPE) - .isNullAllowed(COLUMN_4_6_NULL) - .autoGenerated(COLUMN_4_6_AUTO_GENERATED) - .enums(COLUMN_4_6_ENUM_VALUES) - .sets(COLUMN_4_6_SET_VALUES) + .name("Eggs") + .internalName("eggs") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_7_ID) - .ordinalPosition(COLUMN_4_7_ORDINALPOS) + .id(51L) + .ordinalPosition(6) .table(TABLE_5) - .name(COLUMN_4_7_NAME) - .internalName(COLUMN_4_7_INTERNAL_NAME) - .columnType(COLUMN_4_7_TYPE) - .isNullAllowed(COLUMN_4_7_NULL) - .autoGenerated(COLUMN_4_7_AUTO_GENERATED) - .enums(COLUMN_4_7_ENUM_VALUES) - .sets(COLUMN_4_7_SET_VALUES) + .name("Milk") + .internalName("milk") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_8_ID) - .ordinalPosition(COLUMN_4_8_ORDINALPOS) + .id(52L) + .ordinalPosition(7) .table(TABLE_5) - .name(COLUMN_4_8_NAME) - .internalName(COLUMN_4_8_INTERNAL_NAME) - .columnType(COLUMN_4_8_TYPE) - .isNullAllowed(COLUMN_4_8_NULL) - .autoGenerated(COLUMN_4_8_AUTO_GENERATED) - .enums(COLUMN_4_8_ENUM_VALUES) - .sets(COLUMN_4_8_SET_VALUES) + .name("Water") + .internalName("water") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_9_ID) - .ordinalPosition(COLUMN_4_9_ORDINALPOS) + .id(53L) + .ordinalPosition(8) .table(TABLE_5) - .name(COLUMN_4_9_NAME) - .internalName(COLUMN_4_9_INTERNAL_NAME) - .columnType(COLUMN_4_9_TYPE) - .isNullAllowed(COLUMN_4_9_NULL) - .autoGenerated(COLUMN_4_9_AUTO_GENERATED) - .enums(COLUMN_4_9_ENUM_VALUES) - .sets(COLUMN_4_9_SET_VALUES) + .name("Airborne") + .internalName("airborne") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_10_ID) - .ordinalPosition(COLUMN_4_10_ORDINALPOS) + .id(54L) + .ordinalPosition(9) .table(TABLE_5) - .name(COLUMN_4_10_NAME) - .internalName(COLUMN_4_10_INTERNAL_NAME) - .columnType(COLUMN_4_10_TYPE) - .isNullAllowed(COLUMN_4_10_NULL) - .autoGenerated(COLUMN_4_10_AUTO_GENERATED) - .enums(COLUMN_4_10_ENUM_VALUES) - .sets(COLUMN_4_10_SET_VALUES) + .name("Waterborne") + .internalName("waterborne") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_11_ID) - .ordinalPosition(COLUMN_4_11_ORDINALPOS) + .id(55L) + .ordinalPosition(10) .table(TABLE_5) - .name(COLUMN_4_11_NAME) - .internalName(COLUMN_4_11_INTERNAL_NAME) - .columnType(COLUMN_4_11_TYPE) - .isNullAllowed(COLUMN_4_11_NULL) - .autoGenerated(COLUMN_4_11_AUTO_GENERATED) - .enums(COLUMN_4_11_ENUM_VALUES) - .sets(COLUMN_4_11_SET_VALUES) + .name("Aquantic") + .internalName("aquantic") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_12_ID) - .ordinalPosition(COLUMN_4_12_ORDINALPOS) + .id(56L) + .ordinalPosition(11) .table(TABLE_5) - .name(COLUMN_4_12_NAME) - .internalName(COLUMN_4_12_INTERNAL_NAME) - .columnType(COLUMN_4_12_TYPE) - .isNullAllowed(COLUMN_4_12_NULL) - .autoGenerated(COLUMN_4_12_AUTO_GENERATED) - .enums(COLUMN_4_12_ENUM_VALUES) - .sets(COLUMN_4_12_SET_VALUES) + .name("Predator") + .internalName("predator") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_13_ID) - .ordinalPosition(COLUMN_4_13_ORDINALPOS) + .id(57L) + .ordinalPosition(12) .table(TABLE_5) - .name(COLUMN_4_13_NAME) - .internalName(COLUMN_4_13_INTERNAL_NAME) - .columnType(COLUMN_4_13_TYPE) - .isNullAllowed(COLUMN_4_13_NULL) - .autoGenerated(COLUMN_4_13_AUTO_GENERATED) - .enums(COLUMN_4_13_ENUM_VALUES) - .sets(COLUMN_4_13_SET_VALUES) + .name("Backbone") + .internalName("backbone") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_14_ID) - .ordinalPosition(COLUMN_4_14_ORDINALPOS) + .id(58L) + .ordinalPosition(13) .table(TABLE_5) - .name(COLUMN_4_14_NAME) - .internalName(COLUMN_4_14_INTERNAL_NAME) - .columnType(COLUMN_4_14_TYPE) - .isNullAllowed(COLUMN_4_14_NULL) - .autoGenerated(COLUMN_4_14_AUTO_GENERATED) - .enums(COLUMN_4_14_ENUM_VALUES) - .sets(COLUMN_4_14_SET_VALUES) + .name("Breathes") + .internalName("breathes") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_15_ID) - .ordinalPosition(COLUMN_4_15_ORDINALPOS) + .id(59L) + .ordinalPosition(14) .table(TABLE_5) - .name(COLUMN_4_15_NAME) - .internalName(COLUMN_4_15_INTERNAL_NAME) - .columnType(COLUMN_4_15_TYPE) - .isNullAllowed(COLUMN_4_15_NULL) - .autoGenerated(COLUMN_4_15_AUTO_GENERATED) - .enums(COLUMN_4_15_ENUM_VALUES) - .sets(COLUMN_4_15_SET_VALUES) + .name("Venomous") + .internalName("venomous") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_16_ID) - .ordinalPosition(COLUMN_4_16_ORDINALPOS) + .id(60L) + .ordinalPosition(15) .table(TABLE_5) - .name(COLUMN_4_16_NAME) - .internalName(COLUMN_4_16_INTERNAL_NAME) - .columnType(COLUMN_4_16_TYPE) - .isNullAllowed(COLUMN_4_16_NULL) - .autoGenerated(COLUMN_4_16_AUTO_GENERATED) - .enums(COLUMN_4_16_ENUM_VALUES) - .sets(COLUMN_4_16_SET_VALUES) + .name("Fin") + .internalName("fin") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_17_ID) - .ordinalPosition(COLUMN_4_17_ORDINALPOS) + .id(61L) + .ordinalPosition(16) .table(TABLE_5) - .name(COLUMN_4_17_NAME) - .internalName(COLUMN_4_17_INTERNAL_NAME) - .columnType(COLUMN_4_17_TYPE) - .isNullAllowed(COLUMN_4_17_NULL) - .autoGenerated(COLUMN_4_17_AUTO_GENERATED) - .enums(COLUMN_4_17_ENUM_VALUES) - .sets(COLUMN_4_17_SET_VALUES) + .name("Legs") + .internalName("legs") + .columnType(TableColumnType.INT) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_18_ID) - .ordinalPosition(COLUMN_4_18_ORDINALPOS) + .id(62L) + .ordinalPosition(17) .table(TABLE_5) - .name(COLUMN_4_18_NAME) - .internalName(COLUMN_4_18_INTERNAL_NAME) - .columnType(COLUMN_4_18_TYPE) - .isNullAllowed(COLUMN_4_18_NULL) - .autoGenerated(COLUMN_4_18_AUTO_GENERATED) - .enums(COLUMN_4_18_ENUM_VALUES) - .sets(COLUMN_4_18_SET_VALUES) + .name("Tail") + .internalName("tail") + .columnType(TableColumnType.DECIMAL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_19_ID) - .ordinalPosition(COLUMN_4_19_ORDINALPOS) + .id(63L) + .ordinalPosition(18) .table(TABLE_5) - .name(COLUMN_4_19_NAME) - .internalName(COLUMN_4_19_INTERNAL_NAME) - .columnType(COLUMN_4_19_TYPE) - .isNullAllowed(COLUMN_4_19_NULL) - .autoGenerated(COLUMN_4_19_AUTO_GENERATED) - .enums(COLUMN_4_19_ENUM_VALUES) - .sets(COLUMN_4_19_SET_VALUES) + .name("Domestic") + .internalName("domestic") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_20_ID) - .ordinalPosition(COLUMN_4_20_ORDINALPOS) + .id(64L) + .ordinalPosition(19) .table(TABLE_5) - .name(COLUMN_4_20_NAME) - .internalName(COLUMN_4_20_INTERNAL_NAME) - .columnType(COLUMN_4_20_TYPE) - .isNullAllowed(COLUMN_4_20_NULL) - .autoGenerated(COLUMN_4_20_AUTO_GENERATED) - .enums(COLUMN_4_20_ENUM_VALUES) - .sets(COLUMN_4_20_SET_VALUES) + .name("Catsize") + .internalName("catsize") + .columnType(TableColumnType.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_4_21_ID) - .ordinalPosition(COLUMN_4_21_ORDINALPOS) + .id(64L) + .ordinalPosition(20) .table(TABLE_5) - .name(COLUMN_4_21_NAME) - .internalName(COLUMN_4_21_INTERNAL_NAME) - .columnType(COLUMN_4_21_TYPE) - .isNullAllowed(COLUMN_4_21_NULL) - .autoGenerated(COLUMN_4_21_AUTO_GENERATED) - .enums(COLUMN_4_21_ENUM_VALUES) - .sets(COLUMN_4_21_SET_VALUES) + .name("Class Type") + .internalName("class_type") + .columnType(TableColumnType.DECIMAL) + .isNullAllowed(true) + .autoGenerated(false) .build()); public final static List<ColumnDto> TABLE_5_COLUMNS_DTO = List.of(ColumnDto.builder() - .id(COLUMN_4_1_ID) - .name(COLUMN_4_1_NAME) - .internalName(COLUMN_4_1_INTERNAL_NAME) - .columnType(COLUMN_4_1_TYPE_DTO) - .isNullAllowed(COLUMN_4_1_NULL) - .autoGenerated(COLUMN_4_1_AUTO_GENERATED) - .enums(COLUMN_4_1_ENUM_VALUES) - .sets(COLUMN_4_1_SET_VALUES) + .id(45L) + .ordinalPosition(0) + .table(TABLE_5_DTO) + .name("id") + .internalName("id") + .columnType(ColumnTypeDto.BIGINT) + .isNullAllowed(false) + .autoGenerated(true) .build(), ColumnDto.builder() - .id(COLUMN_4_2_ID) - .name(COLUMN_4_2_NAME) - .internalName(COLUMN_4_2_INTERNAL_NAME) - .columnType(COLUMN_4_2_TYPE_DTO) - .isNullAllowed(COLUMN_4_2_NULL) - .autoGenerated(COLUMN_4_2_AUTO_GENERATED) - .enums(COLUMN_4_2_ENUM_VALUES) - .sets(COLUMN_4_2_SET_VALUES) + .id(46L) + .ordinalPosition(1) + .table(TABLE_5_DTO) + .name("Animal Name") + .internalName("animal_name") + .columnType(ColumnTypeDto.VARCHAR) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_3_ID) - .name(COLUMN_4_3_NAME) - .internalName(COLUMN_4_3_INTERNAL_NAME) - .columnType(COLUMN_4_3_TYPE_DTO) - .isNullAllowed(COLUMN_4_3_NULL) - .autoGenerated(COLUMN_4_3_AUTO_GENERATED) - .enums(COLUMN_4_3_ENUM_VALUES) - .sets(COLUMN_4_3_SET_VALUES) + .id(47L) + .ordinalPosition(2) + .table(TABLE_5_DTO) + .name("Hair") + .internalName("hair") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_4_ID) - .name(COLUMN_4_4_NAME) - .internalName(COLUMN_4_4_INTERNAL_NAME) - .columnType(COLUMN_4_4_TYPE_DTO) - .isNullAllowed(COLUMN_4_4_NULL) - .autoGenerated(COLUMN_4_4_AUTO_GENERATED) - .enums(COLUMN_4_4_ENUM_VALUES) - .sets(COLUMN_4_4_SET_VALUES) + .id(48L) + .ordinalPosition(3) + .table(TABLE_5_DTO) + .name("Feathers") + .internalName("feathers") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_5_ID) - .name(COLUMN_4_5_NAME) - .internalName(COLUMN_4_5_INTERNAL_NAME) - .columnType(COLUMN_4_5_TYPE_DTO) - .isNullAllowed(COLUMN_4_5_NULL) - .autoGenerated(COLUMN_4_5_AUTO_GENERATED) - .enums(COLUMN_4_5_ENUM_VALUES) - .sets(COLUMN_4_5_SET_VALUES) + .id(49L) + .ordinalPosition(4) + .table(TABLE_5_DTO) + .name("Bread") + .internalName("bread") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_6_ID) - .name(COLUMN_4_6_NAME) - .internalName(COLUMN_4_6_INTERNAL_NAME) - .columnType(COLUMN_4_6_TYPE_DTO) - .isNullAllowed(COLUMN_4_6_NULL) - .autoGenerated(COLUMN_4_6_AUTO_GENERATED) - .enums(COLUMN_4_6_ENUM_VALUES) - .sets(COLUMN_4_6_SET_VALUES) + .id(50L) + .ordinalPosition(5) + .table(TABLE_5_DTO) + .name("Eggs") + .internalName("eggs") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_7_ID) - .name(COLUMN_4_7_NAME) - .internalName(COLUMN_4_7_INTERNAL_NAME) - .columnType(COLUMN_4_7_TYPE_DTO) - .isNullAllowed(COLUMN_4_7_NULL) - .autoGenerated(COLUMN_4_7_AUTO_GENERATED) - .enums(COLUMN_4_7_ENUM_VALUES) - .sets(COLUMN_4_7_SET_VALUES) + .id(51L) + .ordinalPosition(6) + .table(TABLE_5_DTO) + .name("Milk") + .internalName("milk") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_8_ID) - .name(COLUMN_4_8_NAME) - .internalName(COLUMN_4_8_INTERNAL_NAME) - .columnType(COLUMN_4_8_TYPE_DTO) - .isNullAllowed(COLUMN_4_8_NULL) - .autoGenerated(COLUMN_4_8_AUTO_GENERATED) - .enums(COLUMN_4_8_ENUM_VALUES) - .sets(COLUMN_4_8_SET_VALUES) + .id(52L) + .ordinalPosition(7) + .table(TABLE_5_DTO) + .name("Water") + .internalName("water") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_9_ID) - .name(COLUMN_4_9_NAME) - .internalName(COLUMN_4_9_INTERNAL_NAME) - .columnType(COLUMN_4_9_TYPE_DTO) - .isNullAllowed(COLUMN_4_9_NULL) - .autoGenerated(COLUMN_4_9_AUTO_GENERATED) - .enums(COLUMN_4_9_ENUM_VALUES) - .sets(COLUMN_4_9_SET_VALUES) + .id(53L) + .ordinalPosition(8) + .table(TABLE_5_DTO) + .name("Airborne") + .internalName("airborne") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_10_ID) - .name(COLUMN_4_10_NAME) - .internalName(COLUMN_4_10_INTERNAL_NAME) - .columnType(COLUMN_4_10_TYPE_DTO) - .isNullAllowed(COLUMN_4_10_NULL) - .autoGenerated(COLUMN_4_10_AUTO_GENERATED) - .enums(COLUMN_4_10_ENUM_VALUES) - .sets(COLUMN_4_10_SET_VALUES) + .id(54L) + .ordinalPosition(9) + .table(TABLE_5_DTO) + .name("Waterborne") + .internalName("waterborne") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_11_ID) - .name(COLUMN_4_11_NAME) - .internalName(COLUMN_4_11_INTERNAL_NAME) - .columnType(COLUMN_4_11_TYPE_DTO) - .isNullAllowed(COLUMN_4_11_NULL) - .autoGenerated(COLUMN_4_11_AUTO_GENERATED) - .enums(COLUMN_4_11_ENUM_VALUES) - .sets(COLUMN_4_11_SET_VALUES) + .id(55L) + .ordinalPosition(10) + .table(TABLE_5_DTO) + .name("Aquantic") + .internalName("aquantic") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_12_ID) - .name(COLUMN_4_12_NAME) - .internalName(COLUMN_4_12_INTERNAL_NAME) - .columnType(COLUMN_4_12_TYPE_DTO) - .isNullAllowed(COLUMN_4_12_NULL) - .autoGenerated(COLUMN_4_12_AUTO_GENERATED) - .enums(COLUMN_4_12_ENUM_VALUES) - .sets(COLUMN_4_12_SET_VALUES) + .id(56L) + .ordinalPosition(11) + .table(TABLE_5_DTO) + .name("Predator") + .internalName("predator") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_13_ID) - .name(COLUMN_4_13_NAME) - .internalName(COLUMN_4_13_INTERNAL_NAME) - .columnType(COLUMN_4_13_TYPE_DTO) - .isNullAllowed(COLUMN_4_13_NULL) - .autoGenerated(COLUMN_4_13_AUTO_GENERATED) - .enums(COLUMN_4_13_ENUM_VALUES) - .sets(COLUMN_4_13_SET_VALUES) + .id(57L) + .ordinalPosition(12) + .table(TABLE_5_DTO) + .name("Backbone") + .internalName("backbone") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_14_ID) - .name(COLUMN_4_14_NAME) - .internalName(COLUMN_4_14_INTERNAL_NAME) - .columnType(COLUMN_4_14_TYPE_DTO) - .isNullAllowed(COLUMN_4_14_NULL) - .autoGenerated(COLUMN_4_14_AUTO_GENERATED) - .enums(COLUMN_4_14_ENUM_VALUES) - .sets(COLUMN_4_14_SET_VALUES) + .id(58L) + .ordinalPosition(13) + .table(TABLE_5_DTO) + .name("Breathes") + .internalName("breathes") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_15_ID) - .name(COLUMN_4_15_NAME) - .internalName(COLUMN_4_15_INTERNAL_NAME) - .columnType(COLUMN_4_15_TYPE_DTO) - .isNullAllowed(COLUMN_4_15_NULL) - .autoGenerated(COLUMN_4_15_AUTO_GENERATED) - .enums(COLUMN_4_15_ENUM_VALUES) - .sets(COLUMN_4_15_SET_VALUES) + .id(59L) + .ordinalPosition(14) + .table(TABLE_5_DTO) + .name("Venomous") + .internalName("venomous") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_16_ID) - .name(COLUMN_4_16_NAME) - .internalName(COLUMN_4_16_INTERNAL_NAME) - .columnType(COLUMN_4_16_TYPE_DTO) - .isNullAllowed(COLUMN_4_16_NULL) - .autoGenerated(COLUMN_4_16_AUTO_GENERATED) - .enums(COLUMN_4_16_ENUM_VALUES) - .sets(COLUMN_4_16_SET_VALUES) + .id(60L) + .ordinalPosition(15) + .table(TABLE_5_DTO) + .name("Fin") + .internalName("fin") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_17_ID) - .name(COLUMN_4_17_NAME) - .internalName(COLUMN_4_17_INTERNAL_NAME) - .columnType(COLUMN_4_17_TYPE_DTO) - .isNullAllowed(COLUMN_4_17_NULL) - .autoGenerated(COLUMN_4_17_AUTO_GENERATED) - .enums(COLUMN_4_17_ENUM_VALUES) - .sets(COLUMN_4_17_SET_VALUES) + .id(61L) + .ordinalPosition(16) + .table(TABLE_5_DTO) + .name("Legs") + .internalName("legs") + .columnType(ColumnTypeDto.INT) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_18_ID) - .name(COLUMN_4_18_NAME) - .internalName(COLUMN_4_18_INTERNAL_NAME) - .columnType(COLUMN_4_18_TYPE_DTO) - .isNullAllowed(COLUMN_4_18_NULL) - .autoGenerated(COLUMN_4_18_AUTO_GENERATED) - .enums(COLUMN_4_18_ENUM_VALUES) - .sets(COLUMN_4_18_SET_VALUES) + .id(62L) + .ordinalPosition(17) + .table(TABLE_5_DTO) + .name("Tail") + .internalName("tail") + .columnType(ColumnTypeDto.DECIMAL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_19_ID) - .name(COLUMN_4_19_NAME) - .internalName(COLUMN_4_19_INTERNAL_NAME) - .columnType(COLUMN_4_19_TYPE_DTO) - .isNullAllowed(COLUMN_4_19_NULL) - .autoGenerated(COLUMN_4_19_AUTO_GENERATED) - .enums(COLUMN_4_19_ENUM_VALUES) - .sets(COLUMN_4_19_SET_VALUES) + .id(63L) + .ordinalPosition(18) + .table(TABLE_5_DTO) + .name("Domestic") + .internalName("domestic") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_20_ID) - .name(COLUMN_4_20_NAME) - .internalName(COLUMN_4_20_INTERNAL_NAME) - .columnType(COLUMN_4_20_TYPE_DTO) - .isNullAllowed(COLUMN_4_20_NULL) - .autoGenerated(COLUMN_4_20_AUTO_GENERATED) - .enums(COLUMN_4_20_ENUM_VALUES) - .sets(COLUMN_4_20_SET_VALUES) + .id(64L) + .ordinalPosition(19) + .table(TABLE_5_DTO) + .name("Catsize") + .internalName("catsize") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), ColumnDto.builder() - .id(COLUMN_4_21_ID) - .name(COLUMN_4_21_NAME) - .internalName(COLUMN_4_21_INTERNAL_NAME) - .columnType(COLUMN_4_21_TYPE_DTO) - .isNullAllowed(COLUMN_4_21_NULL) - .autoGenerated(COLUMN_4_21_AUTO_GENERATED) - .enums(COLUMN_4_21_ENUM_VALUES) - .sets(COLUMN_4_21_SET_VALUES) + .id(64L) + .ordinalPosition(20) + .table(TABLE_5_DTO) + .name("Class Type") + .internalName("class_type") + .columnType(ColumnTypeDto.DECIMAL) + .isNullAllowed(true) + .autoGenerated(false) .build()); public final static List<ForeignKeyCreateDto> TABLE_5_FOREIGN_KEYS_INVALID_CREATE = List.of(ForeignKeyCreateDto.builder() @@ -4649,54 +4155,115 @@ public abstract class BaseTest { .foreignKeys(TABLE_5_FOREIGN_KEYS_INVALID_CREATE) .build(); - public final static List<ColumnCreateDto> TABLE_5_COLUMNS_INVALID_CREATE = List.of(ColumnCreateDto.builder() - .name(COLUMN_4_2_NAME) - .type(COLUMN_4_2_TYPE_DTO) - .nullAllowed(COLUMN_4_2_NULL) - .enums(COLUMN_4_2_ENUM_VALUES_ARR) - .build()); - public final static List<ColumnCreateDto> TABLE_5_COLUMNS_CREATE = List.of(ColumnCreateDto.builder() - .name(COLUMN_5_1_NAME) - .type(COLUMN_5_1_TYPE_DTO) - .nullAllowed(COLUMN_5_1_NULL) - .enums(COLUMN_5_1_ENUM_VALUES_DTO) + .name("id") + .type(ColumnTypeDto.BIGINT) + .nullAllowed(false) + .build(), + ColumnCreateDto.builder() + .name("Animal Name") + .type(ColumnTypeDto.VARCHAR) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Hair") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Feathers") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Bread") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Eggs") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Milk") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Water") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Airborne") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Waterborne") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Aquantic") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Predator") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Backbone") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Breathes") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Venomous") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) + .build(), + ColumnCreateDto.builder() + .name("Fin") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) .build(), ColumnCreateDto.builder() - .name(COLUMN_5_2_NAME) - .type(COLUMN_5_2_TYPE_DTO) - .nullAllowed(COLUMN_5_2_NULL) - .enums(COLUMN_5_2_ENUM_VALUES_DTO) + .name("Legs") + .type(ColumnTypeDto.INT) + .nullAllowed(true) .build(), ColumnCreateDto.builder() - .name(COLUMN_5_3_NAME) - .type(COLUMN_5_3_TYPE_DTO) - .nullAllowed(COLUMN_5_3_NULL) - .enums(COLUMN_5_3_ENUM_VALUES_DTO) + .name("Tail") + .type(ColumnTypeDto.DECIMAL) + .nullAllowed(true) .build(), ColumnCreateDto.builder() - .name(COLUMN_5_4_NAME) - .type(COLUMN_5_4_TYPE_DTO) - .nullAllowed(COLUMN_5_4_NULL) - .enums(COLUMN_5_4_ENUM_VALUES_DTO) + .name("Domestic") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) .build(), ColumnCreateDto.builder() - .name(COLUMN_5_5_NAME) - .type(COLUMN_5_5_TYPE_DTO) - .dfid(COLUMN_5_5_DATE_FORMAT) - .nullAllowed(COLUMN_5_5_NULL) - .enums(COLUMN_5_5_ENUM_VALUES_DTO) + .name("Catsize") + .type(ColumnTypeDto.BOOL) + .nullAllowed(true) .build(), ColumnCreateDto.builder() - .name(COLUMN_5_6_NAME) - .type(COLUMN_5_6_TYPE_DTO) - .nullAllowed(COLUMN_5_6_NULL) - .enums(COLUMN_5_6_ENUM_VALUES_DTO) + .name("Class Type") + .type(ColumnTypeDto.DECIMAL) + .nullAllowed(true) .build()); public final static ConstraintsCreateDto TABLE_5_CREATE_CONSTRAINTS_DTO = ConstraintsCreateDto.builder() - .primaryKey(Set.of(COLUMN_5_1_NAME)) - .uniques(List.of(List.of(COLUMN_5_1_NAME))) + .primaryKey(Set.of("id")) + .uniques(List.of(List.of("id"))) .checks(new LinkedHashSet<>()) .foreignKeys(new LinkedList<>()) .build(); @@ -4716,90 +4283,139 @@ public abstract class BaseTest { .build(); public final static List<TableColumn> TABLE_6_COLUMNS = List.of(TableColumn.builder() - .id(COLUMN_5_1_ID) - .ordinalPosition(COLUMN_5_1_ORDINALPOS) + .id(66L) + .ordinalPosition(0) .table(TABLE_6) - .name(COLUMN_5_1_NAME) - .internalName(COLUMN_5_1_INTERNAL_NAME) - .columnType(COLUMN_5_1_TYPE) - .isNullAllowed(COLUMN_5_1_NULL) - .autoGenerated(COLUMN_5_1_AUTO_GENERATED) - .enums(COLUMN_5_1_ENUM_VALUES) - .sets(COLUMN_5_1_SET_VALUES) + .name("id") + .internalName("id") + .columnType(TableColumnType.BIGINT) + .isNullAllowed(false) + .autoGenerated(true) .build(), TableColumn.builder() - .id(COLUMN_5_2_ID) - .ordinalPosition(COLUMN_5_2_ORDINALPOS) + .id(67L) + .ordinalPosition(1) .table(TABLE_6) - .name(COLUMN_5_2_NAME) - .internalName(COLUMN_5_2_INTERNAL_NAME) - .columnType(COLUMN_5_2_TYPE) - .isNullAllowed(COLUMN_5_2_NULL) - .autoGenerated(COLUMN_5_2_AUTO_GENERATED) - .enums(COLUMN_5_2_ENUM_VALUES) - .sets(COLUMN_5_2_SET_VALUES) + .name("firstname") + .internalName("firstname") + .columnType(TableColumnType.VARCHAR) + .isNullAllowed(false) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_5_3_ID) - .ordinalPosition(COLUMN_5_3_ORDINALPOS) + .id(68L) + .ordinalPosition(2) .table(TABLE_6) - .name(COLUMN_5_3_NAME) - .internalName(COLUMN_5_3_INTERNAL_NAME) - .columnType(COLUMN_5_3_TYPE) - .isNullAllowed(COLUMN_5_3_NULL) - .autoGenerated(COLUMN_5_3_AUTO_GENERATED) - .enums(COLUMN_5_3_ENUM_VALUES) - .sets(COLUMN_5_3_SET_VALUES) + .name("lastname") + .internalName("lastname") + .columnType(TableColumnType.VARCHAR) + .isNullAllowed(false) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_5_4_ID) - .ordinalPosition(COLUMN_5_4_ORDINALPOS) + .id(69L) + .ordinalPosition(3) .table(TABLE_6) - .name(COLUMN_5_4_NAME) - .internalName(COLUMN_5_4_INTERNAL_NAME) - .columnType(COLUMN_5_4_TYPE) - .isNullAllowed(COLUMN_5_4_NULL) - .autoGenerated(COLUMN_5_4_AUTO_GENERATED) - .enums(COLUMN_5_4_ENUM_VALUES) - .sets(COLUMN_5_4_SET_VALUES) + .name("birth") + .internalName("birth") + .columnType(TableColumnType.YEAR) + .isNullAllowed(false) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_5_5_ID) - .ordinalPosition(COLUMN_5_5_ORDINALPOS) + .id(70L) + .ordinalPosition(4) .table(TABLE_6) - .name(COLUMN_5_5_NAME) - .internalName(COLUMN_5_5_INTERNAL_NAME) - .columnType(COLUMN_5_5_TYPE) - .isNullAllowed(COLUMN_5_5_NULL) - .autoGenerated(COLUMN_5_5_AUTO_GENERATED) - .enums(COLUMN_5_5_ENUM_VALUES) - .sets(COLUMN_5_5_SET_VALUES) + .name("reminder") + .internalName("reminder") + .columnType(TableColumnType.TIME) + .dateFormat(IMAGE_DATE_4) + .isNullAllowed(false) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_5_6_ID) - .ordinalPosition(COLUMN_5_6_ORDINALPOS) + .id(71L) + .ordinalPosition(5) .table(TABLE_6) - .name(COLUMN_5_6_NAME) - .internalName(COLUMN_5_6_INTERNAL_NAME) - .columnType(COLUMN_5_6_TYPE) - .isNullAllowed(COLUMN_5_6_NULL) - .autoGenerated(COLUMN_5_6_AUTO_GENERATED) - .enums(COLUMN_5_6_ENUM_VALUES) - .sets(COLUMN_5_6_SET_VALUES) + .name("ref_id") + .internalName("ref_id") + .columnType(TableColumnType.BIGINT) + .isNullAllowed(true) + .autoGenerated(false) + .build()); + + public final static List<ColumnDto> TABLE_6_COLUMNS_DTO = List.of(ColumnDto.builder() + .id(66L) + .ordinalPosition(0) + .table(TABLE_6_DTO) + .name("id") + .internalName("id") + .columnType(ColumnTypeDto.BIGINT) + .isNullAllowed(false) + .autoGenerated(true) + .build(), + ColumnDto.builder() + .id(67L) + .ordinalPosition(1) + .table(TABLE_6_DTO) + .name("firstname") + .internalName("firstname") + .columnType(ColumnTypeDto.VARCHAR) + .isNullAllowed(false) + .autoGenerated(false) + .build(), + ColumnDto.builder() + .id(68L) + .ordinalPosition(2) + .table(TABLE_6_DTO) + .name("lastname") + .internalName("lastname") + .columnType(ColumnTypeDto.VARCHAR) + .isNullAllowed(false) + .autoGenerated(false) + .build(), + ColumnDto.builder() + .id(69L) + .ordinalPosition(3) + .table(TABLE_6_DTO) + .name("birth") + .internalName("birth") + .columnType(ColumnTypeDto.YEAR) + .isNullAllowed(false) + .autoGenerated(false) + .build(), + ColumnDto.builder() + .id(70L) + .ordinalPosition(4) + .table(TABLE_6_DTO) + .name("reminder") + .internalName("reminder") + .columnType(ColumnTypeDto.TIME) + .dateFormat(IMAGE_DATE_4_DTO) + .isNullAllowed(false) + .autoGenerated(false) + .build(), + ColumnDto.builder() + .id(71L) + .ordinalPosition(5) + .table(TABLE_6_DTO) + .name("ref_id") + .internalName("ref_id") + .columnType(ColumnTypeDto.BIGINT) + .isNullAllowed(true) + .autoGenerated(false) .build()); public final static List<List<String>> TABLE_6_UNIQUES_CREATE = List.of( - List.of(COLUMN_5_1_NAME), - List.of(COLUMN_5_2_NAME, COLUMN_5_3_NAME)); + List.of("firstname", "lastname")); public final static List<ForeignKeyCreateDto> TABLE_6_FOREIGN_KEYS_CREATE = List.of(ForeignKeyCreateDto.builder() - .columns(List.of(COLUMN_5_6_NAME)) - .referencedTable(TABLE_5_NAME) - .referencedColumns(List.of(COLUMN_4_1_NAME)) + .columns(List.of("ref_id")) + .referencedTable("zoo") + .referencedColumns(List.of("id")) .build()); - public final static Set<String> TABLE_6_CHECKS_CREATE = Set.of( - COLUMN_5_2_NAME + " != " + COLUMN_5_3_NAME); + public final static Set<String> TABLE_6_CHECKS_CREATE = Set.of("firstname != lastname"); public final static ConstraintsCreateDto TABLE_6_CONSTRAINTS_CREATE = ConstraintsCreateDto.builder() .uniques(TABLE_6_UNIQUES_CREATE) @@ -4808,52 +4424,17 @@ public abstract class BaseTest { .primaryKey(Set.of("id")) .build(); - public final static Long COLUMN_6_1_ID = 26L; - public final static Integer COLUMN_6_1_ORDINALPOS = 0; - public final static Boolean COLUMN_6_1_PRIMARY = true; - public final static String COLUMN_6_1_NAME = "name_id"; - public final static String COLUMN_6_1_INTERNAL_NAME = "name_id"; - public final static TableColumnType COLUMN_6_1_TYPE = TableColumnType.BIGINT; - public final static ColumnTypeDto COLUMN_6_1_TYPE_DTO = ColumnTypeDto.BIGINT; - public final static Long COLUMN_6_1_DATE_FORMAT = null; - public final static Boolean COLUMN_6_1_NULL = false; - public final static Boolean COLUMN_6_1_AUTO_GENERATED = false; - public final static String COLUMN_6_1_FOREIGN_KEY = null; - public final static String COLUMN_6_1_CHECK = null; - public final static List<String> COLUMN_6_1_ENUM_VALUES = null; - public final static List<String> COLUMN_6_1_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_6_1_SET_VALUES = null; - public final static List<String> COLUMN_6_1_SET_VALUES_DTO = null; - - public final static Long COLUMN_6_2_ID = 27L; - public final static Integer COLUMN_6_2_ORDINALPOS = 1; - public final static Boolean COLUMN_6_2_PRIMARY = true; - public final static String COLUMN_6_2_NAME = "zoo_id"; - public final static String COLUMN_6_2_INTERNAL_NAME = "zoo_id"; - public final static TableColumnType COLUMN_6_2_TYPE = TableColumnType.BIGINT; - public final static ColumnTypeDto COLUMN_6_2_TYPE_DTO = ColumnTypeDto.BIGINT; - public final static Long COLUMN_6_2_DATE_FORMAT = null; - public final static Long COLUMN_6_2_SIZE = 255L; - public final static Boolean COLUMN_6_2_NULL = false; - public final static Boolean COLUMN_6_2_AUTO_GENERATED = false; - public final static String COLUMN_6_2_FOREIGN_KEY = null; - public final static String COLUMN_6_2_CHECK = null; - public final static List<String> COLUMN_6_2_ENUM_VALUES = null; - public final static List<String> COLUMN_6_2_ENUM_VALUES_DTO = null; - public final static List<String> COLUMN_6_2_SET_VALUES = null; - public final static List<String> COLUMN_6_2_SET_VALUES_DTO = null; - public final static List<ColumnCreateDto> TABLE_6_COLUMNS_CREATE = List.of( ColumnCreateDto.builder() - .name(COLUMN_6_1_NAME) - .type(COLUMN_6_1_TYPE_DTO) - .nullAllowed(COLUMN_6_1_NULL) + .name("name_id") + .type(ColumnTypeDto.BIGINT) + .nullAllowed(false) .build(), ColumnCreateDto.builder() - .name(COLUMN_6_2_NAME) - .type(COLUMN_6_2_TYPE_DTO) - .size(COLUMN_6_2_SIZE) - .nullAllowed(COLUMN_6_2_NULL) + .name("zoo_id") + .type(ColumnTypeDto.BIGINT) + .size(255L) + .nullAllowed(false) .build()); public final static TableCreateDto TABLE_6_CREATE_DTO = TableCreateDto.builder() @@ -4864,28 +4445,45 @@ public abstract class BaseTest { .build(); public final static List<TableColumn> TABLE_7_COLUMNS = List.of(TableColumn.builder() - .id(COLUMN_6_1_ID) - .ordinalPosition(COLUMN_6_1_ORDINALPOS) + .id(26L) + .ordinalPosition(0) .table(TABLE_7) - .name(COLUMN_6_1_NAME) - .internalName(COLUMN_6_1_INTERNAL_NAME) - .columnType(COLUMN_6_1_TYPE) - .isNullAllowed(COLUMN_6_1_NULL) - .autoGenerated(COLUMN_6_1_AUTO_GENERATED) - .enums(COLUMN_6_1_ENUM_VALUES) - .sets(COLUMN_6_1_SET_VALUES) + .name("name_id") + .internalName("name_id") + .columnType(TableColumnType.BIGINT) + .isNullAllowed(false) + .autoGenerated(false) .build(), TableColumn.builder() - .id(COLUMN_6_2_ID) - .ordinalPosition(COLUMN_6_2_ORDINALPOS) + .id(27L) + .ordinalPosition(1) .table(TABLE_7) - .name(COLUMN_6_2_NAME) - .internalName(COLUMN_6_2_INTERNAL_NAME) - .columnType(COLUMN_6_2_TYPE) - .isNullAllowed(COLUMN_6_2_NULL) - .autoGenerated(COLUMN_6_2_AUTO_GENERATED) - .enums(COLUMN_6_2_ENUM_VALUES) - .sets(COLUMN_6_2_SET_VALUES) + .name("zoo_id") + .internalName("zoo_id") + .columnType(TableColumnType.BIGINT) + .isNullAllowed(false) + .autoGenerated(false) + .build()); + + public final static List<ColumnDto> TABLE_7_COLUMNS_DTO = List.of(ColumnDto.builder() + .id(26L) + .ordinalPosition(0) + .table(TABLE_7_DTO) + .name("name_id") + .internalName("name_id") + .columnType(ColumnTypeDto.BIGINT) + .isNullAllowed(false) + .autoGenerated(false) + .build(), + ColumnDto.builder() + .id(27L) + .ordinalPosition(1) + .table(TABLE_7_DTO) + .name("zoo_id") + .internalName("zoo_id") + .columnType(ColumnTypeDto.BIGINT) + .isNullAllowed(false) + .autoGenerated(false) .build()); public final static Long VIEW_1_ID = 1L; @@ -4898,10 +4496,39 @@ public abstract class BaseTest { public final static String VIEW_1_QUERY = "select `location`, `lat`, `lng` from `weather_location`"; public final static String VIEW_1_QUERY_HASH = "dc81a6877c7c51a6a6f406e1fc2a255e44a0d49a20548596e0d583c3eb849c23"; - public final static List<ColumnDto> VIEW_1_COLUMNS_DTO = List.of( - TABLE_2_COLUMNS_DTO.get(0), - TABLE_2_COLUMNS_DTO.get(1), - TABLE_2_COLUMNS_DTO.get(2) + public final static List<ViewColumnDto> VIEW_1_COLUMNS_DTO = List.of( + ViewColumnDto.builder() + .id(1L) + .name("location") + .internalName("location") + .ordinalPosition(0) + .columnType(ColumnTypeDto.VARCHAR) + .size(255L) + .isNullAllowed(false) + .autoGenerated(false) + .build(), + ViewColumnDto.builder() + .id(2L) + .name("lat") + .internalName("lat") + .ordinalPosition(1) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) + .build(), + ViewColumnDto.builder() + .id(3L) + .name("lng") + .internalName("lng") + .ordinalPosition(2) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) + .build() ); public final static View VIEW_1 = View.builder() @@ -4947,19 +4574,39 @@ public abstract class BaseTest { ViewColumn.builder() .id(1L) .ordinalPosition(0) - .column(TABLE_2_COLUMNS.get(0)) + .name("location") + .internalName("location") + .ordinalPosition(0) + .columnType(TableColumnType.VARCHAR) + .size(255L) + .isNullAllowed(false) + .autoGenerated(false) .view(VIEW_1) .build(), ViewColumn.builder() .id(2L) .ordinalPosition(1) - .column(TABLE_2_COLUMNS.get(1)) + .name("lat") + .internalName("lat") + .ordinalPosition(1) + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_1) .build(), ViewColumn.builder() .id(3L) .ordinalPosition(2) - .column(TABLE_2_COLUMNS.get(2)) + .name("lng") + .internalName("lng") + .ordinalPosition(2) + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_1) .build() ); @@ -5019,11 +4666,48 @@ public abstract class BaseTest { public final static String VIEW_2_QUERY = "select `date`, `location` as loc, `location`, `rainfall`, `mintemp` from `weather_aus` where `location` = 'Albury'"; public final static String VIEW_2_QUERY_HASH = "987fc946772ffb6d85060262dcb5df419692a1f6772ea995e3dedb53c191e984"; - public final static List<ColumnDto> VIEW_2_COLUMNS_DTO = List.of( - TABLE_1_COLUMNS_DTO.get(1), - TABLE_1_COLUMNS_DTO.get(2), - TABLE_1_COLUMNS_DTO.get(4), - TABLE_1_COLUMNS_DTO.get(3) + public final static List<ViewColumnDto> VIEW_2_COLUMNS_DTO = List.of( + ViewColumnDto.builder() + .id(4L) + .name("Date") + .internalName("date") + .ordinalPosition(1) + .columnType(ColumnTypeDto.DATE) + .dateFormat(IMAGE_DATE_1_DTO) + .isNullAllowed(true) + .autoGenerated(false) + .build(), + ViewColumnDto.builder() + .id(5L) + .name("Location") + .internalName("location") + .ordinalPosition(2) + .columnType(ColumnTypeDto.VARCHAR) + .size(255L) + .isNullAllowed(true) + .autoGenerated(false) + .build(), + ViewColumnDto.builder() + .id(6L) + .name("MinTemp") + .internalName("mintemp") + .ordinalPosition(3) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) + .build(), + ViewColumnDto.builder() + .id(7L) + .name("Location") + .internalName("location") + .ordinalPosition(2) + .columnType(ColumnTypeDto.VARCHAR) + .size(255L) + .isNullAllowed(true) + .autoGenerated(false) + .build() ); public final static View VIEW_2 = View.builder() @@ -5043,26 +4727,47 @@ public abstract class BaseTest { ViewColumn.builder() .id(4L) .ordinalPosition(0) - .column(TABLE_1_COLUMNS.get(1)) + .name("Date") + .internalName("date") + .columnType(TableColumnType.DATE) + .dateFormat(IMAGE_DATE_1) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_2) .build(), ViewColumn.builder() .id(5L) .ordinalPosition(1) - .alias("loc") - .column(TABLE_1_COLUMNS.get(2)) + .name("Location") + .internalName("location") + .columnType(TableColumnType.VARCHAR) + .size(255L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_2) .build(), ViewColumn.builder() .id(6L) .ordinalPosition(2) - .column(TABLE_1_COLUMNS.get(4)) + .name("Rainfall") + .internalName("rainfall") + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_2) .build(), ViewColumn.builder() .id(7L) .ordinalPosition(3) - .column(TABLE_1_COLUMNS.get(3)) + .name("MinTemp") + .internalName("mintemp") + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_2) .build() ); @@ -5116,11 +4821,51 @@ public abstract class BaseTest { public final static String VIEW_3_QUERY = "select w.`mintemp`, w.`rainfall`, w.`location`, m.`date` from `weather_aus` w join `junit2` m on m.`location` = w.`location` and m.`date` = w.`date`"; public final static String VIEW_3_QUERY_HASH = "bbbaa56a5206b3dc3e6cf9301b0db9344eb6f19b100c7b88550ffb597a0bd255"; - public final static List<ColumnDto> VIEW_3_COLUMNS_DTO = List.of( - TABLE_1_COLUMNS_DTO.get(3), - TABLE_1_COLUMNS_DTO.get(4), - TABLE_1_COLUMNS_DTO.get(2), - TABLE_1_COLUMNS_DTO.get(1) + public final static List<ViewColumnDto> VIEW_3_COLUMNS_DTO = List.of( + ViewColumnDto.builder() + .id(8L) + .name("MinTemp") + .internalName("mintemp") + .ordinalPosition(0) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) + .build(), + ViewColumnDto.builder() + .id(9L) + .name("Rainfall") + .internalName("rainfall") + .ordinalPosition(1) + .columnType(ColumnTypeDto.DECIMAL) + .size(10L) + .d(0L) + .concept(CONCEPT_1_DTO) + .unit(UNIT_1_DTO) + .isNullAllowed(true) + .autoGenerated(false) + .build(), + ViewColumnDto.builder() + .id(10L) + .name("Location") + .internalName("location") + .ordinalPosition(2) + .columnType(ColumnTypeDto.VARCHAR) + .size(255L) + .isNullAllowed(true) + .autoGenerated(false) + .build(), + ViewColumnDto.builder() + .id(11L) + .name("Date") + .internalName("date") + .ordinalPosition(3) + .columnType(ColumnTypeDto.DATE) + .dateFormat(IMAGE_DATE_1_DTO) + .isNullAllowed(true) + .autoGenerated(false) + .build() ); public final static View VIEW_3 = View.builder() @@ -5136,29 +4881,65 @@ public abstract class BaseTest { .createdBy(USER_1_ID) .build(); + public final static PrivilegedViewDto VIEW_3_PRIVILEGED_DTO = PrivilegedViewDto.builder() + .id(VIEW_3_ID) + .isInitialView(VIEW_3_INITIAL_VIEW) + .database(null) /* DATABASE_1_PRIVILEGED_DTO */ + .name(VIEW_3_NAME) + .internalName(VIEW_3_INTERNAL_NAME) + .vdbid(VIEW_3_DATABASE_ID) + .isPublic(VIEW_3_PUBLIC) + .createdBy(USER_1_ID) + .query(VIEW_3_QUERY) + .queryHash(VIEW_3_QUERY_HASH) + .columns(VIEW_3_COLUMNS_DTO) + .build(); + public final static List<ViewColumn> VIEW_3_COLUMNS = List.of( ViewColumn.builder() .id(8L) .ordinalPosition(0) - .column(TABLE_1_COLUMNS.get(3)) + .name("MinTemp") + .internalName("mintemp") + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_3) .build(), ViewColumn.builder() .id(9L) .ordinalPosition(1) - .column(TABLE_1_COLUMNS.get(4)) + .name("Rainfall") + .internalName("rainfall") + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_3) .build(), ViewColumn.builder() .id(10L) .ordinalPosition(2) - .column(TABLE_1_COLUMNS.get(2)) + .name("Location") + .internalName("location") + .columnType(TableColumnType.VARCHAR) + .size(255L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_3) .build(), ViewColumn.builder() .id(11L) .ordinalPosition(3) - .column(TABLE_1_COLUMNS.get(1)) + .name("Date") + .internalName("date") + .columnType(TableColumnType.DATE) + .dateFormat(IMAGE_DATE_1) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_3) .build() ); @@ -5200,143 +4981,173 @@ public abstract class BaseTest { public final static String VIEW_4_QUERY = "SELECT `animal_name`, `hair`, `feathers`, `eggs`, `milk`, `airborne`, `aquatic`, `predator`, `backbone`, `breathes`, `venomous`, `fins`, `legs`, `tail`, `domestic`, `catsize`, `class_type` FROM `zoo` WHERE `class_type` = 1"; public final static String VIEW_4_QUERY_HASH = "3561cd0bb0b0e94d6f15ae602134252a5760d09d660a71a4fb015b6991c8ba0b"; - public final static List<ColumnDto> VIEW_4_COLUMNS_DTO = List.of( - TABLE_5_COLUMNS_DTO.get(1), - TABLE_5_COLUMNS_DTO.get(2), - TABLE_5_COLUMNS_DTO.get(3), - TABLE_5_COLUMNS_DTO.get(5), - TABLE_5_COLUMNS_DTO.get(6), - TABLE_5_COLUMNS_DTO.get(8), - TABLE_5_COLUMNS_DTO.get(10), - TABLE_5_COLUMNS_DTO.get(11), - TABLE_5_COLUMNS_DTO.get(12), - TABLE_5_COLUMNS_DTO.get(13), - TABLE_5_COLUMNS_DTO.get(14), - TABLE_5_COLUMNS_DTO.get(15), - TABLE_5_COLUMNS_DTO.get(16), - TABLE_5_COLUMNS_DTO.get(17), - TABLE_5_COLUMNS_DTO.get(18), - TABLE_5_COLUMNS_DTO.get(19), - TABLE_5_COLUMNS_DTO.get(20) - ); - - public final static View VIEW_4 = View.builder() - .id(VIEW_4_ID) - .isInitialView(VIEW_4_INITIAL_VIEW) - .name(VIEW_4_NAME) - .internalName(VIEW_4_INTERNAL_NAME) - .vdbid(VIEW_4_DATABASE_ID) - .isPublic(VIEW_4_PUBLIC) - .query(VIEW_4_QUERY) - .queryHash(VIEW_4_QUERY_HASH) - .createdBy(USER_1_ID) - .columns(null) /* VIEW_4_COLUMNS */ - .build(); - - public final static List<ViewColumn> VIEW_4_COLUMNS = List.of( - ViewColumn.builder() + public final static List<ViewColumnDto> VIEW_4_COLUMNS_DTO = List.of( + ViewColumnDto.builder() .id(12L) .ordinalPosition(0) - .column(TABLE_5_COLUMNS.get(1)) - .view(VIEW_4) + .name("Animal Name") + .internalName("animal_name") + .columnType(ColumnTypeDto.VARCHAR) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(13L) .ordinalPosition(1) - .column(TABLE_5_COLUMNS.get(2)) - .view(VIEW_4) + .name("Hair") + .internalName("hair") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(14L) .ordinalPosition(2) - .column(TABLE_5_COLUMNS.get(3)) - .view(VIEW_4) + .name("Feathers") + .internalName("feathers") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(15L) .ordinalPosition(3) - .column(TABLE_5_COLUMNS.get(5)) - .view(VIEW_4) + .name("Eggs") + .internalName("eggs") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(16L) .ordinalPosition(4) - .column(TABLE_5_COLUMNS.get(6)) - .view(VIEW_4) + .name("Milk") + .internalName("milk") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(17L) .ordinalPosition(5) - .column(TABLE_5_COLUMNS.get(8)) - .view(VIEW_4) + .name("Airborne") + .internalName("airborne") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(18L) .ordinalPosition(6) - .column(TABLE_5_COLUMNS.get(10)) - .view(VIEW_4) + .name("Aquantic") + .internalName("aquantic") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(19L) .ordinalPosition(7) - .column(TABLE_5_COLUMNS.get(11)) - .view(VIEW_4) + .name("Predator") + .internalName("predator") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(20L) .ordinalPosition(8) - .column(TABLE_5_COLUMNS.get(12)) - .view(VIEW_4) + .name("Backbone") + .internalName("backbone") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(21L) .ordinalPosition(9) - .column(TABLE_5_COLUMNS.get(13)) - .view(VIEW_4) + .name("Breathes") + .internalName("breathes") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(22L) .ordinalPosition(10) - .column(TABLE_5_COLUMNS.get(14)) - .view(VIEW_4) + .name("Venomous") + .internalName("venomous") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(23L) .ordinalPosition(11) - .column(TABLE_5_COLUMNS.get(15)) - .view(VIEW_4) + .name("Fin") + .internalName("fin") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(24L) .ordinalPosition(12) - .column(TABLE_5_COLUMNS.get(16)) - .view(VIEW_4) + .name("Legs") + .internalName("legs") + .columnType(ColumnTypeDto.INT) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(25L) .ordinalPosition(13) - .column(TABLE_5_COLUMNS.get(17)) - .view(VIEW_4) + .name("Tail") + .internalName("tail") + .columnType(ColumnTypeDto.DECIMAL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(26L) .ordinalPosition(14) - .column(TABLE_5_COLUMNS.get(18)) - .view(VIEW_4) + .name("Domestic") + .internalName("domestic") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(27L) .ordinalPosition(15) - .column(TABLE_5_COLUMNS.get(19)) - .view(VIEW_4) + .name("Catsize") + .internalName("catsize") + .columnType(ColumnTypeDto.BOOL) + .isNullAllowed(true) + .autoGenerated(false) .build(), - ViewColumn.builder() + ViewColumnDto.builder() .id(28L) .ordinalPosition(16) - .column(TABLE_5_COLUMNS.get(20)) - .view(VIEW_4) - .build() - ); + .name("Class Type") + .internalName("class_type") + .columnType(ColumnTypeDto.DECIMAL) + .isNullAllowed(true) + .autoGenerated(false) + .build()); + + public final static View VIEW_4 = View.builder() + .id(VIEW_4_ID) + .isInitialView(VIEW_4_INITIAL_VIEW) + .name(VIEW_4_NAME) + .internalName(VIEW_4_INTERNAL_NAME) + .vdbid(VIEW_4_DATABASE_ID) + .isPublic(VIEW_4_PUBLIC) + .query(VIEW_4_QUERY) + .queryHash(VIEW_4_QUERY_HASH) + .createdBy(USER_1_ID) + .columns(null) /* VIEW_4_COLUMNS */ + .build(); public final static ViewDto VIEW_4_DTO = ViewDto.builder() .id(VIEW_4_ID) @@ -5391,19 +5202,39 @@ public abstract class BaseTest { ViewColumn.builder() .id(29L) .ordinalPosition(0) - .column(TABLE_2_COLUMNS.get(0)) + .name("location") + .internalName("location") + .ordinalPosition(0) + .columnType(TableColumnType.VARCHAR) + .size(255L) + .isNullAllowed(false) + .autoGenerated(false) .view(VIEW_5) .build(), ViewColumn.builder() .id(30L) .ordinalPosition(1) - .column(TABLE_2_COLUMNS.get(1)) + .name("lat") + .internalName("lat") + .ordinalPosition(1) + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_5) .build(), ViewColumn.builder() .id(31L) .ordinalPosition(2) - .column(TABLE_2_COLUMNS.get(2)) + .name("lng") + .internalName("lng") + .ordinalPosition(2) + .columnType(TableColumnType.DECIMAL) + .size(10L) + .d(0L) + .isNullAllowed(true) + .autoGenerated(false) .view(VIEW_5) .build()); @@ -7411,4 +7242,285 @@ public abstract class BaseTest { .huserid(USER_3_ID) .build(); + public final static Constraints TABLE_1_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_1) + .column(TABLE_1_COLUMNS.get(0)) + .pkid(1L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_1_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_1_BRIEF_DTO) + .column(TABLE_1_COLUMNS_DTO.get(0)) + .pkid(1L) + .build()))) + .build(); + + public final static Constraints TABLE_2_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>(List.of("`mintemp` > 0"))) + .foreignKeys(new LinkedList<>(List.of(ForeignKey.builder() + .name("fk_location") + .onDelete(ReferenceType.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReference.builder() + .id(1L) + .column(TABLE_2_COLUMNS.get(2)) + .referencedColumn(TABLE_1_COLUMNS.get(0)) + .foreignKey(null) // set later + .build()))) + .table(TABLE_1) + .referencedTable(TABLE_2) + .onUpdate(ReferenceType.NO_ACTION) + .build()))) + .uniques(new LinkedList<>(List.of(Unique.builder() + .uid(1L) + .table(TABLE_2) + .name("uk_1") + .columns(new LinkedList<>(List.of(TABLE_2_COLUMNS.get(1)))) + .build()))) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_2) + .column(TABLE_2_COLUMNS.get(0)) + .pkid(2L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_2_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>(List.of("`mintemp` > 0"))) + .foreignKeys(new LinkedList<>(List.of(ForeignKeyDto.builder() + .name("fk_location") + .onDelete(ReferenceTypeDto.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() + .id(1L) + .column(TABLE_2_COLUMNS_DTO.get(2)) + .referencedColumn(TABLE_1_COLUMNS_DTO.get(0)) + .foreignKey(null) // set later + .build()))) + .table(TABLE_1_DTO) + .referencedTable(TABLE_2_DTO) + .onUpdate(ReferenceTypeDto.NO_ACTION) + .build()))) + .uniques(new LinkedList<>(List.of(UniqueDto.builder() + .uid(1L) + .table(TABLE_2_BRIEF_DTO) + .name("uk_1") + .columns(new LinkedList<>(List.of(TABLE_2_COLUMNS_DTO.get(1)))) + .build()))) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_2_BRIEF_DTO) + .column(TABLE_2_COLUMNS_DTO.get(0)) + .pkid(2L) + .build()))) + .build(); + + public final static Constraints TABLE_3_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_3) + .column(TABLE_3_COLUMNS.get(0)) + .pkid(3L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_3_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_3_BRIEF_DTO) + .column(TABLE_3_COLUMNS_DTO.get(0)) + .pkid(3L) + .build()))) + .build(); + + public final static Constraints TABLE_4_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_4) + .column(TABLE_4_COLUMNS.get(0)) + .pkid(4L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_4_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_4_BRIEF_DTO) + .column(TABLE_4_COLUMNS_DTO.get(0)) + .pkid(4L) + .build()))) + .build(); + + public final static Constraints TABLE_5_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_5) + .column(TABLE_5_COLUMNS.get(0)) + .pkid(5L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_5_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_5_BRIEF_DTO) + .column(TABLE_5_COLUMNS_DTO.get(0)) + .pkid(5L) + .build()))) + .build(); + + public final static Constraints TABLE_6_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>(List.of())) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_6) + .column(TABLE_6_COLUMNS.get(0)) + .pkid(6L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_6_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_6_BRIEF_DTO) + .column(TABLE_6_COLUMNS_DTO.get(0)) + .pkid(6L) + .build()))) + .build(); + + public final static Constraints TABLE_7_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>(List.of(ForeignKey.builder() + .name("fk_name_id") + .onDelete(ReferenceType.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReference.builder() + .id(2L) + .column(TABLE_6_COLUMNS.get(0)) + .referencedColumn(TABLE_7_COLUMNS.get(0)) + .foreignKey(null) // set later + .build()))) + .table(TABLE_7) + .referencedTable(TABLE_6) + .onUpdate(ReferenceType.NO_ACTION) + .build(), + ForeignKey.builder() + .name("fk_zoo_id") + .onDelete(ReferenceType.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReference.builder() + .id(3L) + .column(TABLE_5_COLUMNS.get(0)) + .referencedColumn(TABLE_7_COLUMNS.get(1)) + .foreignKey(null) // set later + .build()))) + .table(TABLE_7) + .referencedTable(TABLE_5) + .onUpdate(ReferenceType.NO_ACTION) + .build()))) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_7) + .column(TABLE_7_COLUMNS.get(0)) + .pkid(7L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_7_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>(List.of(ForeignKeyDto.builder() + .name("fk_name_id") + .onDelete(ReferenceTypeDto.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() + .id(2L) + .column(TABLE_6_COLUMNS_DTO.get(0)) + .referencedColumn(TABLE_7_COLUMNS_DTO.get(0)) + .foreignKey(null) // set later + .build()))) + .table(TABLE_7_DTO) + .referencedTable(TABLE_6_DTO) + .onUpdate(ReferenceTypeDto.NO_ACTION) + .build(), + ForeignKeyDto.builder() + .name("fk_zoo_id") + .onDelete(ReferenceTypeDto.NO_ACTION) + .references(new LinkedList<>(List.of(ForeignKeyReferenceDto.builder() + .id(3L) + .column(TABLE_5_COLUMNS_DTO.get(0)) + .referencedColumn(TABLE_7_COLUMNS_DTO.get(1)) + .foreignKey(null) // set later + .build()))) + .table(TABLE_7_DTO) + .referencedTable(TABLE_5_DTO) + .onUpdate(ReferenceTypeDto.NO_ACTION) + .build()))) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_7_BRIEF_DTO) + .column(TABLE_7_COLUMNS_DTO.get(0)) + .pkid(7L) + .build()))) + .build(); + + public final static Constraints TABLE_8_CONSTRAINTS = Constraints.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedList<>(List.of(PrimaryKey.builder() + .table(TABLE_8) + .column(TABLE_8_COLUMNS.get(0)) + .pkid(8L) + .build()))) + .build(); + + public final static ConstraintsDto TABLE_8_CONSTRAINTS_DTO = ConstraintsDto.builder() + .checks(new LinkedHashSet<>()) + .foreignKeys(new LinkedList<>()) + .uniques(new LinkedList<>()) + .primaryKey(new LinkedHashSet<>(Set.of(PrimaryKeyDto.builder() + .table(TABLE_8_BRIEF_DTO) + .column(TABLE_8_COLUMNS_DTO.get(0)) + .pkid(8L) + .build()))) + .build(); + + public static void saveObservedMetrics(Map<String, String> observedMetrics) throws IOException { + final int keySize = observedMetrics.keySet().stream().max(Comparator.comparingInt(String::length)).get().length(); + final int valueSize = observedMetrics.values().stream().max(Comparator.comparingInt(String::length)).get().length(); + final StringBuilder content = new StringBuilder("| ") + .append(StringUtils.rightPad("**Metric**", Integer.max(keySize + 2, 16))) + .append(" | ") + .append(StringUtils.rightPad("**Description**", Integer.max(valueSize, 19))) + .append(" |\n") + .append("|-") + .append(StringUtils.leftPad("", Integer.max(keySize + 2, 16), "-")) + .append("-|-") + .append(StringUtils.leftPad("", Integer.max(valueSize, 19), "-")) + .append("-|\n"); + observedMetrics.forEach((key, value) -> content.append("| ") + .append(StringUtils.rightPad("`" + key + "`", Integer.max(keySize + 2, 16))) + .append(" | ") + .append(StringUtils.rightPad(value, Integer.max(valueSize, 19))) + .append(" |\n")); + FileUtils.writeStringToFile(new File("../metrics.md"), content.toString(), Charset.defaultCharset()); + } + } diff --git a/dbrepo-search-service/Pipfile b/dbrepo-search-service/Pipfile index a38e8cdd41d85f1b0e1ecf0aa0c367bb765b16ae..3daa275b49f44deced5816e589d71e6d7e6fd7e8 100644 --- a/dbrepo-search-service/Pipfile +++ b/dbrepo-search-service/Pipfile @@ -18,7 +18,7 @@ jwt = "~=1.3" testcontainers-opensearch = "*" pytest = "*" rdflib = "*" -dbrepo = {path = "./lib/dbrepo-1.4.3.tar.gz"} +dbrepo = {path = "./lib/dbrepo-1.4.4.tar.gz"} gunicorn = "*" [dev-packages] diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock index b2d114395b3eee7150e456523cf44a3e5dc57299..1c60362635327df0034e268b2e037d9dd4a73430 100644 --- a/dbrepo-search-service/Pipfile.lock +++ b/dbrepo-search-service/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "433f88ce7dc4c6ef81f97d831edbf5a111df0974ba884fed63847c72925a28d9" + "sha256": "ece384cd1606901f3d2575f082692a5d5ce3164b4ba5187fc4b457757d3b0fce" }, "pipfile-spec": 6, "requires": { @@ -108,11 +108,11 @@ }, "annotated-types": { "hashes": [ - "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43", - "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d" + "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", + "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" ], "markers": "python_version >= '3.8'", - "version": "==0.6.0" + "version": "==0.7.0" }, "attrs": { "hashes": [ @@ -340,18 +340,18 @@ }, "dbrepo": { "hashes": [ - "sha256:ea77f1bbd4fc79b56f59d5fbc55985de95be562c90da24d7b069ef629459c596" + "sha256:ceab260cf76c050e118ce0f0589fec66059396751e03f2ec41fa489cfacc4e7b" ], - "path": "./lib/dbrepo-1.4.3.tar.gz", - "version": "==1.4.3" + "path": "./lib/dbrepo-1.4.4.tar.gz", + "version": "==1.4.4" }, "docker": { "hashes": [ - "sha256:12ba681f2777a0ad28ffbcc846a69c31b4dfd9752b47eb425a274ee269c5e14b", - "sha256:323736fb92cd9418fc5e7133bc953e11a9da04f4483f828b527db553f1e7e5a3" + "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", + "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0" ], "markers": "python_version >= '3.8'", - "version": "==7.0.0" + "version": "==7.1.0" }, "flasgger": { "hashes": [ @@ -1031,11 +1031,11 @@ }, "pytest": { "hashes": [ - "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233", - "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f" + "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd", + "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1" ], "index": "pypi", - "version": "==8.2.0" + "version": "==8.2.1" }, "python-dateutil": { "hashes": [ @@ -1135,11 +1135,11 @@ }, "requests": { "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289", + "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c" ], - "markers": "python_version >= '3.7'", - "version": "==2.31.0" + "markers": "python_version >= '3.8'", + "version": "==2.32.2" }, "rpds-py": { "hashes": [ @@ -1349,11 +1349,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", - "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" + "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8", + "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594" ], "markers": "python_version >= '3.8'", - "version": "==4.11.0" + "version": "==4.12.0" }, "tzdata": { "hashes": [ @@ -1555,61 +1555,61 @@ "develop": { "coverage": { "hashes": [ - "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de", - "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661", - "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26", - "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41", - "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d", - "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981", - "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2", - "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34", - "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f", - "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a", - "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35", - "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223", - "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1", - "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746", - "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90", - "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c", - "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca", - "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8", - "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596", - "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e", - "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd", - "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e", - "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3", - "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e", - "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312", - "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7", - "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572", - "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428", - "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f", - "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07", - "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e", - "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4", - "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136", - "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5", - "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8", - "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d", - "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228", - "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206", - "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa", - "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e", - "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be", - "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5", - "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668", - "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601", - "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057", - "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146", - "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f", - "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8", - "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7", - "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987", - "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19", - "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece" + "sha256:06d96b9b19bbe7f049c2be3c4f9e06737ec6d8ef8933c7c3a4c557ef07936e46", + "sha256:13017a63b0e499c59b5ba94a8542fb62864ba3016127d1e4ef30d354fc2b00e9", + "sha256:1acc2e2ef098a1d4bf535758085f508097316d738101a97c3f996bccba963ea5", + "sha256:1aef719b6559b521ae913ddeb38f5048c6d1a3d366865e8b320270b7bc4693c2", + "sha256:1e4225990a87df898e40ca31c9e830c15c2c53b1d33df592bc8ef314d71f0281", + "sha256:1f11f98753800eb1ec872562a398081f6695f91cd01ce39819e36621003ec52a", + "sha256:1f29bf497d51a5077994b265e976d78b09d9d0dff6ca5763dbb4804534a5d380", + "sha256:1f96aa94739593ae0707eda9813ce363a0a0374a810ae0eced383340fc4a1f73", + "sha256:20e611fc36e1a0fc7bbf957ef9c635c8807d71fbe5643e51b2769b3cc0fb0b51", + "sha256:23f2f16958b16152b43a39a5ecf4705757ddd284b3b17a77da3a62aef9c057ef", + "sha256:24bb4c7859a3f757a116521d4d3a8a82befad56ea1bdacd17d6aafd113b0071e", + "sha256:26716a1118c6ce2188283b4b60a898c3be29b480acbd0a91446ced4fe4e780d8", + "sha256:29da75ce20cb0a26d60e22658dd3230713c6c05a3465dd8ad040ffc991aea318", + "sha256:2b144d142ec9987276aeff1326edbc0df8ba4afbd7232f0ca10ad57a115e95b6", + "sha256:2c79f058e7bec26b5295d53b8c39ecb623448c74ccc8378631f5cb5c16a7e02c", + "sha256:3bb5b92a0ab3d22dfdbfe845e2fef92717b067bdf41a5b68c7e3e857c0cff1a4", + "sha256:3d3f7744b8a8079d69af69d512e5abed4fb473057625588ce126088e50d05493", + "sha256:3d9c62cff2ffb4c2a95328488fd7aa96a7a4b34873150650fe76b19c08c9c792", + "sha256:3e12536446ad4527ac8ed91d8a607813085683bcce27af69e3b31cd72b3c5960", + "sha256:40dbb8e7727560fe8ab65efcddfec1ae25f30ef02e2f2e5d78cfb52a66781ec5", + "sha256:431a3917e32223fcdb90b79fe60185864a9109631ebc05f6c5aa03781a00b513", + "sha256:448ec61ea9ea7916d5579939362509145caaecf03161f6f13e366aebb692a631", + "sha256:482df956b055d3009d10fce81af6ffab28215d7ed6ad4a15e5c8e67cb7c5251c", + "sha256:4a00bd5ba8f1a4114720bef283cf31583d6cb1c510ce890a6da6c4268f0070b7", + "sha256:51b6cee539168a912b4b3b040e4042b9e2c9a7ad9c8546c09e4eaeff3eacba6b", + "sha256:554c7327bf0fd688050348e22db7c8e163fb7219f3ecdd4732d7ed606b417263", + "sha256:5662bf0f6fb6757f5c2d6279c541a5af55a39772c2362ed0920b27e3ce0e21f7", + "sha256:5997d418c219dcd4dcba64e50671cca849aaf0dac3d7a2eeeb7d651a5bd735b8", + "sha256:59a75e6aa5c25b50b5a1499f9718f2edff54257f545718c4fb100f48d570ead4", + "sha256:60b66b0363c5a2a79fba3d1cd7430c25bbd92c923d031cae906bdcb6e054d9a2", + "sha256:6e34680049eecb30b6498784c9637c1c74277dcb1db75649a152f8004fbd6646", + "sha256:74eeaa13e8200ad72fca9c5f37395fb310915cec6f1682b21375e84fd9770e84", + "sha256:7c5c5b7ae2763533152880d5b5b451acbc1089ade2336b710a24b2b0f5239d20", + "sha256:829fb55ad437d757c70d5b1c51cfda9377f31506a0a3f3ac282bc6a387d6a5f1", + "sha256:878243e1206828908a6b4a9ca7b1aa8bee9eb129bf7186fc381d2646f4524ce9", + "sha256:8809c0ea0e8454f756e3bd5c36d04dddf222989216788a25bfd6724bfcee342c", + "sha256:8941e35a0e991a7a20a1fa3e3182f82abe357211f2c335a9e6007067c3392fcf", + "sha256:894b1acded706f1407a662d08e026bfd0ff1e59e9bd32062fea9d862564cfb65", + "sha256:900532713115ac58bc3491b9d2b52704a05ed408ba0918d57fd72c94bc47fba1", + "sha256:976cd92d9420e6e2aa6ce6a9d61f2b490e07cb468968adf371546b33b829284b", + "sha256:97de509043d3f0f2b2cd171bdccf408f175c7f7a99d36d566b1ae4dd84107985", + "sha256:9a42970ce74c88bdf144df11c52c5cf4ad610d860de87c0883385a1c9d9fa4ab", + "sha256:9e41c94035e5cdb362beed681b58a707e8dc29ea446ea1713d92afeded9d1ddd", + "sha256:9f805481d5eff2a96bac4da1570ef662bf970f9a16580dc2c169c8c3183fa02b", + "sha256:a35c97af60a5492e9e89f8b7153fe24eadfd61cb3a2fb600df1a25b5dab34b7e", + "sha256:a7c6574225f34ce45466f04751d957b5c5e6b69fca9351db017c9249786172ce", + "sha256:c7ebf2a37e4f5fea3c1a11e1f47cea7d75d0f2d8ef69635ddbd5c927083211fc", + "sha256:d0305e02e40c7cfea5d08d6368576537a74c0eea62b77633179748d3519d6705", + "sha256:e1046aab24c48c694f0793f669ac49ea68acde6a0798ac5388abe0a5615b5ec8", + "sha256:e5d22eba19273b2069e4efeff88c897a26bdc64633cbe0357a198f92dca94268", + "sha256:ec27e93bbf5976f0465e8936f02eb5add99bbe4e4e7b233607e4d7622912d68d", + "sha256:fe76d6dee5e4febefa83998b17926df3a04e5089e3d2b1688c74a9157798d7a2" ], "index": "pypi", - "version": "==7.5.1" + "version": "==7.5.2" }, "iniconfig": { "hashes": [ @@ -1637,11 +1637,11 @@ }, "pytest": { "hashes": [ - "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233", - "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f" + "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd", + "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1" ], "index": "pypi", - "version": "==8.2.0" + "version": "==8.2.1" } } } diff --git a/dbrepo-search-service/app.py b/dbrepo-search-service/app.py index 41144c6913c229724cff3052f77c31089519f74d..be4481cf08ee80a38a666e3db3303f12b8fc6613 100644 --- a/dbrepo-search-service/app.py +++ b/dbrepo-search-service/app.py @@ -217,6 +217,7 @@ def health(): @app.route("/api/search/<string:index>", methods=["GET"], endpoint="search_get_index") +@metrics.gauge(name='dbrepo_search_index_list', description='Time needed to list search index') @swag_from("os-yml/get_index.yml") def get_index(index: str): """ @@ -239,6 +240,7 @@ def get_index(index: str): @app.route("/api/search/<string:type>/fields", methods=["GET"], endpoint="search_get_index_fields") +@metrics.gauge(name='dbrepo_search_type_list', description='Time needed to list search types') @swag_from("os-yml/get_fields.yml") def get_fields(type: str): """ @@ -256,6 +258,7 @@ def get_fields(type: str): @app.route("/api/search", methods=["GET"], endpoint="search_fuzzy_search") +@metrics.gauge(name='dbrepo_search_fuzzy', description='Time needed to search fuzzy') @swag_from("os-yml/get_fuzzy_search.yml") def get_fuzzy_search(): """ @@ -274,6 +277,7 @@ def get_fuzzy_search(): @app.route("/api/search/<string:type>", methods=["POST"], endpoint="search_post_general_search") +@metrics.gauge(name='dbrepo_search_type', description='Time needed to search by type') @swag_from("os-yml/post_general_search.yml") def post_general_search(type): """ @@ -353,6 +357,8 @@ def post_general_search(type): @app.route("/api/search/database/<int:database_id>", methods=["PUT"], endpoint="database_put_database") +@metrics.gauge(name='dbrepo_search_update_database', + description='Time needed to update a database in the search database') @auth.login_required(role=['admin']) @swag_from("os-yml/update_database.yml") def update_database(database_id: int): @@ -376,6 +382,8 @@ def update_database(database_id: int): @app.route("/api/search/database/<int:database_id>", methods=["DELETE"], endpoint="database_delete_database") +@metrics.gauge(name='dbrepo_search_delete_database', + description='Time needed to delete a database in the search database') @auth.login_required(role=['admin']) @swag_from("os-yml/delete_database.yml") def delete_database(database_id: int): diff --git a/dbrepo-search-service/lib/dbrepo-1.4.3-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.4.3-py3-none-any.whl index bb0ce570729cffddbd0f77eb818fd40eb0a56195..2e19eddac149ac401c67a52ba56577132e32869a 100644 Binary files a/dbrepo-search-service/lib/dbrepo-1.4.3-py3-none-any.whl and b/dbrepo-search-service/lib/dbrepo-1.4.3-py3-none-any.whl differ diff --git a/dbrepo-search-service/lib/dbrepo-1.4.3.tar.gz b/dbrepo-search-service/lib/dbrepo-1.4.3.tar.gz index 04043f0f56105d80e7f2aaa5fe1598077184ef64..ffb89654bab83c6f72a9381825e41f0dbe7d37c9 100644 Binary files a/dbrepo-search-service/lib/dbrepo-1.4.3.tar.gz and b/dbrepo-search-service/lib/dbrepo-1.4.3.tar.gz differ diff --git a/dbrepo-search-service/lib/dbrepo-1.4.4-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.4.4-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..11873004972bb08703994ba1fb0ddf18f96f6a2c Binary files /dev/null and b/dbrepo-search-service/lib/dbrepo-1.4.4-py3-none-any.whl differ diff --git a/dbrepo-search-service/lib/dbrepo-1.4.4.tar.gz b/dbrepo-search-service/lib/dbrepo-1.4.4.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..f7452a0e12c9a2d44f663bc1f338204b7579144b Binary files /dev/null and b/dbrepo-search-service/lib/dbrepo-1.4.4.tar.gz differ diff --git a/dbrepo-search-service/metrics.md b/dbrepo-search-service/metrics.md new file mode 100644 index 0000000000000000000000000000000000000000..d99df25c8e7806593857ce31419f3cdd578eb7f5 --- /dev/null +++ b/dbrepo-search-service/metrics.md @@ -0,0 +1,8 @@ +| **Metric** | **Description** | +|---------------------------------|---------------------------------------------------------| +| `dbrepo_search_index_list` | Time needed to list search index | +| `dbrepo_search_type_list` | Time needed to list search types | +| `dbrepo_search_fuzzy` | Time needed to search fuzzy | +| `dbrepo_search_type` | Time needed to search by type | +| `dbrepo_search_update_database` | Time needed to update a database in the search database | +| `dbrepo_search_delete_database` | Time needed to delete a database in the search database | \ No newline at end of file diff --git a/dbrepo-ui/components/subset/SubsetList.vue b/dbrepo-ui/components/subset/SubsetList.vue index a921373ae638fe509375823587dd782c6fe7f368..1a0150f4d6ca0817ac773fbd3160f6032ee91c11 100644 --- a/dbrepo-ui/components/subset/SubsetList.vue +++ b/dbrepo-ui/components/subset/SubsetList.vue @@ -20,13 +20,10 @@ <v-list-item lines="two" :title="title(item)" + :subtitle="subtitle(item)" :class="clazz(item)" :to="link(item)" :href="link(item)"> - <v-list-item-subtitle - class="mt-2"> - <pre>{{ item.query }}</pre> - </v-list-item-subtitle> <template v-slot:append> <v-tooltip v-if="hasPublishedIdentifier(item)" @@ -97,6 +94,13 @@ export default { const identifierService = useIdentifierService() return identifierService.identifierPreferEnglishTitle(query.identifiers[0]) }, + subtitle (query) { + if (query.identifiers.length === 0) { + return null + } + const identifierService = useIdentifierService() + return identifierService.identifierPreferEnglishDescription(query.identifiers[0]) + }, link (query) { return `/database/${this.$route.params.database_id}/subset/${query.id}/info` }, diff --git a/dbrepo-ui/components/table/TableList.vue b/dbrepo-ui/components/table/TableList.vue index c192a4b149cd780676f9061c6abd1cebbd11672c..362f4a93665161b36a432d147fb862890c389f1a 100644 --- a/dbrepo-ui/components/table/TableList.vue +++ b/dbrepo-ui/components/table/TableList.vue @@ -16,7 +16,7 @@ lines="two" :title="table.name" :class="clazz(table)" - :subtitle="table.description ? table.description : '(no description)'" + :subtitle="table.description ? table.description : ''" :to="`/database/${$route.params.database_id}/table/${table.id}/info`"> <template v-slot:append> <v-tooltip diff --git a/dbrepo-ui/components/view/ViewList.vue b/dbrepo-ui/components/view/ViewList.vue index 992e74844786d4ecc7b3fc79e66d139321aad23d..ea2dc0946cb3088e9042045a197e7aa35bc8da76 100644 --- a/dbrepo-ui/components/view/ViewList.vue +++ b/dbrepo-ui/components/view/ViewList.vue @@ -13,10 +13,6 @@ :title="view.name" :class="clazz(view)" :to="`/database/${$route.params.database_id}/view/${view.id}/info`"> - <v-list-item-subtitle - class="mt-2"> - <pre v-text="view.query" /> - </v-list-item-subtitle> <template v-slot:append> <v-tooltip v-if="hasPublishedIdentifier(view)" diff --git a/dbrepo-ui/composables/axios-instance.ts b/dbrepo-ui/composables/axios-instance.ts index 7c3fa797b989d23d1182ab87ebe9ebd15c345763..a2b6ca4f6ef5b138473b7812b460981a6f7c7f2f 100644 --- a/dbrepo-ui/composables/axios-instance.ts +++ b/dbrepo-ui/composables/axios-instance.ts @@ -1,6 +1,5 @@ -import axios, {AxiosError, type AxiosInstance} from 'axios' +import axios, {type AxiosInstance} from 'axios' import {useUserStore} from '@/stores/user' -import {axiosErrorToApiError} from '@/utils' let instance: AxiosInstance | null = null; @@ -9,7 +8,7 @@ export const useAxiosInstance = () => { const userStore = useUserStore() if (!instance) { instance = axios.create({ - timeout: 10000, + timeout: 10_000, params: {}, headers: { Accept: 'application/json', @@ -44,9 +43,9 @@ export const useAxiosInstance = () => { config.headers.Authorization = `Bearer ${response.access_token}` return config }) - .catch((error: AxiosError) => { - if (axiosErrorToApiError(error).code === 'error.user.credentials') { - console.error('Invalid user credentials: perform logout') + .catch((error: ApiErrorDto) => { + if (error.code === 'error.user.credentials') { + console.warn('User session expired.') userStore.logout() } return config diff --git a/dbrepo-ui/composables/database-service.ts b/dbrepo-ui/composables/database-service.ts index a992f135470d1c57c18e7ccf953acb643deebe46..6a4e283f8d9fb9d04b00c040bb7d769886ee3a70 100644 --- a/dbrepo-ui/composables/database-service.ts +++ b/dbrepo-ui/composables/database-service.ts @@ -17,6 +17,38 @@ export const useDatabaseService = (): any => { }); } + async function refreshTablesMetadata(databaseId: number): Promise<DatabaseDto> { + const axios = useAxiosInstance(); + console.debug('refresh database tables metadata'); + return new Promise<DatabaseDto>((resolve, reject) => { + axios.put<DatabaseDto>('/api/database/' + databaseId + '/metadata/table', {}) + .then((response) => { + console.info('Refreshed database tables metadata'); + resolve(response.data); + }) + .catch((error) => { + console.error('Failed to refresh database tables metadata', error); + reject(axiosErrorToApiError(error)); + }); + }); + } + + async function refreshViewsMetadata(databaseId: number): Promise<DatabaseDto> { + const axios = useAxiosInstance(); + console.debug('refresh database views metadata'); + return new Promise<DatabaseDto>((resolve, reject) => { + axios.put<DatabaseDto>('/api/database/' + databaseId + '/metadata/view', {}) + .then((response) => { + console.info('Refreshed database views metadata'); + resolve(response.data); + }) + .catch((error) => { + console.error('Failed to refresh database views metadata', error); + reject(axiosErrorToApiError(error)); + }); + }); + } + async function findCount(): Promise<number> { const axios = useAxiosInstance(); console.debug('find databases count'); @@ -185,6 +217,8 @@ export const useDatabaseService = (): any => { return { findAll, + refreshTablesMetadata, + refreshViewsMetadata, findOne, findCount, getServerTime, diff --git a/dbrepo-ui/composables/query-service.ts b/dbrepo-ui/composables/query-service.ts index 381137bba02d170b3f60c465366c4358bc6df28d..fa18a55ec053bad22339a14bcb053b9a405f3716 100644 --- a/dbrepo-ui/composables/query-service.ts +++ b/dbrepo-ui/composables/query-service.ts @@ -93,7 +93,7 @@ export const useQueryService = (): any => { const axios = useAxiosInstance() console.debug('re-execute query in database with id', databaseId) return new Promise<QueryResultDto>((resolve, reject) => { - axios.get<QueryResultDto>(`/api/database/${databaseId}/subset/${queryId}/data`, { params: mapFilter(null, page, size)}) + axios.get<QueryResultDto>(`/api/database/${databaseId}/subset/${queryId}/data`, { params: mapFilter(null, page, size), timeout: 30_000 }) .then((response) => { console.info('Re-executed query in database with id', databaseId) resolve(response.data) @@ -109,7 +109,7 @@ export const useQueryService = (): any => { const axios = useAxiosInstance() console.debug('re-execute query in database with id', databaseId) return new Promise<number>((resolve, reject) => { - axios.head<void>(`/api/database/${databaseId}/subset/${queryId}/data`) + axios.head<void>(`/api/database/${databaseId}/subset/${queryId}/data`, { timeout: 30_000 }) .then((response) => { const count: number = Number(response.headers['x-count']) console.info('Found', count, 'tuples for query', queryId, 'in database with id', databaseId) diff --git a/dbrepo-ui/composables/table-service.ts b/dbrepo-ui/composables/table-service.ts index 37305f24377e3ae7c19cbbd2f0e65683c06cf4a1..393c540f83739ec59ede4c8a6a9bb278f6fd25d4 100644 --- a/dbrepo-ui/composables/table-service.ts +++ b/dbrepo-ui/composables/table-service.ts @@ -71,7 +71,7 @@ export const useTableService = (): any => { const axios = useAxiosInstance() console.debug('get data for table with id', tableId, 'in database with id', databaseId); return new Promise<QueryResultDto>((resolve, reject) => { - axios.get<QueryResultDto>(`/api/database/${databaseId}/table/${tableId}/data`, {params: mapFilter(timestamp, page, size)}) + axios.get<QueryResultDto>(`/api/database/${databaseId}/table/${tableId}/data`, { params: mapFilter(timestamp, page, size), timeout: 30_000 }) .then((response) => { console.info('Got data for table with id', tableId, 'in database with id', databaseId) resolve(response.data) @@ -87,7 +87,7 @@ export const useTableService = (): any => { const axios = useAxiosInstance() console.debug('get data count for table with id', tableId, 'in database with id', databaseId); return new Promise<number>((resolve, reject) => { - axios.head<void>(`/api/database/${databaseId}/table/${tableId}/data`, {params: mapFilter(timestamp, null, null)}) + axios.head<void>(`/api/database/${databaseId}/table/${tableId}/data`, { params: mapFilter(timestamp, null, null), timeout: 30_000 }) .then((response: AxiosResponse<void>) => { const count: number = Number(response.headers['x-count']) console.info('Found' + count + 'in table with id', tableId, 'in database with id', databaseId) diff --git a/dbrepo-ui/composables/user-service.ts b/dbrepo-ui/composables/user-service.ts index cb22cf75b3b876bda04a1935ab433504d6992a87..a8b98916139feabbd288a8dbde3aef7f569fdfdd 100644 --- a/dbrepo-ui/composables/user-service.ts +++ b/dbrepo-ui/composables/user-service.ts @@ -95,7 +95,6 @@ export const useUserService = (): any => { resolve(response.data) }).catch((error) => { console.error('Failed to obtain user token', error) - reject(axiosErrorToApiError(error)) }) }) @@ -115,7 +114,6 @@ export const useUserService = (): any => { resolve(response.data) }).catch((error) => { console.error('Failed to refresh user token', error) - reject(axiosErrorToApiError(error)) }) }) diff --git a/dbrepo-ui/composables/view-service.ts b/dbrepo-ui/composables/view-service.ts index 1c898cea01f0004c8b849077f3cb27f13ccb3d81..adc76e32a1407f7e893cbe92692ec0b2f597591b 100644 --- a/dbrepo-ui/composables/view-service.ts +++ b/dbrepo-ui/composables/view-service.ts @@ -37,7 +37,7 @@ export const useViewService = (): any => { const axios = useAxiosInstance() console.debug('re-execute view with id', viewId, 'in database with id', databaseId) return new Promise<QueryResultDto>((resolve, reject) => { - axios.get<QueryResultDto>(`/api/database/${databaseId}/view/${viewId}/data`, {params: {page, size}}) + axios.get<QueryResultDto>(`/api/database/${databaseId}/view/${viewId}/data`, { params: {page, size}, timeout: 30_000 }) .then((response) => { console.info('Re-executed view with id', viewId, 'in database with id', databaseId) resolve(response.data) @@ -53,7 +53,7 @@ export const useViewService = (): any => { const axios = useAxiosInstance() console.debug('re-execute view with id', viewId, 'in database with id', databaseId) return new Promise<number>((resolve, reject) => { - axios.head<number>(`/api/database/${databaseId}/view/${viewId}/data`) + axios.head<number>(`/api/database/${databaseId}/view/${viewId}/data`, { timeout: 30_000 }) .then((response) => { const count: number = Number(response.headers['x-count']) console.info('Found', count, 'tuples for view with id', viewId, 'in database with id', databaseId) diff --git a/dbrepo-ui/locales/de-AT.json b/dbrepo-ui/locales/de-AT.json index f111e4703758276dccc62b1725b91a785df504bf..15c2664f0f67c97852d58596a27cd6084da2c659 100644 --- a/dbrepo-ui/locales/de-AT.json +++ b/dbrepo-ui/locales/de-AT.json @@ -421,7 +421,7 @@ } }, "schema": { - "title": "Struktur", + "title": "System Versioniert", "bullet": "●", "assign": "Zuordnen", "remove": { @@ -446,7 +446,10 @@ "title": "Nullbar" }, "sequence": { - "title": "Reihenfolge" + "title": "Sequenz" + }, + "description": { + "title": "Beschreibung" }, "name": { "label": "Name", @@ -644,6 +647,13 @@ "image-remove": { "text": "Entferne Bild" }, + "scheme": { + "title": "Schema", + "subtitle": "Aktualisiert die Metadaten im Datenbankschema, um systemversionierte Tabellen und Ansichten in der Benutzeroberfläche anzuzeigen.", + "submit": { + "text": "Aktualisieren" + } + }, "ownership": { "title": "Eigentum", "subtitle": "Benutzer, der Eigentümer dieser Datenbank ist.", @@ -1020,7 +1030,8 @@ "missing": "Der Zugriff in der Metadatendatenbank konnte nicht gefunden werden." }, "axios": { - "connection": "Es konnte keine Verbindung hergestellt werden." + "connection": "Es konnte keine Verbindung hergestellt werden.", + "timeout": "Zeitüberschreitung der Verbindung." }, "concept": { "missing": "Das Konzept konnte in der Metadatendatenbank nicht gefunden werden." @@ -1120,7 +1131,9 @@ "dataset": "Der Datensatz konnte nicht hochgeladen werden." }, "schema": { - "id": "Die Spalte „id“ muss ein Primärschlüssel sein." + "id": "Die Spalte „id“ muss ein Primärschlüssel sein.", + "view": "Ansichtsschema konnte nicht zugeordnet werden.", + "table": "Tabellenschema konnte nicht zugeordnet werden." }, "user": { "exists": "Benutzer mit Benutzername ist in der Authentifizierungsdatenbank vorhanden.", @@ -1162,6 +1175,9 @@ }, "success": { "signup": "Konto erfolgreich erstellt.", + "clipboard": { + "user": "Benutzer-ID erfolgreich kopiert." + }, "query": { "build": "Abfrage konnte nicht erstellt werden: Spalte nicht gefunden", "fatal": "Abfragen mit diesem Schema können derzeit nicht über die Benutzeroberfläche erstellt werden" @@ -1189,6 +1205,10 @@ "created": "Tabelle erfolgreich erstellt.", "semantics": "Semantische Instanz erfolgreich zugewiesen." }, + "schema": { + "tables": "Die Metadaten der Datenbanktabellen wurden erfolgreich aktualisiert.", + "views": "Metadaten der Datenbankansichten wurden erfolgreich aktualisiert." + }, "database": { "upload": "Datenbankbild erfolgreich hochgeladen.", "transfer": "Der Datenbankeigentümer wurde erfolgreich übertragen.", diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index a6a7ca925cb5d0dba693d92679a2566db011cdcc..227ae506c244552c0139582bba97f58cdce60188 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -421,7 +421,7 @@ } }, "schema": { - "title": "Structure", + "title": "System Versioned", "bullet": "●", "assign": "Assign", "remove": { @@ -448,6 +448,9 @@ "sequence": { "title": "Sequence" }, + "description": { + "title": "Description" + }, "name": { "label": "Name", "hint": "Required." @@ -644,6 +647,13 @@ "image-remove": { "text": "Remove Image" }, + "scheme": { + "title": "Schema", + "subtitle": "Update the metadata on the database schema to display system-versioned tables and views in the UI.", + "submit": { + "text": "Refresh" + } + }, "ownership": { "title": "Ownership", "subtitle": "User who has ownership over this database.", @@ -1020,7 +1030,8 @@ "missing": "Failed to find access in metadata database." }, "axios": { - "connection": "Failed to establish connection." + "connection": "Failed to establish connection.", + "timeout": "Connection timed out." }, "concept": { "missing": "Failed to find concept in metadata database." @@ -1120,7 +1131,9 @@ "dataset": "Failed to upload dataset." }, "schema": { - "id": "Column \"id\" must be a primary key." + "id": "Column \"id\" must be a primary key.", + "view": "Failed to map view schema.", + "table": "Failed to map table schema." }, "user": { "exists": "User with username exists in auth database.", @@ -1162,6 +1175,9 @@ }, "success": { "signup": "Successfully created account.", + "clipboard": { + "user": "Successfully copied user id." + }, "query": { "build": "Failed to build query: column not found", "fatal": "Query with this schema is not buildable through the UI at the moment" @@ -1189,6 +1205,10 @@ "created": "Successfully created table.", "semantics": "Successfully assigned semantic instance." }, + "schema": { + "tables": "Successfully refreshed database tables metadata.", + "views": "Successfully refreshed database views metadata." + }, "database": { "upload": "Successfully uploaded database image.", "transfer": "Successfully transferred the database owner.", diff --git a/dbrepo-ui/pages/database/[database_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/settings.vue index 57bf242eff5486101d0318b8379b7c33e1d0b44a..296f639caeb813897b1cb1a08906509af4740a14 100644 --- a/dbrepo-ui/pages/database/[database_id]/settings.vue +++ b/dbrepo-ui/pages/database/[database_id]/settings.vue @@ -173,6 +173,27 @@ </v-row> </v-card-text> </v-card> + <v-divider /> + <v-card + v-if="canUpdateScheme" + :title="$t('pages.database.subpages.settings.scheme.title')" + :subtitle="$t('pages.database.subpages.settings.scheme.subtitle')" + variant="flat" + rounded="0"> + <v-card-text> + <v-row> + <v-col> + <v-btn + size="small" + variant="flat" + color="tertiary" + :loading="loadingSchema" + :text="$t('pages.database.subpages.settings.scheme.submit.text')" + @click="refreshSchema" /> + </v-col> + </v-row> + </v-card-text> + </v-card> </v-window-item> <v-dialog v-model="editAccessDialog" @@ -205,6 +226,7 @@ export default { loading: false, loadingUpload: false, loadingImage: false, + loadingSchema: false, validUpload: false, loadingDeleteImage: false, fileModel: null, @@ -319,6 +341,12 @@ export default { } return this.roles.includes('modify-database-owner') }, + canUpdateScheme () { + if (!this.isOwner) { + return false + } + return this.roles.includes('find-database') + }, canModifyAccess () { if (!this.isOwner) { return false @@ -464,6 +492,28 @@ export default { this.loading = false }) }, + refreshSchema () { + this.loadingSchema = true + const databaseService = useDatabaseService() + databaseService.refreshTablesMetadata(this.$route.params.database_id) + .then(() => { + this.$toast.success(this.$t('success.schema.tables')) + databaseService.refreshViewsMetadata(this.$route.params.database_id) + .then(() => { + this.$toast.success(this.$t('success.schema.views')) + this.cacheStore.reloadDatabase() + this.loadingSchema = false + }) + .catch(({code}) => { + this.$toast.error(this.$t(code)) + this.loadingSchema = false + }) + }) + .catch(({code}) => { + this.$toast.error(this.$t(code)) + this.loadingSchema = false + }) + }, giveAccess () { this.userId = null this.accessType = null diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue index 5bc0cd4a1a7e00b046d79a76b075bf07b98adf93..4af6ba09d796889ec81b2a960b0682847fc24f68 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/schema.vue @@ -74,7 +74,7 @@ </v-data-table> </v-card> <v-card - v-if="table" + v-if="table && hasStructure" variant="flat" rounded="0" tile @@ -82,7 +82,7 @@ <v-card-text> <v-container> <ul> - <li> + <li v-if="table.constraints.primary_key.length > 0"> <strong>PRIMARY KEY</strong> (<i v-text="primaryKeysColumns" />) </li> @@ -168,7 +168,8 @@ export default { { value: 'column_concept', title: this.$t('pages.table.subpages.schema.concept.title') }, { value: 'column_unit', title: this.$t('pages.table.subpages.schema.unit.title') }, { value: 'is_null_allowed', title: this.$t('pages.table.subpages.schema.nullable.title') }, - { value: 'auto_generated', title: this.$t('pages.table.subpages.schema.sequence.title') } + { value: 'auto_generated', title: this.$t('pages.table.subpages.schema.sequence.title') }, + { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') }, ], dateColumns: [], userStore: useUserStore(), @@ -213,6 +214,10 @@ export default { buttonVariant () { const runtimeConfig = useRuntimeConfig() return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal + }, + hasStructure () { + const constraints = this.table.constraints + return constraints.primary_key.length > 0 || constraints.foreign_keys.length > 0 || constraints.checks.length > 0 || constraints.uniques.length > 0 } }, methods: { diff --git a/dbrepo-ui/pages/user/info.vue b/dbrepo-ui/pages/user/info.vue index 91069edd62b076dfe17021e8062f946de017126c..3a085b6008a2362e5dd4c596a7e697fb9cdc3288 100644 --- a/dbrepo-ui/pages/user/info.vue +++ b/dbrepo-ui/pages/user/info.vue @@ -14,9 +14,11 @@ <v-col md="6"> <v-text-field v-model="model.id" - disabled + readonly :variant="inputVariant" - :label="$t('pages.user.subpages.info.id.label')" /> + :label="$t('pages.user.subpages.info.id.label')" + append-inner-icon="mdi-content-copy" + @click:append-inner="copy" /> </v-col> </v-row> <v-row dense> @@ -282,6 +284,10 @@ export default { this.orcidLoading = false }) }, + copy () { + navigator.clipboard.writeText(this.model.id) + this.$toast.success(this.$t('success.clipboard.user')) + } } } </script> diff --git a/dbrepo-ui/utils/index.ts b/dbrepo-ui/utils/index.ts index fe0e7c03f34e3651024c4649c5dbe98a61bcc7d6..66dbe9448329faab2b2c18b4801bb59d878d06bb 100644 --- a/dbrepo-ui/utils/index.ts +++ b/dbrepo-ui/utils/index.ts @@ -1049,6 +1049,15 @@ export function isActiveMessage(message: any) { } export function axiosErrorToApiError(error: AxiosError): ApiErrorDto { + if (error.code === 'ECONNABORTED') { + /* timeout */ + const errorObj: ApiErrorDto = { + status: error.code, + code: 'error.axios.timeout', + message: error.message + } + return errorObj + } if (error.response?.data) { const errorObj: ApiErrorDto = (error.response?.data as ApiErrorDto) return errorObj diff --git a/docker-compose.yml b/docker-compose.yml index 7e4a499a272379d98f56bb3d174fc84f1608bb5e..da0d6a27ea28a19be313f36be686d43116df87d8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -80,6 +80,8 @@ services: container_name: dbrepo-auth-service hostname: auth-service image: dbrepo-auth-service:latest + ports: + - "8080:8080" build: context: ./dbrepo-auth-service network: host @@ -135,7 +137,8 @@ services: GATEWAY_SERVICE_ENDPOINT: ${GATEWAY_SERVICE_ENDPOINT:-http://gateway-service} GRANULARITY: "${GRANULARITY:-YYYY-MM-DDThh:mm:ssZ}" JWT_PUBKEY: "${JWT_PUBKEY:-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}" - LOG_LEVEL: ${LOG_LEVEL:-info} +# LOG_LEVEL: ${LOG_LEVEL:-info} + LOG_LEVEL: trace METADATA_DB: "${METADATA_DB:-dbrepo}" METADATA_HOST: "${METADATA_HOST:-metadata-db}" METADATA_JDBC_EXTRA_ARGS: "${METADATA_JDBC_EXTRA_ARGS:-}" diff --git a/helm/dbrepo/Chart.yaml b/helm/dbrepo/Chart.yaml index d61aa8701a34e5a6f890bf101f1b9775e63bcb03..24e580a29731861c53e63192aa5346531260c135 100644 --- a/helm/dbrepo/Chart.yaml +++ b/helm/dbrepo/Chart.yaml @@ -4,8 +4,8 @@ description: Helm Chart for installing DBRepo sources: - https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services type: application -version: "1.4.3" -appVersion: "1.4.3" +version: "1.4.4" +appVersion: "1.4.4" keywords: - dbrepo maintainers: diff --git a/helm/dbrepo/Makefile b/helm/dbrepo/Makefile index c1e8e02d8f00a08ec29330ed2afd04ff7aff17b1..b89c9b4decd70764a400405af0ff4ccf69b66e61 100644 --- a/helm/dbrepo/Makefile +++ b/helm/dbrepo/Makefile @@ -3,6 +3,6 @@ all: .PHONY: build build: ## Generate Helm values schema JSON - helm package --sign --key 'Martin Weise' . --keyring ~/.gnupg/mweise.gpg --destination ./build + #helm package --sign --key 'Martin Weise' . --keyring ~/.gnupg/mweise.gpg --destination ./build helm schema -input ./values.yaml readme-generator-for-helm --readme README.md --values values.yaml diff --git a/helm/dbrepo/README.md b/helm/dbrepo/README.md index cde2c105fe133fb2117d9a2bf8d5625ecf8d354b..f7c43ba5dbd6f123cb701d9928415fda931e01de 100644 --- a/helm/dbrepo/README.md +++ b/helm/dbrepo/README.md @@ -1,16 +1,16 @@ # DBRepo Helm chart -[DBRepo](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/__CHARTVERSION__/) is a database repository system that +[DBRepo](https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.4.4/) is a database repository system that allows researchers to ingest data into a central, versioned repository through common interfaces. ## TL;DR Download the -sample [`values.yaml`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/master/helm-charts/dbrepo/values.yaml?inline=true) +sample [`values.yaml`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/raw/release-1.4.4/helm-charts/dbrepo/values.yaml?inline=true) for your deployment and update the variables, especially `hostname`. ```bash -helm install my-release "oci://s210.dl.hpc.tuwien.ac.at/dbrepo/helm" --values ./values.yaml --version "1.4.3" +helm install my-release "oci://s210.dl.hpc.tuwien.ac.at/dbrepo/helm" --values ./values.yaml --version "1.4.4" ``` ## Prerequisites @@ -27,7 +27,7 @@ helm install my-release "oci://s210.dl.hpc.tuwien.ac.at/dbrepo/helm" --values ./ To install the chart with the release name `my-release`: ```bash -helm install my-release "oci://s210.dl.hpc.tuwien.ac.at/dbrepo/helm" --values ./values.yaml --version "1.4.3" +helm install my-release "oci://s210.dl.hpc.tuwien.ac.at/dbrepo/helm" --values ./values.yaml --version "1.4.4" ``` The command deploys DBRepo on the Kubernetes cluster in the default configuration. The Parameters section lists the @@ -64,17 +64,18 @@ The command removes all the Kubernetes components associated with the chart and ### Metadata Database -| Name | Description | Value | -| -------------------------------- | -------------------------------------------------------------- | ------------- | -| `metadatadb.enabled` | Enable the Metadata Database. | `true` | -| `metadatadb.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | -| `metadatadb.host` | The hostname for the microservices. | `metadata-db` | -| `metadatadb.rootUser.user` | The root username. | `root` | -| `metadatadb.rootUser.password` | The root user password. | `dbrepo` | -| `metadatadb.jdbcExtraArgs` | The extra arguments for JDBC connections in the microservices. | `""` | -| `metadatadb.db.name` | The database name. | `fda` | -| `metadatadb.persistence.enabled` | Enable persistent storage. Requires PV-provisioner. | `false` | -| `metadatadb.replicaCount` | The number of replicas, should be uneven (2n+1). | `3` | +| Name | Description | Value | +| -------------------------------- | ---------------------------------------------------------------- | ------------- | +| `metadatadb.enabled` | Enable the Metadata Database. | `true` | +| `metadatadb.image.debug` | Set the logging level to `trace`. Otherwise, set to `info`. | `false` | +| `metadatadb.host` | The hostname for the microservices. | `metadata-db` | +| `metadatadb.rootUser.user` | The root username. | `root` | +| `metadatadb.rootUser.password` | The root user password. | `dbrepo` | +| `metadatadb.jdbcExtraArgs` | The extra arguments for JDBC connections in the microservices. | `""` | +| `metadatadb.db.name` | The database name. | `fda` | +| `metadatadb.extraInitDbScripts` | Additional init.db scripts that are executed on the first start. | `{}` | +| `metadatadb.persistence.enabled` | Enable persistent storage. Requires PV-provisioner. | `false` | +| `metadatadb.replicaCount` | The number of replicas, should be uneven (2n+1). | `3` | ### Auth Service @@ -169,19 +170,23 @@ The command removes all the Kubernetes components associated with the chart and ### Data Service -| Name | Description | Value | -| ----------------------------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -| `dataservice.enabled` | Enable the Metadata Service. | `true` | -| `dataservice.endpoint` | The endpoint for the microservices. | `http://data-service` | -| `dataservice.grant.read` | The default database permissions for users with read access. | `SELECT` | -| `dataservice.grant.write` | The default database permissions for users with write access. | `SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE` | -| `dataservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | -| `dataservice.s3.auth.username` | The S3-capable endpoint username (or access key id). | `seaweedfsadmin` | -| `dataservice.s3.auth.password` | The S3-capable endpoint user password (or access key secret). | `seaweedfsadmin` | -| `dataservice.consumerConcurrentMin` | The minimum broker service consumer number. | `1` | -| `dataservice.consumerConcurrentMax` | The maximum broker service consumer number. | `5` | -| `dataservice.requeueRejected` | Enable re-queueing of rejected messages to the broker service. | `false` | -| `dataservice.replicaCount` | The number of replicas. | `2` | +| Name | Description | Value | +| ----------------------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | +| `dataservice.enabled` | Enable the Metadata Service. | `true` | +| `dataservice.endpoint` | The endpoint for the microservices. | `http://data-service` | +| `dataservice.grant.read` | The default database permissions for users with read access. | `SELECT` | +| `dataservice.grant.write` | The default database permissions for users with write access. | `SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE` | +| `dataservice.default.date` | The default date format id for dates. | `3` | +| `dataservice.default.time` | The default date format id for times. | `4` | +| `dataservice.default.timestamp` | The default date format id for timestamps. | `1` | +| `dataservice.s3.endpoint` | The S3-capable endpoint the microservice connects to. | `http://storageservice-s3:9000` | +| `dataservice.s3.auth.username` | The S3-capable endpoint username (or access key id). | `seaweedfsadmin` | +| `dataservice.s3.auth.password` | The S3-capable endpoint user password (or access key secret). | `seaweedfsadmin` | +| `dataservice.s3.filePath` | The local location to download/upload files from/to S3-capable endpoint. | `/s3` | +| `dataservice.consumerConcurrentMin` | The minimum broker service consumer number. | `1` | +| `dataservice.consumerConcurrentMax` | The maximum broker service consumer number. | `5` | +| `dataservice.requeueRejected` | Enable re-queueing of rejected messages to the broker service. | `false` | +| `dataservice.replicaCount` | The number of replicas. | `2` | ### Search Service diff --git a/helm/dbrepo/templates/data-secret.yaml b/helm/dbrepo/templates/data-secret.yaml index 70cec81ca5314152e9544622b86333ba2c7eec65..6e95ab880261312c86d9672ad79a0aff4ddf00e4 100644 --- a/helm/dbrepo/templates/data-secret.yaml +++ b/helm/dbrepo/templates/data-secret.yaml @@ -26,6 +26,9 @@ stringData: GATEWAY_SERVICE_ENDPOINT: "{{ .Values.gateway }}" GRANT_DEFAULT_READ: "{{ .Values.dataservice.grant.read }}" GRANT_DEFAULT_WRITE: "{{ .Values.dataservice.grant.write }}" + DEFAULT_DATE_FORMAT_ID: "{{ .Values.dataservice.default.date }}" + DEFAULT_TIME_FORMAT_ID: "{{ .Values.dataservice.default.time }}" + DEFAULT_TIMESTAMP_FORMAT_ID: "{{ .Values.dataservice.default.timestamp }}" JWT_PUBKEY: "{{ .Values.authservice.jwt.pubkey }}" LOG_LEVEL: "{{ ternary "debug" "info" .Values.dataservice.image.debug }}" MIN_CONCURRENT_CONSUMERS: "{{ .Values.dataservice.consumerConcurrentMin }}" diff --git a/helm/dbrepo/values.schema.json b/helm/dbrepo/values.schema.json index b325533b9c4c05cdc38ac016cc2d44fd9b5595be..3f555c67054181b24d05054dc93fabc9dabb8d86 100644 --- a/helm/dbrepo/values.schema.json +++ b/helm/dbrepo/values.schema.json @@ -580,6 +580,20 @@ "consumerConcurrentMin": { "type": "integer" }, + "default": { + "properties": { + "date": { + "type": "integer" + }, + "time": { + "type": "integer" + }, + "timestamp": { + "type": "integer" + } + }, + "type": "object" + }, "enabled": { "type": "boolean" }, @@ -643,6 +657,9 @@ }, "endpoint": { "type": "string" + }, + "filePath": { + "type": "string" } }, "type": "object" @@ -750,6 +767,10 @@ "enabled": { "type": "boolean" }, + "extraInitDbScripts": { + "properties": {}, + "type": "object" + }, "fullnameOverride": { "type": "string" }, diff --git a/helm/dbrepo/values.yaml b/helm/dbrepo/values.yaml index a2fbad6d501d6844c8fa2bd2fdbb7af5d20f1fd7..d15d46c305eaa829415e181694d18ccd0279f429 100644 --- a/helm/dbrepo/values.yaml +++ b/helm/dbrepo/values.yaml @@ -66,12 +66,12 @@ metadatadb: user: mariabackup password: mariabackup initdbScriptsConfigMap: metadata-db-setup - extraInitDbScripts: {} -# 03-additional-data.sql: | -# BEGIN; -# INSERT INTO `mdb_containers` (name, internal_name, image_id, host, port, sidecar_host, sidecar_port, privileged_username, privileged_password) -# VALUES ('MariaDB Galera TEST', 'mariadb_11_1_3', 1, 'data-db', 3306, 'data-db', 80, 'root', 'dbrepo'); -# COMMIT; + extraInitDbScripts: { } + # 03-additional-data.sql: | + # BEGIN; + # INSERT INTO `mdb_containers` (name, internal_name, image_id, host, port, sidecar_host, sidecar_port, privileged_username, privileged_password) + # VALUES ('MariaDB Galera TEST', 'mariadb_11_1_3', 1, 'data-db', 3306, 'data-db', 80, 'root', 'dbrepo'); + # COMMIT; service: type: ClusterIP annotations: { } @@ -178,7 +178,7 @@ datadb: protocol: TCP sidecars: - name: sidecar - image: s210.dl.hpc.tuwien.ac.at/dbrepo/data-db-sidecar:1.4.3 + image: s210.dl.hpc.tuwien.ac.at/dbrepo/data-db-sidecar:1.4.4 securityContext: runAsUser: 1001 runAsGroup: 0 @@ -436,7 +436,7 @@ brokerservice: analyseservice: enabled: true image: - name: s210.dl.hpc.tuwien.ac.at/dbrepo/analyse-service:1.4.3 + name: s210.dl.hpc.tuwien.ac.at/dbrepo/analyse-service:1.4.4 pullPolicy: Always debug: false s3: @@ -466,7 +466,7 @@ analyseservice: metadataservice: enabled: true image: - name: s210.dl.hpc.tuwien.ac.at/dbrepo/metadata-service:1.4.3 + name: s210.dl.hpc.tuwien.ac.at/dbrepo/metadata-service:1.4.4 pullPolicy: Always debug: false admin: @@ -499,6 +499,9 @@ metadataservice: ## @skip dataservice.image ## @param dataservice.grant.read The default database permissions for users with read access. ## @param dataservice.grant.write The default database permissions for users with write access. +## @param dataservice.default.date The default date format id for dates. +## @param dataservice.default.time The default date format id for times. +## @param dataservice.default.timestamp The default date format id for timestamps. ## @param dataservice.s3.endpoint The S3-capable endpoint the microservice connects to. ## @skip dataservice.s3.bucket ## @param dataservice.s3.auth.username The S3-capable endpoint username (or access key id). @@ -513,12 +516,16 @@ dataservice: enabled: true endpoint: http://data-service image: - name: s210.dl.hpc.tuwien.ac.at/dbrepo/data-service:1.4.3 + name: s210.dl.hpc.tuwien.ac.at/dbrepo/data-service:1.4.4 pullPolicy: Always debug: false grant: read: SELECT write: SELECT, CREATE, CREATE VIEW, CREATE ROUTINE, CREATE TEMPORARY TABLES, LOCK TABLES, INDEX, TRIGGER, INSERT, UPDATE, DELETE + default: + date: 3 + time: 4 + timestamp: 1 s3: endpoint: http://storageservice-s3:9000 bucket: @@ -545,12 +552,12 @@ searchservice: enabled: true endpoint: http://search-service image: - name: s210.dl.hpc.tuwien.ac.at/dbrepo/search-service:1.4.3 + name: s210.dl.hpc.tuwien.ac.at/dbrepo/search-service:1.4.4 pullPolicy: Always debug: false init: image: - name: s210.dl.hpc.tuwien.ac.at/dbrepo/search-service-init:1.4.3 + name: s210.dl.hpc.tuwien.ac.at/dbrepo/search-service-init:1.4.4 pullPolicy: Always replicaCount: 2 @@ -597,7 +604,7 @@ storageservice: username: seaweedfsadmin password: seaweedfsadmin init: - image: s210.dl.hpc.tuwien.ac.at/dbrepo/storage-service-init:1.4.3 + image: s210.dl.hpc.tuwien.ac.at/dbrepo/storage-service-init:1.4.4 pullPolicy: Always ## @section User Interface @@ -626,7 +633,7 @@ storageservice: ui: enabled: true image: - name: s210.dl.hpc.tuwien.ac.at/dbrepo/ui:1.4.3 + name: s210.dl.hpc.tuwien.ac.at/dbrepo/ui:1.4.4 pullPolicy: Always debug: false public: diff --git a/lib/python/build-website.sh b/lib/python/build-site.sh similarity index 54% rename from lib/python/build-website.sh rename to lib/python/build-site.sh index 1178d90892335f55f21d414b7fe7519233bddbd2..75602b09cc6658e572c5d279450a236f354a59d3 100755 --- a/lib/python/build-website.sh +++ b/lib/python/build-site.sh @@ -2,7 +2,5 @@ python3 -m venv ./lib/python/venv source ./lib/python/venv/bin/activate PIPENV_PIPFILE=./lib/python/Pipfile pipenv install --dev -sed -i -e "s/__APPVERSION__/${APP_VERSION}/g" ./lib/python/pyproject.toml ./lib/python/setup.py ./lib/python/README.md ./lib/python/docs/conf.py ./lib/python/docs/index.rst sphinx-apidoc -o ./lib/python/docs/source ./lib/python/dbrepo -sphinx-build -M html ./lib/python/docs/ ./lib/python/docs/build/ -cp -r ./lib/python/docs/build/html ./site/sphinx \ No newline at end of file +sphinx-build -M html ./lib/python/docs/ ./lib/python/docs/build/ \ No newline at end of file diff --git a/lib/python/dbrepo/RestClient.py b/lib/python/dbrepo/RestClient.py index 101bff51a18b15b9e53538e96efae4eb330a5cd9..25f20858a97ef379bdedfa9ccda41f8b566d9560 100644 --- a/lib/python/dbrepo/RestClient.py +++ b/lib/python/dbrepo/RestClient.py @@ -518,6 +518,27 @@ class RestClient: raise NotExistsError(f'Failed to delete table: not found') raise ResponseCodeError(f'Failed to delete table: response code: {response.status_code} is not 202 (ACCEPTED)') + def get_table_metadata(self, database_id: int) -> Database: + """ + Generate metadata of all system-versioned tables in a database with given id. + + :param database_id: The database id. + + :raises ResponseCodeError: If something went wrong with the retrieval. + :raises ForbiddenError: If the action is not allowed. + :raises NotExistsError: If the container does not exist. + """ + url = f'/api/database/{database_id}/metadata/table' + response = self._wrapper(method="put", url=url, force_auth=True) + if response.status_code == 200: + body = response.json() + return Database.model_validate(body) + if response.status_code == 403: + raise ForbiddenError(f'Failed to get tables metadata: not allowed') + if response.status_code == 404: + raise NotExistsError(f'Failed to get tables metadata: not found') + raise ResponseCodeError(f'Failed to get tables metadata: response code: {response.status_code} is not 200 (OK)') + def get_views(self, database_id: int) -> List[View]: """ Gets views of a database with given database id. @@ -655,6 +676,27 @@ class RestClient: raise NotExistsError(f'Failed to get view data: not found') raise ResponseCodeError(f'Failed to get view data: response code: {response.status_code} is not 200 (OK)') + def get_views_metadata(self, database_id: int) -> Database: + """ + Generate metadata of all views in a database with given id. + + :param database_id: The database id. + + :raises ResponseCodeError: If something went wrong with the retrieval. + :raises ForbiddenError: If the action is not allowed. + :raises NotExistsError: If the container does not exist. + """ + url = f'/api/database/{database_id}/metadata/view' + response = self._wrapper(method="put", url=url, force_auth=True) + if response.status_code == 200: + body = response.json() + return Database.model_validate(body) + if response.status_code == 403: + raise ForbiddenError(f'Failed to get views metadata: not allowed') + if response.status_code == 404: + raise NotExistsError(f'Failed to get views metadata: not found') + raise ResponseCodeError(f'Failed to get views metadata: response code: {response.status_code} is not 200 (OK)') + def get_table_data(self, database_id: int, table_id: int, page: int = 0, size: int = 10, timestamp: datetime.datetime = None, df: bool = False) -> Result | DataFrame: """ @@ -1319,7 +1361,7 @@ class RestClient: publication_day: int = None, publication_month: int = None, related_identifiers: List[CreateRelatedIdentifier] = None) -> Identifier: """ - Create an identifier + Create an identifier draft. :param database_id: The database id of the created identifier. :param type: The type of the created identifier. @@ -1367,6 +1409,93 @@ class RestClient: raise ResponseCodeError( f'Failed to create identifier: response code: {response.status_code} is not 201 (CREATED)') + def save_identifier(self, identifier_id: int, database_id: int, type: IdentifierType, + titles: List[CreateIdentifierTitle], publisher: str, creators: List[CreateIdentifierCreator], + publication_year: int, descriptions: List[CreateIdentifierDescription] = None, + funders: List[CreateIdentifierFunder] = None, licenses: List[License] = None, + language: Language = None, query_id: int = None, view_id: int = None, table_id: int = None, + publication_day: int = None, publication_month: int = None, + related_identifiers: List[CreateRelatedIdentifier] = None) -> Identifier: + """ + Save an existing identifier and update the metadata attached to it. + + :param identifier_id: The identifier id. + :param database_id: The database id of the created identifier. + :param type: The type of the created identifier. + :param titles: The titles of the created identifier. + :param publisher: The publisher of the created identifier. + :param creators: The creator(s) of the created identifier. + :param publication_year: The publication year of the created identifier. + :param descriptions: The description(s) of the created identifier. Optional. + :param funders: The funders(s) of the created identifier. Optional. + :param licenses: The license(s) of the created identifier. Optional. + :param language: The language of the created identifier. Optional. + :param query_id: The query id of the created identifier. Required when type=SUBSET, otherwise invalid. Optional. + :param view_id: The view id of the created identifier. Required when type=VIEW, otherwise invalid. Optional. + :param table_id: The table id of the created identifier. Required when type=TABLE, otherwise invalid. Optional. + :param publication_day: The publication day of the created identifier. Optional. + :param publication_month: The publication month of the created identifier. Optional. + :param related_identifiers: The related identifier(s) of the created identifier. Optional. + + :returns: The identifier, if successful. + + :raises ResponseCodeError: If something went wrong with the creation of the identifier. + :raises ForbiddenError: If the action is not allowed. + :raises MalformedError: If the payload is rejected by the service. + :raises NotExistsError: If the database, table/view/subset or user does not exist. + :raises ExternalSystemError: If the external system (DataCite) refused communication with the service. + """ + url = f'/api/identifier/{identifier_id}' + payload = CreateIdentifier(database_id=database_id, type=type, titles=titles, publisher=publisher, + creators=creators, publication_year=publication_year, descriptions=descriptions, + funders=funders, licenses=licenses, language=language, query_id=query_id, + view_id=view_id, table_id=table_id, publication_day=publication_day, + publication_month=publication_month, related_identifiers=related_identifiers) + response = self._wrapper(method="put", url=url, force_auth=True, payload=payload) + if response.status_code == 201: + body = response.json() + return Identifier.model_validate(body) + if response.status_code == 400: + raise MalformedError(f'Failed to save identifier: service rejected malformed payload') + if response.status_code == 403 or response.status_code == 405: + raise ForbiddenError(f'Failed to save identifier: not allowed') + if response.status_code == 404: + raise NotExistsError(f'Failed to save identifier: not found') + if response.status_code == 503: + raise ExternalSystemError(f'Failed to save identifier: external system rejected communication') + raise ResponseCodeError( + f'Failed to save identifier: response code: {response.status_code} is not 202 (ACCEPTED)') + + def publish_identifier(self, identifier_id: int) -> Identifier: + """ + Publish an identifier with given id. + + :param identifier_id: The identifier id. + + :returns: The identifier, if successful. + + :raises ResponseCodeError: If something went wrong with the creation of the identifier. + :raises ForbiddenError: If the action is not allowed. + :raises MalformedError: If the payload is rejected by the service. + :raises NotExistsError: If the database, table/view/subset or user does not exist. + :raises ExternalSystemError: If the external system (DataCite) refused communication with the service. + """ + url = f'/api/identifier/{identifier_id}/publish' + response = self._wrapper(method="put", url=url, force_auth=True) + if response.status_code == 201: + body = response.json() + return Identifier.model_validate(body) + if response.status_code == 400: + raise MalformedError(f'Failed to publish identifier: service rejected malformed payload') + if response.status_code == 403 or response.status_code == 405: + raise ForbiddenError(f'Failed to publish identifier: not allowed') + if response.status_code == 404: + raise NotExistsError(f'Failed to publish identifier: not found') + if response.status_code == 503: + raise ExternalSystemError(f'Failed to publish identifier: external system rejected communication') + raise ResponseCodeError( + f'Failed to publish identifier: response code: {response.status_code} is not 201 (CREATED)') + def suggest_identifier(self, uri: str) -> Identifier: """ Suggest identifier metadata for a given identifier URI. Example: ROR, ORCID, ISNI, GND, DOI. diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index e22b9895418222a4151a68184ee402a0997b7aad..27256c63985dbf1801612cef461cb6a4541b8030 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -624,6 +624,7 @@ class View(BaseModel): is_public: bool initial_view: bool last_modified: Timestamp + columns: List[ViewColumn] identifiers: List[Identifier] = field(default_factory=list) @@ -877,6 +878,7 @@ class Column(BaseModel): is_public: bool is_null_allowed: bool alias: Optional[str] = None + description: Optional[str] = None size: Optional[int] = None d: Optional[int] = None mean: Optional[float] = None @@ -896,6 +898,27 @@ class Column(BaseModel): std_dev: Optional[float] = None +class ViewColumn(BaseModel): + id: int + name: str + database_id: int + internal_name: str + auto_generated: bool + column_type: ColumnType + is_public: bool + is_null_allowed: bool + alias: Optional[str] = None + size: Optional[int] = None + d: Optional[int] = None + mean: Optional[float] = None + median: Optional[float] = None + concept: Optional[Concept] = None + unit: Optional[Unit] = None + date_format: Optional[ImageDate] = None + index_length: Optional[int] = None + length: Optional[int] = None + + class Table(BaseModel): id: int database_id: int diff --git a/lib/python/docs/conf.py b/lib/python/docs/conf.py index 4d955a3a4ccef4a916280d4bc7edfd2a328b9a92..2992f7ada79d565769420968ce1acf11998d1a73 100644 --- a/lib/python/docs/conf.py +++ b/lib/python/docs/conf.py @@ -17,7 +17,7 @@ project = "dbrepo" current_year = datetime.date.today().year copyright = f'{current_year} the DBRepo Developers' author = "Martin Weise" -release = "__APPVERSION__" +release = "" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/lib/python/docs/index.rst b/lib/python/docs/index.rst index d1916a2e2aafc6173b2003379a08ae7140b98559..f905221999ac672b663611b248d6c75266c82e26 100644 --- a/lib/python/docs/index.rst +++ b/lib/python/docs/index.rst @@ -12,7 +12,7 @@ Quickstart ---------- Find numerous quickstart examples on -the `DBRepo website <https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/__APPVERSION__/usage-overview/>`_. +the `DBRepo website <https://www.ifs.tuwien.ac.at/infrastructures/dbrepo//usage-overview/>`_. AMQP API Client ----------- diff --git a/lib/python/package.sh b/lib/python/package.sh index 4478dbf962d7dba47fc787061b5761d2b53a68eb..2ad8d301e8d4ed3b0bac1433505bcd4bfedabdfa 100755 --- a/lib/python/package.sh +++ b/lib/python/package.sh @@ -1,8 +1,3 @@ #!/bin/bash -PRE_RELEASE="" -if [ "${CI_COMMIT_BRANCH:8:8}" = "master" ]; then - PRE_RELEASE="rc${CI_PIPELINE_ID}" -fi -sed -i -e "s/__APPVERSION__/${APP_VERSION}${PRE_RELEASE}/g" ./lib/python/pyproject.toml ./lib/python/setup.py ./lib/python/README.md python -m build --sdist ./lib/python python -m build --wheel ./lib/python diff --git a/lib/python/pyproject.toml b/lib/python/pyproject.toml index e0b1a19844a770f2306b756150495eeb72f1e90e..e8de41883d8bd20d26997934c3de288ec9b218e5 100644 --- a/lib/python/pyproject.toml +++ b/lib/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dbrepo" -version = "1.4.3" +version = "1.4.4" description = "DBRepo Python Library" keywords = [ "DBRepo", diff --git a/lib/python/setup.py b/lib/python/setup.py index f9915ffbd3fc8498c6c04eee5455d24dcabbaf4f..4d5b26206dee68602d6b09fdaf3723956919e4ae 100644 --- a/lib/python/setup.py +++ b/lib/python/setup.py @@ -2,7 +2,7 @@ from distutils.core import setup setup(name="dbrepo", - version="1.4.3", + version="1.4.4", description="A library for communicating with DBRepo", url="https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.4.3/", author="Martin Weise", diff --git a/make/gen.mk b/make/gen.mk index 0ab27496d41060d3fdb42260dde7068a4c60d6cf..e6fceaf2ba3e40a0dc496f885448916a3eb3c766 100644 --- a/make/gen.mk +++ b/make/gen.mk @@ -17,4 +17,4 @@ gen-docs-doc: ## Generate DBRepo documentation. .PHONY: gen-lib-doc gen-lib-doc: ## Generate Python Library documentation. - bash ./lib/python/build.sh + bash ./lib/python/build-site.sh diff --git a/mkdocs.yml b/mkdocs.yml index a1b6f5aad0fec446885c1cfe3b12adbb37637011..e4370152366f1e106cd95e23263bd62b481be5c0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -16,9 +16,9 @@ nav: - Concepts: - Overview: concepts/index.md - Authentication: concepts/authentication.md - - DBMS: concepts/dbms.md + - Databases: concepts/databases.md - Messaging: concepts/messaging.md - - (Meta-)Data: concepts/metadata.md + - Monitoring: concepts/monitoring.md - Persistent Identifier: concepts/pid.md - Search: concepts/search.md - Storage: concepts/storage.md