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/system-services-analyse.md b/.docs/api/analyse-service.md
similarity index 99%
rename from .docs/system-services-analyse.md
rename to .docs/api/analyse-service.md
index 8d940aba68301a693739358db355e8e631afe1fb..be5efdbf5c8c58dd0c0825e7c1328188d01b1aba 100644
--- a/.docs/system-services-analyse.md
+++ b/.docs/api/analyse-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Analyse Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
diff --git a/.docs/system-services-authentication.md b/.docs/api/auth-service.md
similarity index 99%
rename from .docs/system-services-authentication.md
rename to .docs/api/auth-service.md
index 0ec89e11c197e8c1b5c1ede7c1cf7f1f0167ccb1..5d3e0f42b2bb19b28451c8a8c8e40d937ffe9fab 100644
--- a/.docs/system-services-authentication.md
+++ b/.docs/api/auth-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Authentication Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
@@ -38,7 +36,7 @@ We organize the roles into default- and escalated composite roles. There are thr
 Each of the composite role has a set of other associated composite roles.
 
 <figure markdown>
-![](images/groups-roles.png)
+![Grouped Roles](../images/groups-roles.png)
 <figcaption>Three groups (Researchers, Developers, Data Stewards) and their composite roles associated.</figcaption>
 </figure>
 
diff --git a/.docs/system-services-broker.md b/.docs/api/broker-service.md
similarity index 96%
rename from .docs/system-services-broker.md
rename to .docs/api/broker-service.md
index 7ed0c3333f796180f11d0581e248065a979e1238..0345271bf1c23545e029b51f2de70311235ade5a 100644
--- a/.docs/system-services-broker.md
+++ b/.docs/api/broker-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Broker Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
@@ -40,14 +38,14 @@ queue `dbrepo`, connected with a binding of `dbrepo.#` which routes all tuples w
 the dot!) to this queue.
 
 <figure markdown>
-   ![Data ingest](images/queue-quorum.png)
+   ![Data ingest](../images/queue-quorum.png)
    <figcaption>Replicated quorum queue dbrepo in a cluster with three nodes</figcaption>
 </figure>
 
 The consumer takes care of writing it to the correct table in the [Data Service](../system-services-data).
 
 <figure markdown>
-   ![Data ingest](images/exchange-binding.png)
+   ![Data ingest](../images/exchange-binding.png)
    <figcaption>Architecture Broker Service</figcaption>
 </figure>
 
diff --git a/.docs/system-databases-data.md b/.docs/api/data-db.md
similarity index 97%
rename from .docs/system-databases-data.md
rename to .docs/api/data-db.md
index e290bc1342373ea784d25c6ef2da6eb840abd8bd..859264a53a08da57536c221dfd76899a833b3a6d 100644
--- a/.docs/system-databases-data.md
+++ b/.docs/api/data-db.md
@@ -2,10 +2,6 @@
 author: Martin Weise
 ---
 
-# Data Database
-
-## tl;dr
-
 !!! debug "Debug Information"
 
     Image: [`bitnami/mariadb-galera:11.2.2-debian-11-r0`](https://hub.docker.com/r/bitnami/mariadb-galera)
@@ -64,7 +60,7 @@ the [`boto3`](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html
 natively.
 
 <figure markdown>
-![Sidecar architecture detailed](images/architecture-data-db.svg)
+![Sidecar architecture detailed](../images/architecture-data-db.svg)
 <figcaption>Sidecar that handles the CSV-file upload/download.</figcaption>
 </figure>
 
diff --git a/.docs/system-services-data.md b/.docs/api/data-service.md
similarity index 90%
rename from .docs/system-services-data.md
rename to .docs/api/data-service.md
index b8a1fe6263da6f236735206b7477c65adda84128..df6b87e2f06bd59e90ce6116a240d538cd8185c4 100644
--- a/.docs/system-services-data.md
+++ b/.docs/api/data-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Data Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
@@ -26,8 +24,6 @@ Data Service up.
 
 ## Limitations
 
-* No clear differentiation for data-handling endpoints from the [Metadata Service](../system-services-metadata) yet.
-
 !!! question "Do you miss functionality? Do these limitations affect you?"
 
     We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get
diff --git a/.docs/system-services-gateway.md b/.docs/api/gateway-service.md
similarity index 99%
rename from .docs/system-services-gateway.md
rename to .docs/api/gateway-service.md
index 9950110c71c6a86088e3e530f59a5d5bca6935f7..172892e3bdb13411c658093cbc7adf76fbdd6de7 100644
--- a/.docs/system-services-gateway.md
+++ b/.docs/api/gateway-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Gateway Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
diff --git a/.docs/usage-overview.md b/.docs/api/index.md
similarity index 100%
rename from .docs/usage-overview.md
rename to .docs/api/index.md
diff --git a/.docs/api/metadata-db.md b/.docs/api/metadata-db.md
new file mode 100644
index 0000000000000000000000000000000000000000..e56b88ab8b99fb4cdffc9d68c5db28703f4fdaa8
--- /dev/null
+++ b/.docs/api/metadata-db.md
@@ -0,0 +1,5 @@
+---
+author: Martin Weise
+---
+
+TBD
\ No newline at end of file
diff --git a/.docs/system-services-metadata.md b/.docs/api/metadata-service.md
similarity index 99%
rename from .docs/system-services-metadata.md
rename to .docs/api/metadata-service.md
index b7fe150c8b90b09826f66feb8a158abf21793f2a..33f3db3bfe5be3d473420599ff90b6582a9e4443 100644
--- a/.docs/system-services-metadata.md
+++ b/.docs/api/metadata-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Metadata Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
diff --git a/.docs/api/open-api.md b/.docs/api/open-api.md
new file mode 100644
index 0000000000000000000000000000000000000000..f06ec67a0daec31d77ddd0b62716276183c4b728
--- /dev/null
+++ b/.docs/api/open-api.md
@@ -0,0 +1,7 @@
+---
+author: Martin Weise
+---
+
+All services are documented using the 
+[![OpenAPI 3.0](https://img.shields.io/badge/OpenAPI-3.0-leaf?logo=swagger&logoColor=white)](https://www.openapis.org/){ tabindex=-1 }
+documentation standard.
diff --git a/.docs/usage-python.md b/.docs/api/python.md
similarity index 95%
rename from .docs/usage-python.md
rename to .docs/api/python.md
index ce83d6304f0d3f54e8575daac13cc63fa470a07b..7289639bfad0ed3e3408bab54b717a884e0fead6 100644
--- a/.docs/usage-python.md
+++ b/.docs/api/python.md
@@ -2,15 +2,11 @@
 author: Martin Weise
 ---
 
-# Python Library
+[![PyPI - Version](https://img.shields.io/pypi/v/dbrepo)](https://pypi.org/project/dbrepo/){ tabindex=-1 }
 
 ## tl;dr
 
-!!! debug "Debug Information"
-
-    PyPI: [`dbrepo`](https://pypi.org/project/dbrepo/)
-
-    * Full module documentation <a href="../sphinx" target="_blank">:fontawesome-solid-square-up-right: view online</a>
+[:fontawesome-solid-cube: &nbsp;View Docs](../sphinx){ .md-button .md-button--primary }
 
 ## Installing
 
diff --git a/.docs/system-services-search.md b/.docs/api/search-service.md
similarity index 92%
rename from .docs/system-services-search.md
rename to .docs/api/search-service.md
index edca2df6fc70ac39f75a61a8ae416ff072ffa0a7..fff317d6f8adc093cdf6f725bab31f5bbdb424e7 100644
--- a/.docs/system-services-search.md
+++ b/.docs/api/search-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Search Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
@@ -22,7 +20,7 @@ the [User Interface](../system-other-ui) to allow structured search of databases
 views, semantic concepts &amp; units of measurements used in databases.
 
 <figure markdown>
-![Built-in search](images/screenshots/feature-search.png){ .img-border }
+![Built-in search](../images/screenshots/feature-search.png){ .img-border }
 <figcaption>Figure 1: Faceted browsing</figcaption>
 </figure>
 
@@ -33,7 +31,7 @@ index [`database`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fd
 that holds all the metadata information which is mirrored from the [Metadata Database](../system-databases-metadata).
 
 <figure markdown>
-![Mirroring statistical properties in Metadata Database and Search Database](images/statistics-mirror.png)
+![Mirroring statistical properties in Metadata Database and Search Database](../images/statistics-mirror.png)
 <figcaption>Figure 2: Statistical properties in Metadata Database and Search Database</figcaption>
 </figure>
 
@@ -58,7 +56,7 @@ search can be performed when at least two columns have the same semantic concept
 the units of measurements can be transformed.
 
 <figure markdown>
-![Two tables with compatible semantic concepts (Temperature) and units of measurement (left is in degree Celsius, right is in degree Fahrenheit)](images/statistics-example.png)
+![Two tables with compatible semantic concepts (Temperature) and units of measurement (left is in degree Celsius, right is in degree Fahrenheit)](../images/statistics-example.png)
 <figcaption>Figure 3: Two tables with compatible semantic concepts and units of measurement</figcaption>
 </figure>
 
@@ -70,7 +68,7 @@ search service transforms the query to the dataset on the right from &deg;F to c
 between 32 - 50 &deg;F"* instead.
 
 <figure markdown>
-![Unit independent search query transformation](images/statistics-example-unit-independent-search.png)
+![Unit independent search query transformation](../images/statistics-example-unit-independent-search.png)
 <figcaption>Figure 4: Unit independent search query transformation</figcaption>
 </figure>
 
diff --git a/.docs/system-services-storage.md b/.docs/api/storage-service.md
similarity index 95%
rename from .docs/system-services-storage.md
rename to .docs/api/storage-service.md
index f6b9ae28ee48fe5fa8dc319228ffe09ee4e3f030..2219c5fa5759dce36cbb0276594b1f0c5d32ee64 100644
--- a/.docs/system-services-storage.md
+++ b/.docs/api/storage-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Storage Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
@@ -31,10 +29,6 @@ The default configuration creates two buckets `dbrepo-upload`, `dbrepo-download`
 * `dbrepo-upload` for CSV-file upload (for import of data, analysis, etc.) from the User Interface
 * `dbrepo-download` for CSV-file download (exporting data, metadata, etc.)
 
-### Examples
-
-See the [usage page](../usage-storage).
-
 ## Limitations
 
 * No support for multiple regions.
diff --git a/.docs/system-other-ui.md b/.docs/api/ui.md
similarity index 75%
rename from .docs/system-other-ui.md
rename to .docs/api/ui.md
index cb8a1331035b91e7345ae98848bc49e73b05fa5c..659b21ea90137034872c4312aaeeca4caf5bd346 100644
--- a/.docs/system-other-ui.md
+++ b/.docs/api/ui.md
@@ -2,38 +2,13 @@
 author: Martin Weise
 ---
 
-# User Interface
-
-## tl;dr
-
-!!! debug "Debug Information"
-
-    Image: [`dbrepo/ui:__APPVERSION__`](https://hub.docker.com/r/dbrepo/ui)
-
-    * Ports: 3000/tcp
-    * UI: `http://<hostname>/`
-
-## Overview
-
-It provides a graphical interface for a researcher to interact with the API (c.f. Figure 1). 
-
-<figure markdown>
-![User Interface](images/screenshots/ui.png){ .img-border }
-<figcaption>Figure 1: User Interface</figcaption>
-</figure>
-
-For examples on how to use the User Interface, visit the [Usage Overview](../usage-overview/) to find out how to create
-users, databases and how to import your data.
-
-### Settings
-
 The User Interface is configured in the `runtimeConfig` section of the `nuxt.config.ts` file during build time. For the
 runtime, you need to override those values through environment variables or by mounting a `.env` file. As a small
 example, you can configure the logo :material-numeric-1-circle-outline: in Figure 2. Make sure you mount the logo as
 image as well, in this example we want to mount a custom logo `my_logo.png` into the container and specify the name.
 
 <figure markdown>
-![Architecture of the UI microservice](images/screenshots/ui-config-step-1.png){ .img-border }
+![Architecture of the UI microservice](../images/screenshots/ui-config-step-1.png){ .img-border }
 <figcaption>Figure 2: Architecture of the UI microservice</figcaption>
 </figure>
 
@@ -64,7 +39,7 @@ The server-client architecture of the User Interface is shown in [Figure 3](#fig
 User Interface on development.
 
 <figure id="fig3" markdown>
-![Architecture of the UI microservice](images/architecture-ui.svg)
+![Architecture of the UI microservice](../images/architecture-ui.svg)
 <figcaption>Figure 3: Architecture of the User Interface</figcaption>
 </figure>
 
diff --git a/.docs/system-services-upload.md b/.docs/api/upload-service.md
similarity index 95%
rename from .docs/system-services-upload.md
rename to .docs/api/upload-service.md
index 56cfb27ddc3a0d96d032d214aa4efa71101bf81b..88812d308ba856a1d7c77e65a1bf97298cb2e968 100644
--- a/.docs/system-services-upload.md
+++ b/.docs/api/upload-service.md
@@ -2,8 +2,6 @@
 author: Martin Weise
 ---
 
-# Upload Service
-
 ## tl;dr
 
 !!! debug "Debug Information"
@@ -44,7 +42,7 @@ If your deployment is secured with SSL/TLS (recommended) set the `useSsl` variab
 The Upload Service communicates internally with the [Storage Service](../system-services-storage) (c.f. [Figure 1](#fig1)).
 
 <figure id="fig1" markdown>
-![Architecture of the Upload Service](images/architecture-upload-service.svg)
+![Architecture of the Upload Service](../images/architecture-upload-service.svg)
 <figcaption>Figure 1: Architecture of the Upload Service</figcaption>
 </figure>
 
diff --git a/.docs/concepts/authentication.md b/.docs/concepts/authentication.md
new file mode 100644
index 0000000000000000000000000000000000000000..5919b257239af3cb464bc54271037b179d418727
--- /dev/null
+++ b/.docs/concepts/authentication.md
@@ -0,0 +1,15 @@
+---
+author: Martin Weise
+---
+
+## Bearer Authentication
+
+TBD
+
+## Basic Authentication
+
+TBD
+
+## OpenID Connect (OIDC)
+
+TBD
\ No newline at end of file
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>
+![Data ingest](../images/data-ingest.svg)
+<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/index.md b/.docs/concepts/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..8aa7e58597cac0a23dd1adba87227aea200649f2
--- /dev/null
+++ b/.docs/concepts/index.md
@@ -0,0 +1,16 @@
+---
+author: Martin Weise
+---
+
+This is the full system description from a technical/developer view and continuously being updated as the development
+progresses. 
+
+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/messaging.md b/.docs/concepts/messaging.md
new file mode 100644
index 0000000000000000000000000000000000000000..448c7a3f63071e0ce8fc0597b8d06e061e519eeb
--- /dev/null
+++ b/.docs/concepts/messaging.md
@@ -0,0 +1,15 @@
+---
+author: Martin Weise
+---
+
+## Tuple
+
+TBD
+
+## AMQP
+
+TBD
+
+## MQTT
+
+TBD
\ No newline at end of file
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/concepts/pid.md b/.docs/concepts/pid.md
new file mode 100644
index 0000000000000000000000000000000000000000..c5d769192cc561add9f9bba795e8ff78f9edd196
--- /dev/null
+++ b/.docs/concepts/pid.md
@@ -0,0 +1,7 @@
+---
+author: Martin Weise
+---
+
+## tbd
+
+tbd
diff --git a/.docs/concepts/search.md b/.docs/concepts/search.md
new file mode 100644
index 0000000000000000000000000000000000000000..8ae41c80ba2566dce997eed8ac4052b0cfa23631
--- /dev/null
+++ b/.docs/concepts/search.md
@@ -0,0 +1,13 @@
+---
+author: Martin Weise
+---
+
+## Index
+
+TBD
+
+## Document
+
+TBD
+
+## Query
\ No newline at end of file
diff --git a/.docs/concepts/storage.md b/.docs/concepts/storage.md
new file mode 100644
index 0000000000000000000000000000000000000000..fcc975fab2f20d4f3b3b6b0ebd69b02168227bc1
--- /dev/null
+++ b/.docs/concepts/storage.md
@@ -0,0 +1,15 @@
+---
+author: Martin Weise
+---
+
+## S3
+
+TBD
+
+## Sidecar
+
+TBD
+
+## Upload
+
+TBD
\ No newline at end of file
diff --git a/.docs/concepts/ui.md b/.docs/concepts/ui.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab6848b7ba251bde381c81af5fd8fb0b03293910
--- /dev/null
+++ b/.docs/concepts/ui.md
@@ -0,0 +1,21 @@
+---
+author: Martin Weise
+---
+
+It provides a graphical interface for a researcher to interact with the API (c.f. Figure 1). 
+
+<figure markdown>
+![User Interface](../images/screenshots/ui.png){ .img-border }
+<figcaption>Figure 1: User Interface</figcaption>
+</figure>
+
+For examples on how to use the User Interface, visit the [API](../api/) page to find out how to create
+users, databases and how to import your data.
+
+## Server / Client
+
+TBD
+
+## Cache
+
+TBD
\ No newline at end of file
diff --git a/.docs/dev-guide-app.md b/.docs/contributing.md
similarity index 91%
rename from .docs/dev-guide-app.md
rename to .docs/contributing.md
index 6d20ae5065bf8bd52555dcb0869ad9c4096f9ebe..259fcae55b1c3cd91ab9e55ce346db3953709876 100644
--- a/.docs/dev-guide-app.md
+++ b/.docs/contributing.md
@@ -1,4 +1,8 @@
-# Application Developer Guide
+---
+author: Martin Weise
+---
+
+We welcome contributions to DBRepo!
 
 ## Dependencies
 
@@ -104,4 +108,11 @@ repository.
 
 ## Documentation
 
-For consistency reasons across the documentation, the resolution needs to be 1280x800 (16:10 ratio)
\ No newline at end of file
+For consistency reasons across the documentation, the resolution needs to be 1280x800 (16:10 ratio)
+
+## Roadmap
+
+- [x] Q1: Python library, versioning in every component, bumping frontend versions, i18n
+- [ ] Q2: Kubernetes deployment guidelines for OpenShift
+- [ ] Q3: Frontend tests, database dashboards
+- [ ] Q4: Release of 2.0.0
diff --git a/.docs/deployment-helm.md b/.docs/deployment-helm.md
index 59835476e760e824a2cf8e7ebd1cd12dfadf32fe..745ad87b944da4afde11fff736e984ecc860f90c 100644
--- a/.docs/deployment-helm.md
+++ b/.docs/deployment-helm.md
@@ -2,6 +2,8 @@
 author: Martin Weise
 ---
 
+[![Helm Chart version](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/dbrepo)](https://artifacthub.io/packages/helm/dbrepo/dbrepo){ tabindex=-1 }
+
 ## TL;DR
 
 To install DBRepo in your existing cluster, download the
diff --git a/.docs/dev-guide-infra.md b/.docs/dev-guide-infra.md
deleted file mode 100644
index cb01a76473d24e18a2bcbcbe444912be10890b02..0000000000000000000000000000000000000000
--- a/.docs/dev-guide-infra.md
+++ /dev/null
@@ -1,78 +0,0 @@
-# Infrastructure Developer Guide
-
-## tl;dr
-
-```shell
-make cluster-start cluster-image-pull cluster-install
-```
-
-## Dependencies
-
-Local development depends on the following packages for Debian 12:
-
-```shell
-apt install -y make
-```
-
-Required tools with their own installing guides:
-
-* [Docker Engine](https://docs.docker.com/engine/install/) 24+
-* [Minikube](https://minikube.sigs.k8s.io/docs/start/) 1.32.0
-
-## Getting Started
-
-Start the local development cluster with the Docker driver (takes at least 8 vCPUs and 12GB RAM). It installs a Minikube
-single-node Kubernetes cluster with enabled Ingress and Dashboard
-
-```shell
-make cluster-start
-```
-
-Build the local images with `make build-docker` and copy them to the cluster image cache:
-
-```shell
-make cluster-image-pull
-```
-
-Build and install the Helm chart:
-
-```shell
-make cluster-install
-```
-
-## Debug
-
-Open the Minikube (Kubernetes) Dashboard:
-
-```shell
-make cluster-dashboard
-```
-
-<figure markdown>
-![Minikube Dashboard](images/screenshots/minikube-dashboard.png)
-<figcaption>Figure 1: Minikube Dashboard</figcaption>
-</figure>
-
-Optionally enable the Prometheus metrics addon with:
-
-```shell
-minikube addons enable metrics-server
-```
-
-## Test
-
-Test if the Helm chart raises errors on start (the script aborts after 5 minutes automatically if some pods are not
-starting or erroneous).
-
-```shell
-make cluster-test
-```
-
-## Uninstall
-
-To uninstall DBRepo from the local Minikube cluster, removing all data:
-
-```shell
-make cluster-uninstall
-```
-
diff --git a/.docs/dev-overview.md b/.docs/dev-overview.md
deleted file mode 100644
index e7c0e808b9589164e50032d9ffaeb52aa6ae93d6..0000000000000000000000000000000000000000
--- a/.docs/dev-overview.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Overview
-
-## Guides
-
-* The [application developer guide](../dev-guide-app) guides you through the steps on how to build DBRepo from
-  scratch and customize the application.
-* The [infrastructure developer guide](../dev-guide-infra) guides you through the steps on how to build and customize
-  the operation environment.
-
-## Organization
-
-* Monthly sprints with patch-releases (i.e. `1.4.2` in February, `1.4.3` in March, ...).
-* Branching from `dev` for feature development, one release branch per patch (i.e. `release-1.4.2` for release version
-  `1.4.2`).
-
-## Roadmap
-
-- [x] Q1: Python library, versioning in every component, bumping frontend versions, i18n
-- [ ] Q2: Kubernetes deployment guidelines for OpenShift
-- [ ] Q3: Frontend tests, database dashboards
-- [ ] Q4: Release of 2.0.0
\ No newline at end of file
diff --git a/.docs/examples/covid19.md b/.docs/examples/covid19.md
new file mode 100644
index 0000000000000000000000000000000000000000..e5db773195075167bb353d473777fa56916ca52a
--- /dev/null
+++ b/.docs/examples/covid19.md
@@ -0,0 +1,21 @@
+---
+author: Martin Weise
+---
+
+## tl;dr
+
+tbd
+
+## Description
+
+TBD
+
+## Solution
+
+TBD
+
+## DBRepo Features
+
+- [x] Large Dataset &#8776;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
new file mode 100644
index 0000000000000000000000000000000000000000..074c413d31f3f5e1d590d2491c6562677ee75a39
--- /dev/null
+++ b/.docs/examples/influenza.md
@@ -0,0 +1,21 @@
+---
+author: Martin Weise
+---
+
+## tl;dr
+
+tbd
+
+## Description
+
+TBD
+
+## Solution
+
+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
new file mode 100644
index 0000000000000000000000000000000000000000..f3eb32600f44a77f046865f6da212212a0bfdc08
--- /dev/null
+++ b/.docs/examples/manufacturing.md
@@ -0,0 +1,19 @@
+---
+author: Martin Weise
+---
+
+## tl;dr
+
+tbd
+
+## Description
+
+TBD
+
+## Solution
+
+TBD
+
+## DBRepo Features
+
+- [x] TBD
diff --git a/.docs/examples/power.md b/.docs/examples/power.md
new file mode 100644
index 0000000000000000000000000000000000000000..ea16727536bd48046e09d1a0fcdba5e5eaf95359
--- /dev/null
+++ b/.docs/examples/power.md
@@ -0,0 +1,21 @@
+---
+author: Martin Weise
+---
+
+## tl;dr
+
+tbd
+
+## Description
+
+TBD
+
+## Solution
+
+TBD
+
+## DBRepo Features
+
+- [x] High-throughput real-time data import (MQTT)
+- [x] Private database
+- [x] Public embargoed data view
diff --git a/.docs/examples/transportation.md b/.docs/examples/transportation.md
new file mode 100644
index 0000000000000000000000000000000000000000..0aedca2e37ba1bd4b45c6a86398e06d0c568fe17
--- /dev/null
+++ b/.docs/examples/transportation.md
@@ -0,0 +1,11 @@
+---
+author: Martin Weise
+---
+
+## Description
+
+TBD
+
+## Solution
+
+TBD
\ No newline at end of file
diff --git a/.docs/help.md b/.docs/help.md
new file mode 100644
index 0000000000000000000000000000000000000000..eaecbe6b0461a18320f9572bb408728e110281d2
--- /dev/null
+++ b/.docs/help.md
@@ -0,0 +1,11 @@
+---
+author: Martin Weise
+---
+
+## Concepts Documentation
+
+The [concepts documentation](../concepts/) is the most complete guide on how to use DBRepo.
+
+## API Documentation
+
+The [API documentation](../api/) present reference docs for all APIs.
diff --git a/.docs/images/logos.png b/.docs/images/logos.png
new file mode 100644
index 0000000000000000000000000000000000000000..79a5217434fc65a287962c83f6376550b9c2a6a6
Binary files /dev/null and b/.docs/images/logos.png differ
diff --git a/.docs/images/logos.psd b/.docs/images/logos.psd
index f6448014226ff1f39204b9e737fd5748f05128da..c91a87138faa69baf7b66a934035d97438b4c12d 100644
Binary files a/.docs/images/logos.psd and b/.docs/images/logos.psd differ
diff --git a/.docs/index.md b/.docs/index.md
index 4eb23f9e8a289ce59f601c27dab907d6bd78e48d..aa65b7d9396b0390a68ef2e6bddedb5b5cb397b6 100644
--- a/.docs/index.md
+++ b/.docs/index.md
@@ -1,55 +1,36 @@
 ---
 author: Martin Weise
-hide:
-- navigation
-social:
-  cards_layout_options:
-    title: Documentation that simply works
 ---
 
-## Problem Statement
+[![CI/CD Pipeline](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/badges/master/pipeline.svg)](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services){ tabindex=-1 }
+[![Code Coverage](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/badges/master/coverage.svg)](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services){ tabindex=-1 }
+[![GitLab Release](https://img.shields.io/gitlab/v/release/fair-data-austria-db-repository%2Ffda-services?gitlab_url=https%3A%2F%2Fgitlab.phaidra.org&display_name=release&style=flat&cacheSeconds=3600)](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services){ tabindex=-1 }
+[![GitLab License](https://img.shields.io/gitlab/license/fair-data-austria-db-repository%2Ffda-services?gitlab_url=https%3A%2F%2Fgitlab.phaidra.org%2F&style=flat&cacheSeconds=3600)](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services){ tabindex=-1 }
 
-Digital repositories see themselves more frequently encountered with the problem of making databases accessible in their
-collection. Challenges revolve around organizing, searching and retrieving content stored within databases and
-constitute a major technical burden as their internal representation greatly differs from static documents most digital
-repositories are designed for.
+Documentation for version: [v1.4.4](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/releases).
 
-## Application Areas
+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.
 
-We present a database repository system that allows researchers to ingest data into a central, versioned repository
-through common interfaces, provides efficient access to arbitrary subsets of data even when the underlying data store is
-evolving, allows reproducing of query results and supports findable-, accessible-, interoperable- and reusable data.
+## Why use DBRepo?
 
-## Features
+* **Built-in search** makes your dataset searchable without extra effort: most metadata is generated 
+  automatically for data in your databases.
+* **Citable datasets** adopting the recommendations of the RDA-WGDC, arbitrary subsets can be precisely, persistently 
+  identified using system-versioned tables of MariaDB and the DataCite schema for minting DOIs.
+* **Powerful API for Data Scientists** with our strongly typed Python Library, Data Scientists can import, export and
+  work with data from Jupyter Notebook or Python script, optionally using Pandas DataFrames.
+* **Cloud Native** our lightweight Helm chart allows for installations on any cloud provider or private-cloud setting 
+  that has an underlying PV storage provider.
 
-### Built-in search
+Installing DBRepo is very easy or
+[give it a try online](https://test.dbrepo.tuwien.ac.at){ target="_blank" }.
 
-DBRepo makes your dataset searchable without extra effort: most metadata is generated automatically for data in your 
-databases. The fast and powerful OpenSearch database allows a fast retrieval of any information. Adding semantic mapping
-through a suggestion-feature, allows machines to properly understand the context of your data. [Learn more.](../system-services-search/)
+## Who is using DBRepo?
 
-### Citable datasets
+![Logos of DBRepo adopters](../images/logos.png)
 
-Adopting the recommendations of the RDA-WGDC, arbitrary subsets can be precisely, persistently identified using
-system-versioned tables of MariaDB and the DataCite schema for minting DOIs. External systems i.e. metadata harvesters
-(OpenAIRE, Google Datasets) can access these datasets through OAI-PMH, JSON-LD and FAIR Signposting protocols.
-[Learn more.](../system-services-metadata/)
+## How can I try DBRepo
 
-### Powerful API for Data Scientists
-
-With our strongly typed Python Library, Data Scientists can import, export and work with data from Jupyter Notebook or
-Python script, optionally using Pandas DataFrames. For example: the AMQP API Client can collect continuous data from
-edge devices like sensors and store them asynchronous in DBRepo. [Learn more.](../usage-python/)
-
-### Cloud Native
-
-Our lightweight Helm chart allows for installations on any cloud provider or private-cloud setting that has an
-underlying PV storage provider. DBRepo can be installed from the Artifacthub repository. Databases are managed as 
-MariaDB Galera Cluster with high degree of availability ensuring your data is always accessible.
-[Learn more.](../deployment-helm/)
-
-## More Information
-
-- Demonstration instance [https://dbrepo1.ec.tuwien.ac.at](https://dbrepo1.ec.tuwien.ac.at)
-- Test instance [https://test.dbrepo.tuwien.ac.at](https://test.dbrepo.tuwien.ac.at)
-- System description [https://doi.org/10.2218/ijdc.v17i1.825](https://doi.org/10.2218/ijdc.v17i1.825)
+[:fontawesome-solid-flask: &nbsp;Demonstration Instance](https://test.dbrepo.tuwien.ac.at){ .md-button .md-button--primary target="_blank" }
\ No newline at end of file
diff --git a/.docs/migration.md b/.docs/migration.md
new file mode 100644
index 0000000000000000000000000000000000000000..e56b88ab8b99fb4cdffc9d68c5db28703f4fdaa8
--- /dev/null
+++ b/.docs/migration.md
@@ -0,0 +1,5 @@
+---
+author: Martin Weise
+---
+
+TBD
\ No newline at end of file
diff --git a/.docs/operation-actuator.md b/.docs/operation-actuator.md
deleted file mode 100644
index 581027daf1a5a85279163154e4c9da655f95bc7a..0000000000000000000000000000000000000000
--- a/.docs/operation-actuator.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-author: Martin Weise
----
-
-# Actuators
-
-## Usage
-
-TBD documentation of all Healthiness endpoints
\ No newline at end of file
diff --git a/.docs/operation-prometheus.md b/.docs/operation-prometheus.md
deleted file mode 100644
index 8c31d0e94eb42a8f9125e22ba2acdc085e0b2d71..0000000000000000000000000000000000000000
--- a/.docs/operation-prometheus.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-author: Martin Weise
----
-
-# Prometheus
-
-## Usage
-
-TBD documentation of all prometheus metrics
diff --git a/.docs/stylesheets/.sass-cache/10990fa183107f4149f38216a4d00fe324a8131e/extra.scssc b/.docs/stylesheets/.sass-cache/10990fa183107f4149f38216a4d00fe324a8131e/extra.scssc
index af6f91ae62d67828dfbb9235363407bea6d6dd0a..c66d9e0bfba4de127388de9e8ad6f4212c1f5d36 100644
Binary files a/.docs/stylesheets/.sass-cache/10990fa183107f4149f38216a4d00fe324a8131e/extra.scssc and b/.docs/stylesheets/.sass-cache/10990fa183107f4149f38216a4d00fe324a8131e/extra.scssc differ
diff --git a/.docs/stylesheets/extra.css b/.docs/stylesheets/extra.css
index fbdf67bf13ef5c98430ac396ba255bc48a10261e..d46da35109e113a53b127c02144f072752093c20 100644
--- a/.docs/stylesheets/extra.css
+++ b/.docs/stylesheets/extra.css
@@ -1,26 +1,29 @@
 :root,
 [data-md-color-accent=indigo] {
   --md-primary-fg-color: #006699;
-  --md-accent-fg-color: #005c8a /* darken 10% */ ;
-  --md-primary-fg-color--dark: #00537c /* darken 10% */ ; }
+  --md-accent-fg-color: #005c8a;
+  /* darken 10% */
+  --md-primary-fg-color--dark: #00537c;
+  /* darken 10% */ }
 
 img.img-border {
   border: 1px solid #b3b3b3; }
 
-.md-typeset .md-button.md-button--secondary {
-  background: #ffffff; }
-  .md-typeset .md-button.md-button--secondary:focus, .md-typeset .md-button.md-button--secondary:hover {
-    color: var(--md-primary-fg-color);
-    background: #e5e5e5; }
+.md-typeset .md-button.md-button--primary {
+  color: white !important; }
+
+.md-typeset .md-button.md-button--secondary:focus, .md-typeset .md-button.md-button--secondary:hover {
+  color: var(--md-primary-fg-color--dark);
+  background: #e5e5e5; }
 
 .md-main .md-content a:not(.action-button):not([tabindex]),
 .md-main .md-content a:not(.action-button):not([tabindex]) {
-  color: var(--md-typeset-color);
+  color: var(--md-primary-fg-color);
   border-bottom: 2px solid var(--md-primary-fg-color); }
   .md-main .md-content a:not(.action-button):not([tabindex]):focus, .md-main .md-content a:not(.action-button):not([tabindex]):hover,
   .md-main .md-content a:not(.action-button):not([tabindex]):focus,
   .md-main .md-content a:not(.action-button):not([tabindex]):hover {
-    color: var(--md-typeset-color);
+    color: var(--md-primary-fg-color--dark);
     border-bottom: 2px solid var(--md-primary-fg-color--dark); }
 
 .md-banner {
diff --git a/.docs/stylesheets/extra.css.map b/.docs/stylesheets/extra.css.map
index d6ff724b3c656d7bd2b1adbcbc52ae3c96922d2d..89ef3df537a6938c967eddd72fbf28bc85756b5e 100644
--- a/.docs/stylesheets/extra.css.map
+++ b/.docs/stylesheets/extra.css.map
@@ -1,6 +1,6 @@
 {
 "version": 3,
-"mappings": "AAAA;6BAC8B;EAC5B,qBAAqB,CAAC,QAAQ;EAC9B,oBAAoB,CAAC,0BACvB;EACE,2BAA2B,CAAC,0BAC9B;;AAGA,cAAe;EACb,MAAM,EAAE,iBAAiB;;AAG3B,2CAA4C;EAC1C,UAAU,EAAE,OAAO;EAEnB,oGACQ;IACN,KAAK,EAAE,0BAA0B;IACjC,UAAU,EAAE,OAAO;;AAKvB;0DAC2D;EACzD,KAAK,EAAE,uBAAuB;EAC9B,aAAa,EAAE,oCAAoC;EAEnD;;kEACQ;IACN,KAAK,EAAE,uBAAuB;IAC9B,aAAa,EAAE,0CAA0C;;AAK7D,UAAW;EACT,gBAAgB,EAAE,gCAAgC",
+"mappings": "AAAA;6BAC8B;EAC5B,qBAAqB,CAAC,QAAQ;EAC9B,oBAAoB,CAAC,QAAQ;EAAE,gBAAgB;EAC/C,2BAA2B,CAAC,QAAQ;EAAE,gBAAgB;;AAGxD,cAAe;EACb,MAAM,EAAE,iBAAiB;;AAG3B,yCAA0C;EACxC,KAAK,EAAE,gBAAgB;;AAIvB,oGACQ;EACN,KAAK,EAAE,gCAAgC;EACvC,UAAU,EAAE,OAAO;;AAIvB;0DAC2D;EACzD,KAAK,EAAE,0BAA0B;EACjC,aAAa,EAAE,oCAAoC;EAEnD;;kEACQ;IACN,KAAK,EAAE,gCAAgC;IACvC,aAAa,EAAE,0CAA0C;;AAK7D,UAAW;EACT,gBAAgB,EAAE,gCAAgC",
 "sources": ["extra.scss"],
 "names": [],
 "file": "extra.css"
diff --git a/.docs/stylesheets/extra.scss b/.docs/stylesheets/extra.scss
index 59fee68b6e277108d3ee17079beb4de337c92701..1262644f003e901721a9b2a9c59d08ed88d4c59a 100644
--- a/.docs/stylesheets/extra.scss
+++ b/.docs/stylesheets/extra.scss
@@ -1,35 +1,34 @@
 :root,
 [data-md-color-accent=indigo] {
   --md-primary-fg-color: #006699;
-  --md-accent-fg-color: #005c8a /* darken 10% */
-;
-  --md-primary-fg-color--dark: #00537c /* darken 10% */
-;
+  --md-accent-fg-color: #005c8a; /* darken 10% */
+  --md-primary-fg-color--dark: #00537c; /* darken 10% */
 }
 
 img.img-border {
   border: 1px solid #b3b3b3;
 }
 
-.md-typeset .md-button.md-button--secondary {
-  background: #ffffff;
+.md-typeset .md-button.md-button--primary {
+  color: white !important;
+}
 
+.md-typeset .md-button.md-button--secondary {
   &:focus,
   &:hover {
-    color: var(--md-primary-fg-color);
+    color: var(--md-primary-fg-color--dark);
     background: #e5e5e5 /* darken 10% */
-  ;
   }
 }
 
 .md-main .md-content a:not(.action-button):not([tabindex]),
 .md-main .md-content a:not(.action-button):not([tabindex]) {
-  color: var(--md-typeset-color);
+  color: var(--md-primary-fg-color);
   border-bottom: 2px solid var(--md-primary-fg-color);
 
   &:focus,
   &:hover {
-    color: var(--md-typeset-color);
+    color: var(--md-primary-fg-color--dark);
     border-bottom: 2px solid var(--md-primary-fg-color--dark);
   }
 }
diff --git a/.docs/system-databases-authentication.md b/.docs/system-databases-authentication.md
deleted file mode 100644
index 42b729403f03dab8cae8a0d31ea9fbcf06e819f2..0000000000000000000000000000000000000000
--- a/.docs/system-databases-authentication.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-author: Martin Weise
----
-
-# Authentication Database
-
-## tl;dr
-
-!!! debug "Debug Information"
-
-    Image: [`bitnami/mariadb:11.2.2-debian-11-r0`](https://hub.docker.com/r/bitnami/mariadb)
-
-    * Ports: 3306/tcp
-    * JDBC: `jdbc://mariadb:<hostname>:3306`
-
-## Overview
-
-This is the database in which the [Authentication Service](../system-services-authentication) writes into. In the
-default configuration, only MariaDB is supported.
-
-## Limitations
-
-* No support for MariaDB Galera at the moment.
-
-!!! question "Do you miss functionality? Do these limitations affect you?"
-
-    We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get
-    in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming 
-    experience!
-
-## Security
-
-(none)
diff --git a/.docs/system-databases-metadata.md b/.docs/system-databases-metadata.md
deleted file mode 100644
index 4ff9980f2538fda70ba5eebfd213ec1ceee07f53..0000000000000000000000000000000000000000
--- a/.docs/system-databases-metadata.md
+++ /dev/null
@@ -1,37 +0,0 @@
----
-author: Martin Weise
----
-
-# Metadata Database
-
-## tl;dr
-
-!!! debug "Debug Information"
-
-    Image: [`dbrepo/metadata-db:__APPVERSION__`](https://hub.docker.com/r/dbrepo/metadata-db)
-
-    * Ports: 3306/tcp
-    * JDBC: `jdbc://mariadb:<hostname>:3306`
-
-It is the core component of the project. It is a relational database that contains metadata about all researcher
-database created in the database repository like column names, check expressions, value enumerations or key/value
-constraints and relevant data for citing data sets. Additionally, the concept, e.g. URI of units of measurements of
-numerical columns is stored in the Metadata Database in order to provide semantic knowledge context. We use MariaDB for
-its rich capabilities in the reference implementation.
-
-The default credentials are `root:dbrepo` for the database `fda`. Connect to the database via the JDBC connector on
-port `3306`.
-
-## Limitations
-
-(none)
-
-!!! question "Do you miss functionality? Do these limitations affect you?"
-
-    We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get
-    in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming 
-    experience!
-
-## Security
-
-(none)
diff --git a/.docs/system-databases-search.md b/.docs/system-databases-search.md
deleted file mode 100644
index 130347215b195972dd47d9d3dfaef9d63e103192..0000000000000000000000000000000000000000
--- a/.docs/system-databases-search.md
+++ /dev/null
@@ -1,45 +0,0 @@
----
-author: Martin Weise
----
-
-# Search Database
-
-## tl;dr
-
-!!! debug "Debug Information"
-
-    Image: [`dbrepo/search-db:__APPVERSION__`](https://hub.docker.com/r/dbrepo/search-db)
-
-    * Ports: 9200/tcp
-
-## Overview
-
-It processes search requests from the Gateway Service for full-text lookups in 
-the [Metadata Database](../system-databases-metadata). We use [OpenSearch](https://opensearch.org/) in the default 
-configuration and create a searchable index on all databases that is updated regularly by 
-the [Mirror Service](../system-services-mirror).
-
-All requests need to be authenticated, by default the credentials `admin:admin` are used.
-
-Please see the [Search Database Dashboard](../system-other-search-dashboard) for information how to inspect the Search
-Database more efficient.
-
-## Limitations
-
-(none)
-
-!!! question "Do you miss functionality? Do these limitations affect you?"
-
-    We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get
-    in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming 
-    experience!
-
-## Security
-
-1. Change the default credentials in the [Search Database Dashboard](../system-other-search-dashboard) with the default
-   credentials `admin:admin` and navigate to your username on the top right and click "Reset password".
-
-<figure markdown>
-   ![Data ingest](images/opensearch-dashboards-reset-pw.png){ .img-border }
-   <figcaption>Reset the admin password in Opensearch Dashboards</figcaption>
-</figure>
diff --git a/.docs/system-other-search-dashboard.md b/.docs/system-other-search-dashboard.md
deleted file mode 100644
index dd23d56c6784a6765f2b9b403632a209ac045932..0000000000000000000000000000000000000000
--- a/.docs/system-other-search-dashboard.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-author: Martin Weise
----
-
-# Search Database Dashboard
-
-## tl;dr
-
-!!! debug "Debug Information"
-
-    Image: [`opensearchproject/opensearch-dashboards:2.10.0`](https://hub.docker.com/r/opensearchproject/opensearch-dashboards)
-
-    * Ports: 5601/tcp
-    * UI: `http://<hostname>/admin/dashboard/`
-
-## Overview
-
-It provides a *graphical user interface* (GUI) for an administrator to interact with 
-the [Search Database](../system-databases-search).
-
-<figure markdown>
-   ![Data ingest](images/opensearch-dashboards.png){ .img-border }
-   <figcaption>Opensearch Dashboards on first start</figcaption>
-</figure>
-
-## Limitations
-
-(none)
-
-!!! question "Do you miss functionality? Do these limitations affect you?"
-
-    We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get
-    in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming 
-    experience!
-
-## Security
-
-(none)
diff --git a/.docs/system-overview.md b/.docs/system-overview.md
deleted file mode 100644
index 12b6553820e14feae108f51e4ce0649d81227e66..0000000000000000000000000000000000000000
--- a/.docs/system-overview.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-author: Martin Weise
----
-
-# System
-
-!!! abstract "Abstract"
-
-    This is the full system description from a technical/developer view and continously being updated as the development
-    progresses.
-
-## Usage
-
-<figure markdown>
-![Data ingest](images/data-ingest.svg)
-<figcaption>Figure 1: Modes of data ingest</figcaption>
-</figure>
-
-More [usage examples](../usage-overview/) include how to ingest datasets, data dumps, live data, etc.
-
-## Limitations
-
-!!! question "Do you miss functionality? Do these limitations affect you?"
-
-    We strongly encourage you to help us implement it as we are welcoming contributors to open-source software and get
-    in [contact](../contact) with us, we happily answer requests for collaboration with attached CV and your programming 
-    experience!
\ No newline at end of file
diff --git a/.docs/why.md b/.docs/why.md
new file mode 100644
index 0000000000000000000000000000000000000000..1e6e52cc7f2d0c932fd5640cdfde752d48862e30
--- /dev/null
+++ b/.docs/why.md
@@ -0,0 +1,50 @@
+---
+author: Martin Weise
+---
+
+## Why use DBRepo?
+
+Digital repositories see themselves more frequently encountered with the problem of making databases accessible in their
+collection. Challenges revolve around organizing, searching and retrieving content stored within databases and
+constitute a major technical burden as their internal representation greatly differs from static documents most digital
+repositories are designed for.
+
+## Application Areas
+
+We present a database repository system that allows researchers to ingest data into a central, versioned repository
+through common interfaces, provides efficient access to arbitrary subsets of data even when the underlying data store is
+evolving, allows reproducing of query results and supports findable-, accessible-, interoperable- and reusable data.
+
+## Features
+
+### Built-in search
+
+DBRepo makes your dataset searchable without extra effort: most metadata is generated automatically for data in your 
+databases. The fast and powerful OpenSearch database allows a fast retrieval of any information. Adding semantic mapping
+through a suggestion-feature, allows machines to properly understand the context of your data. [Learn more.](../system-services-search/)
+
+### Citable datasets
+
+Adopting the recommendations of the RDA-WGDC, arbitrary subsets can be precisely, persistently identified using
+system-versioned tables of MariaDB and the DataCite schema for minting DOIs. External systems i.e. metadata harvesters
+(OpenAIRE, Google Datasets) can access these datasets through OAI-PMH, JSON-LD and FAIR Signposting protocols.
+[Learn more.](../system-services-metadata/)
+
+### Powerful API for Data Scientists
+
+With our strongly typed Python Library, Data Scientists can import, export and work with data from Jupyter Notebook or
+Python script, optionally using Pandas DataFrames. For example: the AMQP API Client can collect continuous data from
+edge devices like sensors and store them asynchronous in DBRepo. [Learn more.](../usage-python/)
+
+### Cloud Native
+
+Our lightweight Helm chart allows for installations on any cloud provider or private-cloud setting that has an
+underlying PV storage provider. DBRepo can be installed from 
+the [Artifact Hub](https://artifacthub.io/packages/helm/dbrepo/dbrepo) repository. Databases are managed as MariaDB
+Galera Cluster with high degree of availability ensuring your data is always accessible.
+[Learn more.](../deployment-helm/)
+
+## Demo Site
+
+We run a small demonstration instance so you can see the latest version of DBRepo in action. The demonstration instance
+is updated with new releases and should be considered ephemeral.
\ 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 0e3043113a6df2bdea8dc69a8760671cec9d1c37..de1ca37a4d5ac444ddb527a86e041d5868bf1e4b 100644
--- a/dbrepo-analyse-service/app.py
+++ b/dbrepo-analyse-service/app.py
@@ -132,11 +132,11 @@ app.config["AUTH_SERVICE_CLIENT"] = os.getenv("AUTH_SERVICE_CLIENT", "dbrepo")
 app.config["AUTH_SERVICE_CLIENT_SECRET"] = os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG")
 app.config["ADMIN_USERNAME"] = os.getenv('ADMIN_USERNAME', 'admin')
 app.config["ADMIN_PASSWORD"] = os.getenv('ADMIN_PASSWORD', 'admin')
-app.config["S3_ENDPOINT"] = os.getenv('S3_ENDPOINT', 'http://localhost:9000')
 app.config["S3_ACCESS_KEY_ID"] = os.getenv('S3_ACCESS_KEY_ID', 'seaweedfsadmin')
-app.config["S3_SECRET_ACCESS_KEY"] = os.getenv('S3_SECRET_ACCESS_KEY', 'seaweedfsadmin')
+app.config["S3_ENDPOINT"] = os.getenv('S3_ENDPOINT', 'http://localhost:9000')
 app.config["S3_EXPORT_BUCKET"] = os.getenv('S3_EXPORT_BUCKET', 'dbrepo-download')
 app.config["S3_IMPORT_BUCKET"] = os.getenv('S3_IMPORT_BUCKET', 'dbrepo-upload')
+app.config["S3_SECRET_ACCESS_KEY"] = os.getenv('S3_SECRET_ACCESS_KEY', 'seaweedfsadmin')
 
 app.json_encoder = LazyJSONEncoder
 
@@ -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/clients/s3_client.py b/dbrepo-analyse-service/clients/s3_client.py
index 22f21966b73fe4c91e28db666ca002d1d3d4cdfe..5e8f3bb4378f7c448cf9722f63a27e91fb3e9f39 100644
--- a/dbrepo-analyse-service/clients/s3_client.py
+++ b/dbrepo-analyse-service/clients/s3_client.py
@@ -20,7 +20,7 @@ class S3Client:
         self.bucket_exists_or_exit(current_app.config['S3_EXPORT_BUCKET'])
         self.bucket_exists_or_exit(current_app.config['S3_IMPORT_BUCKET'])
 
-    def upload_file(self, filename: str, path: str = "/tmp/", bucket: str = "dbrepo-upload") -> bool:
+    def upload_file(self, filename: str, path: str = "/tmp", bucket: str = "dbrepo-upload") -> bool:
         """
         Uploads a file to the blob storage.
         Follows the official API https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html.
@@ -43,15 +43,16 @@ class S3Client:
             logging.warning(f"Failed to upload file with key {filename}")
             raise ConnectionRefusedError(f"Failed to upload file with key {filename}", e)
 
-    def download_file(self, filename: str, bucket: str):
+    def download_file(self, filename: str, path: str = "/tmp", bucket: str = "dbrepo-download"):
         """
         Downloads a file from the blob storage.
         Follows the official API https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-example-download-file.html
         :param filename: The filename.
+        :param path: The path the file is located.
         :param bucket: The bucket to download the file from.
         """
         self.file_exists(bucket, filename)
-        filepath = os.path.join("/tmp/", filename)
+        filepath = os.path.join(path, filename)
         self.client.download_file(bucket, filename, filepath)
         logging.info(f"Downloaded .csv with key {filename} into {filepath}")
 
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 ffca4d3753d09ed300820fc8163920bd0c1dc7fd..f4342301dfed6a16dc21a60db21c1d0272b07061 100644
--- a/dbrepo-data-db/sidecar/app.py
+++ b/dbrepo-data-db/sidecar/app.py
@@ -121,14 +121,16 @@ app.config["AUTH_SERVICE_CLIENT"] = os.getenv("AUTH_SERVICE_CLIENT", "dbrepo-cli
 app.config["AUTH_SERVICE_CLIENT_SECRET"] = os.getenv("AUTH_SERVICE_CLIENT_SECRET", "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG")
 app.config["ADMIN_USERNAME"] = os.getenv('ADMIN_USERNAME', 'admin')
 app.config["ADMIN_PASSWORD"] = os.getenv('ADMIN_PASSWORD', 'admin')
-app.config["S3_ENDPOINT"] = os.getenv('S3_ENDPOINT', 'http://localhost:9000')
 app.config["S3_ACCESS_KEY_ID"] = os.getenv('S3_ACCESS_KEY_ID', 'seaweedfsadmin')
-app.config["S3_SECRET_ACCESS_KEY"] = os.getenv('S3_SECRET_ACCESS_KEY', 'seaweedfsadmin')
+app.config["S3_ENDPOINT"] = os.getenv('S3_ENDPOINT', 'http://localhost:9000')
 app.config["S3_EXPORT_BUCKET"] = os.getenv('S3_EXPORT_BUCKET', 'dbrepo-download')
+app.config["S3_FILE_PATH"] = os.getenv('S3_FILE_PATH', '/tmp')
+app.config["S3_SECRET_ACCESS_KEY"] = os.getenv('S3_SECRET_ACCESS_KEY', 'seaweedfsadmin')
 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 == "":
@@ -176,25 +178,27 @@ 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):
     auth.current_user()
     logging.debug('endpoint import csv, filename=%s, body=%s', filename, request)
     s3_client = S3Client()
-    response = s3_client.download_file(filename)
+    response = s3_client.download_file(filename, app.config["S3_FILE_PATH"], app.config['S3_IMPORT_BUCKET'])
     if response is False:
         return Response(), 400
     return Response(json.dumps(response)), 202
 
 
 @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):
     logging.debug('endpoint export csv, filename=%s, body=%s', filename, request)
     s3_client = S3Client()
-    response = s3_client.upload_file(filename)
+    response = s3_client.upload_file(filename, app.config["S3_FILE_PATH"], app.config['S3_EXPORT_BUCKET'])
     if response is False:
         return Response(), 400
     return Response(), 202
diff --git a/dbrepo-data-db/sidecar/clients/s3_client.py b/dbrepo-data-db/sidecar/clients/s3_client.py
index 135654da70d47b22d5d38edf6de19a34ba204f51..547a1c3a30d5dce07000a49852aef04673163de1 100644
--- a/dbrepo-data-db/sidecar/clients/s3_client.py
+++ b/dbrepo-data-db/sidecar/clients/s3_client.py
@@ -20,32 +20,35 @@ class S3Client:
         self.bucket_exists_or_exit(current_app.config['S3_IMPORT_BUCKET'])
         self.bucket_exists_or_exit(current_app.config['S3_EXPORT_BUCKET'])
 
-    def upload_file(self, filename) -> bool:
+    def upload_file(self, filename, path, bucket) -> bool:
         """
         Uploads a file to the blob storage.
         Follows the official API https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html.
         :param filename: The filename.
+        :param path: The path.
+        :param bucket: The bucket.
         :return: True if the file was uploaded.
         """
-        filepath = os.path.join("/tmp/", filename)
+        filepath = os.path.join(path, filename)
         try:
-            self.client.upload_file(filepath, current_app.config['S3_EXPORT_BUCKET'], filename)
-            logging.info(f"Uploaded .csv {filepath} with key {filename} into bucket dbrepo-download")
+            self.client.upload_file(filepath, bucket, filename)
+            logging.info(f"Uploaded .csv {filepath} with key {filename} into bucket {bucket}")
             return True
         except ClientError as e:
             logging.error(e)
             return False
 
-    def download_file(self, filename) -> bool:
+    def download_file(self, filename, path, bucket) -> bool:
         """
         Downloads a file from the blob storage.
         Follows the official API https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-example-download-file.html
         :param filename: The filename.
+        :param path: The path.
+        :param bucket: The bucket.
         :return: True if the file was downloaded and saved.
         """
-        self.file_exists(current_app.config['S3_IMPORT_BUCKET'], filename)
-        filepath = os.path.join("/tmp/", filename)
-        bucket = current_app.config['S3_IMPORT_BUCKET']
+        self.file_exists(bucket, filename)
+        filepath = os.path.join(path, filename)
         try:
             self.client.download_file(bucket, filename, filepath)
             logging.info(f"Downloaded .csv with key {filename} into {filepath} from bucket {bucket}")
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 819f9d0f08bc3c588787ce0618f711e977e3dc07..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
@@ -57,6 +57,7 @@ dbrepo:
     secretAccessKey: seaweedfsadmin
     importBucket: dbrepo-upload
     exportBucket: dbrepo-download
+    filePath: /tmp
   admin:
     username: admin
     password: admin
@@ -67,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 8bb8fe43f19bd4cefb3927c1192ce11f7b2c8cfc..44daf91e46c603ae27ee7780e4ecc62de90b5339 100644
--- a/dbrepo-data-service/rest-service/src/main/resources/application.yml
+++ b/dbrepo-data-service/rest-service/src/main/resources/application.yml
@@ -58,6 +58,7 @@ dbrepo:
     secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}"
     importBucket: "${S3_IMPORT_BUCKET:dbrepo-upload}"
     exportBucket: "${S3_EXPORT_BUCKET:dbrepo-download}"
+    filePath: "${S3_FILE_PATH:/tmp}"
   admin:
     username: "${ADMIN_USERNAME:admin}"
     password: "${ADMIN_PASSWORD:admin}"
@@ -80,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/config/S3Config.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/S3Config.java
index 763505b933dd62259b95745e2059dea0c3edc9c6..8adaf38d19ba81ae61a54a57988dd1c08910a09b 100644
--- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/S3Config.java
+++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/S3Config.java
@@ -33,6 +33,9 @@ public class S3Config {
     @Value("${dbrepo.s3.exportBucket}")
     private String s3ExportBucket;
 
+    @Value("${dbrepo.s3.filePath}")
+    private String s3FilePath;
+
     @Bean
     public S3Client s3client() {
         final AwsCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(
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 2bac11bd4f770a02fea20d6c7f037c49364a1df7..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);
@@ -369,7 +429,7 @@ public interface MariaDbMapper {
     }
 
     default String tableOrViewToRawExportQuery(String databaseName, String tableOrView, List<ColumnDto> columns,
-                                               Instant timestamp, String filename) {
+                                               Instant timestamp, String filePath) {
         final StringBuilder statement = new StringBuilder("SELECT ");
         int[] idx = new int[]{0};
         columns.forEach(column -> {
@@ -399,30 +459,60 @@ public interface MariaDbMapper {
                     .append(mariaDbFormatter.format(timestamp))
                     .append("'");
         }
-        statement.append(" INTO OUTFILE '/tmp/")
-                .append(filename)
+        statement.append(" INTO OUTFILE '")
+                .append(filePath)
                 .append("' CHARACTER SET utf8 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"';");
         statement.append(";");
         log.debug("mapped table/view export query: {}", statement);
         return statement.toString();
     }
 
-    default String subsetToRawExportQuery(String query, Instant timestamp, String filename) {
+    default String subsetToRawExportQuery(String query, Instant timestamp, String filePath) {
         final StringBuilder statement = new StringBuilder(query.replaceAll(";", ""))
                 .append(" FOR SYSTEM_TIME AS OF TIMESTAMP'")
                 .append(mariaDbFormatter.format(timestamp))
                 .append("'")
-                .append(" INTO OUTFILE '/tmp/")
-                .append(filename)
+                .append(" INTO OUTFILE '")
+                .append(filePath)
                 .append("' CHARACTER SET utf8 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"';");
         log.debug("mapped export query: {}", statement);
         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<>();
@@ -507,7 +679,7 @@ public interface MariaDbMapper {
     }
 
     default String datasetToRawInsertQuery(String databaseName, PrivilegedTableDto table, ImportCsvDto data) {
-        final StringBuilder statement = new StringBuilder("LOAD DATA INFILE '/tmp/")
+        final StringBuilder statement = new StringBuilder("LOAD DATA INFILE '")
                 .append(data.getLocation())
                 .append("' REPLACE INTO TABLE `")
                 .append(databaseName)
@@ -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/SubsetServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java
index 4df35be00b62a662f56bd88b6193f1bef20bef6d..57d7472dde490ae39143ca04fd255454e7c3b724 100644
--- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java
+++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java
@@ -10,6 +10,7 @@ import at.tuwien.api.database.table.columns.ColumnDto;
 import at.tuwien.api.identifier.IdentifierDto;
 import at.tuwien.api.identifier.IdentifierTypeDto;
 import at.tuwien.api.user.UserDto;
+import at.tuwien.config.S3Config;
 import at.tuwien.exception.*;
 import at.tuwien.gateway.DataDatabaseSidecarGateway;
 import at.tuwien.gateway.MetadataServiceGateway;
@@ -33,6 +34,7 @@ import java.util.UUID;
 @Service
 public class SubsetServiceMariaDbImpl extends HibernateConnector implements SubsetService {
 
+    private final S3Config s3Config;
     private final MariaDbMapper mariaDbMapper;
     private final MetadataMapper metadataMapper;
     private final StorageService storageService;
@@ -40,9 +42,10 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
     private final DataDatabaseSidecarGateway dataDatabaseSidecarGateway;
 
     @Autowired
-    public SubsetServiceMariaDbImpl(MariaDbMapper mariaDbMapper, MetadataMapper metadataMapper,
+    public SubsetServiceMariaDbImpl(S3Config s3Config, MariaDbMapper mariaDbMapper, MetadataMapper metadataMapper,
                                     StorageService storageService, MetadataServiceGateway metadataServiceGateway,
                                     DataDatabaseSidecarGateway dataDatabaseSidecarGateway) {
+        this.s3Config = s3Config;
         this.mariaDbMapper = mariaDbMapper;
         this.metadataMapper = metadataMapper;
         this.storageService = storageService;
@@ -146,11 +149,12 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
     public ExportResourceDto export(PrivilegedDatabaseDto database, QueryDto query, Instant timestamp, String filename)
             throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException,
             StorageUnavailableException {
+        final String filePath = s3Config.getS3FilePath() + "/" + filename;
         final ComboPooledDataSource dataSource = getPrivilegedDataSource(database);
         final Connection connection = dataSource.getConnection();
         try {
             /* export to data database sidecar */
-            connection.prepareStatement(mariaDbMapper.subsetToRawExportQuery(query.getQuery(), timestamp, filename))
+            connection.prepareStatement(mariaDbMapper.subsetToRawExportQuery(query.getQuery(), timestamp, filePath))
                     .executeUpdate();
             connection.commit();
         } catch (SQLException e) {
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 32eaaf953332842a93a75c12e90c9f5d55495dbb..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
@@ -9,9 +9,11 @@ import at.tuwien.api.database.table.columns.ColumnDto;
 import at.tuwien.api.database.table.columns.ColumnTypeDto;
 import at.tuwien.api.database.table.internal.PrivilegedTableDto;
 import at.tuwien.api.database.table.internal.TableCreateDto;
+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;
@@ -28,21 +30,64 @@ import java.util.*;
 @Service
 public class TableServiceMariaDbImpl extends HibernateConnector implements TableService {
 
+    private final S3Config s3Config;
     private final MariaDbMapper mariaDbMapper;
+    private final SchemaService schemaService;
     private final StorageService storageService;
     private final DataDatabaseSidecarGateway dataDatabaseSidecarGateway;
 
     @Autowired
-    public TableServiceMariaDbImpl(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();
@@ -69,6 +114,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             dataSource.close();
         }
         log.info("Created table with name {}", tableName);
+        return find(database, tableName);
     }
 
     @Override
@@ -213,6 +259,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
         final Connection connection = dataSource.getConnection();
         try {
             /* import tuple */
+            data.setLocation(s3Config.getS3FilePath() + "/" + data.getLocation());
             connection.prepareStatement(mariaDbMapper.datasetToRawInsertQuery(table.getDatabase().getInternalName(), table, data))
                     .execute();
             connection.commit();
@@ -331,13 +378,14 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
     public ExportResourceDto exportDataset(PrivilegedTableDto table, Instant timestamp)
             throws SQLException, SidecarExportException, StorageNotFoundException, StorageUnavailableException,
             QueryMalformedException {
-        final String filename = RandomStringUtils.randomAlphabetic(40) + ".csv";
+        final String fileName = RandomStringUtils.randomAlphabetic(40) + ".csv";
+        final String filePath = s3Config.getS3FilePath() + "/" + fileName;
         final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase());
         final Connection connection = dataSource.getConnection();
         try {
             /* export to data database sidecar */
             connection.prepareStatement(mariaDbMapper.tableOrViewToRawExportQuery(table.getDatabase().getInternalName(),
-                            table.getInternalName(), table.getColumns(), timestamp, filename))
+                            table.getInternalName(), table.getColumns(), timestamp, filePath))
                     .executeUpdate();
             connection.commit();
         } catch (SQLException e) {
@@ -347,8 +395,8 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
         } finally {
             dataSource.close();
         }
-        dataDatabaseSidecarGateway.exportFile(table.getDatabase().getContainer().getSidecarHost(), table.getDatabase().getContainer().getSidecarPort(), filename);
-        return storageService.getResource(filename);
+        dataDatabaseSidecarGateway.exportFile(table.getDatabase().getContainer().getSidecarHost(), table.getDatabase().getContainer().getSidecarPort(), fileName);
+        return storageService.getResource(fileName);
     }
 
 }
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 b0a66dfe0fdeea79677430d884b627d8d16b274a..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,9 +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;
@@ -16,38 +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(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();
@@ -56,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
@@ -67,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) {
@@ -105,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());
@@ -133,13 +207,18 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
     public ExportResourceDto exportDataset(PrivilegedDatabaseDto database, ViewDto view, Instant timestamp)
             throws SQLException, QueryMalformedException, SidecarExportException, StorageNotFoundException,
             StorageUnavailableException {
-        final String filename = RandomStringUtils.randomAlphabetic(40) + ".csv";
+        final String fileName = RandomStringUtils.randomAlphabetic(40) + ".csv";
+        final String filePath = s3Config.getS3FilePath() + "/" + fileName;
         final ComboPooledDataSource dataSource = getPrivilegedDataSource(database);
         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, filename))
+                            view.getInternalName(), columns, timestamp, filePath))
                     .executeUpdate();
             connection.commit();
         } catch (SQLException e) {
@@ -149,8 +228,9 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
         } finally {
             dataSource.close();
         }
-        dataDatabaseSidecarGateway.exportFile(database.getContainer().getSidecarHost(), database.getContainer().getSidecarPort(), filename);
-        return storageService.getResource(filename);
+        dataDatabaseSidecarGateway.exportFile(database.getContainer().getSidecarHost(),
+                database.getContainer().getSidecarPort(), fileName);
+        return storageService.getResource(fileName);
     }
 
 }
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 7b128e1d57292f39502cfb1e120b043b65104a0b..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:-}"
@@ -287,6 +290,7 @@ services:
       S3_ACCESS_KEY_ID: "${S3_ACCESS_KEY_ID:-seaweedfsadmin}"
       S3_ENDPOINT: "${S3_ENDPOINT:-http://storage-service:9000}"
       S3_EXPORT_BUCKET: "${S3_EXPORT_BUCKET:-dbrepo-download}"
+      S3_FILE_PATH: "${S3_FILE_PATH:-/tmp}"
       S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}"
       S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}"
     volumes:
@@ -483,7 +487,12 @@ services:
       QUEUE_NAME: ${QUEUE_NAME:-dbrepo}
       REQUEUE_REJECTED: ${REQUEUE_REJECTED:-false}
       ROUTING_KEY: "${ROUTING_KEY:-dbrepo.#}"
-      STORAGE_SERVICE_ENDPOINT: ${BROKER_SERVICE_ENDPOINT:-http://storage-service:9000}
+      S3_ACCESS_KEY_ID: "${S3_ACCESS_KEY_ID:-seaweedfsadmin}"
+      S3_ENDPOINT: "${S3_ENDPOINT:-http://storage-service:9000}"
+      S3_EXPORT_BUCKET: "${S3_EXPORT_BUCKET:-dbrepo-download}"
+      S3_FILE_PATH: "${S3_FILE_PATH:-/tmp}"
+      S3_IMPORT_BUCKET: "${S3_IMPORT_BUCKET:-dbrepo-upload}"
+      S3_SECRET_ACCESS_KEY: "${S3_SECRET_ACCESS_KEY:-seaweedfsadmin}"
     healthcheck:
       test: wget -qO- localhost:8080/actuator/health/readiness | grep -q "UP" || exit 1
       interval: 10s
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 57c1ebd1a0db7202de8918f01217909ce54652ff..b5307a23d95df9abcf06868646ddc8ac85c80e70 100644
--- a/helm/dbrepo/templates/data-secret.yaml
+++ b/helm/dbrepo/templates/data-secret.yaml
@@ -12,7 +12,7 @@ stringData:
   AUTH_SERVICE_ADMIN_PASSWORD: "{{ .Values.authservice.auth.adminPassword }}"
   AUTH_SERVICE_CLIENT: "{{ .Values.authservice.client.id }}"
   AUTH_SERVICE_CLIENT_SECRET: "{{ .Values.authservice.client.secret }}"
-  AUTH_SERVICE_ENDPOINT: "{{ .Values.authservice.endpoint }}"
+  AUTH_SERVICE_HOST: "{{ .Values.authservice.endpoint }}"
   BROKER_EXCHANGE_NAME: "{{ .Values.brokerservice.exchangeName }}"
   BROKER_HOST: "{{ .Values.brokerservice.host }}"
   BROKER_QUEUE_NAME: "{{ .Values.brokerservice.queueName }}"
@@ -26,13 +26,17 @@ 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 }}"
   MAX_CONCURRENT_CONSUMERS: "{{ .Values.dataservice.consumerConcurrentMax }}"
   REQUEUE_REJECTED: "{{ .Values.dataservice.requeueRejected }}"
-  S3_ENDPOINT: "{{ .Values.dataservice.s3.endpoint }}"
   S3_ACCESS_KEY_ID: "{{ .Values.dataservice.s3.auth.username }}"
+  S3_ENDPOINT: "{{ .Values.dataservice.s3.endpoint }}"
+  S3_EXPORT_BUCKET: "{{ .Values.dataservice.s3.bucket.export }}"
+  S3_FILE_PATH: "{{ .Values.dataservice.s3.filePath }}"
   S3_SECRET_ACCESS_KEY: "{{ .Values.dataservice.s3.auth.password }}"
   S3_IMPORT_BUCKET: "{{ .Values.dataservice.s3.bucket.import }}"
-  S3_EXPORT_BUCKET: "{{ .Values.dataservice.s3.bucket.export }}"
diff --git a/helm/dbrepo/templates/metadata-configmap.yaml b/helm/dbrepo/templates/metadata-configmap.yaml
index b0c927e9158b97bf6b147daee506465c3a536ccf..88c761643a70da48cd6032f3225ceb5459543052 100644
--- a/helm/dbrepo/templates/metadata-configmap.yaml
+++ b/helm/dbrepo/templates/metadata-configmap.yaml
@@ -4,8 +4,11 @@ apiVersion: v1
 kind: ConfigMap
 metadata:
   name: metadata-db-setup
-  namespace: {{ $.Values.namespace }}
+  namespace: {{ .Values.namespace }}
 data:
+  {{- with .Values.metadatadb.extraInitDbScripts }}
+  {{ toYaml . | nindent 2 }}
+  {{- end }}
   02-setup-data.sql: |
     BEGIN;
     INSERT INTO `mdb_containers` (name, internal_name, image_id, host, port, sidecar_host, sidecar_port, privileged_username, privileged_password)
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 3b2e12c65674aa751381cac3fccaa6f172081cf3..d15d46c305eaa829415e181694d18ccd0279f429 100644
--- a/helm/dbrepo/values.yaml
+++ b/helm/dbrepo/values.yaml
@@ -42,6 +42,7 @@ admin:
 ## @skip metadatadb.metrics.enabled The Prometheus settings.
 ## @skip metadatadb.galera The Galera settings.
 ## @skip metadatadb.initdbScriptsConfigMap The initial database scripts.
+## @param metadatadb.extraInitDbScripts Additional init.db scripts that are executed on the first start.
 ## @skip metadatadb.service The initial database scripts.
 ## @param metadatadb.persistence.enabled Enable persistent storage. Requires PV-provisioner.
 ## @param metadatadb.replicaCount The number of replicas, should be uneven (2n+1).
@@ -65,6 +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;
   service:
     type: ClusterIP
     annotations: { }
@@ -171,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
@@ -207,10 +214,10 @@ datadb:
         periodSeconds: 30
       volumeMounts:
         - name: s3
-          mountPath: /tmp
+          mountPath: /s3
   extraVolumeMounts:
     - name: s3
-      mountPath: /tmp
+      mountPath: /s3
   extraVolumes:
     - name: s3
       emptyDir: { }
@@ -429,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:
@@ -459,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:
@@ -492,10 +499,14 @@ 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).
 ## @param dataservice.s3.auth.password The S3-capable endpoint user password (or access key secret).
+## @param dataservice.s3.filePath The local location to download/upload files from/to S3-capable endpoint.
 ## @param dataservice.consumerConcurrentMin The minimum broker service consumer number.
 ## @param dataservice.consumerConcurrentMax The maximum broker service consumer number.
 ## @param dataservice.requeueRejected Enable re-queueing of rejected messages to the broker service.
@@ -505,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:
@@ -519,6 +534,7 @@ dataservice:
     auth:
       username: seaweedfsadmin
       password: seaweedfsadmin
+    filePath: /s3
   consumerConcurrentMin: 1
   consumerConcurrentMax: 5
   requeueRejected: false
@@ -536,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
 
@@ -588,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
@@ -617,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 05933f2ddd0884d22b9ad8544b6b9bee070cde9e..e4370152366f1e106cd95e23263bd62b481be5c0 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -5,44 +5,49 @@ site_author: Research Unit Data Science, Technische Universit&auml;t Wien
 copyright: CC-BY 4.0 Technische Universit&auml;t Wien & Universit&auml;t Wien
 docs_dir: .docs
 nav:
-  - Home: index.md
-  - Deployment:
-    - Docker Compose: deployment-docker-compose.md
+  - Get Started:
+    - Welcome to DBRepo: index.md
+    - Why use DBRepo: why.md
+    - Help with DBRepo: help.md
+    - Installation: deployment-docker-compose.md
     - Kubernetes: deployment-helm.md
-  - System:
-    - Overview: system-overview.md
-    - Services:
-      - Analyse Service: system-services-analyse.md
-      - Authentication Service: system-services-authentication.md
-      - Broker Service: system-services-broker.md
-      - Data Service: system-services-data.md
-      - Gateway Service: system-services-gateway.md
-      - Metadata Service: system-services-metadata.md
-      - Search Service: system-services-search.md
-      - Storage Service: system-services-storage.md
-      - Upload Service: system-services-upload.md
+    - Migration Guide: migration.md
+    - contributing.md
+  - Concepts:
+    - Overview: concepts/index.md
+    - Authentication: concepts/authentication.md
+    - Databases: concepts/databases.md
+    - Messaging: concepts/messaging.md
+    - Monitoring: concepts/monitoring.md
+    - Persistent Identifier: concepts/pid.md
+    - Search: concepts/search.md
+    - Storage: concepts/storage.md
+    - User Interface: concepts/ui.md
+  - API:
+    - Overview: api/index.md
     - Databases:
-      - Authentication Database: system-databases-authentication.md
-      - Data Database: system-databases-data.md
-      - Metadata Database: system-databases-metadata.md
-      - Search Database: system-databases-search.md
-    - Other:
-      - User Interface: system-other-ui.md
-      - Search Database Dashboard: system-other-search-dashboard.md
-    - Operation:
-      - Actuator: operation-actuator.md
-      - Prometheus: operation-prometheus.md
-  - Usage:
-    - Overview: usage-overview.md
-    - Python Library: usage-python.md
+      - Data Database: api/data-db.md
+      - Metadata Database: api/metadata-db.md
+    - SDK:
+      - Python Library: api/python.md
+      - Swagger / OpenAPI: api/open-api.md
     - Services:
-      - Authentication Service: usage-authentication.md
-      - Storage Service: usage-storage.md
-      - Upload Service: usage-upload.md
-  - Development:
-    - Overview: dev-overview.md
-    - Application Guide: dev-guide-app.md
-    - Infrastructure Guide: dev-guide-infra.md
+      - Analyse Service: api/analyse-service.md
+      - Auth Service: api/auth-service.md
+      - Data Service: api/data-service.md
+      - Gateway Service: api/gateway-service.md
+      - Metadata Service: api/metadata-service.md
+      - Search Service: api/search-service.md
+      - Storage Service: api/storage-service.md
+      - Upload Service: api/upload-service.md
+    - UI:
+      - Customization: api/ui.md
+  - Examples:
+    - COVID-19 Tweets: examples/covid19.md
+    - Influenza Monitoring: examples/influenza.md
+    - Manufacturing Data: examples/manufacturing.md
+    - Power Usage: examples/power.md
+    - Transportation Monitoring: examples/transportation.md
   - publications.md
   - contact.md
 extra_css:
diff --git a/versions.json b/versions.json
index 4378f772357e093e48e74b7a254be20bd62538fc..5eb8a9b173e23a19c4045963287d81ac6604e3ba 100644
--- a/versions.json
+++ b/versions.json
@@ -1,8 +1,13 @@
 [
+  {
+    "version": "1.4.3",
+    "title": "1.4.3",
+    "aliases": ["latest"]
+  },
   {
     "version": "1.4.2",
     "title": "1.4.2",
-    "aliases": ["latest"]
+    "aliases": []
   },
   {
     "version": "1.4.1",