diff --git a/.docs/api/data-service.md b/.docs/api/data-service.md
index 64f03976132352cea195c6c231e3cc16ebc3d54b..257c68c1957fa697957c9dfc3f6b681693ac3f9d 100644
--- a/.docs/api/data-service.md
+++ b/.docs/api/data-service.md
@@ -28,8 +28,23 @@ The Data Service is responsible for inserting AMQP tuples from the Broker Servic
 via [Spring AMQP](https://docs.spring.io/spring-amqp/reference/html/). To increase the number of consumers, scale the
 Data Service up.
 
+## Data Processing
+
+The Data Service uses [Apache Spark](https://spark.apache.org/), a data engine to load data from/into 
+the [Data Database](../data-db) with a wide range of open-source connectors. The default deployment uses a local mode of
+embedded processing directly in the service until there exists 
+a [Bitnami Chart](https://artifacthub.io/packages/helm/bitnami/spark) for Spark 4.
+
+Retrieving data from a subset internally generates a view with the 64-character hash of the query. This view is not
+automatically deleted currently.
+
 ## Limitations
 
+* Views in DBRepo can only have 63-character length (it is assumed only internal views have the maximum length of 64 
+  characters).
+* Local mode of embedded processing of Apache Spark directly in the service using 
+  a [`local[2]`](https://spark.apache.org/docs/latest/#running-the-examples-and-shell) configuration.
+
 !!! 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/api/ui.md b/.docs/api/ui.md
index 08e21b1c26e8ad6a25ca548de475c76ae82e5dc8..30b32c0a0ccde771c8bde22f21ca630d6354a9b3 100644
--- a/.docs/api/ui.md
+++ b/.docs/api/ui.md
@@ -101,7 +101,8 @@ See the [API Overview](..) page for detailed examples.
 
 ## Limitations
 
-(none)
+* When developing locally, the `axios` module does not parse custom headers (such as `X-Count`, `X-Headers`) and/or
+  blocks CORS requests wrongfully.
 
 !!! question "Do you miss functionality? Do these limitations affect you?"
 
diff --git a/.docs/changelog.md b/.docs/changelog.md
index 98a65bf4cebdc205490b2cdfd7e1e0ee72f13984..429f6933b649570531700cbf2265c43b34329c5d 100644
--- a/.docs/changelog.md
+++ b/.docs/changelog.md
@@ -2,6 +2,17 @@
 author: Martin Weise
 ---
 
+## v1.5.3 (2024-12-13)
+
+[:simple-gitlab: GitLab Release](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/tags/v1.5.3)
+
+### What's Changed
+
+#### Fixes
+
+* Fixed a bug where subsets containing sub-queries are not able to retrieve data
+  in [#476](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/issues/476).
+
 ## v1.5.2 (2024-12-03)
 
 [:simple-gitlab: GitLab Release](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/tags/v1.5.2)
diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock
index 9ed4639d1a80f49d4d191d9c89b206a6e222ab4f..36e6d6a0c21a6dd4c05493d7731b37962e02119e 100644
--- a/dbrepo-analyse-service/Pipfile.lock
+++ b/dbrepo-analyse-service/Pipfile.lock
@@ -175,20 +175,20 @@
         },
         "boto3": {
             "hashes": [
-                "sha256:5ef7166fe5060637b92af8dc152cd7acecf96b3fc9c5456706a886cadb534391",
-                "sha256:fc8001519c8842e766ad3793bde3fbd0bb39e821a582fc12cf67876b8f3cf7f1"
+                "sha256:21a3b18c3a7fd20e463708fe3fa035983105dc7f3a1c274e1903e1583ab91159",
+                "sha256:50dae461ab5fbedfb81b690895d48a918fed0d5fdff37be1c4232770c0dc9712"
             ],
             "index": "pypi",
             "markers": "python_version >= '3.8'",
-            "version": "==1.35.78"
+            "version": "==1.35.80"
         },
         "botocore": {
             "hashes": [
-                "sha256:41c37bd7c0326f25122f33ec84fb80fc0a14d7fcc9961431b0e57568e88c9cb5",
-                "sha256:6905036c25449ae8dba5e950e4b908e4b8a6fe6b516bf61e007ecb62fa21f323"
+                "sha256:36e589dccb62380abd628b08fecfa2f7c89b99f41ec9fc42c467c94008c0be4a",
+                "sha256:b8dfceca58891cb2711bd6455ec4f7159051f3796e0f64adef9bb334f19d8a92"
             ],
             "markers": "python_version >= '3.8'",
-            "version": "==1.35.78"
+            "version": "==1.35.80"
         },
         "certifi": {
             "hashes": [
@@ -397,7 +397,6 @@
                 "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b",
                 "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc",
                 "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543",
-                "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385",
                 "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c",
                 "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591",
                 "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede",
@@ -405,7 +404,6 @@
                 "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f",
                 "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123",
                 "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c",
-                "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba",
                 "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c",
                 "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285",
                 "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd",
@@ -427,7 +425,7 @@
         },
         "dbrepo": {
             "hashes": [
-                "sha256:14ffe47cb4fbe4bb1d4de392975e232ae1a93127ee3199640db146b42fa02993"
+                "sha256:6096e237ff5b00f471d88e74229952f1e5fcba8683f486952d76a9e257de35c8"
             ],
             "path": "./lib/dbrepo-1.6.0.tar.gz"
         },
@@ -1627,7 +1625,7 @@
                 "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac",
                 "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"
             ],
-            "markers": "python_version >= '3.10'",
+            "markers": "python_version >= '3.8'",
             "version": "==2.2.3"
         },
         "werkzeug": {
@@ -2264,7 +2262,7 @@
                 "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac",
                 "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"
             ],
-            "markers": "python_version >= '3.10'",
+            "markers": "python_version >= '3.8'",
             "version": "==2.2.3"
         },
         "wrapt": {
diff --git a/dbrepo-analyse-service/lib/dbrepo-1.5.3.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.5.3.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..2bb796d8fece2d97c3b2168248ff493dfa24a549
Binary files /dev/null and b/dbrepo-analyse-service/lib/dbrepo-1.5.3.tar.gz differ
diff --git a/dbrepo-analyse-service/lib/dbrepo-1.6.0.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.6.0.tar.gz
index 39b56b881d32601bf876dae9807d648910488cc2..8c30bf71a45ba3f95b7a82f05f225506a8a3dfe4 100644
Binary files a/dbrepo-analyse-service/lib/dbrepo-1.6.0.tar.gz and b/dbrepo-analyse-service/lib/dbrepo-1.6.0.tar.gz differ
diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml
index 87bdec0b480a7f63c792cf6625d75e03fbf90774..cd5c809af1f872239d234c8f1e6cba56f25a95fb 100644
--- a/dbrepo-data-service/pom.xml
+++ b/dbrepo-data-service/pom.xml
@@ -44,7 +44,6 @@
         <jwt.version>4.3.0</jwt.version>
         <opencsv.version>5.7.1</opencsv.version>
         <super-csv.version>2.4.0</super-csv.version>
-        <jsql.version>4.6</jsql.version>
         <springdoc-openapi.version>2.3.0</springdoc-openapi.version>
         <hsqldb.version>2.7.2</hsqldb.version>
         <testcontainers.version>1.19.1</testcontainers.version>
@@ -64,6 +63,10 @@
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
@@ -208,11 +211,6 @@
             <artifactId>jackson-datatype-hibernate6</artifactId>
             <version>${jackson-datatype.version}</version>
         </dependency>
-        <dependency>
-            <groupId>com.github.jsqlparser</groupId>
-            <artifactId>jsqlparser</artifactId>
-            <version>${jsql.version}</version>
-        </dependency>
         <!-- Authentication -->
         <dependency>
             <groupId>com.auth0</groupId>
diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..334128637ec5113e6478567d30e44b2f61ea3f5b
--- /dev/null
+++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java
@@ -0,0 +1,34 @@
+package at.tuwien.endpoints;
+
+import org.apache.spark.sql.Dataset;
+import org.apache.spark.sql.Row;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class AbstractEndpoint {
+
+    public List<Map<String, Object>> transform(Dataset<Row> dataset) {
+        return dataset.collectAsList()
+                .stream()
+                .map(row -> {
+                    final Map<String, Object> map = new LinkedHashMap<>();
+                    for (int i = 0; i < dataset.columns().length; i++) {
+                        if (row.get(i) == null) {
+                            map.put(dataset.columns()[i], null);
+                            continue;
+                        }
+                        try {
+                            map.put(dataset.columns()[i], Integer.parseInt(String.valueOf(row.get(i))));
+                            map.put(dataset.columns()[i], Double.parseDouble(String.valueOf(row.get(i))));
+                        } catch (NumberFormatException e) {
+                            /* ignore */
+                        }
+                        map.put(dataset.columns()[i], String.valueOf(row.get(i)));
+                    }
+                    return map;
+                })
+                .toList();
+    }
+}
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 63962694f164a79e6268b579372f6324704f9fa7..22b74f9d5ad3fe19b122cd008eb0ec7009cd6074 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
@@ -1,14 +1,18 @@
 package at.tuwien.endpoints;
 
 import at.tuwien.ExportResourceDto;
+import at.tuwien.api.database.ViewColumnDto;
+import at.tuwien.api.database.ViewDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
 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.mapper.MetadataMapper;
+import at.tuwien.service.SchemaService;
+import at.tuwien.service.StorageService;
 import at.tuwien.service.SubsetService;
 import at.tuwien.utils.UserUtil;
 import at.tuwien.validation.EndpointValidator;
@@ -25,10 +29,10 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
 import lombok.extern.log4j.Log4j2;
-import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.spark.sql.Dataset;
+import org.apache.spark.sql.Row;
 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;
@@ -38,22 +42,30 @@ import java.security.Principal;
 import java.sql.SQLException;
 import java.time.Instant;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 @Log4j2
 @RestController
 @CrossOrigin(origins = "*")
 @RequestMapping(path = "/api/database/{databaseId}/subset")
-public class SubsetEndpoint {
+public class SubsetEndpoint extends AbstractEndpoint {
 
+    private final SchemaService schemaService;
     private final SubsetService subsetService;
+    private final MetadataMapper metadataMapper;
+    private final StorageService storageService;
     private final EndpointValidator endpointValidator;
     private final MetadataServiceGateway metadataServiceGateway;
 
     @Autowired
-    public SubsetEndpoint(SubsetService queryService, EndpointValidator endpointValidator,
+    public SubsetEndpoint(SchemaService schemaService, SubsetService subsetService, MetadataMapper metadataMapper,
+                          StorageService storageService, EndpointValidator endpointValidator,
                           MetadataServiceGateway metadataServiceGateway) {
-        this.subsetService = queryService;
+        this.schemaService = schemaService;
+        this.subsetService = subsetService;
+        this.metadataMapper = metadataMapper;
+        this.storageService = storageService;
         this.endpointValidator = endpointValidator;
         this.metadataServiceGateway = metadataServiceGateway;
     }
@@ -145,16 +157,15 @@ public class SubsetEndpoint {
                                       @NotNull HttpServletRequest httpServletRequest,
                                       @RequestParam(required = false) Instant timestamp)
             throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException,
-            QueryNotFoundException, FormatNotAvailableException, StorageUnavailableException, QueryMalformedException,
-            StorageNotFoundException, UserNotFoundException, MetadataServiceException, ViewNotFoundException,
-            MalformedException {
+            QueryNotFoundException, FormatNotAvailableException, StorageUnavailableException, UserNotFoundException,
+            MetadataServiceException, TableNotFoundException, ViewMalformedException, QueryMalformedException {
         String accept = httpServletRequest.getHeader("Accept");
         log.debug("endpoint find subset in database, databaseId={}, subsetId={}, accept={}, timestamp={}", databaseId,
                 subsetId, accept, timestamp);
         final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId);
-        final QueryDto query;
+        final QueryDto subset;
         try {
-            query = subsetService.findById(database, subsetId);
+            subset = subsetService.findById(database, subsetId);
         } 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);
@@ -171,21 +182,21 @@ public class SubsetEndpoint {
         switch (accept) {
             case MediaType.APPLICATION_JSON_VALUE:
                 log.trace("accept header matches json");
-                return ResponseEntity.ok(query);
+                return ResponseEntity.ok(subset);
             case "text/csv":
                 log.trace("accept header matches csv");
                 try {
-                    final ExportResourceDto resource = subsetService.export(database, query, timestamp);
+                    final Dataset<Row> dataset = subsetService.getData(database, subset, null, null);
+                    final ExportResourceDto resource = storageService.transformDataset(dataset);
                     final HttpHeaders headers = new HttpHeaders();
                     headers.add("Content-Disposition", "attachment; filename=\"" + resource.getFilename() + "\"");
                     log.trace("export table resulted in resource {}", resource);
                     return ResponseEntity.ok()
                             .headers(headers)
                             .body(resource.getResource());
-
                 } 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);
+                    log.error("Failed to find data: {}", e.getMessage());
+                    throw new DatabaseUnavailableException("Failed to find data: " + e.getMessage(), e);
                 }
         }
         throw new FormatNotAvailableException("Must provide either application/json or text/csv headers");
@@ -201,7 +212,7 @@ public class SubsetEndpoint {
                     description = "Created subset",
                     content = {@Content(
                             mediaType = "application/json",
-                            schema = @Schema(implementation = QueryResultDto.class))}),
+                            schema = @Schema(implementation = List.class))}),
             @ApiResponse(responseCode = "400",
                     description = "Malformed select query",
                     content = {@Content(
@@ -233,16 +244,18 @@ public class SubsetEndpoint {
                             mediaType = "application/json",
                             schema = @Schema(implementation = ApiErrorDto.class))}),
     })
-    public ResponseEntity<QueryResultDto> create(@NotNull @PathVariable("databaseId") Long databaseId,
-                                                 @Valid @RequestBody ExecuteStatementDto data,
-                                                 Principal principal,
-                                                 @RequestParam(required = false) Long page,
-                                                 @RequestParam(required = false) Long size,
-                                                 @RequestParam(required = false) Instant timestamp)
+    public ResponseEntity<List<Map<String, Object>>> create(@NotNull @PathVariable("databaseId") Long databaseId,
+                                                            @Valid @RequestBody ExecuteStatementDto data,
+                                                            Principal principal,
+                                                            @NotNull HttpServletRequest request,
+                                                            @RequestParam(required = false) Instant timestamp,
+                                                            @RequestParam(required = false) Long page,
+                                                            @RequestParam(required = false) Long size)
             throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException,
             QueryNotFoundException, StorageUnavailableException, QueryMalformedException, StorageNotFoundException,
             QueryStoreInsertException, TableMalformedException, PaginationException, QueryNotSupportedException,
-            NotAllowedException, UserNotFoundException, MetadataServiceException {
+            NotAllowedException, UserNotFoundException, MetadataServiceException, TableNotFoundException,
+            ViewMalformedException, ViewNotFoundException {
         log.debug("endpoint create subset in database, databaseId={}, data.statement={}, page={}, size={}, " +
                         "timestamp={}", databaseId, data.getStatement(), page, size,
                 timestamp);
@@ -265,17 +278,13 @@ public class SubsetEndpoint {
         }
         /* create */
         final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId);
-        final QueryResultDto queryResult;
         try {
-            queryResult = subsetService.execute(database, data.getStatement(), timestamp, userId, page, size, null,
-                    null);
+            final Long subsetId = subsetService.create(database, data.getStatement(), timestamp, userId);
+            return getData(databaseId, subsetId, principal, request, page, size);
         } 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);
         }
-        log.info("Created subset with id: {}", queryResult.getId());
-        return ResponseEntity.status(HttpStatus.CREATED)
-                .body(queryResult);
     }
 
     @RequestMapping(value = "/{subsetId}/data", method = {RequestMethod.GET, RequestMethod.HEAD})
@@ -286,11 +295,13 @@ public class SubsetEndpoint {
     @ApiResponses(value = {
             @ApiResponse(responseCode = "200",
                     description = "Retrieved subset data",
-                    headers = {@Header(name = "X-Count", description = "Number of rows", schema = @Schema(implementation = Long.class), required = true),
-                            @Header(name = "Access-Control-Expose-Headers", description = "Expose `X-Count` custom header", schema = @Schema(implementation = String.class), required = true)},
+                    headers = {@Header(name = "X-Count", description = "Number of rows", schema = @Schema(implementation = Long.class)),
+                            @Header(name = "X-Headers", description = "The list of headers separated by comma", schema = @Schema(implementation = String.class)),
+                            @Header(name = "X-Id", description = "The subset id", schema = @Schema(implementation = Long.class), required = true),
+                            @Header(name = "Access-Control-Expose-Headers", description = "Reverse proxy exposing of custom headers", schema = @Schema(implementation = String.class), required = true)},
                     content = {@Content(
                             mediaType = "application/json",
-                            schema = @Schema(implementation = QueryResultDto.class))}),
+                            schema = @Schema(implementation = List.class))}),
             @ApiResponse(responseCode = "400",
                     description = "Invalid pagination",
                     content = {@Content(
@@ -312,16 +323,16 @@ public class SubsetEndpoint {
                             mediaType = "application/json",
                             schema = @Schema(implementation = ApiErrorDto.class))}),
     })
-    public ResponseEntity<QueryResultDto> getData(@NotNull @PathVariable("databaseId") Long databaseId,
-                                                  @NotNull @PathVariable("subsetId") Long subsetId,
-                                                  Principal principal,
-                                                  @NotNull HttpServletRequest request,
-                                                  @RequestParam(required = false) Long page,
-                                                  @RequestParam(required = false) Long size) throws PaginationException,
-            DatabaseNotFoundException, RemoteUnavailableException, NotAllowedException, QueryNotFoundException,
-            DatabaseUnavailableException, TableMalformedException, QueryMalformedException, UserNotFoundException,
-            MetadataServiceException {
-        log.debug("endpoint re-execute query, databaseId={}, subsetId={}, principal.name={} page={}, size={}",
+    public ResponseEntity<List<Map<String, Object>>> getData(@NotNull @PathVariable("databaseId") Long databaseId,
+                                                             @NotNull @PathVariable("subsetId") Long subsetId,
+                                                             Principal principal,
+                                                             @NotNull HttpServletRequest request,
+                                                             @RequestParam(required = false) Long page,
+                                                             @RequestParam(required = false) Long size)
+            throws PaginationException, DatabaseNotFoundException, RemoteUnavailableException, NotAllowedException,
+            QueryNotFoundException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException,
+            UserNotFoundException, MetadataServiceException, TableNotFoundException, ViewMalformedException, ViewNotFoundException {
+        log.debug("endpoint get subset data, databaseId={}, subsetId={}, principal.name={} page={}, size={}",
                 databaseId, subsetId, principal != null ? principal.getName() : null, page, size);
         endpointValidator.validateDataParams(page, size);
         final PrivilegedDatabaseDto database = metadataServiceGateway.getDatabaseById(databaseId);
@@ -342,21 +353,24 @@ public class SubsetEndpoint {
             log.debug("size not set: default to {}", size);
         }
         try {
-            final QueryDto query = subsetService.findById(database, subsetId);
+            final HttpHeaders headers = new HttpHeaders();
+            headers.set("X-Id", "" + subsetId);
+            final QueryDto subset = subsetService.findById(database, subsetId);
             if (request.getMethod().equals("HEAD")) {
-                final HttpHeaders headers = new HttpHeaders();
-                headers.set("Access-Control-Expose-Headers", "X-Count");
-                final Long count = subsetService.reExecuteCount(database, query);
+                headers.set("Access-Control-Expose-Headers", "X-Count X-Id");
+                final Long count = subsetService.reExecuteCount(database, subset);
                 headers.set("X-Count", "" + count);
                 return ResponseEntity.ok()
                         .headers(headers)
                         .build();
             }
-            final QueryResultDto result = subsetService.reExecute(database, query, page, size, null, null);
-            result.setId(subsetId);
-            log.trace("re-execute query resulted in result {}", result);
+            final Dataset<Row> dataset = subsetService.getData(database, subset, page, size);
+            final ViewDto view = schemaService.inspectView(database, metadataMapper.queryDtoToViewName(subset));
+            headers.set("Access-Control-Expose-Headers", "X-Id X-Headers");
+            headers.set("X-Headers", String.join(",", view.getColumns().stream().map(ViewColumnDto::getInternalName).toList()));
             return ResponseEntity.ok()
-                    .body(result);
+                    .headers(headers)
+                    .body(transform(dataset));
         } 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);
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 08d287e15356beba71c57ea88aa17e21f13ad200..689c38e7daaba89af9c253308bfb50aec2b07bf4 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
@@ -5,14 +5,15 @@ import at.tuwien.api.database.DatabaseAccessDto;
 import at.tuwien.api.database.DatabaseDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
 import at.tuwien.api.database.query.ImportDto;
-import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.*;
+import at.tuwien.api.database.table.columns.ColumnDto;
 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.SchemaService;
+import at.tuwien.service.StorageService;
 import at.tuwien.service.TableService;
 import at.tuwien.utils.UserUtil;
 import at.tuwien.validation.EndpointValidator;
@@ -29,6 +30,8 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
 import lombok.extern.log4j.Log4j2;
+import org.apache.spark.sql.Dataset;
+import org.apache.spark.sql.Row;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.InputStreamResource;
 import org.springframework.http.HttpHeaders;
@@ -41,23 +44,26 @@ import java.security.Principal;
 import java.sql.SQLException;
 import java.time.Instant;
 import java.util.List;
+import java.util.Map;
 
 @Log4j2
 @RestController
 @CrossOrigin(origins = "*")
 @RequestMapping(path = "/api/database/{databaseId}/table")
-public class TableEndpoint {
+public class TableEndpoint extends AbstractEndpoint {
 
     private final TableService tableService;
     private final SchemaService schemaService;
+    private final StorageService storageService;
     private final EndpointValidator endpointValidator;
     private final MetadataServiceGateway metadataServiceGateway;
 
     @Autowired
-    public TableEndpoint(TableService tableService, SchemaService schemaService, EndpointValidator endpointValidator,
-                         MetadataServiceGateway metadataServiceGateway) {
+    public TableEndpoint(TableService tableService, SchemaService schemaService, StorageService storageService,
+                         EndpointValidator endpointValidator, MetadataServiceGateway metadataServiceGateway) {
         this.tableService = tableService;
         this.schemaService = schemaService;
+        this.storageService = storageService;
         this.endpointValidator = endpointValidator;
         this.metadataServiceGateway = metadataServiceGateway;
     }
@@ -215,7 +221,7 @@ public class TableEndpoint {
                             @Header(name = "Access-Control-Expose-Headers", description = "Expose `X-Count` custom header", schema = @Schema(implementation = String.class), required = true)},
                     content = {@Content(
                             mediaType = "application/json",
-                            schema = @Schema(implementation = QueryResultDto.class))}),
+                            schema = @Schema(implementation = List.class))}),
             @ApiResponse(responseCode = "400",
                     description = "Request pagination or table data select query is malformed",
                     content = {@Content(
@@ -237,17 +243,16 @@ public class TableEndpoint {
                             mediaType = "application/json",
                             schema = @Schema(implementation = ApiErrorDto.class))}),
     })
-    public ResponseEntity<QueryResultDto> getData(@NotNull @PathVariable("databaseId") Long databaseId,
-                                                  @NotNull @PathVariable("tableId") Long tableId,
-                                                  @RequestParam(required = false) Instant timestamp,
-                                                  @RequestParam(required = false) Long page,
-                                                  @RequestParam(required = false) Long size,
-                                                  @NotNull HttpServletRequest request,
-                                                  Principal principal)
+    public ResponseEntity<List<Map<String, Object>>> getData(@NotNull @PathVariable("databaseId") Long databaseId,
+                                                             @NotNull @PathVariable("tableId") Long tableId,
+                                                             @RequestParam(required = false) Instant timestamp,
+                                                             @RequestParam(required = false) Long page,
+                                                             @RequestParam(required = false) Long size,
+                                                             @NotNull HttpServletRequest request,
+                                                             Principal principal)
             throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException,
-            TableMalformedException, PaginationException, QueryMalformedException, MetadataServiceException,
-            NotAllowedException {
-        log.debug("endpoint find table data, databaseId={}, tableId={}, timestamp={}, page={}, size={}", databaseId,
+            PaginationException, QueryMalformedException, MetadataServiceException, NotAllowedException {
+        log.debug("endpoint get table data, databaseId={}, tableId={}, timestamp={}, page={}, size={}", databaseId,
                 tableId, timestamp, page, size);
         endpointValidator.validateDataParams(page, size);
         /* parameters */
@@ -272,18 +277,21 @@ public class TableEndpoint {
             metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal));
         }
         try {
+            final HttpHeaders headers = new HttpHeaders();
             if (request.getMethod().equals("HEAD")) {
-                final HttpHeaders headers = new HttpHeaders();
                 headers.set("Access-Control-Expose-Headers", "X-Count");
                 headers.set("X-Count", "" + tableService.getCount(table, timestamp));
                 return ResponseEntity.ok()
                         .headers(headers)
                         .build();
             }
-            final QueryResultDto dto = tableService.getPaginatedData(table, timestamp, page, size);
+            headers.set("Access-Control-Expose-Headers", "X-Headers");
+            headers.set("X-Headers", String.join(",", table.getColumns().stream().map(ColumnDto::getInternalName).toList()));
             return ResponseEntity.ok()
-                    .body(dto);
-        } catch (SQLException e) {
+                    .headers(headers)
+                    .body(transform(tableService.getData(table.getDatabase(), table.getInternalName(), timestamp,
+                            null, null, null, null)));
+        } catch (SQLException | QueryMalformedException e) {
             log.error("Failed to establish connection to database: {}", e.getMessage());
             throw new DatabaseUnavailableException("Failed to establish connection to database: " + e.getMessage(), e);
         }
@@ -596,13 +604,14 @@ public class TableEndpoint {
                                                              @RequestParam(required = false) Instant timestamp,
                                                              Principal principal)
             throws RemoteUnavailableException, TableNotFoundException, NotAllowedException, StorageUnavailableException,
-            QueryMalformedException, MetadataServiceException, MalformedException {
+            QueryMalformedException, MetadataServiceException {
         log.debug("endpoint export table data, databaseId={}, tableId={}, timestamp={}", databaseId, tableId, timestamp);
         /* parameters */
         if (timestamp == null) {
             timestamp = Instant.now();
             log.debug("timestamp not set: default to {}", timestamp);
         }
+        // TODO improve to single operation checking if user xyz has access to table abc
         final PrivilegedTableDto table = metadataServiceGateway.getTableById(databaseId, tableId);
         if (!table.getIsPublic()) {
             if (principal == null) {
@@ -611,8 +620,10 @@ public class TableEndpoint {
             }
             metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal));
         }
+        final Dataset<Row> dataset = tableService.getData(table.getDatabase(), table.getInternalName(), timestamp, null,
+                null, null, null);
+        final ExportResourceDto resource = storageService.transformDataset(dataset);
         final HttpHeaders headers = new HttpHeaders();
-        final ExportResourceDto resource = tableService.exportDataset(table, timestamp);
         headers.add("Content-Disposition", "attachment; filename=\"" + resource.getFilename() + "\"");
         log.trace("export table resulted in resource {}", resource);
         return ResponseEntity.ok()
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 f0b1b891e73990b56510ec292643db96fbe6c1da..001350246e68e7e75bbfc781695b284138c01ace 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,14 +1,16 @@
 package at.tuwien.endpoints;
 
 import at.tuwien.ExportResourceDto;
+import at.tuwien.api.database.ViewColumnDto;
 import at.tuwien.api.database.ViewCreateDto;
 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.error.ApiErrorDto;
 import at.tuwien.exception.*;
 import at.tuwien.gateway.MetadataServiceGateway;
+import at.tuwien.service.StorageService;
+import at.tuwien.service.TableService;
 import at.tuwien.service.ViewService;
 import at.tuwien.utils.UserUtil;
 import at.tuwien.validation.EndpointValidator;
@@ -22,7 +24,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses;
 import io.swagger.v3.oas.annotations.security.SecurityRequirement;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -37,21 +38,26 @@ import java.security.Principal;
 import java.sql.SQLException;
 import java.time.Instant;
 import java.util.List;
+import java.util.Map;
 
 @Log4j2
 @RestController
 @CrossOrigin(origins = "*")
 @RequestMapping(path = "/api/database/{databaseId}/view")
-public class ViewEndpoint {
+public class ViewEndpoint extends AbstractEndpoint {
 
     private final ViewService viewService;
+    private final TableService tableService;
+    private final StorageService storageService;
     private final EndpointValidator endpointValidator;
     private final MetadataServiceGateway metadataServiceGateway;
 
     @Autowired
-    public ViewEndpoint(ViewService viewService, EndpointValidator endpointValidator,
-                        MetadataServiceGateway metadataServiceGateway) {
+    public ViewEndpoint(ViewService viewService, TableService tableService, StorageService storageService,
+                        EndpointValidator endpointValidator, MetadataServiceGateway metadataServiceGateway) {
         this.viewService = viewService;
+        this.tableService = tableService;
+        this.storageService = storageService;
         this.endpointValidator = endpointValidator;
         this.metadataServiceGateway = metadataServiceGateway;
     }
@@ -188,7 +194,7 @@ public class ViewEndpoint {
         log.debug("endpoint delete view, databaseId={}, viewId={}", databaseId, viewId);
         final PrivilegedViewDto view = metadataServiceGateway.getViewById(databaseId, viewId);
         try {
-            viewService.delete(view);
+            viewService.delete(view.getDatabase(), view.getInternalName());
             return ResponseEntity.status(HttpStatus.ACCEPTED)
                     .build();
         } catch (SQLException e) {
@@ -209,7 +215,7 @@ public class ViewEndpoint {
                             @Header(name = "Access-Control-Expose-Headers", description = "Expose `X-Count` custom header", schema = @Schema(implementation = String.class), required = true)},
                     content = {@Content(
                             mediaType = "application/json",
-                            schema = @Schema(implementation = QueryResultDto.class))}),
+                            schema = @Schema(implementation = List.class))}),
             @ApiResponse(responseCode = "400",
                     description = "Request pagination is malformed",
                     content = {@Content(
@@ -236,16 +242,15 @@ public class ViewEndpoint {
                             mediaType = "application/json",
                             schema = @Schema(implementation = ApiErrorDto.class))}),
     })
-    public ResponseEntity<QueryResultDto> getData(@NotNull @PathVariable("databaseId") Long databaseId,
-                                                  @NotNull @PathVariable("viewId") Long viewId,
-                                                  @RequestParam(required = false) Long page,
-                                                  @RequestParam(required = false) Long size,
-                                                  @RequestParam(required = false) Instant timestamp,
-                                                  @NotNull HttpServletRequest request,
-                                                  Principal principal)
-            throws DatabaseUnavailableException, RemoteUnavailableException, ViewNotFoundException,
-            QueryMalformedException, ViewMalformedException, PaginationException, NotAllowedException,
-            MetadataServiceException {
+    public ResponseEntity<List<Map<String, Object>>> getData(@NotNull @PathVariable("databaseId") Long databaseId,
+                                                             @NotNull @PathVariable("viewId") Long viewId,
+                                                             @RequestParam(required = false) Long page,
+                                                             @RequestParam(required = false) Long size,
+                                                             @RequestParam(required = false) Instant timestamp,
+                                                             @NotNull HttpServletRequest request,
+                                                             Principal principal)
+            throws DatabaseUnavailableException, RemoteUnavailableException, ViewNotFoundException, PaginationException,
+            QueryMalformedException, NotAllowedException, MetadataServiceException, TableNotFoundException {
         log.debug("endpoint get view data, databaseId={}, viewId={}, page={}, size={}, timestamp={}", databaseId,
                 viewId, page, size, timestamp);
         endpointValidator.validateDataParams(page, size);
@@ -262,23 +267,26 @@ public class ViewEndpoint {
             timestamp = Instant.now();
             log.debug("timestamp not set: default to {}", timestamp);
         }
+        // TODO improve with a single operation that checks if user xyz has access to view abc
         final PrivilegedViewDto view = metadataServiceGateway.getViewById(databaseId, viewId);
         if (!view.getIsPublic()) {
             metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal));
         }
         try {
+            final HttpHeaders headers = new HttpHeaders();
             if (request.getMethod().equals("HEAD")) {
-                final HttpHeaders headers = new HttpHeaders();
                 headers.set("Access-Control-Expose-Headers", "X-Count");
                 headers.set("X-Count", "" + viewService.count(view, timestamp));
                 return ResponseEntity.ok()
                         .headers(headers)
                         .build();
             }
-            final QueryResultDto result = viewService.data(view, timestamp, page, size);
-            log.trace("get view data resulted in result {}", result);
+            headers.set("Access-Control-Expose-Headers", "X-Headers");
+            headers.set("X-Headers", String.join(",", view.getColumns().stream().map(ViewColumnDto::getInternalName).toList()));
             return ResponseEntity.ok()
-                    .body(result);
+                    .headers(headers)
+                    .body(transform(tableService.getData(view.getDatabase(), view.getInternalName(), timestamp, page,
+                            size, null, null)));
         } 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);
@@ -319,11 +327,17 @@ public class ViewEndpoint {
     })
     public ResponseEntity<InputStreamResource> exportDataset(@NotNull @PathVariable("databaseId") Long databaseId,
                                                              @NotNull @PathVariable("viewId") Long viewId,
+                                                             @RequestParam(required = false) Instant timestamp,
                                                              Principal principal)
             throws RemoteUnavailableException, ViewNotFoundException, NotAllowedException, MetadataServiceException,
-            StorageUnavailableException, QueryMalformedException, MalformedException {
+            StorageUnavailableException, QueryMalformedException, TableNotFoundException {
         log.debug("endpoint export view data, databaseId={}, viewId={}", databaseId, viewId);
         /* parameters */
+        if (timestamp == null) {
+            timestamp = Instant.now();
+            log.debug("timestamp not set: default to {}", timestamp);
+        }
+        /* parameters */
         final PrivilegedViewDto view = metadataServiceGateway.getViewById(databaseId, viewId);
         if (!view.getIsPublic()) {
             if (principal == null) {
@@ -332,8 +346,13 @@ public class ViewEndpoint {
             }
             metadataServiceGateway.getAccess(databaseId, UserUtil.getId(principal));
         }
+        final List<String> columns = view.getColumns()
+                .stream()
+                .map(ViewColumnDto::getInternalName)
+                .toList();
         final HttpHeaders headers = new HttpHeaders();
-        final ExportResourceDto resource = viewService.exportDataset(view);
+        final ExportResourceDto resource = storageService.transformDataset(tableService.getData(view.getDatabase(),
+                view.getInternalName(), timestamp, null, null, null, null));
         headers.add("Content-Disposition", "attachment; filename=\"" + resource.getFilename() + "\"");
         log.trace("export table resulted in resource {}", resource);
         return ResponseEntity.ok()
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 9bd16e6089443bfb2eb8972d7a8bc362661cb2a5..c23c50bad69ac5916357f276efddb51c00e10202 100644
--- a/dbrepo-data-service/rest-service/src/main/resources/application.yml
+++ b/dbrepo-data-service/rest-service/src/main/resources/application.yml
@@ -3,27 +3,26 @@ application:
   version: '@project.version@'
 spring:
   datasource:
-    url: jdbc:h2:mem:fda;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS FDA;NON_KEYWORDS=value
+    url: "jdbc:h2:mem:dbrepo;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS dbrepo;NON_KEYWORDS=value"
     driver-class-name: org.h2.Driver
     username: sa
     password: password
-  rabbitmq:
-    host: "${BROKER_HOST:broker-service}"
-    virtual-host: "${BROKER_VIRTUALHOST:dbrepo}"
-    password: "${BROKER_PASSWORD:admin}"
-    username: "${BROKER_USERNAME:admin}"
-    port: ${BROKER_PORT:5672}
   jpa:
     show-sql: false
-    database-platform: org.hibernate.dialect.H2Dialect
     open-in-view: false
     properties:
       hibernate:
-        default_schema: fda
+        default_schema: "${METADATA_DB:dbrepo}"
         jdbc:
           time_zone: UTC
   application:
     name: data-service
+  rabbitmq:
+    host: "${BROKER_HOST:broker-service}"
+    virtual-host: "${BROKER_VIRTUALHOST:dbrepo}"
+    username: "${BROKER_USERNAME:admin}"
+    password: "${BROKER_PASSWORD:admin}"
+    port: ${BROKER_PORT:5672}
   main:
     banner-mode: off
 management:
@@ -65,8 +64,8 @@ dbrepo:
   jwt:
     public_key: "${JWT_PUBKEY:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}"
   keycloak:
-    username: "${AUTH_SERVICE_ADMIN:fda}"
-    password: "${AUTH_SERVICE_ADMIN_PASSWORD:fda}"
+    username: "${AUTH_SERVICE_ADMIN:admin}"
+    password: "${AUTH_SERVICE_ADMIN_PASSWORD:admin}"
     client: "${AUTH_SERVICE_CLIENT:dbrepo-client}"
     clientSecret: "${AUTH_SERVICE_CLIENT_SECRET:MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG}"
   sql:
@@ -81,4 +80,4 @@ dbrepo:
   queueName: "${BROKER_QUEUE_NAME:dbrepo}"
   exchangeName: "${BROKER_EXCHANGE_NAME:dbrepo}"
   routingKey: "${BROKER_ROUTING_KEY:#}"
-  connectionTimeout: ${CONNECTION_TIMEOUT:10000}
+  connectionTimeout: "${SPARQL_CONNECTION_TIMEOUT:10000}"
diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/annotations/MockAmqp.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/annotations/MockAmqp.java
deleted file mode 100644
index 0f3868c25e5494ffe409046883f4ad6d5babff4a..0000000000000000000000000000000000000000
--- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/annotations/MockAmqp.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package at.tuwien.annotations;
-
-import at.tuwien.listener.DefaultListener;
-import com.rabbitmq.client.Channel;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.boot.test.mock.mockito.MockBeans;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-@MockBeans({@MockBean(Channel.class), @MockBean(DefaultListener.class)})
-public @interface MockAmqp {
-}
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 5f302368eedec06766e77328fe4d738c28e9a168..f1d1b6d795a88f14e3f256df3ccf097a59afc292 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
@@ -1,25 +1,27 @@
 package at.tuwien.endpoint;
 
-import at.tuwien.ExportResourceDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
 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.endpoints.SubsetEndpoint;
 import at.tuwien.exception.*;
 import at.tuwien.gateway.MetadataServiceGateway;
+import at.tuwien.service.SchemaService;
+import at.tuwien.service.StorageService;
 import at.tuwien.service.SubsetService;
 import at.tuwien.test.AbstractUnitTest;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.extern.log4j.Log4j2;
+import org.apache.spark.sql.Dataset;
+import org.apache.spark.sql.Row;
+import org.apache.spark.sql.SparkSession;
 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.boot.test.mock.mockito.MockBean;
-import org.springframework.core.io.InputStreamResource;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
@@ -28,13 +30,12 @@ import org.springframework.security.test.context.support.WithAnonymousUser;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
-import java.io.InputStream;
 import java.sql.SQLException;
 import java.time.Instant;
 import java.util.List;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 @Log4j2
@@ -45,12 +46,21 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @Autowired
     private SubsetEndpoint subsetEndpoint;
 
+    @Autowired
+    private SparkSession sparkSession;
+
     @MockBean
     private SubsetService subsetService;
 
+    @MockBean
+    private SchemaService schemaService;
+
     @MockBean
     private HttpServletRequest httpServletRequest;
 
+    @MockBean
+    private StorageService storageService;
+
     @MockBean
     private MetadataServiceGateway metadataServiceGateway;
 
@@ -108,8 +118,8 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @WithAnonymousUser
     public void findById_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException,
             DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException,
-            FormatNotAvailableException, StorageNotFoundException, SQLException, MetadataServiceException,
-            ViewNotFoundException, MalformedException {
+            FormatNotAvailableException, TableNotFoundException, MetadataServiceException, SQLException,
+            ViewMalformedException {
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
@@ -142,19 +152,18 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @WithAnonymousUser
     public void findById_acceptCsv_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException,
             UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException,
-            QueryNotFoundException, FormatNotAvailableException, StorageNotFoundException, SQLException,
-            MetadataServiceException, ViewNotFoundException, MalformedException {
-        final ExportResourceDto mock = ExportResourceDto.builder()
-                .filename("deadbeef")
-                .resource(new InputStreamResource(InputStream.nullInputStream()))
-                .build();
+            QueryNotFoundException, FormatNotAvailableException, SQLException, MetadataServiceException,
+            TableNotFoundException, ViewMalformedException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
                 .thenReturn(DATABASE_3_PRIVILEGED_DTO);
         when(subsetService.findById(DATABASE_3_PRIVILEGED_DTO, QUERY_5_ID))
                 .thenReturn(QUERY_5_DTO);
-        when(subsetService.export(any(PrivilegedDatabaseDto.class), any(QueryDto.class), any(Instant.class)))
+        when(storageService.transformDataset(any(Dataset.class)))
+                .thenReturn(EXPORT_RESOURCE_DTO);
+        when(subsetService.getData(any(PrivilegedDatabaseDto.class), any(QueryDto.class), eq(null), eq(null)))
                 .thenReturn(mock);
 
         /* test */
@@ -165,20 +174,19 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @WithAnonymousUser
     public void findById_timestamp_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException,
             UserNotFoundException, DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException,
-            QueryNotFoundException, FormatNotAvailableException, StorageNotFoundException, SQLException,
-            MetadataServiceException, ViewNotFoundException, MalformedException {
-        final ExportResourceDto mock = ExportResourceDto.builder()
-                .filename("deadbeef")
-                .resource(new InputStreamResource(InputStream.nullInputStream()))
-                .build();
+            QueryNotFoundException, FormatNotAvailableException, SQLException, MetadataServiceException,
+            TableNotFoundException, ViewMalformedException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
                 .thenReturn(DATABASE_3_PRIVILEGED_DTO);
         when(subsetService.findById(DATABASE_3_PRIVILEGED_DTO, QUERY_5_ID))
                 .thenReturn(QUERY_5_DTO);
-        when(subsetService.export(any(PrivilegedDatabaseDto.class), any(QueryDto.class), any(Instant.class)))
+        when(subsetService.getData(any(PrivilegedDatabaseDto.class), any(QueryDto.class), eq(null), eq(null)))
                 .thenReturn(mock);
+        when(storageService.transformDataset(any(Dataset.class)))
+                .thenReturn(EXPORT_RESOURCE_DTO);
 
         /* test */
         generic_findById(QUERY_5_ID, MediaType.parseMediaType("text/csv"), Instant.now());
@@ -220,23 +228,19 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @Test
     @WithAnonymousUser
     public void findById_unavailableExport_fails() throws DatabaseNotFoundException, RemoteUnavailableException,
-            MetadataServiceException, SQLException, StorageUnavailableException, QueryMalformedException,
-            StorageNotFoundException, UserNotFoundException, QueryNotFoundException, ViewNotFoundException, MalformedException {
-        final ExportResourceDto mock = ExportResourceDto.builder()
-                .filename("deadbeef")
-                .resource(new InputStreamResource(InputStream.nullInputStream()))
-                .build();
+            MetadataServiceException, SQLException, QueryMalformedException, UserNotFoundException,
+            QueryNotFoundException, TableNotFoundException, ViewMalformedException, StorageUnavailableException {
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
                 .thenReturn(DATABASE_3_PRIVILEGED_DTO);
         when(subsetService.findById(DATABASE_3_PRIVILEGED_DTO, QUERY_5_ID))
                 .thenReturn(QUERY_5_DTO);
-        when(subsetService.export(any(PrivilegedDatabaseDto.class), any(QueryDto.class), any(Instant.class)))
-                .thenReturn(mock);
+        when(storageService.transformDataset(any(Dataset.class)))
+                .thenReturn(EXPORT_RESOURCE_DTO);
         doThrow(SQLException.class)
                 .when(subsetService)
-                .export(eq(DATABASE_3_PRIVILEGED_DTO), eq(QUERY_5_DTO), any(Instant.class));
+                .getData(eq(DATABASE_3_PRIVILEGED_DTO), eq(QUERY_5_DTO), eq(null), eq(null));
 
         /* test */
         assertThrows(DatabaseUnavailableException.class, () -> {
@@ -248,9 +252,10 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-query"})
     public void create_noAccess_succeeds() throws UserNotFoundException, QueryStoreInsertException,
             TableMalformedException, NotAllowedException, QueryNotSupportedException, PaginationException,
-            StorageNotFoundException, DatabaseUnavailableException, StorageUnavailableException,
+            StorageNotFoundException, DatabaseUnavailableException, StorageUnavailableException, SQLException,
             QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException,
-            SQLException, MetadataServiceException {
+            MetadataServiceException, TableNotFoundException, ViewMalformedException, ViewNotFoundException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_5_STATEMENT)
                 .build();
@@ -258,11 +263,17 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
                 .thenReturn(DATABASE_3_PRIVILEGED_DTO);
-        when(subsetService.execute(eq(DATABASE_3_PRIVILEGED_DTO), anyString(), any(Instant.class), eq(USER_1_ID), eq(0L), eq(10L), eq(null), eq(null)))
-                .thenReturn(QUERY_5_RESULT_DTO);
+        when(subsetService.getData(eq(DATABASE_3_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L)))
+                .thenReturn(mock);
+        when(subsetService.findById(eq(DATABASE_3_PRIVILEGED_DTO), anyLong()))
+                .thenReturn(QUERY_5_DTO);
+        when(schemaService.inspectView(eq(DATABASE_3_PRIVILEGED_DTO), anyString()))
+                .thenReturn(VIEW_5_DTO);
+        when(httpServletRequest.getMethod())
+                .thenReturn("POST");
 
         /* test */
-        subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, 0L, 10L, null);
+        subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, httpServletRequest, null, 0L, 10L);
     }
 
     @Test
@@ -272,9 +283,13 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
                 .statement("SELECT COUNT(id) FROM tbl")
                 .build();
 
+        /* mock */
+        when(httpServletRequest.getMethod())
+                .thenReturn("POST");
+
         /* test */
         assertThrows(QueryNotSupportedException.class, () -> {
-            subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, 0L, 10L, null);
+            subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, httpServletRequest, null, 0L, 10L);
         });
     }
 
@@ -284,7 +299,9 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
             TableMalformedException, NotAllowedException, QueryNotSupportedException,
             PaginationException, StorageNotFoundException, DatabaseUnavailableException, StorageUnavailableException,
             QueryMalformedException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException,
-            SQLException, MetadataServiceException {
+            SQLException, MetadataServiceException, TableNotFoundException, ViewMalformedException,
+            ViewNotFoundException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_5_STATEMENT)
                 .build();
@@ -292,18 +309,24 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
                 .thenReturn(DATABASE_3_PRIVILEGED_DTO);
-        when(subsetService.execute(eq(DATABASE_3_PRIVILEGED_DTO), anyString(), any(Instant.class), eq(USER_1_ID), eq(0L), eq(10L), eq(null), eq(null)))
-                .thenReturn(QUERY_5_RESULT_DTO);
+        when(schemaService.inspectView(eq(DATABASE_3_PRIVILEGED_DTO), anyString()))
+                .thenReturn(VIEW_5_DTO);
+        when(subsetService.findById(eq(DATABASE_3_PRIVILEGED_DTO), anyLong()))
+                .thenReturn(QUERY_5_DTO);
+        when(subsetService.getData(eq(DATABASE_3_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L)))
+                .thenReturn(mock);
+        when(httpServletRequest.getMethod())
+                .thenReturn("POST");
 
         /* test */
-        subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, null, null, null);
+        subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, httpServletRequest, null, null, null);
     }
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-query"})
-    public void create_unavailable_succeeds() throws UserNotFoundException, QueryStoreInsertException,
-            TableMalformedException, NotAllowedException, QueryNotFoundException, DatabaseNotFoundException,
-            RemoteUnavailableException, SQLException, MetadataServiceException {
+    public void create_unavailable_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException,
+            SQLException, MetadataServiceException, QueryMalformedException, TableNotFoundException,
+            ViewMalformedException, UserNotFoundException, QueryNotFoundException, QueryStoreInsertException {
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_5_STATEMENT)
                 .build();
@@ -313,11 +336,18 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
                 .thenReturn(DATABASE_3_PRIVILEGED_DTO);
         doThrow(SQLException.class)
                 .when(subsetService)
-                .execute(eq(DATABASE_3_PRIVILEGED_DTO), anyString(), any(Instant.class), eq(USER_1_ID), eq(0L), eq(10L), eq(null), eq(null));
+                .getData(eq(DATABASE_3_PRIVILEGED_DTO), any(QueryDto.class), eq(null), eq(null));
+        when(subsetService.findById(eq(DATABASE_3_PRIVILEGED_DTO), anyLong()))
+                .thenReturn(QUERY_5_DTO);
+        doThrow(SQLException.class)
+                .when(subsetService)
+                .create(eq(DATABASE_3_PRIVILEGED_DTO), eq(QUERY_5_STATEMENT), any(Instant.class), eq(USER_1_ID));
+        when(httpServletRequest.getMethod())
+                .thenReturn("POST");
 
         /* test */
         assertThrows(DatabaseUnavailableException.class, () -> {
-            subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, null, null, null);
+            subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, httpServletRequest, null, null, null);
         });
     }
 
@@ -333,10 +363,12 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
         doThrow(DatabaseNotFoundException.class)
                 .when(metadataServiceGateway)
                 .getDatabaseById(DATABASE_3_ID);
+        when(httpServletRequest.getMethod())
+                .thenReturn("POST");
 
         /* test */
         assertThrows(DatabaseNotFoundException.class, () -> {
-            subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, null, null, null);
+            subsetEndpoint.create(DATABASE_3_ID, request, USER_1_PRINCIPAL, httpServletRequest, null, null, null);
         });
     }
 
@@ -346,7 +378,8 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
             MetadataServiceException, UserNotFoundException, QueryStoreInsertException, TableMalformedException,
             NotAllowedException, SQLException, QueryNotFoundException, DatabaseUnavailableException,
             StorageUnavailableException, QueryMalformedException, QueryNotSupportedException, PaginationException,
-            StorageNotFoundException {
+            StorageNotFoundException, TableNotFoundException, ViewMalformedException, ViewNotFoundException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_5_STATEMENT)
                 .build();
@@ -354,11 +387,17 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
                 .thenReturn(DATABASE_3_PRIVILEGED_DTO);
-        when(subsetService.execute(eq(DATABASE_3_PRIVILEGED_DTO), anyString(), any(Instant.class), eq(USER_4_ID), eq(0L), eq(10L), eq(null), eq(null)))
-                .thenReturn(QUERY_5_RESULT_DTO);
+        when(subsetService.getData(eq(DATABASE_3_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L)))
+                .thenReturn(mock);
+        when(subsetService.findById(eq(DATABASE_3_PRIVILEGED_DTO), anyLong()))
+                .thenReturn(QUERY_5_DTO);
+        when(schemaService.inspectView(eq(DATABASE_3_PRIVILEGED_DTO), anyString()))
+                .thenReturn(VIEW_5_DTO);
+        when(httpServletRequest.getMethod())
+                .thenReturn("POST");
 
         /* test */
-        subsetEndpoint.create(DATABASE_3_ID, request, USER_4_PRINCIPAL, null, null, null);
+        subsetEndpoint.create(DATABASE_3_ID, request, USER_4_PRINCIPAL, httpServletRequest, null, null, null);
     }
 
     @Test
@@ -367,7 +406,8 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
             MetadataServiceException, UserNotFoundException, QueryStoreInsertException, TableMalformedException,
             NotAllowedException, SQLException, QueryNotFoundException, DatabaseUnavailableException,
             StorageUnavailableException, QueryMalformedException, QueryNotSupportedException, PaginationException,
-            StorageNotFoundException {
+            StorageNotFoundException, TableNotFoundException, ViewMalformedException, ViewNotFoundException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_5_STATEMENT)
                 .build();
@@ -375,17 +415,25 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
                 .thenReturn(DATABASE_3_PRIVILEGED_DTO);
-        when(subsetService.execute(eq(DATABASE_3_PRIVILEGED_DTO), anyString(), any(Instant.class), eq(null), eq(0L), eq(10L), eq(null), eq(null)))
-                .thenReturn(QUERY_5_RESULT_DTO);
+        when(subsetService.findById(eq(DATABASE_3_PRIVILEGED_DTO), anyLong()))
+                .thenReturn(QUERY_5_DTO);
+        when(subsetService.getData(eq(DATABASE_3_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L)))
+                .thenReturn(mock);
+        when(schemaService.inspectView(eq(DATABASE_3_PRIVILEGED_DTO), anyString()))
+                .thenReturn(VIEW_5_DTO);
+        when(httpServletRequest.getMethod())
+                .thenReturn("POST");
 
         /* test */
-        subsetEndpoint.create(DATABASE_3_ID, request, null, null, null, null);
+        subsetEndpoint.create(DATABASE_3_ID, request, null, httpServletRequest, null, null, null);
     }
 
     @Test
     public void getData_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException,
             NotAllowedException, SQLException, QueryNotFoundException, TableMalformedException, QueryMalformedException,
-            DatabaseUnavailableException, PaginationException, MetadataServiceException {
+            DatabaseUnavailableException, PaginationException, MetadataServiceException, TableNotFoundException,
+            ViewMalformedException, ViewNotFoundException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
@@ -394,21 +442,24 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
                 .thenReturn(QUERY_5_DTO);
         when(subsetService.reExecuteCount(DATABASE_3_PRIVILEGED_DTO, QUERY_5_DTO))
                 .thenReturn(QUERY_5_RESULT_NUMBER);
-        when(subsetService.reExecute(DATABASE_3_PRIVILEGED_DTO, QUERY_5_DTO, 0L, 10L, null, null))
-                .thenReturn(QUERY_5_RESULT_DTO);
+        when(subsetService.getData(eq(DATABASE_3_PRIVILEGED_DTO), any(QueryDto.class), eq(0L), eq(10L)))
+                .thenReturn(mock);
+        when(schemaService.inspectView(eq(DATABASE_3_PRIVILEGED_DTO), anyString()))
+                .thenReturn(VIEW_5_DTO);
         when(httpServletRequest.getMethod())
                 .thenReturn("GET");
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = subsetEndpoint.getData(DATABASE_3_ID, QUERY_5_ID, null, httpServletRequest, null, null);
+        final ResponseEntity<List<Map<String, Object>>> response = subsetEndpoint.getData(DATABASE_3_ID, QUERY_5_ID, null, httpServletRequest, null, null);
         assertEquals(HttpStatus.OK, response.getStatusCode());
         assertNotNull(response.getBody());
     }
 
     @Test
-    public void getData_head_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException,
-            NotAllowedException, SQLException, QueryNotFoundException, TableMalformedException, QueryMalformedException,
-            DatabaseUnavailableException, PaginationException, MetadataServiceException {
+    public void getData_head_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException,
+            UserNotFoundException, NotAllowedException, SQLException, QueryNotFoundException, TableMalformedException,
+            QueryMalformedException, DatabaseUnavailableException, PaginationException, MetadataServiceException,
+            TableNotFoundException, ViewMalformedException, ViewNotFoundException {
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_3_ID))
@@ -421,7 +472,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
                 .thenReturn("HEAD");
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = subsetEndpoint.getData(DATABASE_3_ID, QUERY_5_ID, null, httpServletRequest, null, null);
+        final ResponseEntity<List<Map<String, Object>>> response = subsetEndpoint.getData(DATABASE_3_ID, QUERY_5_ID, null, httpServletRequest, null, null);
         assertEquals(HttpStatus.OK, response.getStatusCode());
         assertNotNull(response.getHeaders().get("X-Count"));
         assertEquals(1, response.getHeaders().get("X-Count").size());
@@ -432,22 +483,26 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @WithMockUser(username = USER_1_USERNAME)
     public void getData_private_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException,
             UserNotFoundException, DatabaseUnavailableException, NotAllowedException, TableMalformedException,
-            QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, MetadataServiceException {
+            QueryMalformedException, QueryNotFoundException, PaginationException, SQLException,
+            MetadataServiceException, TableNotFoundException, ViewMalformedException, ViewNotFoundException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID))
                 .thenReturn(DATABASE_1_PRIVILEGED_DTO);
-        when(httpServletRequest.getMethod())
-                .thenReturn("GET");
         when(subsetService.findById(DATABASE_1_PRIVILEGED_DTO, QUERY_1_ID))
                 .thenReturn(QUERY_1_DTO);
         when(subsetService.reExecuteCount(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO))
                 .thenReturn(QUERY_1_RESULT_NUMBER);
-        when(subsetService.reExecute(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, 0L, 10L, null, null))
-                .thenReturn(QUERY_1_RESULT_DTO);
+        when(subsetService.getData(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, 0L, 10L))
+                .thenReturn(mock);
+        when(schemaService.inspectView(eq(DATABASE_1_PRIVILEGED_DTO), anyString()))
+                .thenReturn(VIEW_1_DTO);
+        when(httpServletRequest.getMethod())
+                .thenReturn("GET");
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = subsetEndpoint.getData(DATABASE_1_ID, QUERY_1_ID, USER_1_PRINCIPAL, httpServletRequest, null, null);
+        final ResponseEntity<List<Map<String, Object>>> response = subsetEndpoint.getData(DATABASE_1_ID, QUERY_1_ID, USER_1_PRINCIPAL, httpServletRequest, null, null);
         assertEquals(HttpStatus.OK, response.getStatusCode());
         assertNotNull(response.getBody());
     }
@@ -489,7 +544,8 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @WithMockUser(username = USER_1_USERNAME)
     public void getData_privateHead_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException,
             UserNotFoundException, DatabaseUnavailableException, NotAllowedException, TableMalformedException,
-            QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, MetadataServiceException {
+            QueryMalformedException, QueryNotFoundException, PaginationException, SQLException,
+            MetadataServiceException, TableNotFoundException, ViewMalformedException, ViewNotFoundException {
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID))
@@ -502,7 +558,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
                 .thenReturn("HEAD");
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = subsetEndpoint.getData(DATABASE_1_ID, QUERY_1_ID, USER_1_PRINCIPAL, httpServletRequest, null, null);
+        final ResponseEntity<List<Map<String, Object>>> response = subsetEndpoint.getData(DATABASE_1_ID, QUERY_1_ID, USER_1_PRINCIPAL, httpServletRequest, null, null);
         assertEquals(HttpStatus.OK, response.getStatusCode());
         assertNotNull(response.getHeaders().get("X-Count"));
         assertEquals(1, response.getHeaders().get("X-Count").size());
@@ -512,8 +568,8 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     @Test
     @WithMockUser(username = USER_1_USERNAME)
     public void getData_unavailable_fails() throws DatabaseNotFoundException, RemoteUnavailableException, SQLException,
-            UserNotFoundException, NotAllowedException, TableMalformedException, QueryNotFoundException,
-            MetadataServiceException {
+            UserNotFoundException, QueryNotFoundException, MetadataServiceException, QueryMalformedException,
+            TableNotFoundException, ViewMalformedException {
 
         /* mock */
         when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID))
@@ -524,7 +580,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
                 .thenReturn("GET");
         doThrow(SQLException.class)
                 .when(subsetService)
-                .reExecute(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, 0L, 10L, null, null);
+                .getData(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, 0L, 10L);
 
         /* test */
         assertThrows(DatabaseUnavailableException.class, () -> {
@@ -654,7 +710,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest {
     protected void generic_findById(Long subsetId, MediaType accept, Instant timestamp) throws UserNotFoundException,
             DatabaseUnavailableException, StorageUnavailableException, QueryMalformedException, QueryNotFoundException,
             DatabaseNotFoundException, RemoteUnavailableException, FormatNotAvailableException,
-            StorageNotFoundException, MetadataServiceException, ViewNotFoundException, MalformedException {
+            MetadataServiceException, TableNotFoundException, ViewMalformedException, SQLException {
 
         /* mock */
         when(mockHttpServletRequest.getHeader("Accept"))
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 d9adc26ffeedfe80ae6d0436e46ed3216550e5e2..9058542c5494d1829cd206c613b6f77ccb74ba87 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
@@ -1,9 +1,7 @@
 package at.tuwien.endpoint;
 
-import at.tuwien.ExportResourceDto;
 import at.tuwien.api.database.DatabaseAccessDto;
 import at.tuwien.api.database.query.ImportDto;
-import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.*;
 import at.tuwien.api.database.table.internal.PrivilegedTableDto;
 import at.tuwien.endpoints.TableEndpoint;
@@ -14,6 +12,9 @@ import at.tuwien.service.TableService;
 import at.tuwien.test.AbstractUnitTest;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.extern.log4j.Log4j2;
+import org.apache.spark.sql.Dataset;
+import org.apache.spark.sql.Row;
+import org.apache.spark.sql.SparkSession;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -31,11 +32,11 @@ import org.springframework.security.test.context.support.WithAnonymousUser;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
-import java.io.InputStream;
 import java.sql.SQLException;
 import java.time.Instant;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Stream;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -50,6 +51,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest {
     private TableEndpoint tableEndpoint;
 
     @Autowired
+    private SparkSession sparkSession;
+
+    @MockBean
     private HttpServletRequest httpServletRequest;
 
     @MockBean
@@ -269,41 +273,43 @@ public class TableEndpointUnitTest extends AbstractUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void getData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException,
-            SQLException, QueryMalformedException, RemoteUnavailableException, PaginationException, MetadataServiceException,
-            NotAllowedException {
+    public void getData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, QueryMalformedException,
+            RemoteUnavailableException, PaginationException, MetadataServiceException, NotAllowedException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getTableById(DATABASE_3_ID, TABLE_8_ID))
                 .thenReturn(TABLE_8_PRIVILEGED_DTO);
-        when(tableService.getPaginatedData(eq(TABLE_8_PRIVILEGED_DTO), any(Instant.class), eq(0L), eq(10L)))
-                .thenReturn(TABLE_8_DATA_DTO);
+        when(tableService.getData(eq(DATABASE_3_PRIVILEGED_DTO), eq(TABLE_8_INTERNAL_NAME), any(Instant.class), eq(null), eq(null), eq(null), eq(null)))
+                .thenReturn(mock);
+        when(httpServletRequest.getMethod())
+                .thenReturn("GET");
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = tableEndpoint.getData(DATABASE_3_ID, TABLE_8_ID, null, null, null, httpServletRequest, null);
+        final ResponseEntity<List<Map<String, Object>>> response = tableEndpoint.getData(DATABASE_3_ID, TABLE_8_ID, null, null, null, httpServletRequest, null);
         assertEquals(HttpStatus.OK, response.getStatusCode());
 
     }
 
     @Test
     @WithAnonymousUser
-    public void getData_head_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException,
-            SQLException, QueryMalformedException, RemoteUnavailableException, PaginationException, MetadataServiceException,
-            NotAllowedException {
-        final HttpServletRequest mock = mock(HttpServletRequest.class);
+    public void getData_head_succeeds() throws DatabaseUnavailableException, TableNotFoundException,
+            SQLException, QueryMalformedException, RemoteUnavailableException, PaginationException,
+            MetadataServiceException, NotAllowedException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getTableById(DATABASE_3_ID, TABLE_8_ID))
                 .thenReturn(TABLE_8_PRIVILEGED_DTO);
-        when(mock.getMethod())
-                .thenReturn("HEAD");
         when(tableService.getCount(eq(TABLE_8_PRIVILEGED_DTO), any(Instant.class)))
                 .thenReturn(3L);
-        when(tableService.getPaginatedData(eq(TABLE_8_PRIVILEGED_DTO), any(Instant.class), eq(0L), eq(10L)))
-                .thenReturn(TABLE_8_DATA_DTO);
+        when(tableService.getData(eq(DATABASE_3_PRIVILEGED_DTO), eq(TABLE_8_INTERNAL_NAME), any(Instant.class), eq(null), eq(null), eq(null), eq(null)))
+                .thenReturn(mock);
+        when(httpServletRequest.getMethod())
+                .thenReturn("HEAD");
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = tableEndpoint.getData(DATABASE_3_ID, TABLE_8_ID, null, null, null, mock, null);
+        final ResponseEntity<List<Map<String, Object>>> response = tableEndpoint.getData(DATABASE_3_ID, TABLE_8_ID, null, null, null, httpServletRequest, null);
         assertEquals(HttpStatus.OK, response.getStatusCode());
         assertNotNull(response.getHeaders().get("Access-Control-Expose-Headers"));
         assertEquals("X-Count", response.getHeaders().get("Access-Control-Expose-Headers").get(0));
@@ -348,14 +354,16 @@ public class TableEndpointUnitTest extends AbstractUnitTest {
     @Test
     @WithAnonymousUser
     public void getData_unavailable_fails() throws TableNotFoundException, RemoteUnavailableException,
-            MetadataServiceException, TableMalformedException, SQLException {
+            MetadataServiceException, QueryMalformedException {
 
         /* mock */
         when(metadataServiceGateway.getTableById(DATABASE_3_ID, TABLE_8_ID))
                 .thenReturn(TABLE_8_PRIVILEGED_DTO);
-        doThrow(SQLException.class)
+        doThrow(QueryMalformedException.class)
                 .when(tableService)
-                .getPaginatedData(eq(TABLE_8_PRIVILEGED_DTO), any(Instant.class), eq(0L), eq(10L));
+                .getData(eq(DATABASE_3_PRIVILEGED_DTO), eq(TABLE_8_INTERNAL_NAME), any(Instant.class), eq(null), eq(null), eq(null), eq(null));
+        when(httpServletRequest.getMethod())
+                .thenReturn("GET");
 
         /* test */
         assertThrows(DatabaseUnavailableException.class, () -> {
@@ -385,19 +393,22 @@ public class TableEndpointUnitTest extends AbstractUnitTest {
     @WithMockUser(username = USER_2_USERNAME)
     @MethodSource("anyAccess_parameters")
     public void getData_private_succeeds(String name, DatabaseAccessDto access) throws DatabaseUnavailableException,
-            TableNotFoundException, TableMalformedException, SQLException, QueryMalformedException,
-            RemoteUnavailableException, PaginationException, MetadataServiceException, NotAllowedException {
+            TableNotFoundException, QueryMalformedException, RemoteUnavailableException, PaginationException,
+            MetadataServiceException, NotAllowedException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID))
                 .thenReturn(TABLE_1_PRIVILEGED_DTO);
         when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_2_ID))
                 .thenReturn(access);
-        when(tableService.getPaginatedData(eq(TABLE_1_PRIVILEGED_DTO), any(Instant.class), eq(0L), eq(10L)))
-                .thenReturn(TABLE_1_DATA_DTO);
+        when(tableService.getData(eq(DATABASE_1_PRIVILEGED_DTO), eq(TABLE_1_INTERNAL_NAME), any(Instant.class), eq(null), eq(null), eq(null), eq(null)))
+                .thenReturn(mock);
+        when(httpServletRequest.getMethod())
+                .thenReturn("GET");
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = tableEndpoint.getData(DATABASE_1_ID, TABLE_1_ID, null, null, null, httpServletRequest, USER_2_PRINCIPAL);
+        final ResponseEntity<List<Map<String, Object>>> response = tableEndpoint.getData(DATABASE_1_ID, TABLE_1_ID, null, null, null, httpServletRequest, USER_2_PRINCIPAL);
         assertEquals(HttpStatus.OK, response.getStatusCode());
     }
 
@@ -1125,24 +1136,19 @@ public class TableEndpointUnitTest extends AbstractUnitTest {
 
     @Test
     @WithAnonymousUser
-    public void exportData_succeeds() throws DatabaseUnavailableException, TableNotFoundException, NotAllowedException,
-            StorageUnavailableException, QueryMalformedException, RemoteUnavailableException, StorageNotFoundException,
-            SQLException, MetadataServiceException, MalformedException {
-        final ExportResourceDto mock = ExportResourceDto.builder()
-                .filename("deadbeef")
-                .resource(new InputStreamResource(InputStream.nullInputStream()))
-                .build();
+    public void exportData_succeeds() throws TableNotFoundException, NotAllowedException,
+            StorageUnavailableException, QueryMalformedException, RemoteUnavailableException, MetadataServiceException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getTableById(DATABASE_3_ID, TABLE_8_ID))
                 .thenReturn(TABLE_8_PRIVILEGED_DTO);
-        when(tableService.exportDataset(eq(TABLE_8_PRIVILEGED_DTO), any(Instant.class)))
+        when(tableService.getData(eq(DATABASE_3_PRIVILEGED_DTO), eq(TABLE_8_INTERNAL_NAME), any(Instant.class), eq(null), eq(null), eq(null), eq(null)))
                 .thenReturn(mock);
 
         /* test */
         final ResponseEntity<InputStreamResource> response = tableEndpoint.exportDataset(DATABASE_3_ID, TABLE_8_ID, null, null);
         assertEquals(HttpStatus.OK, response.getStatusCode());
-
     }
 
     @ParameterizedTest
@@ -1150,24 +1156,20 @@ public class TableEndpointUnitTest extends AbstractUnitTest {
     @MethodSource("anyAccess_parameters")
     public void exportData_private_succeeds(String name, DatabaseAccessDto access) throws TableNotFoundException,
             NotAllowedException, StorageUnavailableException, QueryMalformedException, RemoteUnavailableException,
-            MetadataServiceException, MalformedException {
-        final ExportResourceDto mock = ExportResourceDto.builder()
-                .filename("deadbeef")
-                .resource(new InputStreamResource(InputStream.nullInputStream()))
-                .build();
+            MetadataServiceException {
+        final Dataset<Row> mock = sparkSession.emptyDataFrame();
 
         /* mock */
         when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID))
                 .thenReturn(TABLE_1_PRIVILEGED_DTO);
         when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_2_ID))
                 .thenReturn(access);
-        when(tableService.exportDataset(eq(TABLE_1_PRIVILEGED_DTO), any(Instant.class)))
+        when(tableService.getData(eq(DATABASE_1_PRIVILEGED_DTO), eq(TABLE_1_INTERNAL_NAME), any(Instant.class), eq(null), eq(null), eq(null), eq(null)))
                 .thenReturn(mock);
 
         /* test */
         final ResponseEntity<InputStreamResource> response = tableEndpoint.exportDataset(DATABASE_1_ID, TABLE_1_ID, null, USER_2_PRINCIPAL);
         assertEquals(HttpStatus.OK, response.getStatusCode());
-
     }
 
     @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 2e856b2d2fbdcfc22368bafa72e99e77798a83a1..8062de7b454306dd86c1118c7a7ffca65794d905 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,7 +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.*;
 import at.tuwien.gateway.MetadataServiceGateway;
@@ -22,10 +21,10 @@ import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
 import java.sql.SQLException;
-import java.time.Instant;
 import java.util.List;
 
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.*;
 
 @Log4j2
@@ -189,15 +188,15 @@ public class ViewEndpointUnitTest extends AbstractUnitTest {
 
     @Test
     @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"})
-    public void delete_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException,
-            SQLException, DatabaseUnavailableException, ViewNotFoundException, MetadataServiceException {
+    public void delete_succeeds() throws RemoteUnavailableException, ViewMalformedException, ViewNotFoundException,
+            SQLException, DatabaseUnavailableException, MetadataServiceException {
 
         /* mock */
-        when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID))
-                .thenReturn(DATABASE_1_PRIVILEGED_DTO);
+        when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID))
+                .thenReturn(VIEW_1_PRIVILEGED_DTO);
         doNothing()
                 .when(viewService)
-                .delete(VIEW_1_PRIVILEGED_DTO);
+                .delete(DATABASE_1_PRIVILEGED_DTO, VIEW_1_INTERNAL_NAME);
 
         /* test */
         final ResponseEntity<Void> response = viewEndpoint.delete(DATABASE_1_ID, VIEW_1_ID);
@@ -214,7 +213,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest {
                 .thenReturn(VIEW_1_PRIVILEGED_DTO);
         doThrow(SQLException.class)
                 .when(viewService)
-                .delete(VIEW_1_PRIVILEGED_DTO);
+                .delete(DATABASE_1_PRIVILEGED_DTO, VIEW_1_INTERNAL_NAME);
 
         /* test */
         assertThrows(DatabaseUnavailableException.class, () -> {
@@ -232,7 +231,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest {
                 .thenReturn(DATABASE_1_PRIVILEGED_DTO);
         doNothing()
                 .when(viewService)
-                .delete(VIEW_1_PRIVILEGED_DTO);
+                .delete(DATABASE_1_PRIVILEGED_DTO, VIEW_1_INTERNAL_NAME);
 
         /* test */
         assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
@@ -256,77 +255,77 @@ public class ViewEndpointUnitTest extends AbstractUnitTest {
         });
     }
 
-    @Test
-    @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"})
-    public void getData_private_succeeds() throws RemoteUnavailableException, ViewNotFoundException, ViewMalformedException,
-            SQLException, DatabaseUnavailableException, QueryMalformedException, PaginationException,
-            NotAllowedException, MetadataServiceException {
-
-        /* mock */
-        when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID))
-                .thenReturn(VIEW_1_PRIVILEGED_DTO);
-        when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID))
-                .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO);
-        when(httpServletRequest.getMethod())
-                .thenReturn("GET");
-        when(viewService.data(eq(VIEW_1_PRIVILEGED_DTO), any(Instant.class), eq(0L), eq(10L)))
-                .thenReturn(VIEW_1_DATA_DTO);
-
-        /* test */
-        final ResponseEntity<QueryResultDto> response = viewEndpoint.getData(DATABASE_1_ID, VIEW_1_ID, null, null, null, httpServletRequest, USER_1_PRINCIPAL);
-        assertEquals(HttpStatus.OK, response.getStatusCode());
-        assertNotNull(response.getBody());
-    }
-
-    @Test
-    @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"})
-    public void getData_privateHead_succeeds() throws RemoteUnavailableException, ViewNotFoundException,
-            ViewMalformedException, SQLException, DatabaseUnavailableException, QueryMalformedException,
-            PaginationException, NotAllowedException, MetadataServiceException {
-
-        /* mock */
-        when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_3_ID))
-                .thenReturn(VIEW_3_PRIVILEGED_DTO);
-        when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID))
-                .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO);
-        when(httpServletRequest.getMethod())
-                .thenReturn("HEAD");
-        when(viewService.count(eq(VIEW_3_PRIVILEGED_DTO), any(Instant.class)))
-                .thenReturn(VIEW_3_DATA_COUNT);
-
-        /* test */
-        final ResponseEntity<QueryResultDto> response = viewEndpoint.getData(DATABASE_1_ID, VIEW_3_ID, null, null, null, httpServletRequest, USER_1_PRINCIPAL);
-        assertEquals(HttpStatus.OK, response.getStatusCode());
-        assertNotNull(response.getHeaders().get("X-Count"));
-        assertEquals(1, response.getHeaders().get("X-Count").size());
-        assertEquals(VIEW_3_DATA_COUNT, Long.parseLong(response.getHeaders().get("X-Count").get(0)));
-        assertNotNull(response.getHeaders().get("Access-Control-Expose-Headers"));
-        assertEquals(1, response.getHeaders().get("Access-Control-Expose-Headers").size());
-        assertEquals("X-Count", response.getHeaders().get("Access-Control-Expose-Headers").get(0));
-        assertNull(response.getBody());
-    }
-
-    @Test
-    @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"})
-    public void getData_unavailable_fails() throws RemoteUnavailableException, ViewNotFoundException, SQLException,
-            ViewMalformedException, NotAllowedException, MetadataServiceException {
-
-        /* mock */
-        when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID))
-                .thenReturn(VIEW_1_PRIVILEGED_DTO);
-        when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID))
-                .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO);
-        when(httpServletRequest.getMethod())
-                .thenReturn("GET");
-        doThrow(SQLException.class)
-                .when(viewService)
-                .data(eq(VIEW_1_PRIVILEGED_DTO), any(Instant.class), eq(0L), eq(10L));
-
-        /* test */
-        assertThrows(DatabaseUnavailableException.class, () -> {
-            viewEndpoint.getData(DATABASE_1_ID, VIEW_1_ID, null, null, null, httpServletRequest, USER_1_PRINCIPAL);
-        });
-    }
+//    @Test
+//    @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"})
+//    public void getData_private_succeeds() throws RemoteUnavailableException, ViewNotFoundException, ViewMalformedException,
+//            SQLException, DatabaseUnavailableException, QueryMalformedException, PaginationException,
+//            NotAllowedException, MetadataServiceException {
+//
+//        /* mock */
+//        when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID))
+//                .thenReturn(VIEW_1_PRIVILEGED_DTO);
+//        when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID))
+//                .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO);
+//        when(httpServletRequest.getMethod())
+//                .thenReturn("GET");
+//        when(viewService.data(eq(VIEW_1_PRIVILEGED_DTO), any(Instant.class), eq(0L), eq(10L)))
+//                .thenReturn(VIEW_1_DATA_DTO);
+//
+//        /* test */
+//        final ResponseEntity<QueryResultDto> response = viewEndpoint.getData(DATABASE_1_ID, VIEW_1_ID, null, null, null, httpServletRequest, USER_1_PRINCIPAL);
+//        assertEquals(HttpStatus.OK, response.getStatusCode());
+//        assertNotNull(response.getBody());
+//    }
+//
+//    @Test
+//    @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"})
+//    public void getData_privateHead_succeeds() throws RemoteUnavailableException, ViewNotFoundException,
+//            ViewMalformedException, SQLException, DatabaseUnavailableException, QueryMalformedException,
+//            PaginationException, NotAllowedException, MetadataServiceException {
+//
+//        /* mock */
+//        when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_3_ID))
+//                .thenReturn(VIEW_3_PRIVILEGED_DTO);
+//        when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID))
+//                .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO);
+//        when(httpServletRequest.getMethod())
+//                .thenReturn("HEAD");
+//        when(viewService.count(eq(VIEW_3_PRIVILEGED_DTO), any(Instant.class)))
+//                .thenReturn(VIEW_3_DATA_COUNT);
+//
+//        /* test */
+//        final ResponseEntity<QueryResultDto> response = viewEndpoint.getData(DATABASE_1_ID, VIEW_3_ID, null, null, null, httpServletRequest, USER_1_PRINCIPAL);
+//        assertEquals(HttpStatus.OK, response.getStatusCode());
+//        assertNotNull(response.getHeaders().get("X-Count"));
+//        assertEquals(1, response.getHeaders().get("X-Count").size());
+//        assertEquals(VIEW_3_DATA_COUNT, Long.parseLong(response.getHeaders().get("X-Count").get(0)));
+//        assertNotNull(response.getHeaders().get("Access-Control-Expose-Headers"));
+//        assertEquals(1, response.getHeaders().get("Access-Control-Expose-Headers").size());
+//        assertEquals("X-Count", response.getHeaders().get("Access-Control-Expose-Headers").get(0));
+//        assertNull(response.getBody());
+//    }
+//
+//    @Test
+//    @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"})
+//    public void getData_unavailable_fails() throws RemoteUnavailableException, ViewNotFoundException, SQLException,
+//            ViewMalformedException, NotAllowedException, MetadataServiceException {
+//
+//        /* mock */
+//        when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID))
+//                .thenReturn(VIEW_1_PRIVILEGED_DTO);
+//        when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID))
+//                .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO);
+//        when(httpServletRequest.getMethod())
+//                .thenReturn("GET");
+//        doThrow(SQLException.class)
+//                .when(viewService)
+//                .data(eq(VIEW_1_PRIVILEGED_DTO), any(Instant.class), eq(0L), eq(10L));
+//
+//        /* test */
+//        assertThrows(DatabaseUnavailableException.class, () -> {
+//            viewEndpoint.getData(DATABASE_1_ID, VIEW_1_ID, null, null, null, httpServletRequest, USER_1_PRINCIPAL);
+//        });
+//    }
 
     @Test
     @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"})
@@ -396,7 +395,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest {
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
-            viewEndpoint.exportDataset(DATABASE_1_ID, VIEW_3_ID, USER_3_PRINCIPAL);
+            viewEndpoint.exportDataset(DATABASE_1_ID, VIEW_3_ID, null, USER_3_PRINCIPAL);
         });
     }
 
@@ -412,7 +411,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest {
 
         /* test */
         assertThrows(ViewNotFoundException.class, () -> {
-            viewEndpoint.exportDataset(DATABASE_1_ID, VIEW_1_ID, USER_4_PRINCIPAL);
+            viewEndpoint.exportDataset(DATABASE_1_ID, VIEW_1_ID, null, USER_4_PRINCIPAL);
         });
     }
 
@@ -430,7 +429,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest {
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
-            viewEndpoint.exportDataset(DATABASE_1_ID, VIEW_3_ID, USER_1_PRINCIPAL);
+            viewEndpoint.exportDataset(DATABASE_1_ID, VIEW_3_ID, null, USER_1_PRINCIPAL);
         });
     }
 
diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java
index 6edded0f579ea558176a0bf65526aad674203216..f7c5039a4d2c92b8a43413f83ce7f67c50bf9910 100644
--- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java
+++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java
@@ -63,7 +63,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest {
         headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME);
         headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD);
         headers.set("X-Database", DATABASE_1_INTERNALNAME);
-        headers.set("X-Table", TABLE_1_INTERNALNAME);
+        headers.set("X-Table", TABLE_1_INTERNAL_NAME);
 
         /* mock */
         when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class)))
@@ -79,7 +79,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest {
         assertEquals(CONTAINER_1_PRIVILEGED_USERNAME, response.getDatabase().getContainer().getUsername());
         assertEquals(CONTAINER_1_PRIVILEGED_PASSWORD, response.getDatabase().getContainer().getPassword());
         assertEquals(DATABASE_1_INTERNALNAME, response.getDatabase().getInternalName());
-        assertEquals(TABLE_1_INTERNALNAME, response.getInternalName());
+        assertEquals(TABLE_1_INTERNAL_NAME, response.getInternalName());
     }
 
     @Test
@@ -154,7 +154,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest {
         headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME);
         headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD);
         headers.set("X-Database", DATABASE_1_INTERNALNAME);
-        headers.set("X-Table", TABLE_1_INTERNALNAME);
+        headers.set("X-Table", TABLE_1_INTERNAL_NAME);
 
         /* mock */
         when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class)))
@@ -168,80 +168,6 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest {
         });
     }
 
-    @Test
-    public void getDatabaseByInternalName_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException,
-            MetadataServiceException {
-
-        /* mock */
-        final HttpHeaders headers = new HttpHeaders();
-        headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME);
-        headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD);
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class)))
-                .thenReturn(ResponseEntity.status(HttpStatus.OK)
-                        .headers(headers)
-                        .body(new PrivilegedDatabaseDto[]{DATABASE_1_PRIVILEGED_DTO}));
-
-        /* test */
-        final PrivilegedDatabaseDto response = metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME);
-        assertEquals(response.getId(), response.getId());
-    }
-
-    @Test
-    public void getDatabaseByInternalName_unavailable_fails() {
-
-        /* mock */
-        doThrow(HttpServerErrorException.ServiceUnavailable.class)
-                .when(restTemplate)
-                .exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class));
-
-        /* test */
-        assertThrows(RemoteUnavailableException.class, () -> {
-            metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME);
-        });
-    }
-
-    @Test
-    public void getDatabaseByInternalName_statusCode_fails() {
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class)))
-                .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT)
-                        .body(new PrivilegedDatabaseDto[]{DATABASE_1_PRIVILEGED_DTO}));
-
-        /* test */
-        assertThrows(MetadataServiceException.class, () -> {
-            metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME);
-        });
-    }
-
-    @Test
-    public void getDatabaseByInternalName_emptyBody_fails() {
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class)))
-                .thenReturn(ResponseEntity.ok()
-                        .build());
-
-        /* test */
-        assertThrows(DatabaseNotFoundException.class, () -> {
-            metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME);
-        });
-    }
-
-    @Test
-    public void getDatabaseByInternalName_notFound_fails() {
-
-        /* mock */
-        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(PrivilegedDatabaseDto[].class)))
-                .thenReturn(ResponseEntity.ok()
-                        .body(new PrivilegedDatabaseDto[]{}));
-
-        /* test */
-        assertThrows(DatabaseNotFoundException.class, () -> {
-            metadataServiceGateway.getDatabaseByInternalName(DATABASE_1_INTERNALNAME);
-        });
-    }
-
     @Test
     public void getDatabaseById_succeeds() throws RemoteUnavailableException, MetadataServiceException,
             DatabaseNotFoundException {
diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java
index f074abcc875b1f5389aa0c371f05247fac305cc9..a7a83a6184cab52aa4739df2005680a60eb7f81b 100644
--- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java
+++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/ActuatorEndpointMvcTest.java
@@ -1,6 +1,5 @@
 package at.tuwien.mvc;
 
-import at.tuwien.annotations.MockAmqp;
 import at.tuwien.test.AbstractUnitTest;
 import lombok.extern.log4j.Log4j2;
 import org.junit.jupiter.api.Test;
@@ -21,7 +20,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 @AutoConfigureMockMvc
 @SpringBootTest
 @AutoConfigureObservability
-@MockAmqp
 public class ActuatorEndpointMvcTest extends AbstractUnitTest {
 
     @Autowired
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 d1426cdf69db414892baed59cd121087cea8cc1b..b5ed475ea83a42db6f458d95254a081c5de5ae95 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
@@ -12,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;
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 f4bd429a9039ab2f2fb36c4fc2fce653ceda8054..01bce16b08f84e7ad3901beb143ef0737d9ad571 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
@@ -136,7 +136,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest {
             /* ignore */
         }
         try {
-            subsetEndpoint.create(DATABASE_1_ID, ExecuteStatementDto.builder().statement(QUERY_5_STATEMENT).build(), USER_1_PRINCIPAL, 0L, 10L, null);
+            subsetEndpoint.create(DATABASE_1_ID, ExecuteStatementDto.builder().statement(QUERY_5_STATEMENT).build(), USER_1_PRINCIPAL, httpServletRequest, null, 0L, 10L);
         } catch (Exception e) {
             /* ignore */
         }
diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/SubsetEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/SubsetEndpointMvcTest.java
index 94341550a389505f07301bb34c105547aaaec9b8..6a3851b445cf83b74eaccf1b6a3b86bf61ec03d8 100644
--- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/SubsetEndpointMvcTest.java
+++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/SubsetEndpointMvcTest.java
@@ -1,6 +1,5 @@
 package at.tuwien.mvc;
 
-import at.tuwien.annotations.MockAmqp;
 import at.tuwien.gateway.MetadataServiceGateway;
 import at.tuwien.service.SubsetService;
 import at.tuwien.test.AbstractUnitTest;
@@ -26,7 +25,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 @AutoConfigureMockMvc
 @SpringBootTest
 @AutoConfigureObservability
-@MockAmqp
 public class SubsetEndpointMvcTest extends AbstractUnitTest {
 
     @MockBean
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
index b6867b0c880cdb78ae3c8db040b962db8fdf0630..d5cf6dd22e3cbe341ebe612d246bb716ff5c9f6a 100644
--- 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
@@ -182,8 +182,8 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest {
         assertNotNull(unique0.getTable());
         assertEquals("some_constraint", unique0.getName());
         assertNull(unique0.getTable().getId());
-        assertEquals(TABLE_1_INTERNALNAME, unique0.getTable().getName());
-        assertEquals(TABLE_1_INTERNALNAME, unique0.getTable().getInternalName());
+        assertEquals(TABLE_1_INTERNAL_NAME, unique0.getTable().getName());
+        assertEquals(TABLE_1_INTERNAL_NAME, unique0.getTable().getInternalName());
         assertEquals(TABLE_1_DESCRIPTION, unique0.getTable().getDescription());
         assertTrue(unique0.getTable().getIsVersioned());
         assertNotNull(unique0.getColumns());
@@ -221,8 +221,8 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest {
         final TableBriefDto fk0table = fk0.getTable();
         assertNull(fk0table.getId());
         assertEquals(DATABASE_1_ID, fk0table.getDatabaseId());
-        assertEquals(TABLE_1_INTERNALNAME, fk0table.getName());
-        assertEquals(TABLE_1_INTERNALNAME, fk0table.getInternalName());
+        assertEquals(TABLE_1_INTERNAL_NAME, fk0table.getName());
+        assertEquals(TABLE_1_INTERNAL_NAME, fk0table.getInternalName());
         assertNotNull(fk0.getOnDelete());
         assertNotNull(fk0.getOnUpdate());
         assertNotNull(fk0.getReferencedTable());
diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java
index dc4179f61d44a49ce783c3b1e2e8b25ff7db0fb9..215e919844cab0f595b040eeb340e9f51cec2bde 100644
--- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java
+++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java
@@ -1,18 +1,13 @@
 package at.tuwien.service;
 
-import at.tuwien.ExportResourceDto;
 import at.tuwien.api.database.query.QueryDto;
-import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.identifier.IdentifierDto;
 import at.tuwien.config.MariaDbConfig;
 import at.tuwien.config.MariaDbContainerConfig;
-import at.tuwien.config.S3Config;
 import at.tuwien.exception.*;
 import at.tuwien.gateway.MetadataServiceGateway;
 import at.tuwien.test.AbstractUnitTest;
 import lombok.extern.log4j.Log4j2;
-import org.apache.commons.lang3.RandomStringUtils;
-import org.apache.spark.sql.Dataset;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -24,15 +19,11 @@ import org.testcontainers.containers.MariaDBContainer;
 import org.testcontainers.junit.jupiter.Container;
 import org.testcontainers.junit.jupiter.Testcontainers;
 
-import java.io.IOException;
-import java.math.BigInteger;
 import java.sql.SQLException;
-import java.time.Instant;
 import java.util.List;
 import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.when;
 
 @Log4j2
@@ -47,15 +38,9 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest {
     @MockBean
     private MetadataServiceGateway metadataServiceGateway;
 
-    @MockBean
-    private StorageService storageService;
-
     @Container
     private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer();
 
-    @Autowired
-    private S3Config s3Config;
-
     @BeforeEach
     public void beforeEach() throws SQLException {
         genesis();
@@ -64,138 +49,6 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest {
         MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_DTO);
     }
 
-    @Test
-    public void execute_succeeds() throws QueryStoreInsertException, TableMalformedException, SQLException,
-            QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException,
-            MetadataServiceException, DatabaseNotFoundException, InterruptedException {
-
-        /* pre-condition */
-        Thread.sleep(1000) /* wait for test container some more */;
-
-        /* mock */
-        when(metadataServiceGateway.getUserById(USER_1_ID))
-                .thenReturn(USER_1_DTO);
-
-        /* test */
-        final QueryResultDto response = queryService.execute(DATABASE_1_PRIVILEGED_DTO, QUERY_1_STATEMENT, Instant.now(), USER_1_ID, 0L, 10L, null, null);
-        assertNotNull(response);
-        assertNotNull(response.getId());
-        assertNotNull(response.getHeaders());
-        assertEquals(5, response.getHeaders().size());
-        assertEquals(List.of(Map.of("id", 0), Map.of("date", 1), Map.of("location", 2), Map.of("mintemp", 3), Map.of("rainfall", 4)), response.getHeaders());
-        assertNotNull(response.getResult());
-        assertEquals(3, response.getResult().size());
-        /* row 0 */
-        assertEquals(BigInteger.valueOf(1L), response.getResult().get(0).get("id"));
-        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(BigInteger.valueOf(2L), response.getResult().get(1).get("id"));
-        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(BigInteger.valueOf(3L), response.getResult().get(2).get("id"));
-        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 execute_joinWithAlias_succeeds() throws QueryStoreInsertException, TableMalformedException,
-            SQLException, QueryNotFoundException, UserNotFoundException, NotAllowedException,
-            RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, InterruptedException {
-
-        /* pre-condition */
-        Thread.sleep(1000) /* wait for test container some more */;
-
-        /* mock */
-        when(metadataServiceGateway.getUserById(USER_1_ID))
-                .thenReturn(USER_1_DTO);
-
-        /* test */
-        final QueryResultDto response = queryService.execute(DATABASE_1_PRIVILEGED_DTO, QUERY_7_STATEMENT, Instant.now(), USER_1_ID, 0L, 10L, null, null);
-        assertNotNull(response);
-        assertNotNull(response.getId());
-        assertNotNull(response.getHeaders());
-        assertEquals(5, response.getHeaders().size());
-        assertEquals(List.of(Map.of("id", 0), Map.of("date", 1), Map.of("location", 2), Map.of("lat", 3), Map.of("lng", 4)), response.getHeaders());
-        assertNotNull(response.getResult());
-        assertEquals(1, response.getResult().size());
-        /* row 0 */
-        assertEquals(BigInteger.valueOf(1L), response.getResult().get(0).get("id"));
-        assertEquals(Instant.ofEpochSecond(1228089600), response.getResult().get(0).get("date"));
-        assertEquals("Albury", response.getResult().get(0).get("location"));
-        assertEquals(-36.0653583, response.getResult().get(0).get("lat"));
-        assertEquals(146.9112214, response.getResult().get(0).get("lng"));
-    }
-
-    @Test
-    public void execute_oneResult_succeeds() throws QueryStoreInsertException, TableMalformedException, SQLException,
-            QueryNotFoundException, UserNotFoundException, NotAllowedException, RemoteUnavailableException,
-            MetadataServiceException, DatabaseNotFoundException, InterruptedException {
-
-        /* pre-condition */
-        Thread.sleep(1000) /* wait for test container some more */;
-
-        /* mock */
-        when(metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID))
-                .thenReturn(List.of(IDENTIFIER_2_DTO));
-        when(metadataServiceGateway.getUserById(USER_1_ID))
-                .thenReturn(USER_1_DTO);
-
-        /* test */
-        final QueryResultDto response = queryService.execute(DATABASE_1_PRIVILEGED_DTO, QUERY_1_STATEMENT, Instant.now(), USER_1_ID, 0L, 1L, null, null);
-        assertNotNull(response);
-        assertNotNull(response.getId());
-        assertNotNull(response.getHeaders());
-        assertEquals(5, response.getHeaders().size());
-        assertEquals(List.of(Map.of("id", 0), Map.of("date", 1), Map.of("location", 2), Map.of("mintemp", 3), Map.of("rainfall", 4)), response.getHeaders());
-        assertNotNull(response.getResult());
-        assertEquals(1, response.getResult().size());
-        /* row 0 */
-        assertEquals(BigInteger.valueOf(1L), response.getResult().get(0).get("id"));
-        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"));
-    }
-
-    @Test
-    public void execute_oneResultPagination_succeeds() throws QueryStoreInsertException, TableMalformedException,
-            SQLException, QueryNotFoundException, UserNotFoundException, NotAllowedException,
-            RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException, InterruptedException {
-
-        /* pre-condition */
-        Thread.sleep(1000) /* wait for test container some more */;
-
-        /* mock */
-        when(metadataServiceGateway.getUserById(USER_1_ID))
-                .thenReturn(USER_1_DTO);
-        when(metadataServiceGateway.getIdentifiers(eq(DATABASE_1_ID), anyLong()))
-                .thenReturn(List.of());
-
-        /* test */
-        final QueryResultDto response = queryService.execute(DATABASE_1_PRIVILEGED_DTO, QUERY_1_STATEMENT, Instant.now(), USER_1_ID, 1L, 1L, null, null);
-        assertNotNull(response);
-        assertNotNull(response.getId());
-        assertNotNull(response.getHeaders());
-        assertEquals(5, response.getHeaders().size());
-        assertEquals(List.of(Map.of("id", 0), Map.of("date", 1), Map.of("location", 2), Map.of("mintemp", 3), Map.of("rainfall", 4)), response.getHeaders());
-        assertNotNull(response.getResult());
-        assertEquals(1, response.getResult().size());
-        /* row 1 */
-        assertEquals(BigInteger.valueOf(2L), response.getResult().get(0).get("id"));
-        assertEquals(Instant.ofEpochSecond(1228176000), response.getResult().get(0).get("date"));
-        assertEquals("Albury", response.getResult().get(0).get("location"));
-        assertEquals(7.4, response.getResult().get(0).get("mintemp"));
-        assertEquals(0.0, response.getResult().get(0).get("rainfall"));
-    }
-
     @Test
     public void findAll_succeeds() throws SQLException, QueryNotFoundException, RemoteUnavailableException,
             MetadataServiceException, DatabaseNotFoundException, InterruptedException {
@@ -250,8 +103,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest {
             InterruptedException {
 
         /* mock */
-        when(metadataServiceGateway.getUserById(USER_1_ID))
-                .thenReturn(USER_1_DTO);
+        when(metadataServiceGateway.getUserById(QUERY_2_CREATED_BY))
+                .thenReturn(QUERY_2_CREATOR);
 
         /* test */
         persist_generic(QUERY_2_ID, List.of(IDENTIFIER_5_DTO), true);
@@ -266,8 +119,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest {
             InterruptedException {
 
         /* mock */
-        when(metadataServiceGateway.getUserById(USER_1_ID))
-                .thenReturn(USER_1_DTO);
+        when(metadataServiceGateway.getUserById(QUERY_1_CREATED_BY))
+                .thenReturn(QUERY_1_CREATOR);
 
         /* test */
         persist_generic(QUERY_1_ID, List.of(IDENTIFIER_2_DTO), false);
@@ -295,18 +148,6 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest {
         });
     }
 
-    @Test
-    public void export_succeeds() throws SQLException, StorageUnavailableException, QueryMalformedException,
-            RemoteUnavailableException, IOException, StorageNotFoundException, InterruptedException,
-            AnalyseServiceException, ViewNotFoundException, MalformedException {
-
-        /* mock */
-        MariaDbConfig.dropQueryStore(DATABASE_1_PRIVILEGED_DTO);
-
-        /* test */
-        export_generic();
-    }
-
     protected void findById_generic(Long queryId) throws RemoteUnavailableException, SQLException,
             UserNotFoundException, QueryNotFoundException, MetadataServiceException, DatabaseNotFoundException,
             InterruptedException {
@@ -317,8 +158,8 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest {
         /* mock */
         when(metadataServiceGateway.getIdentifiers(DATABASE_1_ID, QUERY_1_ID))
                 .thenReturn(List.of(IDENTIFIER_2_DTO));
-        when(metadataServiceGateway.getUserById(USER_1_ID))
-                .thenReturn(USER_1_DTO);
+        when(metadataServiceGateway.getUserById(QUERY_1_CREATED_BY))
+                .thenReturn(QUERY_1_CREATOR);
         MariaDbConfig.insertQueryStore(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, USER_1_ID);
 
         /* test */
@@ -373,23 +214,4 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest {
         assertEquals(0, response.size());
     }
 
-    protected void export_generic() throws StorageUnavailableException, SQLException, RemoteUnavailableException,
-            QueryMalformedException, StorageNotFoundException, IOException, InterruptedException,
-            AnalyseServiceException, ViewNotFoundException, MalformedException {
-        final String filename = RandomStringUtils.randomAlphanumeric(40).toLowerCase() + ".tmp";
-        EXPORT_RESOURCE_DTO.setFilename(filename);
-
-        /* pre-condition */
-        Thread.sleep(1000) /* wait for test container some more */;
-
-        /* mock */
-        when(storageService.transformDataset(any(Dataset.class)))
-                .thenReturn(EXPORT_RESOURCE_DTO);
-
-        /* test */
-        final ExportResourceDto response = queryService.export(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO, Instant.now());
-        assertEquals(filename, response.getFilename());
-        assertNotNull(response.getResource().getInputStream());
-    }
-
 }
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 eea27bae218b7ac77dbd81e7c31a3fa122e761a8..1236c549d77c79271576738c6f6a226aea314b5a 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,7 +1,5 @@
 package at.tuwien.service;
 
-import at.tuwien.ExportResourceDto;
-import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.*;
 import at.tuwien.api.database.table.columns.ColumnCreateDto;
 import at.tuwien.api.database.table.columns.ColumnDto;
@@ -26,15 +24,12 @@ 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.core.io.InputStreamResource;
 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.io.InputStream;
 import java.math.BigDecimal;
-import java.math.BigInteger;
 import java.sql.SQLException;
 import java.time.Instant;
 import java.util.*;
@@ -612,12 +607,12 @@ public class TableServiceIntegrationTest extends AbstractUnitTest {
             TableExistsException {
 
         /* mock */
-        MariaDbConfig.dropTable(DATABASE_1_PRIVILEGED_DTO, TABLE_1_INTERNALNAME);
+        MariaDbConfig.dropTable(DATABASE_1_PRIVILEGED_DTO, TABLE_1_INTERNAL_NAME);
 
         /* test */
         final TableDto response = tableService.createTable(DATABASE_1_PRIVILEGED_DTO, TABLE_1_CREATE_INTERNAL_DTO);
         assertEquals(TABLE_1_NAME, response.getName());
-        assertEquals(TABLE_1_INTERNALNAME, response.getInternalName());
+        assertEquals(TABLE_1_INTERNAL_NAME, response.getInternalName());
         assertEquals(TABLE_1_COLUMNS.size(), response.getColumns().size());
     }
 
@@ -668,49 +663,6 @@ public class TableServiceIntegrationTest extends AbstractUnitTest {
         });
     }
 
-    @Test
-    public void getPaginatedData_succeeds() throws SQLException, TableMalformedException {
-
-        /* test */
-        final QueryResultDto response = tableService.getPaginatedData(TABLE_1_PRIVILEGED_DTO, null, 0L, 10L);
-        assertEquals(TABLE_1_ID, response.getId());
-        final List<Map<String, Integer>> headers = response.getHeaders();
-        assertEquals(5, headers.size());
-        assertEquals(0, headers.get(0).get("id"));
-        assertEquals(1, headers.get(1).get("date"));
-        assertEquals(2, headers.get(2).get("location"));
-        assertEquals(3, headers.get(3).get("mintemp"));
-        assertEquals(4, headers.get(4).get("rainfall"));
-        final List<Map<String, Object>> result = response.getResult();
-        assertEquals(Instant.ofEpochSecond(1228089600), result.get(0).get("date"));
-        assertEquals(0.6, result.get(0).get("rainfall"));
-        assertEquals("Albury", result.get(0).get("location"));
-        assertEquals(BigInteger.valueOf(1L), result.get(0).get("id"));
-        assertEquals(13.4, result.get(0).get("mintemp"));
-        assertEquals(Instant.ofEpochSecond(1228176000), result.get(1).get("date"));
-        assertEquals(0.0, result.get(1).get("rainfall"));
-        assertEquals("Albury", result.get(1).get("location"));
-        assertEquals(BigInteger.valueOf(2L), result.get(1).get("id"));
-        assertEquals(7.4, result.get(1).get("mintemp"));
-        assertEquals(Instant.ofEpochSecond(1228262400), result.get(2).get("date"));
-        assertEquals(0.0, result.get(2).get("rainfall"));
-        assertEquals("Albury", result.get(2).get("location"));
-        assertEquals(BigInteger.valueOf(3L), result.get(2).get("id"));
-        assertEquals(12.9, result.get(2).get("mintemp"));
-    }
-
-    @Test
-    public void getPaginatedData_notFound_fails() throws SQLException {
-
-        /* mock */
-        MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME);
-
-        /* test */
-        assertThrows(TableMalformedException.class, () -> {
-            tableService.getPaginatedData(TABLE_5_PRIVILEGED_DTO, null, 0L, 10L);
-        });
-    }
-
     @Test
     public void history_succeeds() throws SQLException, TableNotFoundException {
 
@@ -735,32 +687,4 @@ public class TableServiceIntegrationTest extends AbstractUnitTest {
         });
     }
 
-    @Test
-    public void exportTable_succeeds() throws QueryMalformedException, StorageNotFoundException,
-            StorageUnavailableException, TableNotFoundException, MalformedException {
-        final ExportResourceDto mock = ExportResourceDto.builder()
-                .filename("weather_aus.csv")
-                .resource(new InputStreamResource(InputStream.nullInputStream()))
-                .build();
-
-        /* mock */
-        when(storageService.getResource("weather_aus.csv"))
-                .thenReturn(mock);
-
-        /* test */
-        final ExportResourceDto response = tableService.exportDataset(TABLE_1_PRIVILEGED_DTO, null);
-    }
-
-    @Test
-    public void exportDataset_malformedData_fails() throws SQLException {
-
-        /* mock */
-        MariaDbConfig.createDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME);
-
-        /* test */
-        assertThrows(QueryMalformedException.class, () -> {
-            tableService.exportDataset(TABLE_5_PRIVILEGED_DTO, null);
-        });
-    }
-
 }
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 bcc0e38a46ef1452902b67136e0a7547d8c84336..5bfaa043d1ded11c26797b94d0ff2cf0d9e509ba 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
@@ -2,7 +2,6 @@ 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.config.MariaDbConfig;
 import at.tuwien.config.MariaDbContainerConfig;
 import at.tuwien.exception.DatabaseMalformedException;
@@ -21,9 +20,7 @@ import org.testcontainers.junit.jupiter.Container;
 import org.testcontainers.junit.jupiter.Testcontainers;
 
 import java.sql.SQLException;
-import java.time.Instant;
 import java.util.List;
-import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -51,7 +48,7 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest {
     public void delete_succeeds() throws SQLException, ViewMalformedException {
 
         /* test */
-        viewService.delete(VIEW_1_PRIVILEGED_DTO);
+        viewService.delete(DATABASE_1_PRIVILEGED_DTO, VIEW_1_INTERNAL_NAME);
     }
 
     @Test
@@ -75,36 +72,6 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest {
 
     }
 
-    @Test
-    public void data_succeeds() throws SQLException, ViewMalformedException {
-
-        /* test */
-        final QueryResultDto response = viewService.data(VIEW_2_PRIVILEGED_DTO, Instant.now(), 0L, 10L);
-        assertNotNull(response);
-        assertNotNull(response.getId());
-        assertEquals(VIEW_2_ID, response.getId());
-        assertNotNull(response.getHeaders());
-        assertEquals(4, response.getHeaders().size());
-        assertEquals(List.of(Map.of("date", 0), Map.of("loc", 1), Map.of("mintemp", 2), Map.of("rainfall", 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("loc"));
-        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("loc"));
-        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("loc"));
-        assertEquals(12.9, response.getResult().get(2).get("mintemp"));
-        assertEquals(0.0, response.getResult().get(2).get("rainfall"));
-    }
-
     @Test
     public void getSchemas_succeeds() throws SQLException, ViewNotFoundException, DatabaseMalformedException {
 
diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java
index b12313dfe957d0f02f05c58bfce1066979973d07..e237c32d2862c70e4f0f1ea4ccfae8f44e468ffb 100644
--- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java
+++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/validation/EndpointValidatorUnitTest.java
@@ -1,6 +1,5 @@
 package at.tuwien.validation;
 
-import at.tuwien.annotations.MockAmqp;
 import at.tuwien.exception.PaginationException;
 import at.tuwien.exception.QueryNotSupportedException;
 import at.tuwien.test.AbstractUnitTest;
@@ -12,19 +11,14 @@ import org.springframework.boot.test.autoconfigure.actuate.observability.AutoCon
 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.test.web.servlet.MockMvc;
 
 import static org.junit.jupiter.api.Assertions.assertThrows;
-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;
 
 @Log4j2
 @ExtendWith(SpringExtension.class)
 @AutoConfigureMockMvc
 @SpringBootTest
 @AutoConfigureObservability
-@MockAmqp
 public class EndpointValidatorUnitTest extends AbstractUnitTest {
 
     @Autowired
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 322e67cc07397105bb7c763efe4d37c905cc1b18..7b8dd082b5bce7ba87db7188c8d4814afb20f940 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
@@ -1,6 +1,8 @@
 /* https://www.kaggle.com/jsphyg/weather-dataset-rattle-package */
-CREATE DATABASE weather;
-USE weather;
+CREATE
+DATABASE weather;
+USE
+weather;
 
 CREATE TABLE weather_location
 (
@@ -12,8 +14,8 @@ CREATE TABLE weather_location
 CREATE TABLE weather_aus
 (
     id       SERIAL PRIMARY KEY,
-    `date`   DATE             NOT NULL,
-    location VARCHAR(255)     NULL COMMENT 'Closest city',
+    `date`   DATE NOT NULL,
+    location VARCHAR(255) NULL COMMENT 'Closest city',
     mintemp  DOUBLE PRECISION NULL,
     rainfall DOUBLE PRECISION NULL,
     FOREIGN KEY (location) REFERENCES weather_location (location) ON DELETE SET NULL,
@@ -44,7 +46,7 @@ CREATE TABLE sensor
 
 CREATE TABLE exotic_boolean
 (
-    `bool_default`          BOOLEAN             NOT NULL PRIMARY KEY,
+    `bool_default`          BOOLEAN NOT NULL PRIMARY KEY,
     `bool_tinyint`          TINYINT(1)          NOT NULL,
     `bool_tinyint_unsigned` TINYINT(1) UNSIGNED NOT NULL
 ) WITH SYSTEM VERSIONING;
@@ -91,4 +93,11 @@ CREATE VIEW not_in_metadata_db2 AS
 (
 select `date`, `location`, `mintemp` as `MinTemp`, `rainfall` as `Rainfall`
 from `weather_aus`
+where `location` = 'Vienna');
+
+-- internal view who should not be indexed into schema
+CREATE VIEW 5c7ba02f681b889892ee82987aa6c74ce45a30973cfef06b78ce797f25189b9a 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/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java
index 282e7d593feec58991dc9f4530e3314fa208eb29..6575913040f1c62e242d092d1564bc3dccc87ba0 100644
--- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java
+++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/MetadataServiceGateway.java
@@ -4,11 +4,9 @@ import at.tuwien.api.container.internal.PrivilegedContainerDto;
 import at.tuwien.api.database.DatabaseAccessDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
 import at.tuwien.api.database.internal.PrivilegedViewDto;
-import at.tuwien.api.database.table.TableStatisticDto;
 import at.tuwien.api.database.table.internal.PrivilegedTableDto;
 import at.tuwien.api.identifier.IdentifierDto;
 import at.tuwien.api.user.PrivilegedUserDto;
-import at.tuwien.api.user.UserBriefDto;
 import at.tuwien.api.user.UserDto;
 import at.tuwien.exception.*;
 import jakarta.validation.constraints.NotNull;
@@ -42,18 +40,6 @@ public interface MetadataServiceGateway {
     PrivilegedDatabaseDto getDatabaseById(Long id) throws DatabaseNotFoundException, RemoteUnavailableException,
             MetadataServiceException;
 
-    /**
-     * Get a database with given internal name from the metadata service.
-     *
-     * @param internalName The internal name.
-     * @return The database, if successful.
-     * @throws DatabaseNotFoundException  The database was not found in the metadata service.
-     * @throws RemoteUnavailableException The remote service is not available.
-     * @throws MetadataServiceException   The remote service returned invalid data.
-     */
-    PrivilegedDatabaseDto getDatabaseByInternalName(String internalName) throws DatabaseNotFoundException,
-            RemoteUnavailableException, MetadataServiceException;
-
     /**
      * Get a table with given database id and table id from the metadata service.
      *
@@ -91,17 +77,6 @@ public interface MetadataServiceGateway {
      */
     UserDto getUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException, MetadataServiceException;
 
-    /**
-     * Get a user with given username from the metadata service.
-     *
-     * @return The user, if successful. Otherwise empty list.
-     * @throws RemoteUnavailableException The remote service is not available and invalid data was returned.
-     * @throws UserNotFoundException      The user was not found in the metadata service.
-     * @throws MetadataServiceException   The remote service returned invalid data.
-     */
-    UUID getSystemUserId() throws RemoteUnavailableException, UserNotFoundException,
-            MetadataServiceException;
-
     /**
      * Get a user with given user id from the metadata service.
      *
diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java
index b6593238fd82daadec664bbb2aa7a09a84e50417..abc5f8b6a134e715b16b40bb8f4f389b1eea2a80 100644
--- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java
+++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java
@@ -10,9 +10,7 @@ import at.tuwien.api.database.table.TableDto;
 import at.tuwien.api.database.table.internal.PrivilegedTableDto;
 import at.tuwien.api.identifier.IdentifierDto;
 import at.tuwien.api.user.PrivilegedUserDto;
-import at.tuwien.api.user.UserBriefDto;
 import at.tuwien.api.user.UserDto;
-import at.tuwien.config.GatewayConfig;
 import at.tuwien.exception.*;
 import at.tuwien.gateway.MetadataServiceGateway;
 import at.tuwien.mapper.MetadataMapper;
@@ -37,14 +35,11 @@ import java.util.UUID;
 public class MetadataServiceGatewayImpl implements MetadataServiceGateway {
 
     private final RestTemplate restTemplate;
-    private final GatewayConfig gatewayConfig;
     private final MetadataMapper metadataMapper;
 
     @Autowired
-    public MetadataServiceGatewayImpl(RestTemplate restTemplate, GatewayConfig gatewayConfig,
-                                      MetadataMapper metadataMapper) {
+    public MetadataServiceGatewayImpl(RestTemplate restTemplate, MetadataMapper metadataMapper) {
         this.restTemplate = restTemplate;
-        this.gatewayConfig = gatewayConfig;
         this.metadataMapper = metadataMapper;
     }
 
@@ -123,37 +118,6 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway {
         return database;
     }
 
-    @Override
-    public PrivilegedDatabaseDto getDatabaseByInternalName(String internalName) throws DatabaseNotFoundException,
-            RemoteUnavailableException, MetadataServiceException {
-        final ResponseEntity<PrivilegedDatabaseDto[]> response;
-        final String url = "/api/database/";
-        log.debug("find privileged database from url: {}", url);
-        try {
-            response = restTemplate.exchange(url, HttpMethod.GET, HttpEntity.EMPTY, PrivilegedDatabaseDto[].class);
-        } catch (ResourceAccessException | HttpServerErrorException e) {
-            log.error("Failed to find database with internal name {}: {}", internalName, e.getMessage());
-            throw new RemoteUnavailableException("Failed to find database: " + e.getMessage(), e);
-        }
-        if (!response.getStatusCode().equals(HttpStatus.OK)) {
-            log.error("Failed to find database with internal name {}: service responded unsuccessful: {}", internalName, response.getStatusCode());
-            throw new MetadataServiceException("Failed to find database: service responded unsuccessful: " + response.getStatusCode());
-        }
-        /* body first, then headers next */
-        if (response.getBody() == null || response.getBody().length != 1) {
-            log.error("Failed to find database with internal name {}: body is empty", internalName);
-            throw new DatabaseNotFoundException("Failed to find database: body is empty");
-        }
-        final List<String> expectedHeaders = List.of("X-Username", "X-Password");
-        if (!response.getHeaders().keySet().containsAll(expectedHeaders)) {
-            log.error("Failed to find all privileged database headers");
-            log.debug("expected headers: {}", expectedHeaders);
-            log.debug("found headers: {}", response.getHeaders().keySet());
-            throw new MetadataServiceException("Failed to find all privileged database headers");
-        }
-        return response.getBody()[0];
-    }
-
     @Override
     public PrivilegedTableDto getTableById(Long databaseId, Long id) throws TableNotFoundException,
             RemoteUnavailableException, MetadataServiceException {
@@ -261,34 +225,6 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway {
         return response.getBody();
     }
 
-    @Override
-    public UUID getSystemUserId() throws RemoteUnavailableException, UserNotFoundException,
-            MetadataServiceException {
-        final ResponseEntity<UserBriefDto[]> response;
-        try {
-            response = restTemplate.exchange("/api/user?username=" + gatewayConfig.getSystemUsername(), HttpMethod.GET, HttpEntity.EMPTY, UserBriefDto[].class);
-        } catch (ResourceAccessException | HttpServerErrorException e) {
-            log.error("Failed to find user with username {}: {}", gatewayConfig.getSystemUsername(), e.getMessage());
-            throw new RemoteUnavailableException("Failed to find user with username " + gatewayConfig.getSystemUsername() + ": " + e.getMessage(), e);
-        } catch (HttpClientErrorException.NotFound e) {
-            log.error("Failed to find user with username {}: not found: {}", gatewayConfig.getSystemUsername(), e.getMessage());
-            throw new UserNotFoundException("Failed to find user with username " + gatewayConfig.getSystemUsername() + ": " + e.getMessage(), e);
-        }
-        if (!response.getStatusCode().equals(HttpStatus.OK)) {
-            log.error("Failed to find user with username {}: service responded unsuccessful: {}", gatewayConfig.getSystemUsername(), response.getStatusCode());
-            throw new MetadataServiceException("Failed to find user with username " + gatewayConfig.getSystemUsername() + ": service responded unsuccessful: " + response.getStatusCode());
-        }
-        if (response.getBody() == null) {
-            log.error("Failed to find user with username {}: body is empty", gatewayConfig.getSystemUsername());
-            throw new MetadataServiceException("Failed to find user with username " + gatewayConfig.getSystemUsername() + ": body is empty");
-        }
-        if (response.getBody().length != 1) {
-            log.error("Failed to find system user: expected exactly one result but got {}", response.getBody().length);
-            throw new MetadataServiceException("Failed to find system user: expected exactly one result but got " + response.getBody().length);
-        }
-        return response.getBody()[0].getId();
-    }
-
     @Override
     public PrivilegedUserDto getPrivilegedUserById(UUID userId) throws RemoteUnavailableException, UserNotFoundException,
             MetadataServiceException {
diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java
index f617766d2c50fd4fd10760a99afa11a6f9767c69..f3a83c910f1acbf9f55a219d74af3411dff01237 100644
--- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java
+++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java
@@ -4,7 +4,6 @@ import at.tuwien.api.database.DatabaseDto;
 import at.tuwien.api.database.ViewColumnDto;
 import at.tuwien.api.database.ViewDto;
 import at.tuwien.api.database.query.QueryDto;
-import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.TableBriefDto;
 import at.tuwien.api.database.table.TableDto;
 import at.tuwien.api.database.table.TableHistoryDto;
@@ -24,13 +23,7 @@ import at.tuwien.api.user.UserBriefDto;
 import at.tuwien.config.QueryConfig;
 import at.tuwien.exception.QueryNotFoundException;
 import at.tuwien.exception.TableNotFoundException;
-import net.sf.jsqlparser.JSQLParserException;
-import net.sf.jsqlparser.parser.CCJSqlParserManager;
-import net.sf.jsqlparser.schema.Column;
-import net.sf.jsqlparser.schema.Table;
-import net.sf.jsqlparser.statement.select.*;
 import org.apache.hadoop.shaded.com.google.common.hash.Hashing;
-import org.apache.hadoop.shaded.org.apache.commons.codec.binary.Hex;
 import org.apache.hadoop.shaded.org.apache.commons.io.FileUtils;
 import org.jetbrains.annotations.NotNull;
 import org.mapstruct.Mapper;
@@ -40,15 +33,11 @@ import org.mapstruct.Mappings;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.StringReader;
-import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
 import java.sql.*;
-import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeFormatterBuilder;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -209,161 +198,6 @@ public interface DataMapper {
         return view;
     }
 
-    /**
-     * Parse columns from a SQL statement of a known database.
-     *
-     * @param databaseId The database id.
-     * @param tables     The list of tables.
-     * @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(Long databaseId, List<TableDto> tables, 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.trace("parse columns from query: {}", query);
-        /* bi-directional mapping */
-        tables.forEach(table -> table.getColumns()
-                .forEach(column -> column.setTable(table)));
-        /* check */
-        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 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<ColumnDto> allColumns = tables.stream()
-                .map(TableDto::getColumns)
-                .flatMap(List::stream)
-                .toList();
-        log.trace("columns referenced in the from-clause and join-clause(s): {}", clauses);
-        /* Checking if all columns exist */
-        for (SelectItem clause : clauses) {
-            final SelectExpressionItem item = (SelectExpressionItem) clause;
-            final Column column = (Column) item.getExpression();
-            final String columnName = column.getColumnName().replace("`", "");
-            final List<ColumnDto> filteredColumns = allColumns.stream()
-                    .filter(c -> (c.getAlias() != null && c.getAlias().equals(columnName)) || c.getInternalName().equals(columnName))
-                    .toList();
-            String tableOrView = null;
-            for (Table t : fromItems.stream().map(t -> (net.sf.jsqlparser.schema.Table) t).toList()) {
-                if (column.getTable() == null) {
-                    /* column does not reference a specific table, find out */
-                    final List<String> filteredTables = filteredColumns.stream()
-                            .map(c -> c.getTable().getInternalName())
-                            .filter(table -> fromItems.stream().map(f -> (Table) f).anyMatch(otherTable -> otherTable.getName().replace("`", "").equals(table)))
-                            .toList();
-                    if (filteredTables.size() != 1) {
-                        log.error("Failed to filter column {} to exactly one match: {}", columnName, filteredTables.stream().map(table -> table + "." + columnName).toList());
-                        throw new JSQLParserException("Failed to filter column " + columnName + " to exactly one match");
-                    }
-                    if (tableMatches(t, filteredTables.get(0))) {
-                        tableOrView = t.getName().replace("`", "");
-                        break;
-                    }
-                }
-                /* column references a specific table */
-                final String tableOrAlias = (t.getAlias() != null ? t.getAlias().getName() : column.getTable().getName())
-                        .replace("`", "");
-                if (tableMatches(t, tableOrAlias)) {
-                    tableOrView = t.getName().replace("`", "");
-                    break;
-                }
-            }
-            if (tableOrView == null) {
-                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 finalTableOrView = tableOrView;
-            final List<ColumnDto> selectColumns = filteredColumns.stream()
-                    .filter(c -> c.getTable().getInternalName().equals(finalTableOrView))
-                    .toList();
-            final ColumnDto resultColumn;
-            if (selectColumns.size() != 1) {
-                if (filteredColumns.size() != 1) {
-                    log.error("Failed to filter column {} to exactly one match: {}", columnName, selectColumns.stream().map(c -> c.getTable().getInternalName() + "." + c.getInternalName()).toList());
-                    throw new JSQLParserException("Failed to filter column " + columnName + " to exactly one match");
-                }
-                resultColumn = filteredColumns.get(0);
-            } else {
-                resultColumn = selectColumns.get(0);
-            }
-            if (item.getAlias() != null) {
-                resultColumn.setAlias(item.getAlias().getName().replace("`", ""));
-            }
-            resultColumn.setDatabaseId(databaseId);
-            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);
-        }
-        return columns;
-    }
-
-    default boolean tableMatches(net.sf.jsqlparser.schema.Table table, String tableOrDesignator) {
-        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(tableOrDesignator);
-        }
-        /* has designator */
-        final String designator = table.getAlias()
-                .getName()
-                .trim()
-                .replace("`", "");
-        log.trace("table '{}' has designator {}", tableName, designator);
-        return designator.equals(tableOrDesignator);
-    }
-
-    default List<FromItem> fromItemToFromItems(FromItem data) throws JSQLParserException {
-        return fromItemToFromItems(data, 0);
-    }
-
-    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);
-            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()) {
-                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(tmp);
-            return fromItems;
-        }
-        log.warn("unknown from-item {}", data);
-        return null;
-    }
-
     default QueryDto resultSetToQueryDto(@NotNull ResultSet data) throws SQLException, QueryNotFoundException {
         /* note that next() is called outside this mapping function */
         return QueryDto.builder()
@@ -510,98 +344,6 @@ public interface DataMapper {
                 .build();
     }
 
-    default Object dataColumnToObject(Object data, ColumnDto column) {
-        if (data == null) {
-            return null;
-        }
-        /* boolean encoding fix */
-        if (column.getColumnType().equals(ColumnTypeDto.TINYINT) && column.getSize() == 1) {
-            column.setColumnType(ColumnTypeDto.BOOL);
-        }
-        switch (column.getColumnType()) {
-            case DATE -> {
-                final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
-                        .parseCaseInsensitive() /* case insensitive to parse JAN and FEB */
-                        .appendPattern("yyyy-MM-dd")
-                        .toFormatter(Locale.ENGLISH);
-                final LocalDate date = LocalDate.parse(String.valueOf(data), formatter);
-                return date.atStartOfDay(ZoneId.of("UTC"))
-                        .toInstant();
-            }
-            case TIMESTAMP, DATETIME -> {
-                return Timestamp.valueOf(data.toString())
-                        .toInstant();
-            }
-            case BINARY, VARBINARY, BIT -> {
-                return Long.parseLong(String.valueOf(data), 2);
-            }
-            case TEXT, CHAR, VARCHAR, TINYTEXT, MEDIUMTEXT, LONGTEXT, ENUM, SET -> {
-                return String.valueOf(data);
-            }
-            case BIGINT, SERIAL -> {
-                return new BigInteger(String.valueOf(data));
-            }
-            case INT, SMALLINT, MEDIUMINT, TINYINT -> {
-                return Integer.parseInt(String.valueOf(data));
-            }
-            case DECIMAL, FLOAT, DOUBLE -> {
-                return Double.valueOf(String.valueOf(data));
-            }
-            case BOOL -> {
-                return Boolean.valueOf(String.valueOf(data));
-            }
-            case TIME -> {
-                return String.valueOf(data);
-            }
-            case YEAR -> {
-                final String date = String.valueOf(data);
-                return Short.valueOf(date.substring(0, date.indexOf('-')));
-            }
-        }
-        log.warn("column type {} is not known", column.getColumnType());
-        throw new IllegalArgumentException("Column type not known");
-    }
-
-    default QueryResultDto resultListToQueryResultDto(List<ColumnDto> columns, ResultSet result) throws SQLException {
-        log.trace("mapping result list to query result, columns.size={}", columns.size());
-        final List<Map<String, Object>> resultList = new LinkedList<>();
-        while (result.next()) {
-            /* map the result set to the columns through the stored metadata in the metadata database */
-            int[] idx = new int[]{1};
-            final Map<String, Object> map = new HashMap<>();
-            for (final ColumnDto column : columns) {
-                final String columnOrAlias;
-                if (column.getAlias() != null) {
-                    log.debug("column {} has alias {}", column.getInternalName(), column.getAlias());
-                    columnOrAlias = column.getAlias();
-                } else {
-                    columnOrAlias = column.getInternalName();
-                }
-                if (List.of(ColumnTypeDto.BLOB, ColumnTypeDto.TINYBLOB, ColumnTypeDto.MEDIUMBLOB, ColumnTypeDto.LONGBLOB).contains(column.getColumnType())) {
-                    log.trace("column {} is of type {}", columnOrAlias, column.getColumnType().getType().toLowerCase());
-                    final Blob blob = result.getBlob(idx[0]++);
-                    final String value = blob == null ? null : Hex.encodeHexString(blob.getBytes(1, (int) blob.length())).toUpperCase();
-                    map.put(columnOrAlias, value);
-                    continue;
-                }
-                final Object object = dataColumnToObject(result.getObject(idx[0]++), column);
-                map.put(columnOrAlias, object);
-            }
-            resultList.add(map);
-        }
-        final int[] idx = new int[]{0};
-        final List<Map<String, Integer>> headers = columns.stream()
-                .map(c -> (Map<String, Integer>) new LinkedHashMap<String, Integer>() {{
-                    put(c.getAlias() != null ? c.getAlias() : c.getInternalName(), idx[0]++);
-                }})
-                .toList();
-        log.trace("created ordered header list: {}", headers);
-        return QueryResultDto.builder()
-                .result(resultList)
-                .headers(headers)
-                .build();
-    }
-
     default void prepareStatementWithColumnTypeObject(PreparedStatement ps, ColumnTypeDto columnType, int idx, Object value) throws SQLException {
         switch (columnType) {
             case BLOB, TINYBLOB, MEDIUMBLOB, LONGBLOB:
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 56f51468b7188b463c8fa1e4d10129b17c0cfca7..d918fc966f98c51d90688c48ca9cc3907b164bdb 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
@@ -221,12 +221,6 @@ public interface MariaDbMapper {
         return statement;
     }
 
-    default String tableCreateDtoToCreateSequenceRawQuery(at.tuwien.api.database.table.internal.TableCreateDto data) {
-        final String statement = "CREATE SEQUENCE IF NOT EXISTS `" + tableCreateDtoToSequenceName(data) + "` NOCACHE";
-        log.trace("mapped create sequence statement: {}", statement);
-        return statement;
-    }
-
     default String filterToGetQueriesRawQuery(Boolean filterPersisted) {
         final StringBuilder statement = new StringBuilder("SELECT `id`, `created`, `created_by`, `query`, `query_hash`, `result_hash`, `result_number`, `is_persisted`, `executed` FROM `qs_queries`");
         if (filterPersisted != null) {
@@ -435,6 +429,12 @@ public interface MariaDbMapper {
         return statement.toString();
     }
 
+    default String selectExistsTableOrViewRawQuery() {
+        final String statement = "SELECT IF((SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?), 1, 0) AS `exists`";
+        log.trace("mapped select exists table or view statement: {}", statement);
+        return statement;
+    }
+
     default Long resultSetToNumber(ResultSet data) throws QueryMalformedException, SQLException {
         if (!data.next()) {
             throw new QueryMalformedException("Failed to map number");
@@ -442,38 +442,23 @@ public interface MariaDbMapper {
         return data.getLong(1);
     }
 
-    /**
-     * Selects the dataset page from a table/view.
-     *
-     * @param databaseName The database internal name.
-     * @param tableOrView  The table/view internal name.
-     * @param columns      The columns that should be contained in the result set.
-     * @param timestamp    The moment in time the data should be returned in UTC timezone.
-     * @return The raw SQL query.
-     */
-    default String selectDatasetRawQuery(String databaseName, String tableOrView, List<ColumnDto> columns,
-                                         Instant timestamp, Long size, Long page) {
-        final StringBuilder statement = new StringBuilder("SELECT ")
-                .append(String.join(",", columns.stream().map(c -> "`" + c.getInternalName() + "`").toList()));
-        statement.append(" FROM `")
-                .append(databaseName)
-                .append("`.`")
-                .append(tableOrView)
-                .append("`");
-        if (timestamp != null) {
-            statement.append(" FOR SYSTEM_TIME AS OF TIMESTAMP '")
-                    .append(mariaDbFormatter.format(timestamp))
-                    .append("'");
+    default Boolean resultSetToBoolean(ResultSet data) throws QueryMalformedException, SQLException {
+        if (!data.next()) {
+            throw new QueryMalformedException("Failed to map boolean");
         }
-        log.trace("pagination size/limit of {}", size);
-        statement.append(" LIMIT ")
-                .append(size);
-        log.trace("pagination page/offset of {}", page);
-        statement.append(" OFFSET ")
-                .append(page * size)
-                .append(";");
-        log.trace("mapped select data query: {}", statement);
-        return statement.toString();
+        return data.getBoolean(1);
+    }
+
+    default List<Map<String, Object>> resultSetToList(ResultSet data, List<String> columns) throws SQLException {
+        final List<Map<String, Object>> list = new LinkedList<>();
+        while (data.next()) {
+            final Map<String, Object> tuple = new HashMap<>();
+            for (String column : columns) {
+                tuple.put(column, data.getString(column));
+            }
+            list.add(tuple);
+        }
+        return list;
     }
 
     /**
@@ -500,53 +485,6 @@ public interface MariaDbMapper {
         return "DROP TABLE `" + tableName + "`;";
     }
 
-    default String tableOrViewToRawExportQuery(String databaseName, String tableOrView, List<String> columns,
-                                               Instant timestamp) {
-        final StringBuilder statement = new StringBuilder("(SELECT ");
-        int[] jdx = new int[]{0};
-        columns.forEach(column -> {
-            statement.append(jdx[0] != 0 ? "," : "")
-                    .append("`")
-                    .append(column)
-                    .append("`");
-            jdx[0]++;
-        });
-        statement.append(" FROM `")
-                .append(databaseName)
-                .append("`.`")
-                .append(tableOrView)
-                .append("`");
-        if (timestamp != null) {
-            log.trace("export has timestamp present");
-            statement.append(" FOR SYSTEM_TIME AS OF TIMESTAMP'")
-                    .append(mariaDbFormatter.format(timestamp))
-                    .append("'");
-        }
-        statement.append(") as tbl_alias");
-        log.debug("mapped table/view export query: {}", statement);
-        return statement.toString();
-    }
-
-    default String subsetToRawTemporaryViewQuery(String viewName, String query) {
-        final StringBuilder statement = new StringBuilder("CREATE VIEW `")
-                .append(viewName)
-                .append("` AS (")
-                .append(query)
-                .append(");");
-        log.debug("mapped temporary view query: {}", statement);
-        return statement.toString();
-    }
-
-    default String subsetToRawExportQuery(String viewName, Instant timestamp) {
-        final StringBuilder statement = new StringBuilder("(SELECT * FROM `")
-                .append(viewName)
-                .append("` FOR SYSTEM_TIME AS OF TIMESTAMP'")
-                .append(mariaDbFormatter.format(timestamp))
-                .append("') as tbl");
-        log.debug("mapped export query: {}", statement);
-        return statement.toString();
-    }
-
     default String temporaryTableToRawMergeQuery(String tmp, String table, List<String> columns) {
         final StringBuilder statement = new StringBuilder("INSERT INTO `")
                 .append(table)
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 61a95b32d3f004de402c3619aa322a349a040d32..77345f036ec88664ad739fd0410b95c328a9cbe9 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
@@ -9,6 +9,7 @@ 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.query.QueryDto;
 import at.tuwien.api.database.table.TableBriefDto;
 import at.tuwien.api.database.table.TableDto;
 import at.tuwien.api.database.table.columns.ColumnDto;
@@ -27,6 +28,10 @@ public interface MetadataMapper {
 
     org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MetadataMapper.class);
 
+    default String queryDtoToViewName(QueryDto subset) {
+        return subset.getQueryHash();
+    }
+
     PrivilegedContainerDto containerDtoToPrivilegedContainerDto(ContainerDto data);
 
     DatabaseDto privilegedDatabaseDtoToDatabaseDto(PrivilegedDatabaseDto data);
diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java
index 78b2fe8f8986c97b39618022284f011020e1e26c..4a3455fbc4e10f9632148fbe12e92f4298973f9d 100644
--- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java
+++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java
@@ -1,13 +1,9 @@
 package at.tuwien.service;
 
-import at.tuwien.ExportResourceDto;
-import at.tuwien.api.SortTypeDto;
 import at.tuwien.api.container.internal.PrivilegedContainerDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
 import at.tuwien.api.database.query.QueryDto;
-import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.exception.*;
-import jakarta.validation.constraints.NotNull;
 import org.apache.spark.sql.Dataset;
 import org.apache.spark.sql.Row;
 
@@ -30,49 +26,34 @@ public interface SubsetService {
             QueryStoreCreateException;
 
     /**
-     * Creates a subset from the given statement at given time in the given database.
+     * Retrieve data from a subset in a database and optionally paginate with number of page and size of results.
      *
-     * @param database      The database.
-     * @param statement     The subset statement.
-     * @param timestamp     The timestamp as of which the data is queried. If smaller than <now>, historic data is queried.
-     * @param userId        The user id of the creating user.
-     * @param page          The page number. Optional but requires size to be set too.
-     * @param size          The page size. Optional but requires page to be set too.
-     * @param sortDirection The sort direction.
-     * @param sortColumn    The column that is sorted.
-     * @return The query result.
-     * @throws QueryStoreInsertException  The query store refused to insert the query.
-     * @throws SQLException               The connection to the database could not be established.
-     * @throws QueryNotFoundException     The query was not found for re-execution.
-     * @throws TableMalformedException    The table is malformed.
-     * @throws UserNotFoundException      The user was not found.
-     * @throws NotAllowedException        The operation is not allowed.
-     * @throws RemoteUnavailableException The privileged database information could not be found in the Metadata Service.
-     * @throws DatabaseNotFoundException  The database was not found in the Metadata Service.
-     * @throws MetadataServiceException   The Metadata Service responded unexpected.
+     * @param database The database.
+     * @param subset   The subset.
+     * @param page     The page number.
+     * @param size     Te result size.
+     * @return The data.
+     * @throws ViewMalformedException  The view is malformed.
+     * @throws SQLException            The connection to the database could not be established.
+     * @throws QueryMalformedException The mapped query produced a database error.
+     * @throws TableNotFoundException  The database table is malformed.
      */
-    QueryResultDto execute(PrivilegedDatabaseDto database, String statement, Instant timestamp, UUID userId, Long page,
-                           Long size, SortTypeDto sortDirection, String sortColumn)
-            throws QueryStoreInsertException, SQLException, QueryNotFoundException, TableMalformedException,
-            UserNotFoundException, NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException,
-            MetadataServiceException;
+    Dataset<Row> getData(PrivilegedDatabaseDto database, QueryDto subset, Long page, Long size)
+            throws ViewMalformedException, SQLException, QueryMalformedException, TableNotFoundException;
 
     /**
-     * Re-executes the query of a given subset in the given database.
+     * Creates a subset from the given statement at given time in the given database.
      *
-     * @param database      The database.
-     * @param query         The subset.
-     * @param page          The page number. Optional but requires size to be set too.
-     * @param size          The page size. Optional but requires page to be set too.
-     * @param sortDirection The sort direction.
-     * @param sortColumn    The column that is sorted.
-     * @return The query result.
-     * @throws TableMalformedException The table is malformed.
-     * @throws SQLException            The connection to the database could not be established.
+     * @param database  The database.
+     * @param statement The subset statement.
+     * @param timestamp The timestamp as of which the data is queried. If smaller than <now>, historic data is queried.
+     * @param userId    The user id of the creating user.
+     * @return The query id.
+     * @throws QueryStoreInsertException The query store refused to insert the query.
+     * @throws SQLException              The connection to the database could not be established.
      */
-    QueryResultDto reExecute(PrivilegedDatabaseDto database, QueryDto query, Long page, Long size,
-                             SortTypeDto sortDirection, String sortColumn) throws TableMalformedException,
-            SQLException;
+    Long create(PrivilegedDatabaseDto database, String statement, Instant timestamp, UUID userId)
+            throws QueryStoreInsertException, SQLException;
 
     /**
      * Counts the subset row count of a query of a given subset in the given database.
@@ -82,7 +63,6 @@ public interface SubsetService {
      * @return The row count.
      * @throws TableMalformedException The table is malformed.
      * @throws SQLException            The connection to the database could not be established.
-     * @throws QueryMalformedException The re-execute query is malformed.
      */
     Long reExecuteCount(PrivilegedDatabaseDto database, QueryDto query) throws TableMalformedException,
             SQLException, QueryMalformedException;
@@ -102,24 +82,6 @@ public interface SubsetService {
     List<QueryDto> findAll(PrivilegedDatabaseDto database, Boolean filterPersisted) throws SQLException,
             QueryNotFoundException, RemoteUnavailableException, DatabaseNotFoundException, MetadataServiceException;
 
-    /**
-     * Exports a subset by re-executing the query in a given database with given timestamp to a given s3key.
-     *
-     * @param database  The database.
-     * @param query     The query.
-     * @param timestamp The timestamp.
-     * @return The exported subset.
-     * @throws SQLException                The connection to the database could not be established.
-     * @throws QueryMalformedException     The mapped export query produced a database error.
-     * @throws StorageNotFoundException    The exported subset was not found from the key provided by the sidecar in the Storage Service.
-     * @throws StorageUnavailableException The communication to the Storage Service failed.
-     * @throws RemoteUnavailableException  The privileged database information could not be found in the Metadata Service.
-     * @throws ViewNotFoundException       The source view was not found in the metadata database.
-     */
-    ExportResourceDto export(PrivilegedDatabaseDto database, QueryDto query, Instant timestamp) throws SQLException,
-            QueryMalformedException, StorageNotFoundException, StorageUnavailableException, RemoteUnavailableException,
-            ViewNotFoundException;
-
     /**
      * Executes a subset query without saving it.
      *
@@ -143,11 +105,12 @@ public interface SubsetService {
      * @throws QueryNotFoundException     The query store did not return a query.
      * @throws SQLException               The connection to the database could not be established.
      * @throws RemoteUnavailableException The privileged database information could not be found in the Metadata Service.
+     * @throws UserNotFoundException      The user that created the query was not found in the Metadata Service.
      * @throws DatabaseNotFoundException  The database metadata was not found in the Metadata Service.
      * @throws MetadataServiceException   Communication with the Metadata Service failed.
      */
     QueryDto findById(PrivilegedDatabaseDto database, Long queryId) throws QueryNotFoundException, SQLException,
-            RemoteUnavailableException, DatabaseNotFoundException, MetadataServiceException;
+            RemoteUnavailableException, UserNotFoundException, DatabaseNotFoundException, MetadataServiceException;
 
     /**
      * Inserts a query and metadata to the query store of a given database id.
@@ -182,17 +145,4 @@ public interface SubsetService {
      * @throws QueryStoreGCException The query store failed to delete stale queries.
      */
     void deleteStaleQueries(PrivilegedDatabaseDto database) throws SQLException, QueryStoreGCException;
-
-    /**
-     * Exports data as dataset from the database view with given name at a given timestamp.
-     *
-     * @param database  The database.
-     * @param viewName  The view name.
-     * @param timestamp The timestamp.
-     * @return The dataset.
-     * @throws ViewNotFoundException   The view was not found in the metadata database.
-     * @throws QueryMalformedException The query to eis malformed.
-     */
-    Dataset<Row> getData(@NotNull PrivilegedDatabaseDto database, String viewName, Instant timestamp)
-            throws ViewNotFoundException, QueryMalformedException;
 }
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 7bf4fb3f566b0e490d0ded26abb7dbc568d4e77f..de1f07b8d956f1d194cf561cf05dd852bf3ccfc8 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
@@ -1,14 +1,12 @@
 package at.tuwien.service;
 
-import at.tuwien.ExportResourceDto;
+import at.tuwien.api.SortTypeDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
 import at.tuwien.api.database.query.ImportDto;
-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.exception.*;
-import jakarta.validation.constraints.NotNull;
 import org.apache.spark.sql.Dataset;
 import org.apache.spark.sql.Row;
 
@@ -90,20 +88,6 @@ public interface TableService {
      */
     void delete(PrivilegedTableDto table) throws SQLException, QueryMalformedException;
 
-    /**
-     * Obtains data from a table with given table object at timestamp, loaded as page number and length size.
-     *
-     * @param table     The table object.
-     * @param timestamp The timestamp.
-     * @param page      The page number.
-     * @param size      The page size/length.
-     * @return The data.
-     * @throws SQLException            Failed to parse SQL query, contains invalid syntax.
-     * @throws TableMalformedException The table schema is malformed, likely due to a bug in the application.
-     */
-    QueryResultDto getPaginatedData(PrivilegedTableDto table, Instant timestamp, Long page, Long size)
-            throws SQLException, TableMalformedException;
-
     /**
      * Obtains the table history for a given table object.
      *
@@ -180,28 +164,7 @@ public interface TableService {
     void updateTuple(PrivilegedTableDto table, TupleUpdateDto data) throws SQLException,
             QueryMalformedException, TableMalformedException;
 
-    /**
-     * Exports a table at given system-versioning time.
-     *
-     * @param table     The table.
-     * @param timestamp The system-versioning time.
-     * @return The exported resource.
-     * @throws TableNotFoundException      The table was not found in the data database.
-     * @throws QueryMalformedException     The export query is malformed, likely due to a bug in the application.
-     * @throws StorageUnavailableException Failed to establish a connection with the Storage Service.
-     */
-    ExportResourceDto exportDataset(PrivilegedTableDto table, Instant timestamp) throws TableNotFoundException,
-            QueryMalformedException, StorageUnavailableException, MalformedException;
-
-    /**
-     * Get data from a given table at timestamp.
-     *
-     * @param table     The table.
-     * @param timestamp The timestamp.
-     * @return The data.
-     * @throws TableNotFoundException  The table was not found in the data database.
-     * @throws QueryMalformedException The export query is malformed, likely due to a bug in the application.
-     */
-    Dataset<Row> getData(@NotNull PrivilegedTableDto table, Instant timestamp) throws TableNotFoundException,
-            QueryMalformedException;
+    Dataset<Row> getData(PrivilegedDatabaseDto database, String tableOrView, Instant timestamp,
+                         Long page, Long size, SortTypeDto sortDirection, String sortColumn)
+            throws QueryMalformedException, TableNotFoundException;
 }
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 48aa5ec3cfbd3968a00f3d1dcaf46108fd33eb07..ec7a723261372d1414f0590e74ef915bb62264f4 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
@@ -1,15 +1,14 @@
 package at.tuwien.service;
 
-import at.tuwien.ExportResourceDto;
 import at.tuwien.api.database.ViewCreateDto;
 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.exception.*;
-import jakarta.validation.constraints.NotNull;
-import org.apache.spark.sql.Dataset;
-import org.apache.spark.sql.Row;
+import at.tuwien.api.database.query.QueryDto;
+import at.tuwien.exception.DatabaseMalformedException;
+import at.tuwien.exception.QueryMalformedException;
+import at.tuwien.exception.ViewMalformedException;
+import at.tuwien.exception.ViewNotFoundException;
 
 import java.sql.SQLException;
 import java.time.Instant;
@@ -17,6 +16,9 @@ import java.util.List;
 
 public interface ViewService {
 
+    Boolean existsByName(PrivilegedDatabaseDto database, String name) throws SQLException,
+            QueryMalformedException;
+
     /**
      * Gets the metadata schema for a given database.
      *
@@ -29,6 +31,16 @@ public interface ViewService {
     List<ViewDto> getSchemas(PrivilegedDatabaseDto database) throws SQLException, DatabaseMalformedException,
             ViewNotFoundException;
 
+    /**
+     * Creates a view if not already exists.
+     * @param database
+     * @param subset
+     * @return
+     * @throws ViewMalformedException
+     * @throws SQLException
+     */
+    ViewDto create(PrivilegedDatabaseDto database, QueryDto subset) throws ViewMalformedException, SQLException;
+
     /**
      * Creates a view in the given data database.
      *
@@ -40,28 +52,15 @@ public interface ViewService {
     ViewDto create(PrivilegedDatabaseDto database, ViewCreateDto data) throws SQLException,
             ViewMalformedException;
 
-    /**
-     * Get data from the given view at specific timestamp, paginated by page and size.
-     *
-     * @param view      The view.
-     * @param timestamp The timestamp.
-     * @param page      The page number.
-     * @param size      The page size.
-     * @return The data, if successful.
-     * @throws SQLException           The connection to the data database was unsuccessful.
-     * @throws ViewMalformedException The query is malformed and was rejected by the data database.
-     */
-    QueryResultDto data(PrivilegedViewDto view, Instant timestamp, Long page, Long size) throws SQLException,
-            ViewMalformedException;
-
     /**
      * Deletes a view.
      *
-     * @param view The view.
+     * @param database The database.
+     * @param viewName The view name.
      * @throws SQLException           The connection to the data database was unsuccessful.
      * @throws ViewMalformedException The query is malformed and was rejected by the data database.
      */
-    void delete(PrivilegedViewDto view) throws SQLException, ViewMalformedException;
+    void delete(PrivilegedDatabaseDto database, String viewName) throws SQLException, ViewMalformedException;
 
     /**
      * Counts tuples in a view at system-versioned timestamp.
@@ -73,27 +72,4 @@ public interface ViewService {
      * @throws QueryMalformedException The query is malformed and was rejected by the data database.
      */
     Long count(PrivilegedViewDto view, Instant timestamp) throws SQLException, QueryMalformedException;
-
-    /**
-     * Exports view data into a dataset.
-     *
-     * @param view The view.
-     * @return The dataset.
-     * @throws QueryMalformedException     The query is malformed and was rejected by the data database.
-     * @throws StorageUnavailableException Failed to establish a connection with the Storage Service.
-     * @throws ViewNotFoundException       The view with given name was not found.
-     */
-    ExportResourceDto exportDataset(PrivilegedViewDto view) throws QueryMalformedException,
-            StorageUnavailableException, ViewNotFoundException, MalformedException;
-
-    /**
-     * Get data from a given view.
-     *
-     * @param view The view.
-     * @return The data.
-     * @throws ViewNotFoundException   The view with given name was not found.
-     * @throws QueryMalformedException The query is malformed and was rejected by the data database.
-     */
-    Dataset<Row> getData(@NotNull PrivilegedViewDto view) throws ViewNotFoundException,
-            QueryMalformedException;
 }
diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java
index 7ed5150095a1320c29cfd92ff9687eeab8ef57ee..1493f579fdb6cfc9e5429a27ea6e44314a5d8760 100644
--- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java
+++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/AccessServiceMariaDbImpl.java
@@ -43,22 +43,22 @@ public class AccessServiceMariaDbImpl extends HibernateConnector implements Acce
             long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseCreateUserQuery(user.getUsername(), user.getPassword()))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             /* grant access */
             final String grants = access != AccessTypeDto.READ ? grantDefaultWrite : grantDefaultRead;
             start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseGrantPrivilegesQuery(user.getUsername(), grants))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             /* grant query store */
             start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseGrantProcedureQuery(user.getUsername(), "store_query"))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             /* apply access rights */
             start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseFlushPrivilegesQuery());
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -82,7 +82,7 @@ public class AccessServiceMariaDbImpl extends HibernateConnector implements Acce
             final long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseGrantPrivilegesQuery(user.getUsername(), grants))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             /* apply access rights */
             connection.prepareStatement(mariaDbMapper.databaseFlushPrivilegesQuery());
             connection.commit();
@@ -106,12 +106,12 @@ public class AccessServiceMariaDbImpl extends HibernateConnector implements Acce
             long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseRevokePrivilegesQuery(user.getUsername()))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             /* apply access rights */
             start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseFlushPrivilegesQuery())
                             .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
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 7bb5927692131560b8a54e78c78c418d67ecc757..a15c22f55e9c7731de47e81d114431961114877d 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
@@ -40,7 +40,7 @@ public class DatabaseServiceMariaDbImpl extends HibernateConnector implements Da
             final long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseCreateDatabaseQuery(data.getInternalName()))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -73,7 +73,7 @@ public class DatabaseServiceMariaDbImpl extends HibernateConnector implements Da
             final long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.databaseSetPasswordQuery(data.getUsername(), data.getPassword()))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
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 e2d085ae98c60b2ee0cc0b852fc9954b542d3413..b52d1c792ec25856209e33be2c5fa6dce4996f80 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
@@ -2,26 +2,10 @@ package at.tuwien.service.impl;
 
 import at.tuwien.api.container.internal.PrivilegedContainerDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
-import at.tuwien.api.database.table.internal.PrivilegedTableDto;
-import at.tuwien.config.S3Config;
-import at.tuwien.exception.QueryMalformedException;
-import at.tuwien.exception.TableNotFoundException;
 import com.mchange.v2.c3p0.ComboPooledDataSource;
-import jakarta.validation.constraints.NotNull;
 import lombok.extern.log4j.Log4j2;
-import org.apache.spark.SparkConf;
-import org.apache.spark.sql.Dataset;
-import org.apache.spark.sql.Row;
-import org.apache.spark.sql.SparkSession;
-import org.apache.spark.sql.catalyst.ExtendedAnalysisException;
-import org.springframework.context.annotation.Bean;
 import org.springframework.stereotype.Service;
 
-import java.time.Instant;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
 @Log4j2
 @Service
 public abstract class HibernateConnector {
@@ -45,23 +29,6 @@ public abstract class HibernateConnector {
         return getPrivilegedDataSource(database.getContainer(), database.getInternalName());
     }
 
-    public Map<String, String> getPrivilegedDatabaseOptions(PrivilegedTableDto table) {
-        return new HashMap<>() {{
-            put("url", url(table.getDatabase().getContainer(), table.getDatabase().getInternalName()));
-            put("dbtable", table.getInternalName());
-            put("user", table.getDatabase().getContainer().getUsername());
-            put("password", table.getDatabase().getContainer().getPassword());
-        }};
-    }
-
-    public String getHibernateUrl(PrivilegedContainerDto container, String databaseName) {
-        final StringBuilder sb = new StringBuilder(url(container, databaseName))
-                .append("?currentSchema=")
-                .append(databaseName);
-        log.trace("mapped container to hibernate url: {}", sb.toString());
-        return sb.toString();
-    }
-
     public String getSparkUrl(PrivilegedContainerDto container, String databaseName) {
         final StringBuilder sb = new StringBuilder(url(container, databaseName))
                 .append("?sessionVariables=sql_mode='ANSI_QUOTES'");
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 797de6567445ea6acdc45c656d8910f68084ac8b..aff85137870749a600d1e4c76ef317a978c6c54e 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
@@ -52,7 +52,7 @@ public class QueueServiceRabbitMqImpl extends HibernateConnector implements Queu
             }
             final long start = System.currentTimeMillis();
             preparedStatement.executeUpdate();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             log.trace("successfully inserted tuple");
             amqpDataAccessCounter.increment();
         } finally {
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 faa9510a0981106a1fd6f82038143429d6f71f2b..dc073e855d7505d3bdf9d269040af58040d07174 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
@@ -55,7 +55,7 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche
             statement1.setString(2, tableName);
             log.trace("1={}, 2={}", database.getInternalName(), tableName);
             TableDto table = dataMapper.schemaResultSetToTable(metadataMapper.privilegedDatabaseDtoToDatabaseDto(database), statement1.executeQuery());
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             /* obtain columns metadata */
             start = System.currentTimeMillis();
             final PreparedStatement statement2 = connection.prepareStatement(mariaDbMapper.databaseTableColumnsSelectRawQuery());
@@ -63,7 +63,7 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche
             statement2.setString(2, tableName);
             log.trace("1={}, 2={}", database.getInternalName(), tableName);
             final ResultSet resultSet2 = statement2.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             while (resultSet2.next()) {
                 table = dataMapper.resultSetToTable(resultSet2, table, queryConfig);
             }
@@ -74,7 +74,7 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche
             statement3.setString(2, tableName);
             log.trace("1={}, 2={}", database.getInternalName(), tableName);
             final ResultSet resultSet3 = statement3.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             while (resultSet3.next()) {
                 final String clause = resultSet3.getString(1);
                 table.getConstraints()
@@ -89,7 +89,7 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche
             statement4.setString(2, tableName);
             log.trace("1={}, 2={}", database.getInternalName(), tableName);
             final ResultSet resultSet4 = statement4.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             while (resultSet4.next()) {
                 table = dataMapper.resultSetToConstraint(resultSet4, table);
                 for (UniqueDto uk : table.getConstraints().getUniques()) {
@@ -134,7 +134,7 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche
             statement1.setString(2, viewName);
             log.trace("1={}, 2={}", database.getInternalName(), viewName);
             final ResultSet resultSet1 = statement1.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             if (!resultSet1.next()) {
                 throw new ViewNotFoundException("Failed to find view in the information schema");
             }
@@ -149,7 +149,7 @@ public class SchemaServiceMariaDbImpl extends HibernateConnector implements Sche
             statement2.setString(2, viewName);
             log.trace("1={}, 2={}", database.getInternalName(), viewName);
             final ResultSet resultSet2 = statement2.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             TableDto tmp = TableDto.builder()
                     .columns(new LinkedList<>())
                     .build();
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 9a0f1fb27902a291e4676ba3b565b6161e41a152..1e1e78603ba219e0f929a65e40efad6557f6f1ae 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
@@ -1,14 +1,8 @@
 package at.tuwien.service.impl;
 
-import at.tuwien.ExportResourceDto;
-import at.tuwien.api.SortTypeDto;
 import at.tuwien.api.container.internal.PrivilegedContainerDto;
-import at.tuwien.api.database.ViewColumnDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
 import at.tuwien.api.database.query.QueryDto;
-import at.tuwien.api.database.query.QueryResultDto;
-import at.tuwien.api.database.table.columns.ColumnDto;
-import at.tuwien.api.identifier.IdentifierBriefDto;
 import at.tuwien.api.identifier.IdentifierDto;
 import at.tuwien.api.identifier.IdentifierTypeDto;
 import at.tuwien.exception.*;
@@ -16,56 +10,42 @@ import at.tuwien.gateway.MetadataServiceGateway;
 import at.tuwien.mapper.DataMapper;
 import at.tuwien.mapper.MariaDbMapper;
 import at.tuwien.mapper.MetadataMapper;
-import at.tuwien.service.SchemaService;
-import at.tuwien.service.StorageService;
 import at.tuwien.service.SubsetService;
+import at.tuwien.service.TableService;
+import at.tuwien.service.ViewService;
 import com.mchange.v2.c3p0.ComboPooledDataSource;
-import io.micrometer.core.instrument.Counter;
-import jakarta.validation.constraints.NotNull;
 import lombok.extern.log4j.Log4j2;
-import net.sf.jsqlparser.JSQLParserException;
-import org.apache.commons.lang3.RandomUtils;
 import org.apache.spark.sql.Dataset;
 import org.apache.spark.sql.Row;
-import org.apache.spark.sql.SparkSession;
-import org.apache.spark.sql.catalyst.ExtendedAnalysisException;
-import org.sparkproject.guava.hash.Hashing;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.nio.charset.Charset;
 import java.sql.*;
 import java.time.Instant;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Properties;
 import java.util.UUID;
 
 @Log4j2
 @Service
 public class SubsetServiceMariaDbImpl extends HibernateConnector implements SubsetService {
 
-    private final Counter httpDataAccessCounter;
     private final DataMapper dataMapper;
-    private final SparkSession sparkSession;
+    private final ViewService viewService;
+    private final TableService tableService;
     private final MariaDbMapper mariaDbMapper;
-    private final SchemaService schemaService;
     private final MetadataMapper metadataMapper;
-    private final StorageService storageService;
     private final MetadataServiceGateway metadataServiceGateway;
 
     @Autowired
-    public SubsetServiceMariaDbImpl(Counter httpDataAccessCounter, DataMapper dataMapper, SparkSession sparkSession,
-                                    MariaDbMapper mariaDbMapper, SchemaService schemaService,
-                                    MetadataMapper metadataMapper, StorageService storageService,
+    public SubsetServiceMariaDbImpl(DataMapper dataMapper, ViewService viewService, TableService tableService,
+                                    MariaDbMapper mariaDbMapper, MetadataMapper metadataMapper,
                                     MetadataServiceGateway metadataServiceGateway) {
-        this.httpDataAccessCounter = httpDataAccessCounter;
         this.dataMapper = dataMapper;
-        this.sparkSession = sparkSession;
+        this.viewService = viewService;
+        this.tableService = tableService;
         this.mariaDbMapper = mariaDbMapper;
-        this.schemaService = schemaService;
         this.metadataMapper = metadataMapper;
-        this.storageService = storageService;
         this.metadataServiceGateway = metadataServiceGateway;
     }
 
@@ -79,23 +59,23 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
             long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.queryStoreCreateSequenceRawQuery())
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.queryStoreCreateTableRawQuery())
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.queryStoreCreateHashTableProcedureRawQuery())
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.queryStoreCreateStoreQueryProcedureRawQuery())
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.queryStoreCreateInternalStoreQueryProcedureRawQuery())
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -108,32 +88,21 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
     }
 
     @Override
-    public QueryResultDto execute(PrivilegedDatabaseDto database, String statement, Instant timestamp,
-                                  UUID userId, Long page, Long size, SortTypeDto sortDirection, String sortColumn)
-            throws QueryStoreInsertException, SQLException, QueryNotFoundException, TableMalformedException,
-            UserNotFoundException, NotAllowedException, RemoteUnavailableException, DatabaseNotFoundException,
-            MetadataServiceException {
-        final Long queryId = storeQuery(database, statement, timestamp, userId);
-        final QueryDto query = findById(database, queryId);
-        httpDataAccessCounter.increment();
-        return reExecute(database, query, page, size, sortDirection, sortColumn);
+    public Dataset<Row> getData(PrivilegedDatabaseDto database, QueryDto subset, Long page, Long size)
+            throws ViewMalformedException, SQLException, QueryMalformedException, TableNotFoundException {
+        if (!viewService.existsByName(database, metadataMapper.queryDtoToViewName(subset))) {
+            log.warn("Missing internal view {} for subset with id {}: create it from subset query", metadataMapper.queryDtoToViewName(subset), subset.getId());
+            viewService.create(database, subset);
+        } else {
+            log.debug("internal view {} for subset with id {} exists", metadataMapper.queryDtoToViewName(subset), subset.getId());
+        }
+        return tableService.getData(database, metadataMapper.queryDtoToViewName(subset), subset.getExecution(), page, size, null, null);
     }
 
     @Override
-    public QueryResultDto reExecute(PrivilegedDatabaseDto database, QueryDto query, Long page, Long size,
-                                    SortTypeDto sortDirection, String sortColumn) throws TableMalformedException,
-            SQLException {
-        final List<ColumnDto> columns;
-        try {
-            columns = dataMapper.parseColumns(database.getId(), database.getTables(), query.getQuery());
-        } catch (JSQLParserException e) {
-            log.error("Failed to map/parse columns: {}", e.getMessage());
-            throw new TableMalformedException("Failed to map/parse columns: " + e.getMessage(), e);
-        }
-        final String statement = mariaDbMapper.selectRawSelectQuery(query.getQuery(), query.getExecution(), page, size);
-        final QueryResultDto dto = executeNonPersistent(database, statement, columns);
-        dto.setId(query.getId());
-        return dto;
+    public Long create(PrivilegedDatabaseDto database, String statement, Instant timestamp, UUID userId)
+            throws QueryStoreInsertException, SQLException {
+        return storeQuery(database, statement, timestamp, userId);
     }
 
     @Override
@@ -156,14 +125,13 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
                 log.trace("filter persisted only {}", filterPersisted);
             }
             final ResultSet resultSet = statement.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             final List<QueryDto> queries = new LinkedList<>();
             while (resultSet.next()) {
                 final QueryDto query = dataMapper.resultSetToQueryDto(resultSet);
                 query.setIdentifiers(identifiers.stream()
                         .filter(i -> i.getType().equals(IdentifierTypeDto.SUBSET))
                         .filter(i -> i.getQueryId().equals(query.getId()))
-                        .map(metadataMapper::identifierDtoToIdentifierBriefDto)
                         .toList());
                 queries.add(query);
             }
@@ -177,70 +145,6 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
         }
     }
 
-    @Override
-    public ExportResourceDto export(PrivilegedDatabaseDto database, QueryDto query, Instant timestamp)
-            throws SQLException, QueryMalformedException, StorageNotFoundException, StorageUnavailableException,
-            RemoteUnavailableException, ViewNotFoundException {
-        final String viewName = "ex_" + Hashing.sha512()
-                .hashString(new String(RandomUtils.nextBytes(256), Charset.defaultCharset()), Charset.defaultCharset())
-                .toString()
-                .substring(0, 60);
-        final ExportResourceDto export;
-        final ComboPooledDataSource dataSource = getPrivilegedDataSource(database);
-        final Connection connection = dataSource.getConnection();
-        try {
-            /* export to data database sidecar */
-            long start = System.currentTimeMillis();
-            connection.prepareStatement(mariaDbMapper.subsetToRawTemporaryViewQuery(viewName, query.getQuery()))
-                    .executeUpdate();
-            log.debug("executed create view statement in {} ms", System.currentTimeMillis() - start);
-            start = System.currentTimeMillis();
-            final List<String> columns = schemaService.inspectView(database, viewName)
-                    .getColumns()
-                    .stream()
-                    .map(ViewColumnDto::getInternalName)
-                    .toList();
-            log.debug("executed inspect view columns statement in {} ms", System.currentTimeMillis() - start);
-            start = System.currentTimeMillis();
-            final Dataset<Row> dataset = getData(database, viewName, timestamp)
-                    .selectExpr(columns.toArray(new String[0]));
-            export = storageService.transformDataset(dataset);
-            log.debug("executed extract statement in {} ms", System.currentTimeMillis() - start);
-            start = System.currentTimeMillis();
-            connection.prepareStatement(mariaDbMapper.dropViewRawQuery(viewName))
-                    .executeUpdate();
-            log.debug("executed drop view statement in {} ms", System.currentTimeMillis() - start);
-            connection.commit();
-        } catch (SQLException e) {
-            connection.rollback();
-            log.error("Failed to execute query: {}", e.getMessage());
-            throw new QueryMalformedException("Failed to execute query: " + e.getMessage(), e);
-        } finally {
-            dataSource.close();
-        }
-        httpDataAccessCounter.increment();
-        return export;
-    }
-
-    public QueryResultDto executeNonPersistent(PrivilegedDatabaseDto database, String statement,
-                                               List<ColumnDto> columns) throws SQLException, TableMalformedException {
-        final ComboPooledDataSource dataSource = getPrivilegedDataSource(database);
-        final Connection connection = dataSource.getConnection();
-        try {
-            final long start = System.currentTimeMillis();
-            final PreparedStatement preparedStatement = connection.prepareStatement(statement);
-            final ResultSet resultSet = preparedStatement.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
-            httpDataAccessCounter.increment();
-            return dataMapper.resultListToQueryResultDto(columns, resultSet);
-        } catch (SQLException e) {
-            log.error("Failed to execute and map time-versioned query: {}", e.getMessage());
-            throw new TableMalformedException("Failed to execute and map time-versioned query: " + e.getMessage(), e);
-        } finally {
-            dataSource.close();
-        }
-    }
-
     @Override
     public Long executeCountNonPersistent(PrivilegedDatabaseDto database, String statement, Instant timestamp)
             throws SQLException, QueryMalformedException, TableMalformedException {
@@ -250,8 +154,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
             final long start = System.currentTimeMillis();
             final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.countRawSelectQuery(statement, timestamp))
                     .executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
-            httpDataAccessCounter.increment();
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             return mariaDbMapper.resultSetToNumber(resultSet);
         } catch (SQLException e) {
             log.error("Failed to map object: {}", e.getMessage());
@@ -271,17 +174,13 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
             final PreparedStatement preparedStatement = connection.prepareStatement(mariaDbMapper.queryStoreFindQueryRawQuery());
             preparedStatement.setLong(1, queryId);
             final ResultSet resultSet = preparedStatement.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             if (!resultSet.next()) {
                 throw new QueryNotFoundException("Failed to find query");
             }
             final QueryDto query = dataMapper.resultSetToQueryDto(resultSet);
-            final List<IdentifierBriefDto> identifiers = metadataServiceGateway.getIdentifiers(database.getId(), queryId)
-                    .stream()
-                    .map(metadataMapper::identifierDtoToIdentifierBriefDto)
-                    .toList();
-            query.setIdentifiers(identifiers);
-            query.setOwner(database.getOwner());
+            query.setIdentifiers(metadataServiceGateway.getIdentifiers(database.getId(), queryId));
+            query.setCreator(database.getOwner());
             query.setDatabaseId(database.getId());
             return query;
         } catch (SQLException e) {
@@ -312,7 +211,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
             callableStatement.setTimestamp(3, Timestamp.from(timestamp));
             callableStatement.registerOutParameter(4, Types.BIGINT);
             callableStatement.executeUpdate();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             queryId = callableStatement.getLong(4);
             callableStatement.close();
             log.info("Stored query with id {} in database with name {}", queryId, database.getInternalName());
@@ -339,7 +238,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
             preparedStatement.setBoolean(1, persist);
             preparedStatement.setLong(2, queryId);
             preparedStatement.executeUpdate();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
         } catch (SQLException e) {
             log.error("Failed to (un-)persist query: {}", e.getMessage());
             throw new QueryStorePersistException("Failed to (un-)persist query", e);
@@ -357,7 +256,7 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
             final long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.queryStoreDeleteStaleQueriesRawQuery())
                     .executeUpdate();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
         } catch (SQLException e) {
             log.error("Failed to delete stale queries: {}", e.getMessage());
             throw new QueryStoreGCException("Failed to delete stale queries: " + e.getMessage(), e);
@@ -366,27 +265,4 @@ public class SubsetServiceMariaDbImpl extends HibernateConnector implements Subs
         }
     }
 
-    @Override
-    public Dataset<Row> getData(@NotNull PrivilegedDatabaseDto database, String viewName, Instant timestamp)
-            throws ViewNotFoundException, QueryMalformedException {
-        log.debug("get data from view: {}", viewName);
-        try {
-            final Properties properties = new Properties();
-            properties.setProperty("user", database.getContainer().getUsername());
-            properties.setProperty("password", database.getContainer().getPassword());
-            return sparkSession.read()
-                    .jdbc(getSparkUrl(database.getContainer(), database.getInternalName()),
-                            mariaDbMapper.subsetToRawExportQuery(viewName, timestamp), properties);
-        } catch (Exception e) {
-            if (e instanceof ExtendedAnalysisException exception) {
-                if (exception.getSimpleMessage().contains("TABLE_OR_VIEW_NOT_FOUND")) {
-                    log.error("Failed to find temporary view {}: {}", viewName, exception.getSimpleMessage());
-                    throw new ViewNotFoundException("Failed to find temporary view " + viewName + ": " + exception.getSimpleMessage()) /* remove throwable on purpose, clutters the output */;
-                }
-            }
-            log.error("Failed to find get data from view: {}", e.getMessage());
-            throw new QueryMalformedException("Failed to find get data from view: " + e.getMessage(), 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 db46aed12b9917c25ef5c1a6a348f179e8fd6a42..e552fa7b91d84ecb9549b853a01a10840de85adc 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
@@ -1,9 +1,8 @@
 package at.tuwien.service.impl;
 
-import at.tuwien.ExportResourceDto;
+import at.tuwien.api.SortTypeDto;
 import at.tuwien.api.database.internal.PrivilegedDatabaseDto;
 import at.tuwien.api.database.query.ImportDto;
-import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.*;
 import at.tuwien.api.database.table.columns.ColumnDto;
 import at.tuwien.api.database.table.columns.ColumnStatisticDto;
@@ -18,8 +17,6 @@ import at.tuwien.service.StorageService;
 import at.tuwien.service.TableService;
 import at.tuwien.utils.MariaDbUtil;
 import com.mchange.v2.c3p0.ComboPooledDataSource;
-import io.micrometer.core.instrument.Counter;
-import jakarta.validation.constraints.NotNull;
 import lombok.extern.log4j.Log4j2;
 import org.apache.spark.sql.*;
 import org.apache.spark.sql.catalyst.ExtendedAnalysisException;
@@ -37,7 +34,6 @@ import java.util.*;
 @Service
 public class TableServiceMariaDbImpl extends HibernateConnector implements TableService {
 
-    private final Counter httpDataAccessCounter;
     private final DataMapper dataMapper;
     private final SparkSession sparkSession;
     private final MariaDbMapper mariaDbMapper;
@@ -45,10 +41,8 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
     private final StorageService storageService;
 
     @Autowired
-    public TableServiceMariaDbImpl(Counter httpDataAccessCounter, DataMapper dataMapper, SparkSession sparkSession,
-                                   MariaDbMapper mariaDbMapper, SchemaService schemaService,
-                                   StorageService storageService) {
-        this.httpDataAccessCounter = httpDataAccessCounter;
+    public TableServiceMariaDbImpl(DataMapper dataMapper, SparkSession sparkSession, MariaDbMapper mariaDbMapper,
+                                   SchemaService schemaService, StorageService storageService) {
         this.dataMapper = dataMapper;
         this.sparkSession = sparkSession;
         this.mariaDbMapper = mariaDbMapper;
@@ -68,7 +62,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.databaseTablesSelectRawQuery());
             statement.setString(1, database.getInternalName());
             final ResultSet resultSet1 = statement.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             while (resultSet1.next()) {
                 final String tableName = resultSet1.getString(1);
                 if (database.getTables().stream().anyMatch(t -> t.getInternalName().equals(tableName))) {
@@ -106,7 +100,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             } else {
                 final ResultSet resultSet = connection.prepareStatement(query)
                         .executeQuery();
-                log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+                log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
                 statistic = dataMapper.resultSetToTableStatistic(resultSet);
                 final TableDto tmpTable = schemaService.inspectTable(table.getDatabase(), table.getInternalName());
                 statistic.setAvgRowLength(tmpTable.getAvgRowLength());
@@ -147,7 +141,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             final long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.tableCreateDtoToCreateTableRawQuery(data))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -200,7 +194,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             final long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.dropTableRawQuery(tableName))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -212,37 +206,6 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
         log.info("Deleted table with name {}", tableName);
     }
 
-    @Override
-    public QueryResultDto getPaginatedData(PrivilegedTableDto table, Instant timestamp, Long page, Long size) throws SQLException,
-            TableMalformedException {
-        final ComboPooledDataSource dataSource = getPrivilegedDataSource(table.getDatabase());
-        final Connection connection = dataSource.getConnection();
-        final QueryResultDto queryResult;
-        try {
-            /* find table data */
-            long start = System.currentTimeMillis();
-            final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectDatasetRawQuery(
-                            table.getDatabase().getInternalName(), table.getInternalName(), table.getColumns(),
-                            timestamp, size, page))
-                    .executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
-            start = System.currentTimeMillis();
-            connection.commit();
-            queryResult = dataMapper.resultListToQueryResultDto(table.getColumns(), resultSet);
-            log.debug("mapped result in {} ms", System.currentTimeMillis() - start);
-            httpDataAccessCounter.increment();
-        } catch (SQLException e) {
-            connection.rollback();
-            log.error("Failed to find data from table {}.{}: {}", table.getDatabase().getInternalName(), table.getInternalName(), e.getMessage());
-            throw new TableMalformedException("Failed to find data from table " + table.getDatabase().getInternalName() + "." + table.getInternalName() + ": " + e.getMessage(), e);
-        } finally {
-            dataSource.close();
-        }
-        log.info("Find data from table {}.{}", table.getDatabase().getInternalName(), table.getInternalName());
-        queryResult.setId(table.getId());
-        return queryResult;
-    }
-
     @Override
     public List<TableHistoryDto> history(PrivilegedTableDto table, Long size) throws SQLException,
             TableNotFoundException {
@@ -255,7 +218,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectHistoryRawQuery(
                             table.getDatabase().getInternalName(), table.getInternalName(), size))
                     .executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             history = dataMapper.resultSetToTableHistory(resultSet);
             connection.commit();
         } catch (SQLException e) {
@@ -281,7 +244,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectCountRawQuery(
                             table.getDatabase().getInternalName(), table.getInternalName(), timestamp))
                     .executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             queryResult = mariaDbMapper.resultSetToNumber(resultSet);
             connection.commit();
         } catch (SQLException e) {
@@ -362,7 +325,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             }
             final long start = System.currentTimeMillis();
             statement.executeUpdate();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -406,7 +369,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             }
             final long start = System.currentTimeMillis();
             statement.executeUpdate();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -442,7 +405,7 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
             }
             final long start = System.currentTimeMillis();
             statement.executeUpdate();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -466,34 +429,24 @@ public class TableServiceMariaDbImpl extends HibernateConnector implements Table
     }
 
     @Override
-    public ExportResourceDto exportDataset(PrivilegedTableDto table, Instant timestamp) throws TableNotFoundException,
-            QueryMalformedException, StorageUnavailableException, MalformedException {
-        final Dataset<Row> dataset = getData(table, timestamp);
-        httpDataAccessCounter.increment();
-        return storageService.transformDataset(dataset);
-    }
-
-    @Override
-    public Dataset<Row> getData(@NotNull PrivilegedTableDto table, Instant timestamp) throws TableNotFoundException,
-            QueryMalformedException {
+    public Dataset<Row> getData(PrivilegedDatabaseDto database, String tableOrView, Instant timestamp,
+                                Long page, Long size, SortTypeDto sortDirection, String sortColumn)
+            throws QueryMalformedException, TableNotFoundException {
         try {
             final Properties properties = new Properties();
-            properties.setProperty("user", table.getDatabase().getContainer().getUsername());
-            properties.setProperty("password", table.getDatabase().getContainer().getPassword());
+            properties.setProperty("user", database.getContainer().getUsername());
+            properties.setProperty("password", database.getContainer().getPassword());
             return sparkSession.read()
-                    .jdbc(getSparkUrl(table.getDatabase().getContainer(), table.getDatabase().getInternalName()),
-                            mariaDbMapper.tableOrViewToRawExportQuery(table.getDatabase().getInternalName(),
-                                    table.getInternalName(), table.getColumns().stream()
-                                            .map(ColumnDto::getInternalName).toList(), timestamp), properties);
+                    .jdbc(getSparkUrl(database.getContainer(), database.getInternalName()), tableOrView, properties);
         } catch (Exception e) {
             if (e instanceof ExtendedAnalysisException exception) {
                 if (exception.getSimpleMessage().contains("TABLE_OR_VIEW_NOT_FOUND")) {
-                    log.error("Failed to find table {}: {}", table.getInternalName(), exception.getSimpleMessage());
-                    throw new TableNotFoundException("Failed to find table " + table.getInternalName() + ": " + exception.getSimpleMessage()) /* remove throwable on purpose, clutters the output */;
+                    log.error("Failed to find named reference: {}", exception.getSimpleMessage());
+                    throw new TableNotFoundException("Failed to find named reference: " + exception.getSimpleMessage()) /* remove throwable on purpose, clutters the output */;
                 }
             }
-            log.error("Failed to export dataset: {}", e.getMessage());
-            throw new QueryMalformedException("Failed to export dataset: " + e.getMessage(), e);
+            log.error("Failed to find get data from query statement: {}", e.getMessage());
+            throw new QueryMalformedException("Failed to find get data from query statement: " + e.getMessage(), e);
         }
     }
 
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 49cc6b7505ce3561b6f336196438c692a08e2b16..989fe4e1a1de03502616d02e74e5aba99e6544af 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
@@ -1,30 +1,23 @@
 package at.tuwien.service.impl;
 
-import at.tuwien.ExportResourceDto;
-import at.tuwien.api.database.ViewColumnDto;
 import at.tuwien.api.database.ViewCreateDto;
 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.api.database.query.QueryDto;
 import at.tuwien.config.QueryConfig;
-import at.tuwien.exception.*;
+import at.tuwien.exception.DatabaseMalformedException;
+import at.tuwien.exception.QueryMalformedException;
+import at.tuwien.exception.ViewMalformedException;
+import at.tuwien.exception.ViewNotFoundException;
 import at.tuwien.mapper.DataMapper;
 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.google.common.hash.Hashing;
 import com.mchange.v2.c3p0.ComboPooledDataSource;
-import io.micrometer.core.instrument.Counter;
-import jakarta.validation.constraints.NotNull;
 import lombok.extern.log4j.Log4j2;
-import org.apache.spark.sql.Dataset;
-import org.apache.spark.sql.Row;
-import org.apache.spark.sql.SparkSession;
-import org.apache.spark.sql.catalyst.ExtendedAnalysisException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -36,36 +29,51 @@ import java.sql.SQLException;
 import java.time.Instant;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Properties;
 
 @Log4j2
 @Service
 public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewService {
 
-    private final Counter httpDataAccessCounter;
     private final DataMapper dataMapper;
     private final QueryConfig queryConfig;
-    private final SparkSession sparkSession;
-    private final MariaDbMapper mariaDbMapper;
     private final SchemaService schemaService;
-    private final StorageService storageService;
+    private final MariaDbMapper mariaDbMapper;
     private final MetadataMapper metadataMapper;
 
     @Autowired
-    public ViewServiceMariaDbImpl(Counter httpDataAccessCounter, DataMapper dataMapper,
-                                  QueryConfig queryConfig, SparkSession sparkSession, MariaDbMapper mariaDbMapper,
-                                  SchemaService schemaService, StorageService storageService,
-                                  MetadataMapper metadataMapper) {
-        this.httpDataAccessCounter = httpDataAccessCounter;
+    public ViewServiceMariaDbImpl(DataMapper dataMapper, QueryConfig queryConfig, SchemaService schemaService,
+                                  MariaDbMapper mariaDbMapper, MetadataMapper metadataMapper) {
         this.dataMapper = dataMapper;
         this.queryConfig = queryConfig;
-        this.sparkSession = sparkSession;
-        this.mariaDbMapper = mariaDbMapper;
         this.schemaService = schemaService;
-        this.storageService = storageService;
+        this.mariaDbMapper = mariaDbMapper;
         this.metadataMapper = metadataMapper;
     }
 
+    @Override
+    public Boolean existsByName(PrivilegedDatabaseDto database, String name) throws SQLException,
+            QueryMalformedException {
+        final ComboPooledDataSource dataSource = getPrivilegedDataSource(database);
+        final Connection connection = dataSource.getConnection();
+        final Boolean queryResult;
+        try {
+            /* find view data */
+            final long start = System.currentTimeMillis();
+            final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.selectExistsTableOrViewRawQuery());
+            statement.setString(1, database.getInternalName());
+            statement.setString(2, name);
+            final ResultSet resultSet = statement.executeQuery();
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
+            queryResult = mariaDbMapper.resultSetToBoolean(resultSet);
+        } catch (SQLException e) {
+            log.error("Failed to prepare statement {}", e.getMessage());
+            throw new QueryMalformedException("Failed to prepare statement: " + e.getMessage(), e);
+        } finally {
+            dataSource.close();
+        }
+        return queryResult;
+    }
+
     @Override
     public List<ViewDto> getSchemas(PrivilegedDatabaseDto database) throws SQLException, DatabaseMalformedException,
             ViewNotFoundException {
@@ -78,9 +86,13 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
             statement.setString(1, database.getInternalName());
             final long start = System.currentTimeMillis();
             final ResultSet resultSet1 = statement.executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             while (resultSet1.next()) {
                 final String viewName = resultSet1.getString(1);
+                if (viewName.length() == 64) {
+                    log.trace("view {}.{} seems to be a subset view (name length = 64), skip.", database.getInternalName(), viewName);
+                    continue;
+                }
                 if (database.getViews().stream().anyMatch(v -> v.getInternalName().equals(viewName))) {
                     log.trace("view {}.{} already known to metadata database, skip.", database.getInternalName(), viewName);
                     continue;
@@ -101,6 +113,17 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
         return views;
     }
 
+    @Override
+    public ViewDto create(PrivilegedDatabaseDto database, QueryDto subset) throws ViewMalformedException,
+            SQLException {
+        final ViewCreateDto data = ViewCreateDto.builder()
+                .name(metadataMapper.queryDtoToViewName(subset))
+                .query(subset.getQuery())
+                .isPublic(false)
+                .build();
+        return create(database, data);
+    }
+
     @Override
     public ViewDto create(PrivilegedDatabaseDto database, ViewCreateDto data) throws SQLException,
             ViewMalformedException {
@@ -126,7 +149,7 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
             final long start = System.currentTimeMillis();
             connection.prepareStatement(mariaDbMapper.viewCreateRawQuery(view.getInternalName(), data.getQuery()))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             /* select view columns */
             final PreparedStatement statement2 = connection.prepareStatement(mariaDbMapper.databaseTableColumnsSelectRawQuery());
             statement2.setString(1, database.getInternalName());
@@ -148,47 +171,15 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
     }
 
     @Override
-    public QueryResultDto data(PrivilegedViewDto view, Instant timestamp, Long page, Long size) throws SQLException,
-            ViewMalformedException {
-        final ComboPooledDataSource dataSource = getPrivilegedDataSource(view.getDatabase());
-        final Connection connection = dataSource.getConnection();
-        final QueryResultDto queryResult;
-        try {
-            /* find table data */
-            final List<ColumnDto> mappedColumns = view.getColumns()
-                    .stream()
-                    .map(metadataMapper::viewColumnDtoToColumnDto)
-                    .toList();
-            final long start = System.currentTimeMillis();
-            final ResultSet resultSet = connection.prepareStatement(
-                            mariaDbMapper.selectDatasetRawQuery(view.getDatabase().getInternalName(),
-                                    view.getInternalName(), mappedColumns, timestamp, size, page))
-                    .executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
-            queryResult = dataMapper.resultListToQueryResultDto(mappedColumns, resultSet);
-            queryResult.setId(view.getId());
-            connection.commit();
-            httpDataAccessCounter.increment();
-        } catch (SQLException e) {
-            log.error("Failed to map object: {}", e.getMessage());
-            throw new ViewMalformedException("Failed to map object: " + e.getMessage(), e);
-        } finally {
-            dataSource.close();
-        }
-        log.info("Find data from view {}.{}", view.getDatabase().getInternalName(), view.getInternalName());
-        return queryResult;
-    }
-
-    @Override
-    public void delete(PrivilegedViewDto view) throws SQLException, ViewMalformedException {
-        final ComboPooledDataSource dataSource = getPrivilegedDataSource(view.getDatabase());
+    public void delete(PrivilegedDatabaseDto database, String viewName) throws SQLException, ViewMalformedException {
+        final ComboPooledDataSource dataSource = getPrivilegedDataSource(database);
         final Connection connection = dataSource.getConnection();
         try {
             /* drop view if exists */
             final long start = System.currentTimeMillis();
-            connection.prepareStatement(mariaDbMapper.dropViewRawQuery(view.getInternalName()))
+            connection.prepareStatement(mariaDbMapper.dropViewRawQuery(viewName))
                     .execute();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             connection.commit();
         } catch (SQLException e) {
             connection.rollback();
@@ -197,7 +188,7 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
         } finally {
             dataSource.close();
         }
-        log.info("Deleted view {}.{}", view.getDatabase().getInternalName(), view.getInternalName());
+        log.info("Deleted view {}.{}", database.getInternalName(), viewName);
     }
 
 
@@ -213,7 +204,7 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
             final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectCountRawQuery(
                             view.getDatabase().getInternalName(), view.getInternalName(), timestamp))
                     .executeQuery();
-            log.debug("executed statement in {} ms", System.currentTimeMillis() - start);
+            log.trace("executed statement in {} ms", System.currentTimeMillis() - start);
             queryResult = mariaDbMapper.resultSetToNumber(resultSet);
             connection.commit();
         } catch (SQLException e) {
@@ -227,36 +218,4 @@ public class ViewServiceMariaDbImpl extends HibernateConnector implements ViewSe
         return queryResult;
     }
 
-    @Override
-    public ExportResourceDto exportDataset(PrivilegedViewDto view) throws QueryMalformedException,
-            StorageUnavailableException, ViewNotFoundException, MalformedException {
-        final Dataset<Row> dataset = getData(view);
-        httpDataAccessCounter.increment();
-        return storageService.transformDataset(dataset);
-    }
-
-    @Override
-    public Dataset<Row> getData(@NotNull PrivilegedViewDto view) throws ViewNotFoundException,
-            QueryMalformedException {
-        try {
-            final Properties properties = new Properties();
-            properties.setProperty("user", view.getDatabase().getContainer().getUsername());
-            properties.setProperty("password", view.getDatabase().getContainer().getPassword());
-            return sparkSession.read()
-                    .jdbc(getSparkUrl(view.getDatabase().getContainer(), view.getDatabase().getInternalName()),
-                            mariaDbMapper.tableOrViewToRawExportQuery(view.getDatabase().getInternalName(),
-                                    view.getInternalName(), view.getColumns().stream()
-                                            .map(ViewColumnDto::getInternalName).toList(), Instant.now()), properties);
-        } catch (Exception e) {
-            if (e instanceof ExtendedAnalysisException exception) {
-                if (exception.getSimpleMessage().contains("TABLE_OR_VIEW_NOT_FOUND")) {
-                    log.error("Failed to find view {}: {}", view.getInternalName(), exception.getSimpleMessage());
-                    throw new ViewNotFoundException("Failed to find view " + view.getInternalName() + ": " + exception.getSimpleMessage()) /* remove throwable on purpose, clutters the output */;
-                }
-            }
-            log.error("Failed to export dataset: {}", e.getMessage());
-            throw new QueryMalformedException("Failed to export dataset: " + e.getMessage(), e);
-        }
-    }
-
 }
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 9fcb734f58e342c7bef4d28ab062b6752176eb9f..e63e6933d5da3e7270cc3145cc613800241db382 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
@@ -19,7 +19,7 @@ import lombok.extern.jackson.Jacksonized;
 public class ViewCreateDto {
 
     @NotBlank
-    @Size(min = 1, max = 64)
+    @Size(min = 1, max = 63)
     @Schema(example = "Air Quality")
     private String name;
 
diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryResultDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryResultDto.java
deleted file mode 100644
index 90f2d1a6ce9a8a7127d3ea754d6542ed8ef88c88..0000000000000000000000000000000000000000
--- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryResultDto.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package at.tuwien.api.database.query;
-
-import lombok.*;
-
-import jakarta.validation.constraints.NotNull;
-import lombok.extern.jackson.Jacksonized;
-
-import java.util.List;
-import java.util.Map;
-
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@Jacksonized
-@ToString
-public class QueryResultDto {
-
-    @NotNull
-    private List<Map<String, Object>> result;
-
-    @NotNull
-    private List<Map<String, Integer>> headers;
-
-    @NotNull
-    private Long id;
-
-}
diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/application.yml b/dbrepo-metadata-service/rest-service/src/main/resources/application.yml
index 2d79e7cfae29b68515a6f008fd1aaae2c53f0461..290864eea961100236eea2764297d01251c1ccbc 100644
--- a/dbrepo-metadata-service/rest-service/src/main/resources/application.yml
+++ b/dbrepo-metadata-service/rest-service/src/main/resources/application.yml
@@ -48,21 +48,6 @@ logging:
     at.tuwien.: "${LOG_LEVEL:info}"
     org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug
 dbrepo:
-  repository-name: "${REPOSITORY_NAME:Database Repository}"
-  base-url: "${BASE_URL:http://localhost}"
-  admin-email: "${ADMIN_EMAIL:noreply@example.com}"
-  deleted-record: "${DELETED_RECORD:persistent}"
-  granularity: "${GRANULARITY:YYYY-MM-DDThh:mm:ssZ}"
-  exchangeName: "${BROKER_EXCHANGE_NAME:dbrepo}"
-  queueName: "${BROKER_QUEUE_NAME:dbrepo}"
-  connectionTimeout: "${SPARQL_CONNECTION_TIMEOUT:10000}"
-  s3:
-    accessKeyId: "${S3_ACCESS_KEY_ID:seaweedfsadmin}"
-    secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}"
-    bucket: "${S3_BUCKET:dbrepo}"
-  system:
-    username: "${SYSTEM_USERNAME:admin}"
-    password: "${SYSTEM_PASSWORD:admin}"
   endpoints:
     analyseService: "${ANALYSE_SERVICE_ENDPOINT:http://analyse-service:8080}"
     searchService: "${SEARCH_SERVICE_ENDPOINT:http://search-service:8080}"
@@ -72,6 +57,13 @@ dbrepo:
     storageService: "${S3_ENDPOINT:http://storage-service:9000}"
     rorService: "${ROR_ENDPOINT:https://api.ror.org}"
     crossRefService: "${CROSSREF_ENDPOINT:http://data.crossref.org}"
+  s3:
+    accessKeyId: "${S3_ACCESS_KEY_ID:seaweedfsadmin}"
+    secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}"
+    bucket: "${S3_BUCKET:dbrepo}"
+  system:
+    username: "${SYSTEM_USERNAME:admin}"
+    password: "${SYSTEM_PASSWORD:admin}"
   pid:
     base: "${BASE_URL:http://localhost}/pid/"
   jwt:
@@ -82,3 +74,11 @@ dbrepo:
     client: "${AUTH_SERVICE_CLIENT:dbrepo-client}"
     clientSecret: "${AUTH_SERVICE_CLIENT_SECRET:MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG}"
   website: "${BASE_URL:http://localhost}"
+  repository-name: "${REPOSITORY_NAME:Database Repository}"
+  base-url: "${BASE_URL:http://localhost}"
+  admin-email: "${ADMIN_EMAIL:noreply@example.com}"
+  deleted-record: "${DELETED_RECORD:persistent}"
+  granularity: "${GRANULARITY:YYYY-MM-DDThh:mm:ssZ}"
+  exchangeName: "${BROKER_EXCHANGE_NAME:dbrepo}"
+  queueName: "${BROKER_QUEUE_NAME:dbrepo}"
+  connectionTimeout: "${SPARQL_CONNECTION_TIMEOUT:10000}"
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java
index 66add61c3988c483a83b20d9d10b3cbb123d4fcd..abfd9653dbbdaf8e40916b893d4acae35af865a0 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java
@@ -196,7 +196,7 @@ public class MetadataMapperUnitTest extends AbstractUnitTest {
         final TableBriefDto table0 = response.getTables().get(0);
         assertEquals(TABLE_1_ID, table0.getId());
         assertEquals(TABLE_1_NAME, table0.getName());
-        assertEquals(TABLE_1_INTERNALNAME, table0.getInternalName());
+        assertEquals(TABLE_1_INTERNAL_NAME, table0.getInternalName());
         assertEquals(TABLE_1_DESCRIPTION, table0.getDescription());
         assertEquals(DATABASE_1_ID, table0.getDatabaseId());
         assertEquals(TABLE_1_SCHEMA_PUBLIC, table0.getIsSchemaPublic());
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java
index 1b8419612e2674b43c29c4c377f88ca38b3c7784..3f69453649dac695a7939ffe2881eb02d855c79d 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java
@@ -172,7 +172,7 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest
                 .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT))
                 .andExpect(header().string("X-Type", IMAGE_1_JDBC))
                 .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME))
-                .andExpect(header().string("X-Table", TABLE_1_INTERNALNAME))
+                .andExpect(header().string("X-Table", TABLE_1_INTERNAL_NAME))
                 .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Table"))
                 .andExpect(status().isOk());
     }
@@ -190,7 +190,7 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest
                 .andExpect(header().string("X-Port", "" + CONTAINER_1_PORT))
                 .andExpect(header().string("X-Type", IMAGE_1_JDBC))
                 .andExpect(header().string("X-Database", DATABASE_1_INTERNALNAME))
-                .andExpect(header().string("X-Table", TABLE_1_INTERNALNAME))
+                .andExpect(header().string("X-Table", TABLE_1_INTERNAL_NAME))
                 .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Table"))
                 .andExpect(status().isOk());
     }
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 551a6c350a95e1c9a22fb55d72e04530386cb522..01fc883bc8668b8c163527913b23d1206af302a6 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
@@ -107,7 +107,7 @@ public class TableServiceUnitTest extends AbstractUnitTest {
 
         /* test */
         assertThrows(DatabaseNotFoundException.class, () -> {
-            tableService.findByName(DATABASE_3_ID, TABLE_1_INTERNALNAME);
+            tableService.findByName(DATABASE_3_ID, TABLE_1_INTERNAL_NAME);
         });
     }
 
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 b8c66fa6b75b9041dc61b1d6bebd0f67345f6042..c67cb68ce2ca8bf58d07654a3a05deeb97404a4d 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
@@ -124,6 +124,7 @@ public abstract class AbstractUnitTest extends BaseTest {
         TABLE_8_PRIVILEGED_DTO.setDatabase(DATABASE_3_PRIVILEGED_DTO);
         VIEW_5.setDatabase(DATABASE_3);
         VIEW_5.setColumns(VIEW_5_COLUMNS);
+        VIEW_5_DTO.setColumns(VIEW_5_COLUMNS_DTO);
         IDENTIFIER_6.setDatabase(DATABASE_3);
         /* DATABASE 4 */
         DATABASE_4.setSubsets(new LinkedList<>());
diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock
index 989d39c4e18b5ac3eb206958ba850a44bd4ce4dc..452860e9484791d2f407d636bbe8d08e9d502184 100644
--- a/dbrepo-search-service/Pipfile.lock
+++ b/dbrepo-search-service/Pipfile.lock
@@ -345,7 +345,6 @@
                 "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b",
                 "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc",
                 "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543",
-                "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385",
                 "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c",
                 "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591",
                 "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede",
@@ -353,7 +352,6 @@
                 "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f",
                 "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123",
                 "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c",
-                "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba",
                 "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c",
                 "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285",
                 "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd",
@@ -375,7 +373,7 @@
         },
         "dbrepo": {
             "hashes": [
-                "sha256:14ffe47cb4fbe4bb1d4de392975e232ae1a93127ee3199640db146b42fa02993"
+                "sha256:6096e237ff5b00f471d88e74229952f1e5fcba8683f486952d76a9e257de35c8"
             ],
             "path": "./lib/dbrepo-1.6.0.tar.gz"
         },
diff --git a/dbrepo-search-service/init/lib/dbrepo-1.5.3.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.5.3.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..2bb796d8fece2d97c3b2168248ff493dfa24a549
Binary files /dev/null and b/dbrepo-search-service/init/lib/dbrepo-1.5.3.tar.gz differ
diff --git a/dbrepo-search-service/init/lib/dbrepo-1.6.0.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.6.0.tar.gz
index 39b56b881d32601bf876dae9807d648910488cc2..8c30bf71a45ba3f95b7a82f05f225506a8a3dfe4 100644
Binary files a/dbrepo-search-service/init/lib/dbrepo-1.6.0.tar.gz and b/dbrepo-search-service/init/lib/dbrepo-1.6.0.tar.gz differ
diff --git a/dbrepo-search-service/lib/dbrepo-1.5.3.tar.gz b/dbrepo-search-service/lib/dbrepo-1.5.3.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..2bb796d8fece2d97c3b2168248ff493dfa24a549
Binary files /dev/null and b/dbrepo-search-service/lib/dbrepo-1.5.3.tar.gz differ
diff --git a/dbrepo-search-service/lib/dbrepo-1.6.0.tar.gz b/dbrepo-search-service/lib/dbrepo-1.6.0.tar.gz
index 39b56b881d32601bf876dae9807d648910488cc2..8c30bf71a45ba3f95b7a82f05f225506a8a3dfe4 100644
Binary files a/dbrepo-search-service/lib/dbrepo-1.6.0.tar.gz and b/dbrepo-search-service/lib/dbrepo-1.6.0.tar.gz differ
diff --git a/dbrepo-ui/components/subset/Results.vue b/dbrepo-ui/components/subset/Results.vue
index 4ba414309c5009bdf88914150b6c1afe11e9a65e..ba063dcf5d575071d851da73bfcd0b9da80b5fed 100644
--- a/dbrepo-ui/components/subset/Results.vue
+++ b/dbrepo-ui/components/subset/Results.vue
@@ -171,10 +171,10 @@ export default {
       }
     },
     mapResults (data) {
-      this.result.headers = data.headers.map((h) => {
+      this.result.headers = data.headers.map((header) => {
         return {
-          title: Object.keys(h)[0],
-          value: Object.keys(h)[0],
+          title: header,
+          value: header,
           sortable: false
         }
       })
diff --git a/dbrepo-ui/composables/query-service.ts b/dbrepo-ui/composables/query-service.ts
index b3c21c605344db722259df375d7eba98404c65de..119915de2785763d549bdf3bf2d97379811f8fed 100644
--- a/dbrepo-ui/composables/query-service.ts
+++ b/dbrepo-ui/composables/query-service.ts
@@ -84,7 +84,12 @@ export const useQueryService = (): any => {
       axios.post<QueryResultDto>(`/api/database/${databaseId}/subset`, data, {params: mapFilter(timestamp, page, size), timeout: 600_000})
         .then((response) => {
           console.info('Executed query with id', response.data.id, ' in database with id', databaseId)
-          resolve(response.data)
+          const result: QueryResultDto = {
+            id: 1,
+            headers: [],
+            result: response.data
+          }
+          resolve(result)
         })
         .catch((error) => {
           console.error('Failed to execute query', error)
@@ -100,7 +105,12 @@ export const useQueryService = (): any => {
       axios.get<QueryResultDto>(`/api/database/${databaseId}/subset/${queryId}/data`, { params: mapFilter(null, page, size) })
         .then((response) => {
           console.info('Re-executed query in database with id', databaseId)
-          resolve(response.data)
+          const result: QueryResultDto = {
+            id: Number(response.headers['x-id']),
+            headers: response.headers['x-headers'] ? response.headers['x-headers'].split(',') : [],
+            result: response.data
+          }
+          resolve(result)
         })
         .catch((error) => {
           console.error('Failed to re-execute query', error)
diff --git a/dbrepo-ui/composables/table-service.ts b/dbrepo-ui/composables/table-service.ts
index 35c53edd03077e931b105afba02db404422b13ce..f2e7a3a2f9f07cf9ed25b1220190e22879ef7a83 100644
--- a/dbrepo-ui/composables/table-service.ts
+++ b/dbrepo-ui/composables/table-service.ts
@@ -90,7 +90,12 @@ export const useTableService = (): any => {
       axios.get<QueryResultDto>(`/api/database/${databaseId}/table/${tableId}/data`, { params: mapFilter(timestamp, page, size) })
         .then((response) => {
           console.info('Got data for table with id', tableId, 'in database with id', databaseId)
-          resolve(response.data)
+          const result: QueryResultDto = {
+            id: tableId,
+            headers: response.headers['x-headers'] ? response.headers['x-headers'].split(',') : [],
+            result: response.data
+          }
+          resolve(result)
         })
         .catch((error) => {
           console.error('Failed to get data', error)
diff --git a/dbrepo-ui/composables/view-service.ts b/dbrepo-ui/composables/view-service.ts
index 9c9a6792d37dfb7bccd68f58f9640b1de4fddc11..4c948a57f10b5637cb441baa83e42bb9c3850a46 100644
--- a/dbrepo-ui/composables/view-service.ts
+++ b/dbrepo-ui/composables/view-service.ts
@@ -73,7 +73,12 @@ export const useViewService = (): any => {
       axios.get<QueryResultDto>(`/api/database/${databaseId}/view/${viewId}/data`, {params: {page, size}})
         .then((response) => {
           console.info('Re-executed view with id', viewId, 'in database with id', databaseId)
-          resolve(response.data)
+          const result: QueryResultDto = {
+            id: viewId,
+            headers: response.headers['x-headers'] ? response.headers['x-headers'].split(',') : [],
+            result: response.data
+          }
+          resolve(result)
         })
         .catch((error) => {
           console.error('Failed to re-execute view', error)
diff --git a/dbrepo-ui/dto/index.ts b/dbrepo-ui/dto/index.ts
index b84c6c897d9b397c63eb3a4361135ea2714f7e39..9171734aa350f242d2f38b0d0d0f795871f0306d 100644
--- a/dbrepo-ui/dto/index.ts
+++ b/dbrepo-ui/dto/index.ts
@@ -563,7 +563,7 @@ interface ImportCsv {
 interface QueryResultDto {
   id: number | null;
   result: any;
-  headers: any;
+  headers: string[];
 }
 
 interface TableHistoryDto {
diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json
index 185576248c411e6e0ff3cc5db2866d602f0bd96a..162f4c09d2aa873820e8f4c84e6b73182825aa69 100644
--- a/dbrepo-ui/locales/en-US.json
+++ b/dbrepo-ui/locales/en-US.json
@@ -321,8 +321,8 @@
       "size": {
         "title": "Size"
       },
-      "result-rows": {
-        "title": "Rows"
+      "rows": {
+        "title": "Result Rows"
       },
       "owner": {
         "title": "Owner"
diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/data.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/data.vue
index d4d707fab871efd1773884d8eb5b23f720fba410..3ac8f40d645b44449f5607b9f3b031d06fa463d6 100644
--- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/data.vue
+++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/data.vue
@@ -148,7 +148,7 @@ export default {
           const url = URL.createObjectURL(data)
           const link = document.createElement('a')
           link.href = url
-          link.download = 'table.csv'
+          link.download = 'subset.csv'
           document.body.appendChild(link)
           link.click()
         })
diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue
index 0d59b1ed25e405db59c50e3f492d9122f9fbf5ae..b9ed74a04287e3f8ecb76b88309399b31d234cd4 100644
--- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue
+++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue
@@ -66,7 +66,7 @@
             <pre>{{ $t('pages.subset.hash.prefix') }}:{{ result_hash }}</pre>
           </v-list-item>
           <v-list-item
-            :title="$t('pages.subset.result-rows.title')"
+            :title="$t('pages.subset.rows.title')"
             density="compact">
             {{ subset.result_number }}
           </v-list-item>
diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue
index 5baedc281c94951ae7072f287657c9ec4c5c3425..5f322fa498b4b05607db6422cc7964d98515cb74 100644
--- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue
+++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue
@@ -47,7 +47,7 @@
           </v-list-item>
           <v-list-item
             v-if="table"
-            :title="$t('pages.table.result-rows.title')">
+            :title="$t('pages.table.rows.title')">
             {{ table.num_rows }}
           </v-list-item>
           <v-list-item
@@ -83,24 +83,6 @@
         </v-list>
       </v-card-text>
     </v-card>
-    <v-divider />
-    <v-card
-      :title="$t('pages.database.title')"
-      variant="flat">
-      <v-card-text>
-        <v-list dense>
-          <v-list-item
-            v-if="database"
-            :title="$t('pages.database.name.title')">
-            <NuxtLink
-              class="text-primary"
-              :to="`/database/${$route.params.database_id}`">
-              {{ database.internal_name }}
-            </NuxtLink>
-          </v-list-item>
-        </v-list>
-      </v-card-text>
-    </v-card>
     <v-divider
       v-if="canWrite && canWriteQueues" />
     <v-card
@@ -146,6 +128,29 @@
         </v-list>
       </v-card-text>
     </v-card>
+    <v-divider />
+    <v-card
+      :title="$t('pages.database.title')"
+      variant="flat">
+      <v-card-text>
+        <v-list dense>
+          <v-list-item
+            v-if="database"
+            :title="$t('pages.database.visibility.title')">
+            {{ database.is_public ? $t('toolbars.database.public') : $t('toolbars.database.private') }}
+          </v-list-item>
+          <v-list-item
+            v-if="database"
+            :title="$t('pages.database.name.title')">
+            <NuxtLink
+              class="text-primary"
+              :to="`/database/${database.id}`">
+              {{ database.internal_name }}
+            </NuxtLink>
+          </v-list-item>
+        </v-list>
+      </v-card-text>
+    </v-card>
     <v-breadcrumbs :items="items" class="pa-0 mt-2" />
   </div>
 </template>
diff --git a/dbrepo-upload-service/pom.xml b/dbrepo-upload-service/pom.xml
index 9684d60454c1fecdeb0de0c3c88ffc2170a9e5f9..ba4567da8db9d4a61d03fdceb3e08aea29f558a7 100644
--- a/dbrepo-upload-service/pom.xml
+++ b/dbrepo-upload-service/pom.xml
@@ -5,13 +5,13 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.1.12</version>
+        <version>3.3.5</version>
     </parent>
 
     <groupId>at.tuwien</groupId>
     <artifactId>dbrepo-upload-service</artifactId>
     <name>dbrepo-upload-service</name>
-    <version>1.5.2</version>
+    <version>1.5.3</version>
 
     <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.5/</url>
     <developers>
@@ -24,11 +24,11 @@
 
     <properties>
         <java.version>17</java.version>
-        <spring-cloud.version>4.0.2</spring-cloud.version>
+        <spring-cloud.version>4.1.4</spring-cloud.version>
         <mapstruct.version>1.5.5.Final</mapstruct.version>
         <rabbitmq.version>5.20.0</rabbitmq.version>
         <jackson-datatype.version>2.15.0</jackson-datatype.version>
-        <commons-io.version>2.15.0</commons-io.version>
+        <commons-io.version>2.17.0</commons-io.version>
         <commons-validator.version>1.8.0</commons-validator.version>
         <guava.version>33.0.0-jre</guava.version>
         <jacoco.version>0.8.12</jacoco.version>
diff --git a/dbrepo-upload-service/src/main/resources/application.yml b/dbrepo-upload-service/src/main/resources/application.yml
index 2d79e7cfae29b68515a6f008fd1aaae2c53f0461..e0285aa736a747004d99d90da05a0259ba0500a4 100644
--- a/dbrepo-upload-service/src/main/resources/application.yml
+++ b/dbrepo-upload-service/src/main/resources/application.yml
@@ -2,11 +2,6 @@ application:
   title: DBRepo
   version: '@project.version@'
 spring:
-  datasource:
-    url: "jdbc:mariadb://${METADATA_HOST:metadata-db}:${METADATA_PORT:3306}/${METADATA_DB:dbrepo}${METADATA_JDBC_EXTRA_ARGS}"
-    driver-class-name: org.mariadb.jdbc.Driver
-    username: "${METADATA_USERNAME:root}"
-    password: "${METADATA_DB_PASSWORD:dbrepo}"
   jpa:
     show-sql: false
     open-in-view: false
@@ -16,13 +11,7 @@ spring:
         jdbc:
           time_zone: UTC
   application:
-    name: metadata-service
-  rabbitmq:
-    host: "${BROKER_HOST:broker-service}"
-    virtual-host: "${BROKER_VIRTUALHOST:dbrepo}"
-    username: "${BROKER_USERNAME:admin}"
-    password: "${BROKER_PASSWORD:admin}"
-    port: ${BROKER_PORT:5672}
+    name: upload-service
   main:
     banner-mode: off
 management:
@@ -47,38 +36,3 @@ logging:
     root: warn
     at.tuwien.: "${LOG_LEVEL:info}"
     org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug
-dbrepo:
-  repository-name: "${REPOSITORY_NAME:Database Repository}"
-  base-url: "${BASE_URL:http://localhost}"
-  admin-email: "${ADMIN_EMAIL:noreply@example.com}"
-  deleted-record: "${DELETED_RECORD:persistent}"
-  granularity: "${GRANULARITY:YYYY-MM-DDThh:mm:ssZ}"
-  exchangeName: "${BROKER_EXCHANGE_NAME:dbrepo}"
-  queueName: "${BROKER_QUEUE_NAME:dbrepo}"
-  connectionTimeout: "${SPARQL_CONNECTION_TIMEOUT:10000}"
-  s3:
-    accessKeyId: "${S3_ACCESS_KEY_ID:seaweedfsadmin}"
-    secretAccessKey: "${S3_SECRET_ACCESS_KEY:seaweedfsadmin}"
-    bucket: "${S3_BUCKET:dbrepo}"
-  system:
-    username: "${SYSTEM_USERNAME:admin}"
-    password: "${SYSTEM_PASSWORD:admin}"
-  endpoints:
-    analyseService: "${ANALYSE_SERVICE_ENDPOINT:http://analyse-service:8080}"
-    searchService: "${SEARCH_SERVICE_ENDPOINT:http://search-service:8080}"
-    dataService: "${DATA_SERVICE_ENDPOINT:http://data-service:8080}"
-    brokerService: "${BROKER_SERVICE_ENDPOINT:http://broker-service:15672}"
-    authService: "${AUTH_SERVICE_ENDPOINT:http://auth-service:8080}"
-    storageService: "${S3_ENDPOINT:http://storage-service:9000}"
-    rorService: "${ROR_ENDPOINT:https://api.ror.org}"
-    crossRefService: "${CROSSREF_ENDPOINT:http://data.crossref.org}"
-  pid:
-    base: "${BASE_URL:http://localhost}/pid/"
-  jwt:
-    public_key: "${JWT_PUBKEY:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB}"
-  keycloak:
-    username: "${AUTH_SERVICE_ADMIN:admin}"
-    password: "${AUTH_SERVICE_ADMIN_PASSWORD:admin}"
-    client: "${AUTH_SERVICE_CLIENT:dbrepo-client}"
-    clientSecret: "${AUTH_SERVICE_CLIENT_SECRET:MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG}"
-  website: "${BASE_URL:http://localhost}"
diff --git a/dbrepo-upload-service/src/test/resources/application.properties b/dbrepo-upload-service/src/test/resources/application.properties
index 088fec498b6cd74aba161d18ec30ad500e18bd4c..cb41084578e2b476f1d550d6f890234cbea64180 100644
--- a/dbrepo-upload-service/src/test/resources/application.properties
+++ b/dbrepo-upload-service/src/test/resources/application.properties
@@ -4,15 +4,8 @@ spring.profiles.active=local,junit
 # disable discovery
 spring.cloud.discovery.enabled=false
 
-# internal datasource
-spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS DBREPO;NON_KEYWORDS=value
-spring.datasource.driverClassName=org.h2.Driver
-spring.datasource.username=sa
-spring.datasource.password=password
-spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
-spring.sql.init.mode=always
-spring.sql.init.schema-locations=classpath*:init/schema.sql
-spring.jpa.hibernate.ddl-auto=create
+# disable datasource
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
 
 # logging
 logging.level.root=error