From 8eadc95c242dc691c129d53dec941fb2300ada62 Mon Sep 17 00:00:00 2001
From: Moritz Staudinger <moritz.staudinger@tuwien.ac.at>
Date: Thu, 3 Mar 2022 02:44:01 +0100
Subject: [PATCH] refactored execute to use re-execute, limited on resultnumber

Former-commit-id: 60fdf6dccf16c9687cc1c58fda0f634683bf26cb
---
 .../at/tuwien/endpoint/QueryEndpoint.java     |  6 +--
 .../endpoint/QueryEndpointUnitTest.java       |  8 ++--
 .../service/QueryServiceIntegrationTest.java  |  5 ++-
 .../java/at/tuwien/service/QueryService.java  |  2 +-
 .../java/at/tuwien/service/StoreService.java  |  5 +++
 .../tuwien/service/impl/QueryServiceImpl.java | 40 +++----------------
 .../tuwien/service/impl/StoreServiceImpl.java | 39 ++++++++++++++++++
 7 files changed, 61 insertions(+), 44 deletions(-)

diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
index 4b61ff7963..2b0266168f 100644
--- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
+++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
@@ -53,9 +53,9 @@ public class QueryEndpoint {
     public ResponseEntity<QueryResultDto> execute(@NotNull @PathVariable("id") Long id,
                                                   @NotNull @PathVariable("databaseId") Long databaseId,
                                                   @Valid @RequestBody ExecuteStatementDto data,
-                                                  @RequestParam("page") Long page, @RequestParam("size") Long size)
+                                                  @RequestParam(value = "page", required = false ) Long page, @RequestParam(value = "size", required = false) Long size)
             throws DatabaseNotFoundException, ImageNotSupportedException, QueryStoreException, QueryMalformedException,
-            TableNotFoundException, ContainerNotFoundException {
+            TableNotFoundException, ContainerNotFoundException, SQLException, JSQLParserException {
         /* validation */
         if (data.getStatement() == null || data.getStatement().isBlank()) {
             log.error("Query is empty");
@@ -103,7 +103,7 @@ public class QueryEndpoint {
     public ResponseEntity<QueryResultDto> reExecute(@NotNull @PathVariable("id") Long id,
                                                     @NotNull @PathVariable("databaseId") Long databaseId,
                                                     @NotNull @PathVariable("queryId") Long queryId,
-                                                    @RequestParam("page") Long page, @RequestParam("size") Long size)
+                                                    @RequestParam(value = "page", required = false) Long page, @RequestParam(value = "size", required = false) Long size)
             throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
             TableNotFoundException, QueryMalformedException, ContainerNotFoundException, SQLException, JSQLParserException {
         final Query query = storeService.findOne(id, databaseId, queryId);
diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java
index 2b8bd543cc..6aaedeb4ca 100644
--- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java
+++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java
@@ -10,6 +10,7 @@ import at.tuwien.exception.*;
 import at.tuwien.service.StoreService;
 import at.tuwien.service.impl.QueryServiceImpl;
 import lombok.extern.log4j.Log4j2;
+import net.sf.jsqlparser.JSQLParserException;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -19,6 +20,7 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
+import java.sql.SQLException;
 import java.time.Instant;
 import java.util.List;
 import java.util.Map;
@@ -45,7 +47,7 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
 
     @Test
     public void execute_succeeds() throws TableNotFoundException, QueryStoreException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException {
+            DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, SQLException, JSQLParserException {
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_1_STATEMENT)
                 .build();
@@ -71,7 +73,7 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
 
     @Test
     public void execute_emptyResult_succeeds() throws TableNotFoundException, QueryStoreException,
-            QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException {
+            QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, SQLException, JSQLParserException {
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_1_STATEMENT)
                 .build();
@@ -97,7 +99,7 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
 
     @Test
     public void execute_tableNotFound_fails() throws TableNotFoundException, QueryMalformedException,
-            DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, QueryStoreException {
+            DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, QueryStoreException, SQLException, JSQLParserException {
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_1_STATEMENT)
                 .build();
diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
index 0c3ad1d614..13d99fdd74 100644
--- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
+++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
@@ -17,6 +17,7 @@ import com.github.dockerjava.api.model.Bind;
 import com.github.dockerjava.api.model.Network;
 import lombok.SneakyThrows;
 import lombok.extern.log4j.Log4j2;
+import net.sf.jsqlparser.JSQLParserException;
 import org.junit.Rule;
 import org.junit.rules.Timeout;
 import org.junit.jupiter.api.*;
@@ -173,7 +174,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
 
     @Test
     public void execute_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, InterruptedException,
-            QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException {
+            QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, SQLException, JSQLParserException {
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement(QUERY_1_STATEMENT)
                 .build();
@@ -207,7 +208,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
     @Disabled
     public void execute_modifyData_fails() throws DatabaseNotFoundException, ImageNotSupportedException,
             InterruptedException, QueryMalformedException, TableNotFoundException, QueryStoreException,
-            ContainerNotFoundException {
+            ContainerNotFoundException, SQLException, JSQLParserException {
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
                 .statement("DELETE FROM `weather_aus`;")
                 .build();
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
index 3e1280f054..774748022e 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
@@ -32,7 +32,7 @@ public interface QueryService {
      * @throws ImageNotSupportedException
      */
     QueryResultDto execute(Long containerId, Long databaseId, ExecuteStatementDto query, Long page, Long size) throws TableNotFoundException,
-            QueryStoreException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException;
+            QueryStoreException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, SQLException, JSQLParserException;
 
     /**
      * Re-Executes an arbitrary query on the database container. We allow the user to only view the data, therefore the
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/StoreService.java b/fda-query-service/services/src/main/java/at/tuwien/service/StoreService.java
index ed49db862f..12368f14b0 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/StoreService.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/StoreService.java
@@ -6,6 +6,7 @@ import at.tuwien.api.database.query.SaveStatementDto;
 import at.tuwien.exception.*;
 import at.tuwien.querystore.Query;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.time.Instant;
 import java.util.List;
@@ -69,4 +70,8 @@ public interface StoreService {
                  Instant execution) throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
             ContainerNotFoundException;
 
+    @Transactional(readOnly = true)
+    Query update(Long containerId, Long databaseId, QueryResultDto result, Long resultNumber, Query metadata)
+            throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
+            ContainerNotFoundException;
 }
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
index 22a5a66f50..ccbf4f5ff6 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
@@ -61,42 +61,12 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
     @Override
     @Transactional
     public QueryResultDto execute(Long containerId, Long databaseId, ExecuteStatementDto statement, Long page, Long size)
-            throws DatabaseNotFoundException, ImageNotSupportedException, QueryMalformedException, QueryStoreException, ContainerNotFoundException {
-        /* find */
-        final Database database = databaseService.find(databaseId);
-        if (!database.getContainer().getImage().getRepository().equals("mariadb")) {
-            throw new ImageNotSupportedException("Currently only MariaDB is supported");
-        }
-        /* run query */
-        final long startSession = System.currentTimeMillis();
-        final SessionFactory factory = getSessionFactory(database);
-        final Session session = factory.openSession();
-        log.debug("opened hibernate session in {} ms", System.currentTimeMillis() - startSession);
-        session.beginTransaction();
-        /* prepare the statement */
+            throws DatabaseNotFoundException, ImageNotSupportedException, QueryMalformedException, QueryStoreException, ContainerNotFoundException, TableNotFoundException, SQLException, JSQLParserException {
         Instant i = Instant.now();
-        final NativeQuery<?> query = session.createSQLQuery(queryMapper.queryToRawTimestampedQuery(statement.getStatement(), database, i));
-        final int affectedTuples;
-        try {
-            log.debug("execute raw view-only query {}", statement);
-            affectedTuples = query.executeUpdate();
-            log.info("Execution on database id {} affected {} rows", databaseId, affectedTuples);
-            session.getTransaction()
-                    .commit();
-        } catch (SQLGrammarException e) {
-            session.close();
-            factory.close();
-            throw new QueryMalformedException("Query not valid for this database", e);
-        }
-        /* map the result to the tables (with respective columns) from the statement metadata */
-        final List<TableColumn> columns = parseColumns(databaseId, statement);
-        final QueryResultDto result = queryMapper.resultListToQueryResultDto(columns, query.getResultList());
-        /* Save query in the querystore */
-        Query q = storeService.insert(containerId, databaseId, result, statement, i);
-        result.setId(q.getId());
-        session.close();
-        factory.close();
-        log.debug("query id {}", result.getId());
+        Query q = storeService.insert(containerId, databaseId, null, statement, i);
+        final QueryResultDto result = this.reExecute(containerId,databaseId,q,page,size);
+        Long resultNumber = 0L;
+        q = storeService.update(containerId,databaseId,result, resultNumber,q);
         return result;
     }
 
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/StoreServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/StoreServiceImpl.java
index 7fbda87023..992a0767f1 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/StoreServiceImpl.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/StoreServiceImpl.java
@@ -146,4 +146,43 @@ public class StoreServiceImpl extends HibernateConnector implements StoreService
         return query;
     }
 
+    @Override
+    @Transactional(readOnly = true)
+    public Query update(Long containerId, Long databaseId, QueryResultDto result, Long resultNumber, Query metadata)
+            throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
+            ContainerNotFoundException {
+        /* find */
+        final Container container = containerService.find(containerId);
+        final Database database = databaseService.find(databaseId);
+        if (!database.getContainer().getImage().getRepository().equals("mariadb")) {
+            throw new ImageNotSupportedException("Currently only MariaDB is supported");
+        }
+
+        log.debug("Update database id {}, metadata {}", databaseId, metadata);
+        /* save */
+        final SessionFactory factory = getSessionFactory(database, true);
+        final Session session = factory.openSession();
+        final Transaction transaction = session.beginTransaction();
+        final Query query = Query.builder()
+                .cid(containerId)
+                .dbid(databaseId)
+                .query(metadata.getQuery())
+                .queryNormalized(metadata.getQuery())
+                .queryHash(DigestUtils.sha256Hex(metadata.getQuery()))
+                .resultNumber(resultNumber)
+                .resultHash(storeMapper.queryResultDtoToString(result))
+                .execution(metadata.getExecution())
+                .build();
+        session.update(query);
+        transaction.commit();
+        /* store the result in the query store */
+        log.info("Update query with id {}", query.getId());
+        log.debug("saved query {}", query);
+        session.close();
+        factory.close();
+        return query;
+    }
+
+
+
 }
-- 
GitLab