From c95b460aa972d23b86e554ee68a9f74982e4e18f Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Mon, 17 Oct 2022 13:13:37 +0200
Subject: [PATCH] WIP: SELECT for GRPC

---
 caosdb-proto                                  |  2 +-
 .../server/grpc/CaosDBToGrpcConverters.java   |  9 ++++++++
 .../grpc/EntityTransactionServiceImpl.java    |  6 +++++
 .../server/jobs/core/CheckQueryTemplate.java  | 22 +++++++++----------
 .../caosdb/server/jobs/core/ExecuteQuery.java | 18 ++++++++++-----
 .../java/org/caosdb/server/query/CQLParser.g4 |  2 +-
 .../java/org/caosdb/server/query/Query.java   |  5 +++--
 7 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/caosdb-proto b/caosdb-proto
index c439aa40..0b301401 160000
--- a/caosdb-proto
+++ b/caosdb-proto
@@ -1 +1 @@
-Subproject commit c439aa40a30c9214db315018b84fa50112c9251e
+Subproject commit 0b301401cf28d7a3edeb2c55e418f072b83cf5a7
diff --git a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
index fc3c26f6..12cbc921 100644
--- a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
+++ b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
@@ -45,6 +45,7 @@ import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.api.entity.v1.Parent;
 import org.caosdb.api.entity.v1.ReferenceDataType;
 import org.caosdb.api.entity.v1.ScalarValue;
+import org.caosdb.api.entity.v1.SelectQueryResult;
 import org.caosdb.api.entity.v1.SpecialValue;
 import org.caosdb.api.entity.v1.Version;
 import org.caosdb.datetime.DateTimeInterface;
@@ -71,6 +72,7 @@ import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.Role;
 import org.caosdb.server.entity.StatementStatus;
 import org.caosdb.server.entity.container.ParentContainer;
+import org.caosdb.server.entity.container.RetrieveContainer;
 import org.caosdb.server.entity.wrapper.Property;
 import org.caosdb.server.entity.xml.SerializeFieldStrategy;
 import org.caosdb.server.permissions.EntityACI;
@@ -588,4 +590,11 @@ public class CaosDBToGrpcConverters {
     }
     return result;
   }
+
+  public org.caosdb.api.entity.v1.SelectQueryResult.Builder convertSelectResult(
+      RetrieveContainer container) {
+    // TODO(tf)
+    SelectQueryResult.Builder result = SelectQueryResult.newBuilder();
+    return result;
+  }
 }
diff --git a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
index 315358de..30c493a8 100644
--- a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
@@ -43,6 +43,7 @@ import org.caosdb.api.entity.v1.MultiTransactionResponse;
 import org.caosdb.api.entity.v1.MultiUpdateEntityACLRequest;
 import org.caosdb.api.entity.v1.MultiUpdateEntityACLResponse;
 import org.caosdb.api.entity.v1.RetrieveResponse;
+import org.caosdb.api.entity.v1.SelectQueryResult;
 import org.caosdb.api.entity.v1.TransactionRequest;
 import org.caosdb.api.entity.v1.TransactionRequest.WrappedRequestsCase;
 import org.caosdb.api.entity.v1.TransactionResponse;
@@ -130,10 +131,15 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
     final Retrieve transaction = new Retrieve(container);
     transaction.execute();
     if (container.getFlags().containsKey("query_count_result")) {
+      // this was a count query
       final int count = Integer.parseInt(container.getFlags().get("query_count_result"));
       builder
           .addResponsesBuilder()
           .setRetrieveResponse(RetrieveResponse.newBuilder().setCountResult(count));
+    } else if (container.getFlags().containsKey("query_select") && "true".equals(container.getFlags().get("query_select"))) {
+      // this was a select query
+      SelectQueryResult.Builder selectResult = caosdbToGrpc.convertSelectResult(container);
+      builder.addResponsesBuilder().setRetrieveResponse(RetrieveResponse.newBuilder().setSelectResult(selectResult));
     } else {
       final boolean download_files_container = container.getFlags().containsKey("download_files");
       for (final EntityInterface entity : container) {
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckQueryTemplate.java b/src/main/java/org/caosdb/server/jobs/core/CheckQueryTemplate.java
index 1b5ccb41..42dccf55 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckQueryTemplate.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckQueryTemplate.java
@@ -26,8 +26,6 @@ import org.caosdb.server.entity.Role;
 import org.caosdb.server.jobs.EntityJob;
 import org.caosdb.server.query.Query;
 import org.caosdb.server.query.Query.ParsingException;
-import org.caosdb.server.query.Query.Type;
-import org.caosdb.server.utils.EntityStatus;
 import org.caosdb.server.utils.ServerMessages;
 
 public class CheckQueryTemplate extends EntityJob {
@@ -40,20 +38,22 @@ public class CheckQueryTemplate extends EntityJob {
         final Query q = new Query(getEntity().getQueryTemplateDefinition());
         try {
           q.parse();
-          if (q.getType() == Type.COUNT) {
-            getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
-            getEntity().addError(ServerMessages.QUERY_TEMPLATE_WITH_COUNT);
-          }
-          if (q.getSelections() != null && !q.getSelections().isEmpty()) {
-            getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
-            getEntity().addError(ServerMessages.QUERY_TEMPLATE_WITH_SELECT);
+          switch (q.getType()) {
+            case COUNT:
+              getEntity().addError(ServerMessages.QUERY_TEMPLATE_WITH_COUNT);
+              break;
+
+            case SELECT:
+              getEntity().addError(ServerMessages.QUERY_TEMPLATE_WITH_SELECT);
+              break;
+
+            default:
+              break;
           }
         } catch (final ParsingException e) {
-          getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
           getEntity().addError(ServerMessages.QUERY_PARSING_ERROR);
         }
       } else {
-        getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
         getEntity().addError(ServerMessages.QUERY_TEMPLATE_HAS_NO_QUERY_DEFINITION);
       }
     }
diff --git a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
index 0a19977b..0126c83e 100644
--- a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
+++ b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
@@ -31,7 +31,6 @@ import org.caosdb.server.jobs.JobAnnotation;
 import org.caosdb.server.jobs.TransactionStage;
 import org.caosdb.server.query.Query;
 import org.caosdb.server.query.Query.ParsingException;
-import org.caosdb.server.query.Query.Type;
 import org.caosdb.server.utils.EntityStatus;
 import org.caosdb.server.utils.ServerMessages;
 
@@ -55,10 +54,19 @@ public class ExecuteQuery extends FlagJob {
       getContainer().addMessage(new Message(MessageType.Info, (MessageCode) null, e.getMessage()));
     }
     getContainer().addMessage(queryInstance);
-    if (queryInstance.getQuery().getType() == Type.COUNT) {
-      getContainer()
-          .getFlags()
-          .put("query_count_result", Integer.toString(queryInstance.getCount()));
+    switch (queryInstance.getQuery().getType()) {
+      case COUNT:
+        getContainer()
+            .getFlags()
+            .put("query_count_result", Integer.toString(queryInstance.getCount()));
+        break;
+      case SELECT:
+        getContainer()
+            .getFlags()
+            .put("query_select", "true");
+
+      default:
+        break;
     }
     for (final EntityInterface entity : getContainer()) {
       getTransaction().getSchedule().addAll(loadJobs(entity, getTransaction()));
diff --git a/src/main/java/org/caosdb/server/query/CQLParser.g4 b/src/main/java/org/caosdb/server/query/CQLParser.g4
index c4a68e5f..d44674b2 100644
--- a/src/main/java/org/caosdb/server/query/CQLParser.g4
+++ b/src/main/java/org/caosdb/server/query/CQLParser.g4
@@ -40,7 +40,7 @@ cq returns [Query.Type t, List<Query.Selection> s, Query.Pattern e, Query.Role r
 :
 
     (
-       SELECT prop_sel {$s = $prop_sel.s;} FROM {$t = Query.Type.FIND;}
+       SELECT prop_sel {$s = $prop_sel.s;} FROM {$t = Query.Type.SELECT;}
        | FIND {$t = Query.Type.FIND;}
        | COUNT {$t = Query.Type.COUNT;})
     (version {$v = $version.v;})?
diff --git a/src/main/java/org/caosdb/server/query/Query.java b/src/main/java/org/caosdb/server/query/Query.java
index 7da810c3..88da39bc 100644
--- a/src/main/java/org/caosdb/server/query/Query.java
+++ b/src/main/java/org/caosdb/server/query/Query.java
@@ -165,7 +165,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
 
   public enum Type {
     FIND,
-    COUNT
+    COUNT,
+    SELECT,
   };
 
   public static final class Pattern {
@@ -722,7 +723,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
   }
   /** Fill entities from `resultSet` into `container`. */
   private void fillContainerWithResult() {
-    if (this.container != null && this.type == Type.FIND) {
+    if (this.container != null && (this.type == Type.FIND || this.type == Type.SELECT)) {
       for (final IdVersionAclTriplet t : this.resultSet) {
 
         final Entity e = new RetrieveEntity(new EntityID(t.id), t.version);
-- 
GitLab