From 094123970a0f106f4dd7fc9c851107d5ddef1642 Mon Sep 17 00:00:00 2001 From: Timm Fitschen <t.fitschen@indiscale.com> Date: Fri, 21 Oct 2022 17:39:22 +0200 Subject: [PATCH] WIP: SELECT for GRPC API --- .../container/TransactionContainer.java | 10 +++ .../server/grpc/CaosDBToGrpcConverters.java | 63 ++++++++++++++++++- .../grpc/EntityTransactionServiceImpl.java | 9 +-- .../caosdb/server/jobs/core/ExecuteQuery.java | 42 +++++-------- 4 files changed, 90 insertions(+), 34 deletions(-) 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 289287c8..d3963455 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 0494e348..867beae5 100644 --- a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java +++ b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java @@ -48,9 +48,11 @@ 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; @@ -79,6 +81,8 @@ 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 { @@ -595,16 +599,69 @@ public class CaosDBToGrpcConverters { public org.caosdb.api.entity.v1.SelectQueryResult.Builder convertSelectResult( RetrieveContainer container) { - // TODO(tf) 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 = getValue(s, e); + result.addCells(value); + } + return result; + } + + private org.caosdb.api.entity.v1.Value.Builder getValue(Selection s, EntityInterface e) { + org.caosdb.api.entity.v1.Value.Builder result = org.caosdb.api.entity.v1.Value.newBuilder(); + String selector = s.getSelector(); + switch (selector) { + case "name": + if (e.getName() != null) { + result.setScalarValue(ScalarValue.newBuilder().setStringValue(e.getName())); + } + break; + + case "id": + result.setScalarValue(ScalarValue.newBuilder().setStringValue(e.getId().toString())); + break; + + default: + // selector for a normal property + for (Property p : e.getProperties()) { + if (p.getName() != null && p.getName().equals(selector) && s.getSubselection() == null) { + try { + p.parseValue(); + } catch (Message m) { + throw new TransactionException(m); + } + if (!p.hasValue()) { + continue; + } else if (p.getValue() instanceof CollectionValue) { + + } else { + result.setScalarValue( + ScalarValue.newBuilder().setStringValue(p.getValue().toString())); + } + } + } + break; + } + // TODO Auto-generated method stub return result; } private SelectQueryHeader.Builder convertSelectQueryHeader(RetrieveContainer container) { SelectQueryHeader.Builder result = SelectQueryHeader.newBuilder(); - // TODO(tf) - result.addColumns(SelectQueryColumn.newBuilder().setName("col1")); + 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 09ba156e..8835cb6e 100644 --- a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java +++ b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java @@ -60,6 +60,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; @@ -130,14 +131,14 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa final Retrieve transaction = new Retrieve(container); transaction.execute(); - if (container.getFlags().containsKey("query_count_result")) { + if (container.getQuery() != null && container.getQuery().getType() == Query.Type.COUNT) { // this was a count query - final int count = Integer.parseInt(container.getFlags().get("query_count_result")); + final int count = container.getQuery().getCount(); builder .addResponsesBuilder() .setRetrieveResponse(RetrieveResponse.newBuilder().setCountResult(count)); - } else if (container.getFlags().containsKey("query_select") - && "true".equals(container.getFlags().get("query_select"))) { + } else if (container.getQuery() != null + && container.getQuery().getType() == Query.Type.SELECT) { // this was a select query SelectQueryResult.Builder selectResult = caosdbToGrpc.convertSelectResult(container); builder 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 f584d365..352a7428 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.utils.EntityStatus; import org.caosdb.server.utils.ServerMessages; @JobAnnotation(flag = "query", stage = TransactionStage.INIT) @@ -40,34 +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().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); - switch (queryInstance.getQuery().getType()) { - case COUNT: + } catch (final ParsingException e) { + getContainer().addError(ServerMessages.QUERY_PARSING_ERROR); + } catch (final UnsupportedOperationException e) { + getContainer().addError(ServerMessages.QUERY_EXCEPTION); 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())); + .addMessage(new Message(MessageType.Info, (MessageCode) null, e.getMessage())); + } + getContainer().addMessage(queryInstance); + for (final EntityInterface entity : getContainer()) { + getTransaction().getSchedule().addAll(loadJobs(entity, getTransaction())); + } } } } -- GitLab