From 7f7a0d4b5e277e283db116788a937241a99e53d4 Mon Sep 17 00:00:00 2001 From: Stefano Ciccarelli Date: Tue, 15 Apr 2025 17:33:39 +0200 Subject: [PATCH 1/4] no more transaction check for query without ancestor the Firestore in Datastore mode allows to perform queries without an ancestor inside a transaction --- .../com/google/appengine/api/datastore/ValidatedQuery.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/api/src/main/java/com/google/appengine/api/datastore/ValidatedQuery.java b/api/src/main/java/com/google/appengine/api/datastore/ValidatedQuery.java index 05e4346f..5c356fc2 100644 --- a/api/src/main/java/com/google/appengine/api/datastore/ValidatedQuery.java +++ b/api/src/main/java/com/google/appengine/api/datastore/ValidatedQuery.java @@ -93,13 +93,6 @@ private void validateQuery() { } } - // Transaction requires ancestor - if (query.hasTransaction() && !query.hasAncestor()) { - throw new IllegalQueryException( - "Only ancestor queries are allowed inside transactions.", - IllegalQueryType.TRANSACTION_REQUIRES_ANCESTOR); - } - // Filters and sort orders require kind. if (!query.hasKind()) { for (Filter filter : query.filters()) { From 38b760e10226c2e4ae954e033ea423b32e2fa910 Mon Sep 17 00:00:00 2001 From: Stefano Ciccarelli Date: Wed, 16 Apr 2025 08:45:36 +0200 Subject: [PATCH 2/4] rimosso check --- .../google/appengine/api/datastore/PreparedQueryImpl.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/api/src/main/java/com/google/appengine/api/datastore/PreparedQueryImpl.java b/api/src/main/java/com/google/appengine/api/datastore/PreparedQueryImpl.java index 4dfa0fdc..5a483176 100644 --- a/api/src/main/java/com/google/appengine/api/datastore/PreparedQueryImpl.java +++ b/api/src/main/java/com/google/appengine/api/datastore/PreparedQueryImpl.java @@ -36,11 +36,6 @@ public PreparedQueryImpl(Query query, Transaction txn, QueryRunner queryRunner) this.txn = txn; this.queryRunner = queryRunner; - // TODO Move this check and the one that follows into the - // LocalDatastoreService (it may already be there). - checkArgument( - txn == null || query.getAncestor() != null, - "Only ancestor queries are allowed inside transactions."); TransactionImpl.ensureTxnActive(txn); } From 53f3f6743f72e4565b73ec68c02c4344f3368ae0 Mon Sep 17 00:00:00 2001 From: Stefano Ciccarelli Date: Wed, 16 Apr 2025 11:04:12 +0200 Subject: [PATCH 3/4] changed the local datastore to support non ancestor queries in transaction the new Firestore in Datastore mode allows not ancestor queries in transaction so the local datastore is changed to accept this behaviour --- .../datastore/dev/LocalDatastoreService.java | 42 ++++++++----------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/api_dev/src/main/java/com/google/appengine/api/datastore/dev/LocalDatastoreService.java b/api_dev/src/main/java/com/google/appengine/api/datastore/dev/LocalDatastoreService.java index e33510fa..f0c45b21 100644 --- a/api_dev/src/main/java/com/google/appengine/api/datastore/dev/LocalDatastoreService.java +++ b/api_dev/src/main/java/com/google/appengine/api/datastore/dev/LocalDatastoreService.java @@ -1207,29 +1207,23 @@ public QueryResult runQuery(Status status, Query query) { String app = query.getApp(); Profile profile = getOrCreateProfile(app); - // The real datastore supports executing ancestor queries in transactions. - // For now we're just going to make sure the entity group of the ancestor - // is the same entity group with which the transaction is associated and - // skip providing a transactionally consistent result set. - synchronized (profile) { - // Having a transaction implies we have an ancestor, but having an - // ancestor does not imply we have a transaction. - if (query.hasTransaction() || query.hasAncestor()) { - // Query can only have a txn if it is an ancestor query. Either way we - // know we've got an ancestor. + + if (query.hasTransaction()) { + if (!app.equals(query.getTransaction().getApp())) { + throw newError( + ErrorCode.INTERNAL_ERROR, + "Can't query app " + + app + + "in a transaction on app " + + query.getTransaction().getApp()); + } + } + + if (query.hasAncestor()) { Path groupPath = getGroup(query.getAncestor()); Profile.EntityGroup eg = profile.getGroup(groupPath); if (query.hasTransaction()) { - if (!app.equals(query.getTransaction().getApp())) { - throw newError( - ErrorCode.INTERNAL_ERROR, - "Can't query app " - + app - + "in a transaction on app " - + query.getTransaction().getApp()); - } - LiveTxn liveTxn = profile.getTxn(query.getTransaction().getHandle()); // this will throw an exception if we attempt to read from // the wrong entity group @@ -1238,12 +1232,10 @@ public QueryResult runQuery(Status status, Query query) { profile = eg.getSnapshot(liveTxn); } - if (query.hasAncestor()) { - if (query.hasTransaction() || !query.hasFailoverMs()) { - // Either we have a transaction or the user has requested strongly - // consistent results. Either way, we need to apply jobs. - eg.rollForwardUnappliedJobs(); - } + if (query.hasTransaction() || !query.hasFailoverMs()) { + // Either we have a transaction or the user has requested strongly + // consistent results. Either way, we need to apply jobs. + eg.rollForwardUnappliedJobs(); } } From f220f12b7fdcb0855ec7210f116427c7de398a84 Mon Sep 17 00:00:00 2001 From: Stefano Ciccarelli Date: Wed, 16 Apr 2025 14:13:37 +0200 Subject: [PATCH 4/4] unused value --- .../java/com/google/appengine/api/datastore/ValidatedQuery.java | 1 - 1 file changed, 1 deletion(-) diff --git a/api/src/main/java/com/google/appengine/api/datastore/ValidatedQuery.java b/api/src/main/java/com/google/appengine/api/datastore/ValidatedQuery.java index 5c356fc2..56552def 100644 --- a/api/src/main/java/com/google/appengine/api/datastore/ValidatedQuery.java +++ b/api/src/main/java/com/google/appengine/api/datastore/ValidatedQuery.java @@ -302,7 +302,6 @@ enum IllegalQueryType { FILTER_WITH_MULTIPLE_PROPS, MULTIPLE_INEQ_FILTERS, FIRST_SORT_NEQ_INEQ_PROP, - TRANSACTION_REQUIRES_ANCESTOR, ILLEGAL_VALUE, ILLEGAL_PROJECTION, ILLEGAL_GROUPBY,