Skip to content
Snippets Groups Projects
Commit 605d46f9 authored by Henrik tom Wörden's avatar Henrik tom Wörden
Browse files

Merge branch 'f-semantic-select-query' into 'dev'

F semantic select query

See merge request caosdb/caosdb-server!70
parents c9e63feb 1f2e8a52
No related branches found
No related tags found
No related merge requests found
......@@ -23,6 +23,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
* Select queries would originally only select the returned properties by their
names and would not check if a property is a subtype of a selected property. This
has changed now and select queries will also return subtypes of selected
properties.
### Deprecated
* `SERVER_SIDE_SCRIPTING_BIN_DIR` property is deprecated.
......
......@@ -351,6 +351,33 @@ Any result set can be filtered by logically combining POV filters or back refere
* REFERENCE:: This one is tricky: `REFERENCE TO` expresses a the state of _having_ a reference property. `REFERENCED BY` expresses the state of _being_ referenced by another entity.
* COUNT:: `COUNT` works like `FIND` but doesn't return the entities.
## Select Queries
In contrast to `FIND` queries, which always return the complete entity, there are `SELECT` queries which only return the entity with only those properties which are specified in the query. The syntax is very similar to `FIND` queries - just replace the `FIND` by `SELECT <comma separated list of selectors> FROM`:
`SELECT p1, p2, p3 FROM Record ename`
However, the `SELECT` query can also return properties of referenced entities and thereby are a means of joining entities together and return a custom view or projection:
`SELECT Conductor.Last Name FROM Experiment`
would return the conductor's last name, when `Conductor` is a reference property of `Experiment` and `Last Name` is a property of the `Conductor` records.
### Selectors
Selectors are strings of entity names which are separated by `.` (dot). E.g. `Conductor.Last Name` or `Conductor.Address` or even `Experiment.Conductor.Last name`. Selectors in a `SELECT` queries are separated by `,` (comma). E.g. `Conductor.First Name, Conductor.Last Name`.
### Evaluation of Selectors
The query will return all those properties which have the same name as
specified by the selector (case-insensitive). However, `SELECT` queries are
also capable of subtyping in the selectors:
`SELECT Person FROM Experiment` would return all `Person` properties but all `Conductors` as well, if `Conductor` is a child of `Person`.
Note: When a property `responsible` with data type `Person` exists, the above `SELECT` statement would not include records that use this property (since `responsible` is not a child of Person).
## Versioning
Since Caosdb 0.2 entities are optionally version controlled. The query language will be extended to include versioning in the future. A current minimal implementation introduces the `ANY VERSION OF` modifier which can be used to return all matching versions in the results of `COUNT`, `FIND`, and `SELECT` queries.
......
......@@ -29,19 +29,36 @@ import org.caosdb.server.database.exceptions.TransactionException;
public class IsSubType extends BackendTransaction {
private final Integer child;
private final Integer parent;
private Integer parent = null;
private String parentName = null;
public IsSubType(final Integer child, final Integer parent) {
this.child = child;
this.parent = parent;
}
private boolean isSubType;
public IsSubType(Integer child, String parent) {
this.parentName = parent;
this.child = child;
}
private Boolean isSubType = null;
@Override
public void execute() throws TransactionException {
final IsSubTypeImpl t = getImplementation(IsSubTypeImpl.class);
this.isSubType = t.execute(this.child, this.parent);
if (this.parent == null) {
this.isSubType = false;
for (Integer parent : execute(new GetIDByName(parentName, false)).getList()) {
this.isSubType = t.execute(this.child, parent);
if (this.isSubType) {
return;
}
}
} else {
this.isSubType = t.execute(this.child, this.parent);
}
}
public boolean isSubType() {
......
/*
* ** header v3.0
* This file is a part of the CaosDB Project.
* ** header v3.0 This file is a part of the CaosDB Project.
*
* Copyright (C) 2018 Research Group Biomedical Physics,
* Max-Planck-Institute for Dynamics and Self-Organization Göttingen
* Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
* Copyright (C) 2018 Research Group Biomedical Physics, Max-Planck-Institute for Dynamics and
* Self-Organization Göttingen Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> Copyright
* (C) 2020 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*
* ** end header
*/
......@@ -27,6 +23,7 @@ package org.caosdb.server.database.backend.transaction;
import java.util.LinkedList;
import java.util.List;
import org.caosdb.server.database.BackendTransaction;
import org.caosdb.server.database.exceptions.EntityDoesNotExistException;
import org.caosdb.server.datatype.ReferenceDatatype;
import org.caosdb.server.datatype.ReferenceValue;
import org.caosdb.server.entity.EntityInterface;
......@@ -124,10 +121,9 @@ public class RetrieveFullEntity extends BackendTransaction {
*/
public void retrieveSubEntities(EntityInterface e, List<Selection> selections) {
for (final Selection s : selections) {
String propertyName = s.getSelector();
if (s.getSubselection() != null) {
String propertyName = s.getSelector();
// Find matching (i.e. referencing) Properties
for (Property p : e.getProperties()) {
// get reference properties by name.
......@@ -142,10 +138,47 @@ public class RetrieveFullEntity extends BackendTransaction {
ReferenceValue value = (ReferenceValue) p.getValue();
RetrieveEntity ref = new RetrieveEntity(value.getId());
// recursion! (Only for the matching selections)
// recursion! (Only for the matching selections)
retrieveFullEntity(ref, getSubSelects(selections, propertyName));
value.setEntity(ref, true);
}
continue;
}
try {
boolean isSubtype = execute(new IsSubType(p.getId(), propertyName)).isSubType();
if (isSubtype) {
if (p.getValue() != null) {
if (p.getDatatype() instanceof ReferenceDatatype) {
try {
p.parseValue();
} catch (Message m) {
p.addError(m);
}
ReferenceValue value = (ReferenceValue) p.getValue();
RetrieveEntity ref = new RetrieveEntity(value.getId());
// recursion! (Only for the matching selections)
retrieveFullEntity(ref, getSubSelects(selections, propertyName));
value.setEntity(ref, true);
p.setName(propertyName);
}
}
}
} catch (EntityDoesNotExistException exc) {
// unknown parent name.
}
}
} else {
for (Property p : e.getProperties()) {
if (!propertyName.equalsIgnoreCase(p.getName())) {
try {
boolean isSubtype = execute(new IsSubType(p.getId(), propertyName)).isSubType();
if (isSubtype) {
p.setName(propertyName);
}
} catch (EntityDoesNotExistException exc) {
// unknown parent name.
}
}
}
}
......
......@@ -57,12 +57,10 @@ import org.caosdb.server.utils.Observer;
import org.caosdb.server.utils.ServerMessages;
import org.reflections.Reflections;
/**
* This is a Job.
*
* @todo Describe me.
*
*/
public abstract class Job extends AbstractObservable implements Observer {
private Transaction<? extends TransactionContainer> transaction = null;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment