diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d94ff5f6d730050d2b3925f8bad96df01de01eb..e6f200e107cdee3aa2382c99166b921650a8eb5f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Added
 
+* SELECT query support for the GRPC API
+
 ### Changed
 
 ### Deprecated
diff --git a/caosdb-proto b/caosdb-proto
index c439aa40a30c9214db315018b84fa50112c9251e..13d083b84400507f6f1967a099e2af006af2a231 160000
--- a/caosdb-proto
+++ b/caosdb-proto
@@ -1 +1 @@
-Subproject commit c439aa40a30c9214db315018b84fa50112c9251e
+Subproject commit 13d083b84400507f6f1967a099e2af006af2a231
diff --git a/src/main/java/org/caosdb/server/datatype/BooleanDatatype.java b/src/main/java/org/caosdb/server/datatype/BooleanDatatype.java
index 92c3440aeab6ef1cc86426c4e5d2356aef6720aa..366b77937d3dcf020d98c035821bed0aedaadf8d 100644
--- a/src/main/java/org/caosdb/server/datatype/BooleanDatatype.java
+++ b/src/main/java/org/caosdb/server/datatype/BooleanDatatype.java
@@ -32,6 +32,8 @@ public class BooleanDatatype extends AbstractDatatype {
   public SingleValue parseValue(final Object value) throws Message {
     if (value instanceof BooleanValue) {
       return (SingleValue) value;
+    } else if (value instanceof CollectionValue) {
+      throw ServerMessages.DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES;
     } else if (value instanceof SingleValue) {
       return parse(((SingleValue) value).toDatabaseString());
     } else {
diff --git a/src/main/java/org/caosdb/server/datatype/DoubleDatatype.java b/src/main/java/org/caosdb/server/datatype/DoubleDatatype.java
index e9e2526521d044fc89746eb0e3204de97f473e0c..f3f17ace28802cdb045a4cd66a7ca2a78cde2d1c 100644
--- a/src/main/java/org/caosdb/server/datatype/DoubleDatatype.java
+++ b/src/main/java/org/caosdb/server/datatype/DoubleDatatype.java
@@ -34,6 +34,8 @@ public class DoubleDatatype extends AbstractDatatype {
     try {
       if (value instanceof GenericValue) {
         return parse(((GenericValue) value).toDatabaseString());
+      } else if (value instanceof CollectionValue) {
+        throw ServerMessages.DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES;
       } else {
         return parse(value.toString());
       }
diff --git a/src/main/java/org/caosdb/server/datatype/IntegerDatatype.java b/src/main/java/org/caosdb/server/datatype/IntegerDatatype.java
index 0b1116ed5cbc135f846b5c7fbc0e1d497576380f..f3a58a4a52b888e00ec80f71793cd452c4b98910 100644
--- a/src/main/java/org/caosdb/server/datatype/IntegerDatatype.java
+++ b/src/main/java/org/caosdb/server/datatype/IntegerDatatype.java
@@ -33,6 +33,8 @@ public class IntegerDatatype extends AbstractDatatype {
     try {
       if (value instanceof GenericValue) {
         return new GenericValue(Long.parseLong(((GenericValue) value).toDatabaseString()));
+      } else if (value instanceof CollectionValue) {
+        throw ServerMessages.DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES;
       } else {
         return new GenericValue(Long.parseLong(value.toString()));
       }
diff --git a/src/main/java/org/caosdb/server/datatype/TextDatatype.java b/src/main/java/org/caosdb/server/datatype/TextDatatype.java
index af06ed6de1f0f49b481b2a706f529037e555785e..3b32fadcb3467528ac377e67db1081295f85c7ec 100644
--- a/src/main/java/org/caosdb/server/datatype/TextDatatype.java
+++ b/src/main/java/org/caosdb/server/datatype/TextDatatype.java
@@ -23,6 +23,7 @@
 package org.caosdb.server.datatype;
 
 import org.caosdb.server.entity.Message;
+import org.caosdb.server.utils.ServerMessages;
 
 @DatatypeDefinition(name = "Text")
 public class TextDatatype extends AbstractDatatype {
@@ -31,6 +32,8 @@ public class TextDatatype extends AbstractDatatype {
   public SingleValue parseValue(final Object value) throws Message {
     if (value instanceof GenericValue) {
       return (GenericValue) value;
+    } else if (value instanceof CollectionValue) {
+      throw ServerMessages.DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES;
     }
     return new GenericValue(value.toString());
   }
diff --git a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
index 289287c82fcd32092d15cb1f10a9dbbd83e77fde..d396345508a028700db6fd8e973390fd634e54d9 100644
--- a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
+++ b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java
@@ -34,6 +34,7 @@ import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.Message.MessageType;
 import org.caosdb.server.entity.xml.ToElementable;
 import org.caosdb.server.jobs.JobTarget;
+import org.caosdb.server.query.Query;
 import org.caosdb.server.utils.EntityStatus;
 import org.jdom2.Element;
 
@@ -120,6 +121,7 @@ public class TransactionContainer extends Container<EntityInterface>
   private HashMap<String, FileProperties> files = new HashMap<String, FileProperties>();
 
   private TransactionBenchmark benchmark;
+  private Query query;
 
   public void setFiles(final HashMap<String, FileProperties> files) {
     this.files = files;
@@ -183,4 +185,12 @@ public class TransactionContainer extends Container<EntityInterface>
       addMessage(new Message(MessageType.Error, m.getCode(), m.getDescription(), m.getBody()));
     }
   }
+
+  public void setQuery(Query query) {
+    this.query = query;
+  }
+
+  public Query getQuery() {
+    return query;
+  }
 }
diff --git a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
index fc3c26f664cd81ec27139c2591f52be7af29c3bd..6fef590746bbf2c3ff802baec73385e4b061ec95 100644
--- a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
+++ b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
@@ -45,9 +45,14 @@ 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.SelectQueryColumn;
+import org.caosdb.api.entity.v1.SelectQueryHeader;
+import org.caosdb.api.entity.v1.SelectQueryResult;
+import org.caosdb.api.entity.v1.SelectQueryRow;
 import org.caosdb.api.entity.v1.SpecialValue;
 import org.caosdb.api.entity.v1.Version;
 import org.caosdb.datetime.DateTimeInterface;
+import org.caosdb.server.database.exceptions.TransactionException;
 import org.caosdb.server.datatype.AbstractCollectionDatatype;
 import org.caosdb.server.datatype.AbstractDatatype;
 import org.caosdb.server.datatype.BooleanDatatype;
@@ -71,10 +76,13 @@ 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;
 import org.caosdb.server.permissions.EntityPermission;
+import org.caosdb.server.query.Query;
+import org.caosdb.server.query.Query.Selection;
 
 public class CaosDBToGrpcConverters {
 
@@ -588,4 +596,200 @@ public class CaosDBToGrpcConverters {
     }
     return result;
   }
+
+  public org.caosdb.api.entity.v1.SelectQueryResult.Builder convertSelectResult(
+      RetrieveContainer container) {
+    SelectQueryResult.Builder result = SelectQueryResult.newBuilder();
+    result.setHeader(convertSelectQueryHeader(container));
+    for (EntityInterface e : container) {
+      result.addDataRows(convert(container.getQuery().getSelections(), e));
+    }
+    return result;
+  }
+
+  private SelectQueryRow.Builder convert(List<Selection> selections, EntityInterface e) {
+
+    SelectQueryRow.Builder result = SelectQueryRow.newBuilder();
+    for (Selection s : selections) {
+      org.caosdb.api.entity.v1.Value.Builder value = getSelectedValue(s, e);
+      result.addCells(value);
+    }
+    return result;
+  }
+
+  /**
+   * Handle special selectors like "id", "name", "value", "parent",...
+   *
+   * @return a {@link org.caosdb.api.entity.v1.Value.Builder}, if the selector has been handled.
+   *     Return null when the caller must handle the selector otherwise.
+   */
+  private org.caosdb.api.entity.v1.Value.Builder handleSpecialSelectors(
+      String selector, EntityInterface e) {
+    org.caosdb.api.entity.v1.Value.Builder result = null;
+    switch (selector) {
+      case "value":
+        try {
+          e.parseValue();
+        } catch (Message m) {
+          throw new TransactionException(m);
+        }
+        if (e.hasValue()) {
+          return convert(e.getValue());
+        }
+        break;
+      case "version":
+        if (e.hasVersion()) {
+          result = org.caosdb.api.entity.v1.Value.newBuilder();
+          result.setScalarValue(convertStringValue(e.getVersion().getId()));
+          return result;
+        }
+        break;
+      case "name":
+        if (e.hasName()) {
+          result = org.caosdb.api.entity.v1.Value.newBuilder();
+          result.setScalarValue(convertStringValue(e.getName()));
+          return result;
+        }
+        break;
+
+      case "id":
+        result = org.caosdb.api.entity.v1.Value.newBuilder();
+        result.setScalarValue(convertStringValue(e.getId().toString()));
+        return result;
+
+      case "description":
+        if (e.hasDescription()) {
+          result = org.caosdb.api.entity.v1.Value.newBuilder();
+          result.setScalarValue(convertStringValue(e.getDescription()));
+          return result;
+        }
+        break;
+
+      case "unit":
+        final String unit = getStringUnit(e);
+        if (unit != null) {
+          result = org.caosdb.api.entity.v1.Value.newBuilder();
+          result.setScalarValue(convertStringValue(unit));
+          return result;
+        }
+        break;
+      case "datatype":
+        if (e.hasDatatype()) {
+          result = org.caosdb.api.entity.v1.Value.newBuilder();
+          result.setScalarValue(convertStringValue(e.getDatatype().toString()));
+          return result;
+        }
+        break;
+      case "path":
+        if (e.hasFileProperties() && e.getFileProperties().hasPath()) {
+          result = org.caosdb.api.entity.v1.Value.newBuilder();
+          result.setScalarValue(convertStringValue(e.getFileProperties().getPath()));
+          return result;
+        }
+        break;
+      case "parent":
+        if (e.hasParents()) {
+          result = org.caosdb.api.entity.v1.Value.newBuilder();
+          CollectionValues.Builder parents = CollectionValues.newBuilder();
+          for (org.caosdb.server.entity.wrapper.Parent p : e.getParents()) {
+            parents.addValues(ScalarValue.newBuilder().setStringValue(p.getName()));
+          }
+          result.setListValues(parents);
+          return result;
+        }
+        break;
+      default:
+        break;
+    }
+    return null;
+  }
+
+  private org.caosdb.api.entity.v1.Value.Builder getSelectedValue(Selection s, EntityInterface e) {
+    org.caosdb.api.entity.v1.Value.Builder result = null;
+    String selector = s.getSelector();
+    result = handleSpecialSelectors(selector, e);
+    if (result == null) {
+      // selector for a normal property
+      List<org.caosdb.api.entity.v1.Value.Builder> results = new LinkedList<>();
+      for (Property p : e.getProperties()) {
+        if (p.getName() != null && p.getName().equals(selector)) {
+          if (s.getSubselection() == null) {
+            // no subselection -> just return the actual value
+            try {
+              p.parseValue();
+            } catch (Message m) {
+              throw new TransactionException(m);
+            }
+
+            results.add(convert(p.getValue()));
+          } else {
+            // with subselection, e.g. p1.unit, site.geolocation.longitude
+            String subselection = s.getSubselection().getSelector();
+            result = handleSpecialSelectors(subselection, p);
+            if (result == null) {
+              // normal property
+              Value v = p.getValue();
+
+              if (v instanceof ReferenceValue) {
+                EntityInterface referenced_entity = ((ReferenceValue) v).getEntity();
+                result = getSelectedValue(s.getSubselection(), referenced_entity);
+              } else if (v instanceof CollectionValue) {
+                for (Value i : (CollectionValue) v) {
+                  if (i instanceof ReferenceValue) {
+                    EntityInterface referenced_entity = ((ReferenceValue) i).getEntity();
+                    result = getSelectedValue(s.getSubselection(), referenced_entity);
+                    results.add(result);
+                  } else {
+                    // Non-reference scalar value
+                    result = getSelectedValue(s.getSubselection(), p);
+                    results.add(result);
+                  }
+                }
+              } else {
+                // Actual sub-property
+                result = getSelectedValue(s.getSubselection(), p);
+                results.add(result);
+              }
+
+            } else {
+              results.add(result);
+            }
+          }
+        }
+      }
+
+      if (results.size() > 1) {
+        // There have been multiple matching properties
+        CollectionValues.Builder values = CollectionValues.newBuilder();
+        for (org.caosdb.api.entity.v1.Value.Builder v : results) {
+          // Concatenate all found values to a list
+          if (v.hasScalarValue()) {
+            values.addValues(v.getScalarValueBuilder());
+          } else {
+            values.addAllValues(v.getListValuesBuilder().getValuesList());
+          }
+        }
+        result = org.caosdb.api.entity.v1.Value.newBuilder();
+        result.setListValues(values);
+      } else if (results.size() == 1) {
+        // There has been exactly one matching property
+        result = results.get(0);
+      }
+    }
+
+    if (result == null) {
+      // no matching property found
+      result = org.caosdb.api.entity.v1.Value.newBuilder();
+    }
+    return result;
+  }
+
+  private SelectQueryHeader.Builder convertSelectQueryHeader(RetrieveContainer container) {
+    SelectQueryHeader.Builder result = SelectQueryHeader.newBuilder();
+    Query query = container.getQuery();
+    for (Selection s : query.getSelections()) {
+      result.addColumns(SelectQueryColumn.newBuilder().setName(s.toString()));
+    }
+    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 315358deacf2d77828add722d29a6c4643acd283..030b52544fec858ef3c62c531e9627baf5500551 100644
--- a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
@@ -33,6 +33,7 @@ import org.caosdb.api.entity.v1.Entity;
 import org.caosdb.api.entity.v1.EntityRequest;
 import org.caosdb.api.entity.v1.EntityResponse;
 import org.caosdb.api.entity.v1.EntityTransactionServiceGrpc.EntityTransactionServiceImplBase;
+import org.caosdb.api.entity.v1.FindQueryResult;
 import org.caosdb.api.entity.v1.IdResponse;
 import org.caosdb.api.entity.v1.InsertRequest;
 import org.caosdb.api.entity.v1.InsertResponse;
@@ -43,6 +44,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;
@@ -59,6 +61,7 @@ import org.caosdb.server.entity.UpdateEntity;
 import org.caosdb.server.entity.container.RetrieveContainer;
 import org.caosdb.server.entity.container.WritableContainer;
 import org.caosdb.server.permissions.EntityPermission;
+import org.caosdb.server.query.Query;
 import org.caosdb.server.transaction.Retrieve;
 import org.caosdb.server.transaction.RetrieveACL;
 import org.caosdb.server.transaction.UpdateACL;
@@ -77,6 +80,24 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
     this.fileTransmissionService = fileTransmissionService;
   }
 
+  private void prepareDownload(
+      EntityResponse.Builder entityResponse, EntityInterface entity, FileDownload fileDownload)
+      throws Exception {
+    try {
+      entity.checkPermission(EntityPermission.RETRIEVE_FILE);
+      if (fileDownload == null) {
+        fileDownload = fileTransmissionService.registerFileDownload(null);
+      }
+      entity.getFileProperties().retrieveFromFileSystem();
+      entityResponse.setDownloadId(
+          fileTransmissionService.registerFileDownload(
+              fileDownload.getId(), entity.getFileProperties()));
+    } catch (AuthenticationException exc) {
+      entityResponse.addErrors(caosdbToGrpc.convert(ServerMessages.AUTHORIZATION_ERROR));
+      entityResponse.addInfos(caosdbToGrpc.convert(new Message(exc.getMessage())));
+    }
+  }
+
   /**
    * Handle read-only transactions. Of these only one may be a query at the moment, the others must
    * be ID retrieves.
@@ -129,30 +150,42 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
 
     final Retrieve transaction = new Retrieve(container);
     transaction.execute();
-    if (container.getFlags().containsKey("query_count_result")) {
-      final int count = Integer.parseInt(container.getFlags().get("query_count_result"));
+    if (container.getQuery() != null && container.getQuery().getType() == Query.Type.COUNT) {
+      // this was a count query
+      final int count = container.getQuery().getCount();
       builder
           .addResponsesBuilder()
           .setRetrieveResponse(RetrieveResponse.newBuilder().setCountResult(count));
+    } else if (container.getQuery() != null
+        && container.getQuery().getType() == Query.Type.SELECT) {
+      // this was a select query
+      SelectQueryResult.Builder selectResult = caosdbToGrpc.convertSelectResult(container);
+      builder
+          .addResponsesBuilder()
+          .setRetrieveResponse(RetrieveResponse.newBuilder().setSelectResult(selectResult));
+    } else if (container.getQuery() != null && container.getQuery().getType() == Query.Type.FIND) {
+      // this was a find query
+      final boolean download_files_container = container.getFlags().containsKey("download_files");
+      FindQueryResult.Builder findResult = FindQueryResult.newBuilder();
+      for (final EntityInterface entity : container) {
+        final EntityResponse.Builder entityResponse = caosdbToGrpc.convert(entity);
+        if ((download_files_container || entity.getFlags().containsKey("download_files"))
+            && entity.hasFileProperties()) {
+          prepareDownload(entityResponse, entity, fileDownload);
+        }
+        findResult.addResultSet(entityResponse);
+      }
+      builder
+          .addResponsesBuilder()
+          .setRetrieveResponse(RetrieveResponse.newBuilder().setFindResult(findResult));
     } else {
+      // normal retrieval via id
       final boolean download_files_container = container.getFlags().containsKey("download_files");
       for (final EntityInterface entity : container) {
         final EntityResponse.Builder entityResponse = caosdbToGrpc.convert(entity);
         if ((download_files_container || entity.getFlags().containsKey("download_files"))
             && entity.hasFileProperties()) {
-          try {
-            entity.checkPermission(EntityPermission.RETRIEVE_FILE);
-            if (fileDownload == null) {
-              fileDownload = fileTransmissionService.registerFileDownload(null);
-            }
-            entity.getFileProperties().retrieveFromFileSystem();
-            entityResponse.setDownloadId(
-                fileTransmissionService.registerFileDownload(
-                    fileDownload.getId(), entity.getFileProperties()));
-          } catch (AuthenticationException exc) {
-            entityResponse.addErrors(caosdbToGrpc.convert(ServerMessages.AUTHORIZATION_ERROR));
-            entityResponse.addInfos(caosdbToGrpc.convert(new Message(exc.getMessage())));
-          }
+          prepareDownload(entityResponse, entity, fileDownload);
         }
         builder
             .addResponsesBuilder()
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 1b5ccb41f58b92d2230fb99e5635ad02bd9922f5..42dccf552d69bbba6bee2ab909eaf31b5159041f 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 0a19977b199195610d96f887c4c538a75b491511..352a7428f2007fc59cbf0b3fb7f067d1198857c1 100644
--- a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
+++ b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
@@ -31,8 +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;
 
 @JobAnnotation(flag = "query", stage = TransactionStage.INIT)
@@ -41,27 +39,23 @@ public class ExecuteQuery extends FlagJob {
   @Override
   protected void job(final String value) {
 
-    final Query queryInstance = new Query(value, getTransaction().getTransactor(), getContainer());
-    try {
-      if (value != null) {
+    if (value != null) {
+      final Query queryInstance =
+          new Query(value, getTransaction().getTransactor(), getContainer());
+      getContainer().setQuery(queryInstance);
+      try {
         queryInstance.execute(getTransaction().getAccess());
+      } catch (final ParsingException e) {
+        getContainer().addError(ServerMessages.QUERY_PARSING_ERROR);
+      } catch (final UnsupportedOperationException e) {
+        getContainer().addError(ServerMessages.QUERY_EXCEPTION);
+        getContainer()
+            .addMessage(new Message(MessageType.Info, (MessageCode) null, e.getMessage()));
+      }
+      getContainer().addMessage(queryInstance);
+      for (final EntityInterface entity : getContainer()) {
+        getTransaction().getSchedule().addAll(loadJobs(entity, getTransaction()));
       }
-    } catch (final ParsingException e) {
-      getContainer().addMessage(ServerMessages.QUERY_PARSING_ERROR);
-      getContainer().setStatus(EntityStatus.UNQUALIFIED);
-    } catch (final UnsupportedOperationException e) {
-      getContainer().addMessage(ServerMessages.QUERY_EXCEPTION);
-      getContainer().setStatus(EntityStatus.UNQUALIFIED);
-      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()));
-    }
-    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 c4a68e5fbd3b4ad6cf61e5a7bd07b02ff1085095..d44674b29d5c35fab2db9f4a8395e064219b79c9 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 7da810c3d8f50ab739dd72a65551b45449b4d183..88da39bce24f1cabf651eebf1532cab14bddb82c 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);
diff --git a/src/test/java/org/caosdb/server/query/TestCQL.java b/src/test/java/org/caosdb/server/query/TestCQL.java
index cfd53f94f305088f04f9a5eb0a2e443ad65f9c6c..fe73e2b2c33749fac6d72a4c5b478eca5d154465 100644
--- a/src/test/java/org/caosdb/server/query/TestCQL.java
+++ b/src/test/java/org/caosdb/server/query/TestCQL.java
@@ -278,6 +278,10 @@ public class TestCQL {
       "SELECT 'name with spaces.and dot', 'name with spaces'.name, name with spaces.name, name with\\,comma and\\.dot and \\'single_quote.sub FROM ENTITY";
   String issue130b = "SELECT 'Wrapper' FROM RECORD TestRT";
 
+  // quotation marks gone rogue
+  String quotation1 =
+      "FIND ENTITY WHICH HAS A PROPERTY LIKE '*with double*' AND A PROPERTY LIKE '*and single*' AND A PROPERTY LIKE '*what\\'s wrong?*' AND A PROPERTY LIKE '*\\'*' AND A PROPERTY LIKE '*nothin\\'*' AND A PROPERTY LIKE '*\"\\'bla*'";
+
   @Test
   public void testQuery1()
       throws InterruptedException, SQLException, ConnectionException, QueryException {
@@ -6082,7 +6086,7 @@ public class TestCQL {
     assertEquals(Query.Pattern.TYPE_NORMAL, sfq.e.type);
     assertEquals("ename", sfq.e.toString());
     assertEquals(Query.Role.RECORD, sfq.r);
-    assertEquals(Query.Type.FIND, sfq.t);
+    assertEquals(Query.Type.SELECT, sfq.t);
     assertNotNull(sfq.s);
     assertFalse(sfq.s.isEmpty());
     assertEquals(1, sfq.s.size());
@@ -6105,7 +6109,7 @@ public class TestCQL {
     assertEquals(Query.Pattern.TYPE_NORMAL, sfq.e.type);
     assertEquals("ename", sfq.e.toString());
     assertEquals(Query.Role.RECORD, sfq.r);
-    assertEquals(Query.Type.FIND, sfq.t);
+    assertEquals(Query.Type.SELECT, sfq.t);
     assertNotNull(sfq.s);
     assertFalse(sfq.s.isEmpty());
     assertEquals(1, sfq.s.size());
@@ -6128,7 +6132,7 @@ public class TestCQL {
     assertEquals(Query.Pattern.TYPE_NORMAL, sfq.e.type);
     assertEquals("ename", sfq.e.toString());
     assertEquals(Query.Role.RECORD, sfq.r);
-    assertEquals(Query.Type.FIND, sfq.t);
+    assertEquals(Query.Type.SELECT, sfq.t);
     assertNotNull(sfq.s);
     assertFalse(sfq.s.isEmpty());
     assertEquals(3, sfq.s.size());
@@ -6156,7 +6160,7 @@ public class TestCQL {
     assertEquals(Query.Pattern.TYPE_NORMAL, sfq.e.type);
     assertEquals("ename", sfq.e.toString());
     assertEquals(Query.Role.RECORD, sfq.r);
-    assertEquals(Query.Type.FIND, sfq.t);
+    assertEquals(Query.Type.SELECT, sfq.t);
     assertNotNull(sfq.s);
     assertFalse(sfq.s.isEmpty());
     assertEquals(4, sfq.s.size());
@@ -6619,7 +6623,7 @@ public class TestCQL {
     assertEquals(Query.Pattern.TYPE_NORMAL, sfq.e.type);
     assertEquals("ename", sfq.e.toString());
     assertNull(sfq.r);
-    assertEquals(Query.Type.FIND, sfq.t);
+    assertEquals(Query.Type.SELECT, sfq.t);
     assertNotNull(sfq.s);
     assertFalse(sfq.s.isEmpty());
     assertEquals(1, sfq.s.size());
@@ -6989,4 +6993,24 @@ public class TestCQL {
     assertEquals("Wrapper", sfq.s.get(0).getSelector());
     assertNull(sfq.s.get(0).getSubselection());
   }
+
+  @Test
+  public void testQuotation1() {
+    CQLLexer lexer;
+    lexer = new CQLLexer(CharStreams.fromString(this.quotation1));
+    final CommonTokenStream tokens = new CommonTokenStream(lexer);
+
+    final CQLParser parser = new CQLParser(tokens);
+    final CqContext sfq = parser.cq();
+
+    assertTrue(sfq.filter instanceof Conjunction);
+    Conjunction conj = (Conjunction) sfq.filter;
+    assertEquals(6, conj.getFilters().size());
+    assertEquals("POV(null,LIKE ,%with double%)", conj.getFilters().get(0).toString());
+    assertEquals("POV(null,LIKE ,%and single%)", conj.getFilters().get(1).toString());
+    assertEquals("POV(null,LIKE ,%what's wrong?%)", conj.getFilters().get(2).toString());
+    assertEquals("POV(null,LIKE ,%'%)", conj.getFilters().get(3).toString());
+    assertEquals("POV(null,LIKE ,%nothin'%)", conj.getFilters().get(4).toString());
+    assertEquals("POV(null,LIKE ,%\"'bla%)", conj.getFilters().get(5).toString());
+  }
 }