diff --git a/CHANGELOG.md b/CHANGELOG.md index ab5fd2c3cf5ca809c59cb54e6fc63861f06accb5..a744c76cc738e76a01ddfe886d2f9a4792b10b1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +* `FIND ENTITY <ID> is broken`. + [linkahead-server#323](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/323) + ### Security ## [0.11.0] 2023-10-13 ## diff --git a/conf/core/server.conf b/conf/core/server.conf index 1e22c5c7a3aad2d0aa53b098eb4666e25e591f31..63ecaa9b410b896ce345f888b898f2b99a5fcd65 100644 --- a/conf/core/server.conf +++ b/conf/core/server.conf @@ -69,7 +69,7 @@ MYSQL_USER_NAME=caosdb # Password for the user MYSQL_USER_PASSWORD=random1234 # Schema of mysql procedures and tables which is required by this CaosDB instance -MYSQL_SCHEMA_VERSION=v6.0.0-SNAPSHOT-EXTID +MYSQL_SCHEMA_VERSION=v6.1 # -------------------------------------------------- diff --git a/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java b/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java index 01b0ecb2274a85635dee3fe88f041e50178936fe..becc6499c1c1b5c8e236da12c9531a28490d634c 100644 --- a/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java +++ b/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java @@ -833,8 +833,10 @@ public abstract class EntityStateJob extends EntityJob { + " WHICH REFERENCES " + stateEntity.getId().toString(), getUser(), - c); - query.execute(getTransaction().getAccess()); + c, + getTransaction(), + getTransaction().getAccess()); + query.execute(); result = resolve(c.get(0).getId()); putCache(key, result); return result; 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 2d7a45d099fa5bec35586b58257eb2c71d61cbe0..56107e72b333dbbdf822cecca0e7e1f0bce1811c 100644 --- a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java +++ b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java @@ -45,11 +45,10 @@ public class ExecuteQuery extends FlagJob { // run paging job first getTransaction().getSchedule().runJob(null, Paging.class); - final Query queryInstance = - new Query(value, getTransaction().getTransactor(), getContainer()); + final Query queryInstance = new Query(value, getTransaction()); getContainer().setQuery(queryInstance); try { - queryInstance.execute(getTransaction().getAccess()); + queryInstance.execute(); } catch (final ParsingException e) { getContainer().addError(ServerMessages.QUERY_PARSING_ERROR(e.getMessage())); } catch (final UnsupportedOperationException e) { diff --git a/src/main/java/org/caosdb/server/query/Query.java b/src/main/java/org/caosdb/server/query/Query.java index 53cd7bf04bccf03eab9422e591750849bfa48728..117176ec5c6a1fcb10e588b860926b02eb76a2a9 100644 --- a/src/main/java/org/caosdb/server/query/Query.java +++ b/src/main/java/org/caosdb/server/query/Query.java @@ -71,12 +71,13 @@ import org.caosdb.server.permissions.EntityACL; import org.caosdb.server.permissions.EntityPermission; import org.caosdb.server.query.CQLParser.CqContext; import org.caosdb.server.query.CQLParsingErrorListener.ParsingError; -import org.caosdb.server.transaction.TransactionInterface; +import org.caosdb.server.transaction.EntityTransactionInterface; +import org.caosdb.server.transaction.Transaction; import org.caosdb.server.transaction.WriteTransaction; import org.jdom2.Element; import org.slf4j.Logger; -public class Query implements QueryInterface, ToElementable, TransactionInterface { +public class Query implements QueryInterface, ToElementable, EntityTransactionInterface { /** Class which represents the selection of (sub)properties. */ public static class Selection { @@ -313,6 +314,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac */ private boolean filteredIntermediateResult = false; + private EntityTransactionInterface transaction; + /** * Tags the query cache and is renewed each time the cache is being cleared, i.e. each time the * database is being updated. @@ -326,19 +329,34 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac } public Query(final String query) { - this(query, null); + this(query, (Subject) null); } public Query(final String query, final Subject user) { - this(query, user, null); + this(query, user, null, null, null); + } + + public Query(final String query, final Transaction<? extends TransactionContainer> transaction) { + this( + query, + transaction.getTransactor(), + transaction.getContainer(), + transaction, + transaction.getAccess()); } - public Query(final String query, final Subject user, final TransactionContainer container) { + public Query( + final String query, + final Subject user, + final TransactionContainer container, + final EntityTransactionInterface transaction, + final Access access) { this.container = container; + this.transaction = transaction; this.query = query; this.user = user; + this.access = access; } - ; /** * Fill the initially empty resultSet with all entities which match the name, or the id. Then @@ -350,9 +368,9 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac final CallableStatement callInitEntity = getConnection().prepareCall("call initEntity(?,?,?,?,?,?)"); - try { - callInitEntity.setInt(1, Integer.parseInt(this.entity.toString())); - } catch (final NumberFormatException e) { + if (matchIdPattern(this.entity.toString())) { + callInitEntity.setString(1, this.entity.toString()); + } else { callInitEntity.setNull(1, Types.INTEGER); } switch (this.entity.type) { @@ -448,8 +466,8 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac } // ... apply them... - final Query subQuery = new Query(q.getValue(), query.getUser()); - subQuery.setAccess(query.getAccess()); + final Query subQuery = + new Query(q.getValue(), query.getUser(), null, transaction, query.getAccess()); subQuery.parse(); // versioning for QueryTemplates is not supported and probably never will. @@ -778,11 +796,10 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac * * <p>First try the cache and only then use the back-end. * - * @param access - * @return * @throws ParsingException, QueryException */ - public Query execute(final Access access) throws ParsingException, QueryException { + @Override + public void execute() throws ParsingException, QueryException { try { parse(); setAccess(access); @@ -806,7 +823,6 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac e.printStackTrace(); throw new QueryException(e); } - return this; } /** Remove all cached queries from the cache. */ @@ -1109,11 +1125,6 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac return this.targetSet; } - @Override - public void execute() throws Exception { - execute(getAccess()); - } - public List<Selection> getSelections() { return this.selections; } @@ -1207,4 +1218,9 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac public UTCDateTime getTimestamp() { return null; } + + @Override + public boolean matchIdPattern(String id) { + return transaction.matchIdPattern(id); + } } diff --git a/src/test/java/org/caosdb/server/query/TestCQL.java b/src/test/java/org/caosdb/server/query/TestCQL.java index 61a87b7f5764a8da26bc7bb6ccd8f06a320302f1..9ca5904a5b851a4a32de5f2328647b64fa05cfec 100644 --- a/src/test/java/org/caosdb/server/query/TestCQL.java +++ b/src/test/java/org/caosdb/server/query/TestCQL.java @@ -39,13 +39,11 @@ import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Vocabulary; import org.antlr.v4.runtime.tree.ParseTree; import org.caosdb.server.CaosDBServer; -import org.caosdb.server.database.access.Access; import org.caosdb.server.database.backend.implementation.MySQL.ConnectionException; import org.caosdb.server.database.exceptions.TransactionException; import org.caosdb.server.query.CQLParser.CqContext; import org.caosdb.server.query.Query.Pattern; import org.caosdb.server.query.Query.QueryException; -import org.caosdb.server.utils.Initialization; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -58,8 +56,6 @@ public class TestCQL { CaosDBServer.initServerProperties(); } - static Access access = Initialization.setUp().getAccess(); - String query1 = "FIND ename.pname1=val1"; String query1a = "FIND ename WITH pname1=val1"; String query1b = "FIND ename WHICH HAS A PROPERTY pname1=val1"; @@ -3568,7 +3564,7 @@ public class TestCQL { final Query query = new Query(this.ticket147i); try { - query.execute(access); + query.execute(); fail("This should throw a QueryException!"); } catch (final QueryException q) { } @@ -7118,8 +7114,6 @@ public class TestCQL { final CommonTokenStream tokens = new CommonTokenStream(lexer); Vocabulary vocab = lexer.getVocabulary(); - final CQLParser parser = new CQLParser(tokens); - final CqContext sfq = parser.cq(); int no = 0; for (final Token t : tokens.getTokens()) { if (no % 3 == 0) {