Repository: googleapis/java-datastore
Pull request #1465 (2024-05-28 18:54:26)

chore: sync with main, update version numbers
pull latest from upstream/main

generated-files-bot[bot]: <!-- probot comment [12634855]-->
*Warning*: This pull request is touching the following templated files:

* .github/sync-repo-settings.yaml
* .github/workflows/approve-readme.yaml
* .github/workflows/ci.yaml
* .github/workflows/samples.yaml
* .kokoro/presubmit/graalvm-native.cfg
* proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/DatastoreProto.java
* proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequest.java
* proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequestOrBuilder.java
* proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/Mutation.java
* proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/MutationOrBuilder.java
* proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequest.java
* proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequestOrBuilder.java
* proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/datastore.proto
* proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/entity.proto
* proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query.proto
* samples/install-without-bom/pom.xml
* samples/pom.xml
* samples/snapshot/pom.xml
* samples/snippets/pom.xml

Patch:
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index 6167135e..f817c5f4 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
 # limitations under the License.
 docker:
   image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
-  digest: sha256:81c3ec554428c8ff6c92f0d58668b7ef52265d053a82284c97a326745e786949
-# created: 2024-03-27T17:59:25.436353226Z
+  digest: sha256:31aa2ef27b071c2e7844b0eb1d5a24254daff06615b1b138b994dd6345c0b0ea
+# created: 2024-05-17T15:15:57.6714113Z
diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml
index 0159d7ae..4bdaef4e 100644
--- a/.github/sync-repo-settings.yaml
+++ b/.github/sync-repo-settings.yaml
@@ -162,6 +162,23 @@ branchProtectionRules:
       - 'Kokoro - Test: Java GraalVM Native Image'
       - 'Kokoro - Test: Java 17 GraalVM Native Image'
       - javadoc
+  - pattern: grpc-experimental
+    isAdminEnforced: true
+    requiredApprovingReviewCount: 1
+    requiresCodeOwnerReviews: true
+    requiresStrictStatusChecks: false
+    requiredStatusCheckContexts:
+      - dependencies (17)
+      - lint
+      - clirr
+      - units (8)
+      - units (11)
+      - 'Kokoro - Test: Integration'
+      - cla/google
+      - OwlBot Post Processor
+      - 'Kokoro - Test: Java GraalVM Native Image'
+      - 'Kokoro - Test: Java 17 GraalVM Native Image'
+      - javadoc
 permissionRules:
   - team: yoshi-admins
     permission: admin
diff --git a/.github/workflows/approve-readme.yaml b/.github/workflows/approve-readme.yaml
index f5fc7d51..59f00b8e 100644
--- a/.github/workflows/approve-readme.yaml
+++ b/.github/workflows/approve-readme.yaml
@@ -21,7 +21,7 @@ jobs:
     runs-on: ubuntu-latest
     if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme'
     steps:
-      - uses: actions/github-script@v6
+      - uses: actions/github-script@v7
         with:
           github-token: ${{secrets.YOSHI_APPROVER_TOKEN}}
           script: |
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ae66b197..b91fa381 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -27,8 +27,8 @@ jobs:
       matrix:
         java: [11, 17, 21]
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: ${{matrix.java}}
@@ -41,8 +41,8 @@ jobs:
     name: "units (8)"
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-java@v3
+      - uses: actions/checkout@v4
+      - uses: actions/setup-java@v4
         with:
           java-version: 8
           distribution: temurin
@@ -51,7 +51,7 @@ jobs:
         # https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#jvm
         run: echo "SUREFIRE_JVM_OPT=-Djvm=${JAVA_HOME}/bin/java" >> $GITHUB_ENV
         shell: bash
-      - uses: actions/setup-java@v3
+      - uses: actions/setup-java@v4
         with:
           java-version: 17
           distribution: temurin
@@ -63,8 +63,8 @@ jobs:
     steps:
     - name: Support longpaths
       run: git config --system core.longpaths true
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 8
@@ -78,8 +78,8 @@ jobs:
       matrix:
         java: [17]
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: ${{matrix.java}}
@@ -88,8 +88,8 @@ jobs:
   javadoc:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 17
@@ -100,8 +100,8 @@ jobs:
   lint:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 11
@@ -112,8 +112,8 @@ jobs:
   clirr:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 8
diff --git a/.github/workflows/renovate_config_check.yaml b/.github/workflows/renovate_config_check.yaml
index 87d8eb2b..7c5ec786 100644
--- a/.github/workflows/renovate_config_check.yaml
+++ b/.github/workflows/renovate_config_check.yaml
@@ -14,7 +14,7 @@ jobs:
       uses: actions/checkout@v4
 
     - name: Set up Node.js
-      uses: actions/setup-node@v3
+      uses: actions/setup-node@v4
       with:
         node-version: '20'
 
diff --git a/.github/workflows/samples.yaml b/.github/workflows/samples.yaml
index 10d252d7..03b29395 100644
--- a/.github/workflows/samples.yaml
+++ b/.github/workflows/samples.yaml
@@ -20,8 +20,8 @@ jobs:
   checkstyle:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-java@v3
+      - uses: actions/checkout@v4
+      - uses: actions/setup-java@v4
         with:
           distribution: temurin
           java-version: 8
diff --git a/.github/workflows/unmanaged_dependency_check.yaml b/.github/workflows/unmanaged_dependency_check.yaml
index 851d94b2..5ff23d7a 100644
--- a/.github/workflows/unmanaged_dependency_check.yaml
+++ b/.github/workflows/unmanaged_dependency_check.yaml
@@ -5,8 +5,8 @@ jobs:
   unmanaged_dependency_check:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v3
-    - uses: actions/setup-java@v3
+    - uses: actions/checkout@v4
+    - uses: actions/setup-java@v4
       with:
         distribution: temurin
         java-version: 11
@@ -14,6 +14,6 @@ jobs:
       shell: bash
       run: .kokoro/build.sh
     - name: Unmanaged dependency check
-      uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.29.0
+      uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.30.1
       with:
         bom-path: google-cloud-datastore-bom/pom.xml
diff --git a/.kokoro/presubmit/graalvm-native-17.cfg b/.kokoro/presubmit/graalvm-native-17.cfg
index d7a73c2c..3b76021c 100644
--- a/.kokoro/presubmit/graalvm-native-17.cfg
+++ b/.kokoro/presubmit/graalvm-native-17.cfg
@@ -3,7 +3,7 @@
 # Configure the docker image for kokoro-trampoline.
 env_vars: {
   key: "TRAMPOLINE_IMAGE"
-  value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.29.0"
+  value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.30.1"
 }
 
 env_vars: {
diff --git a/.kokoro/presubmit/graalvm-native.cfg b/.kokoro/presubmit/graalvm-native.cfg
index b5c7f594..8c9d2b10 100644
--- a/.kokoro/presubmit/graalvm-native.cfg
+++ b/.kokoro/presubmit/graalvm-native.cfg
@@ -3,7 +3,7 @@
 # Configure the docker image for kokoro-trampoline.
 env_vars: {
   key: "TRAMPOLINE_IMAGE"
-  value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.29.0"
+  value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.30.1"
 }
 
 env_vars: {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba6bc10f..37dd53f5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,41 @@
 # Changelog
 
+## [2.20.0](https://github.com/googleapis/java-datastore/compare/v2.19.3...v2.20.0) (2024-05-27)
+
+
+### Features
+
+* New PropertyMask field which allows partial commits, lookups, and query results ([#1455](https://github.com/googleapis/java-datastore/issues/1455)) ([ff5e397](https://github.com/googleapis/java-datastore/commit/ff5e39775446216b4806f55f14dacb7fc8e8854b))
+
+
+### Bug Fixes
+
+* Migrate off TextPrinter's deprecated methods ([#1452](https://github.com/googleapis/java-datastore/issues/1452)) ([c3c1317](https://github.com/googleapis/java-datastore/commit/c3c131735863d71971110e2ac7ac0244ce16ee92))
+* Set the correct database id on the key parent when calling Key#getParent ([#1457](https://github.com/googleapis/java-datastore/issues/1457)) ([992815d](https://github.com/googleapis/java-datastore/commit/992815d9989d04f7b371dfa320ed17894626a07f))
+
+## [2.19.3](https://github.com/googleapis/java-datastore/compare/v2.19.2...v2.19.3) (2024-05-16)
+
+
+### Dependencies
+
+* Update actions/checkout action to v4 ([#1390](https://github.com/googleapis/java-datastore/issues/1390)) ([80dbca1](https://github.com/googleapis/java-datastore/commit/80dbca1246facf21b08d33e5c6a09b9708b6ce63))
+* Update dependency com.google.cloud:sdk-platform-java-config to v3.30.1 ([#1443](https://github.com/googleapis/java-datastore/issues/1443)) ([79f6c46](https://github.com/googleapis/java-datastore/commit/79f6c46bdbabc66082f23e9562ee9541e0fdeac9))
+
+## [2.19.2](https://github.com/googleapis/java-datastore/compare/v2.19.1...v2.19.2) (2024-05-03)
+
+
+### Bug Fixes
+
+* **deps:** Update the Java code generator (gapic-generator-java) to 2.39.0 ([#1406](https://github.com/googleapis/java-datastore/issues/1406)) ([b265fb3](https://github.com/googleapis/java-datastore/commit/b265fb3c3b8ebc972edbe5a7beae816379846dac))
+
+
+### Dependencies
+
+* Update dependency com.google.cloud:sdk-platform-java-config to v3.30.0 ([#1426](https://github.com/googleapis/java-datastore/issues/1426)) ([ac3a1c1](https://github.com/googleapis/java-datastore/commit/ac3a1c10f64c8338346f8fb39f4857f47e8fc639))
+* Update dependency com.google.errorprone:error_prone_core to v2.27.0 ([#1411](https://github.com/googleapis/java-datastore/issues/1411)) ([a3f5a2c](https://github.com/googleapis/java-datastore/commit/a3f5a2c24bff408479541e08278e888cf3166727))
+* Update dependency com.google.errorprone:error_prone_core to v2.27.1 ([#1421](https://github.com/googleapis/java-datastore/issues/1421)) ([48d7daf](https://github.com/googleapis/java-datastore/commit/48d7dafc0c7a49e95bf41d29865ac872b0de0faf))
+* Update dependency com.google.guava:guava-testlib to v33.2.0-jre ([#1422](https://github.com/googleapis/java-datastore/issues/1422)) ([5a5dfdf](https://github.com/googleapis/java-datastore/commit/5a5dfdfb0855cf485b875ab071b79979d24f98dd))
+
 ## [2.19.1](https://github.com/googleapis/java-datastore/compare/v2.19.0...v2.19.1) (2024-04-19)
 
 
diff --git a/README.md b/README.md
index 3f6f9916..9bdf33b2 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file:
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>libraries-bom</artifactId>
-      <version>26.38.0</version>
+      <version>26.39.0</version>
       <type>pom</type>
       <scope>import</scope>
     </dependency>
@@ -42,7 +42,7 @@ If you are using Maven without the BOM, add this to your dependencies:
 <dependency>
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-datastore</artifactId>
-  <version>2.19.1</version>
+  <version>2.20.0</version>
 </dependency>
 
 ```
@@ -50,20 +50,20 @@ If you are using Maven without the BOM, add this to your dependencies:
 If you are using Gradle 5.x or later, add this to your dependencies:
 
 ```Groovy
-implementation platform('com.google.cloud:libraries-bom:26.38.0')
+implementation platform('com.google.cloud:libraries-bom:26.39.0')
 
 implementation 'com.google.cloud:google-cloud-datastore'
 ```
 If you are using Gradle without BOM, add this to your dependencies:
 
 ```Groovy
-implementation 'com.google.cloud:google-cloud-datastore:2.19.1'
+implementation 'com.google.cloud:google-cloud-datastore:2.20.0'
 ```
 
 If you are using SBT, add this to your dependencies:
 
 ```Scala
-libraryDependencies += "com.google.cloud" % "google-cloud-datastore" % "2.19.1"
+libraryDependencies += "com.google.cloud" % "google-cloud-datastore" % "2.20.0"
 ```
 <!-- {x-version-update-end} -->
 
@@ -384,7 +384,7 @@ Java is a registered trademark of Oracle and/or its affiliates.
 [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-datastore/java11.html
 [stability-image]: https://img.shields.io/badge/stability-stable-green
 [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-datastore.svg
-[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-datastore/2.19.1
+[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-datastore/2.20.0
 [authentication]: https://github.com/googleapis/google-cloud-java#authentication
 [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes
 [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles
diff --git a/datastore-v1-proto-client/pom.xml b/datastore-v1-proto-client/pom.xml
index 3d373497..3d1aac27 100644
--- a/datastore-v1-proto-client/pom.xml
+++ b/datastore-v1-proto-client/pom.xml
@@ -19,12 +19,12 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.cloud.datastore</groupId>
   <artifactId>datastore-v1-proto-client</artifactId>
-  <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:datastore-v1-proto-client:current} -->
+  <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:datastore-v1-proto-client:current} -->
 
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-datastore-parent</artifactId>
-    <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+    <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
   </parent>
 
   <packaging>jar</packaging>
diff --git a/google-cloud-datastore-bom/pom.xml b/google-cloud-datastore-bom/pom.xml
index eeafd1e5..dcb03297 100644
--- a/google-cloud-datastore-bom/pom.xml
+++ b/google-cloud-datastore-bom/pom.xml
@@ -3,12 +3,12 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-datastore-bom</artifactId>
-  <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore-bom:current} -->
+  <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore-bom:current} -->
   <packaging>pom</packaging>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>sdk-platform-java-config</artifactId>
-    <version>3.29.0</version>
+    <version>3.30.1</version>
   </parent>
 
   <name>Google Cloud datastore BOM</name>
@@ -52,22 +52,22 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-datastore</artifactId>
-        <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+        <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>grpc-google-cloud-datastore-admin-v1</artifactId>
-        <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-admin-v1:current} -->
+        <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-admin-v1:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>proto-google-cloud-datastore-v1</artifactId>
-        <version>0.110.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-v1:current} -->
+        <version>0.111.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-v1:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>proto-google-cloud-datastore-admin-v1</artifactId>
-        <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-admin-v1:current} -->
+        <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-admin-v1:current} -->
       </dependency>
     </dependencies>
   </dependencyManagement>
diff --git a/google-cloud-datastore/pom.xml b/google-cloud-datastore/pom.xml
index ed183db3..37a753ea 100644
--- a/google-cloud-datastore/pom.xml
+++ b/google-cloud-datastore/pom.xml
@@ -2,7 +2,7 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <artifactId>google-cloud-datastore</artifactId>
-  <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+  <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
   <packaging>jar</packaging>
   <name>Google Cloud Datastore</name>
   <url>https://github.com/googleapis/java-datastore</url>
@@ -12,7 +12,7 @@
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-datastore-parent</artifactId>
-    <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+    <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
   </parent>
   <properties>
     <site.installationModule>google-cloud-datastore</site.installationModule>
@@ -130,7 +130,7 @@
     <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava-testlib</artifactId>
-      <version>33.1.0-jre</version>
+      <version>33.2.0-jre</version>
       <scope>test</scope>
     </dependency>
     <!-- Need testing utility classes for generated gRPC clients tests -->
diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/IncompleteKey.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/IncompleteKey.java
index db9973cb..71e31b94 100644
--- a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/IncompleteKey.java
+++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/IncompleteKey.java
@@ -91,9 +91,11 @@ public class IncompleteKey extends BaseKey {
     PathElement parent = ancestors.get(ancestors.size() - 1);
     Key.Builder keyBuilder;
     if (parent.hasName()) {
-      keyBuilder = Key.newBuilder(getProjectId(), parent.getKind(), parent.getName());
+      keyBuilder =
+          Key.newBuilder(getProjectId(), parent.getKind(), parent.getName(), getDatabaseId());
     } else {
-      keyBuilder = Key.newBuilder(getProjectId(), parent.getKind(), parent.getId());
+      keyBuilder =
+          Key.newBuilder(getProjectId(), parent.getKind(), parent.getId(), getDatabaseId());
     }
     String namespace = getNamespace();
     if (namespace != null) {
diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Key.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Key.java
index 9e851d0c..14fe264b 100644
--- a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Key.java
+++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Key.java
@@ -145,7 +145,7 @@ public final class Key extends IncompleteKey {
   /** Returns the key in an encoded form that can be used as part of a URL. */
   public String toUrlSafe() {
     try {
-      return URLEncoder.encode(TextFormat.printToString(toPb()), UTF_8.name());
+      return URLEncoder.encode(TextFormat.printer().printToString(toPb()), UTF_8.name());
     } catch (UnsupportedEncodingException e) {
       throw new IllegalStateException("Unexpected encoding exception", e);
     }
diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/admin/v1/stub/DatastoreAdminStubSettings.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/admin/v1/stub/DatastoreAdminStubSettings.java
index 64ad035d..fc346d38 100644
--- a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/admin/v1/stub/DatastoreAdminStubSettings.java
+++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/admin/v1/stub/DatastoreAdminStubSettings.java
@@ -258,15 +258,6 @@ public class DatastoreAdminStubSettings extends StubSettings<DatastoreAdminStubS
             "Transport not supported: %s", getTransportChannelProvider().getTransportName()));
   }
 
-  /** Returns the endpoint set by the user or the the service's default endpoint. */
-  @Override
-  public String getEndpoint() {
-    if (super.getEndpoint() != null) {
-      return super.getEndpoint();
-    }
-    return getDefaultEndpoint();
-  }
-
   /** Returns the default service name. */
   @Override
   public String getServiceName() {
@@ -716,15 +707,6 @@ public class DatastoreAdminStubSettings extends StubSettings<DatastoreAdminStubS
       return listIndexesSettings;
     }
 
-    /** Returns the endpoint set by the user or the the service's default endpoint. */
-    @Override
-    public String getEndpoint() {
-      if (super.getEndpoint() != null) {
-        return super.getEndpoint();
-      }
-      return getDefaultEndpoint();
-    }
-
     @Override
     public DatastoreAdminStubSettings build() throws IOException {
       return new DatastoreAdminStubSettings(this);
diff --git a/grpc-google-cloud-datastore-admin-v1/pom.xml b/grpc-google-cloud-datastore-admin-v1/pom.xml
index 2721d86d..48292987 100644
--- a/grpc-google-cloud-datastore-admin-v1/pom.xml
+++ b/grpc-google-cloud-datastore-admin-v1/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>grpc-google-cloud-datastore-admin-v1</artifactId>
-  <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-admin-v1:current} -->
+  <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-admin-v1:current} -->
   <name>grpc-google-cloud-datastore-admin-v1</name>
   <description>GRPC library for google-cloud-datastore</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-datastore-parent</artifactId>
-    <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+    <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/grpc-google-cloud-datastore-v1/pom.xml b/grpc-google-cloud-datastore-v1/pom.xml
index b98b9aaa..23476b2d 100644
--- a/grpc-google-cloud-datastore-v1/pom.xml
+++ b/grpc-google-cloud-datastore-v1/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>grpc-google-cloud-datastore-v1</artifactId>
-  <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-v1:current} -->
+  <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-v1:current} -->
   <name>grpc-google-cloud-datastore-v1</name>
   <description>GRPC library for google-cloud-datastore</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-datastore-parent</artifactId>
-    <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+    <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/pom.xml b/pom.xml
index b3f6a077..caa254f2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
   <groupId>com.google.cloud</groupId>
   <artifactId>google-cloud-datastore-parent</artifactId>
   <packaging>pom</packaging>
-  <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+  <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
   <name>Google Cloud Datastore Parent</name>
   <url>https://github.com/googleapis/java-datastore</url>
   <description>
@@ -14,7 +14,7 @@
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>sdk-platform-java-config</artifactId>
-    <version>3.29.0</version>
+    <version>3.30.1</version>
   </parent>
 
   <developers>
@@ -143,7 +143,7 @@
     <github.global.server>github</github.global.server>
     <site.installationModule>google-cloud-datastore-parent</site.installationModule>
     <project.javadoc.protobufBaseURL>https://googleapis.dev/java/google-api-grpc/latest</project.javadoc.protobufBaseURL>
-    <error-prone.version>2.27.0</error-prone.version>
+    <error-prone.version>2.27.1</error-prone.version>
   </properties>
 
   <dependencyManagement>
@@ -159,32 +159,32 @@
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>proto-google-cloud-datastore-admin-v1</artifactId>
-        <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-admin-v1:current} -->
+        <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-admin-v1:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>grpc-google-cloud-datastore-admin-v1</artifactId>
-        <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-admin-v1:current} -->
+        <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-admin-v1:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-datastore</artifactId>
-        <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+        <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>proto-google-cloud-datastore-v1</artifactId>
-        <version>0.110.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-v1:current} -->
+        <version>0.111.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-v1:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.api.grpc</groupId>
         <artifactId>grpc-google-cloud-datastore-v1</artifactId>
-        <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-v1:current} -->
+        <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-datastore-v1:current} -->
       </dependency>
       <dependency>
         <groupId>com.google.cloud.datastore</groupId>
         <artifactId>datastore-v1-proto-client</artifactId>
-        <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:datastore-v1-proto-client:current} -->
+        <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:datastore-v1-proto-client:current} -->
         <exclusions>
           <exclusion>
             <groupId>com.google.api.grpc</groupId>
diff --git a/proto-google-cloud-datastore-admin-v1/pom.xml b/proto-google-cloud-datastore-admin-v1/pom.xml
index e5e7e9a6..f1c28067 100644
--- a/proto-google-cloud-datastore-admin-v1/pom.xml
+++ b/proto-google-cloud-datastore-admin-v1/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>proto-google-cloud-datastore-admin-v1</artifactId>
-  <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-admin-v1:current} -->
+  <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-admin-v1:current} -->
   <name>proto-google-cloud-datastore-admin-v1</name>
   <description>Proto library for google-cloud-datastore</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-datastore-parent</artifactId>
-    <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+    <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/datastore_admin.proto b/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/datastore_admin.proto
index 79ca3df6..a8b3f998 100644
--- a/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/datastore_admin.proto
+++ b/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/datastore_admin.proto
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// Copyright 2024 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/index.proto b/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/index.proto
index 60bb5af5..6a1d1222 100644
--- a/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/index.proto
+++ b/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/index.proto
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// Copyright 2024 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/migration.proto b/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/migration.proto
index e5f7477d..813de87d 100644
--- a/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/migration.proto
+++ b/proto-google-cloud-datastore-admin-v1/src/main/proto/google/datastore/admin/v1/migration.proto
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// Copyright 2024 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-datastore-v1/pom.xml b/proto-google-cloud-datastore-v1/pom.xml
index 6931ca87..205debc7 100644
--- a/proto-google-cloud-datastore-v1/pom.xml
+++ b/proto-google-cloud-datastore-v1/pom.xml
@@ -4,13 +4,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.api.grpc</groupId>
   <artifactId>proto-google-cloud-datastore-v1</artifactId>
-  <version>0.110.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-v1:current} -->
+  <version>0.111.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-datastore-v1:current} -->
   <name>proto-google-cloud-datastore-v1</name>
   <description>PROTO library for proto-google-cloud-datastore-v1</description>
   <parent>
     <groupId>com.google.cloud</groupId>
     <artifactId>google-cloud-datastore-parent</artifactId>
-    <version>2.19.2-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
+    <version>2.20.0-grpc-experimental-1-SNAPSHOT</version><!-- {x-version-update:google-cloud-datastore:current} -->
   </parent>
   <dependencies>
     <dependency>
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/DatastoreProto.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/DatastoreProto.java
index 1b8753e3..e637dd01 100644
--- a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/DatastoreProto.java
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/DatastoreProto.java
@@ -100,6 +100,10 @@ public final class DatastoreProto {
       internal_static_google_datastore_v1_MutationResult_descriptor;
   static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
       internal_static_google_datastore_v1_MutationResult_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+      internal_static_google_datastore_v1_PropertyMask_descriptor;
+  static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_google_datastore_v1_PropertyMask_fieldAccessorTable;
   static final com.google.protobuf.Descriptors.Descriptor
       internal_static_google_datastore_v1_ReadOptions_descriptor;
   static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
@@ -134,151 +138,157 @@ public final class DatastoreProto {
           + "entity.proto\032\037google/datastore/v1/query."
           + "proto\032\'google/datastore/v1/query_profile"
           + ".proto\032\037google/protobuf/timestamp.proto\""
-          + "\242\001\n\rLookupRequest\022\027\n\nproject_id\030\010 \001(\tB\003\340"
+          + "\334\001\n\rLookupRequest\022\027\n\nproject_id\030\010 \001(\tB\003\340"
           + "A\002\022\023\n\013database_id\030\t \001(\t\0226\n\014read_options\030"
           + "\001 \001(\0132 .google.datastore.v1.ReadOptions\022"
           + "+\n\004keys\030\003 \003(\0132\030.google.datastore.v1.KeyB"
-          + "\003\340A\002\"\346\001\n\016LookupResponse\0220\n\005found\030\001 \003(\0132!"
-          + ".google.datastore.v1.EntityResult\0222\n\007mis"
-          + "sing\030\002 \003(\0132!.google.datastore.v1.EntityR"
-          + "esult\022*\n\010deferred\030\003 \003(\0132\030.google.datasto"
-          + "re.v1.Key\022\023\n\013transaction\030\005 \001(\014\022-\n\tread_t"
-          + "ime\030\007 \001(\0132\032.google.protobuf.Timestamp\"\341\002"
-          + "\n\017RunQueryRequest\022\027\n\nproject_id\030\010 \001(\tB\003\340"
-          + "A\002\022\023\n\013database_id\030\t \001(\t\0226\n\014partition_id\030"
-          + "\002 \001(\0132 .google.datastore.v1.PartitionId\022"
-          + "6\n\014read_options\030\001 \001(\0132 .google.datastore"
-          + ".v1.ReadOptions\022+\n\005query\030\003 \001(\0132\032.google."
-          + "datastore.v1.QueryH\000\0222\n\tgql_query\030\007 \001(\0132"
-          + "\035.google.datastore.v1.GqlQueryH\000\022A\n\017expl"
-          + "ain_options\030\014 \001(\0132#.google.datastore.v1."
-          + "ExplainOptionsB\003\340A\001B\014\n\nquery_type\"\306\001\n\020Ru"
-          + "nQueryResponse\0224\n\005batch\030\001 \001(\0132%.google.d"
-          + "atastore.v1.QueryResultBatch\022)\n\005query\030\002 "
-          + "\001(\0132\032.google.datastore.v1.Query\022\023\n\013trans"
-          + "action\030\005 \001(\014\022<\n\017explain_metrics\030\t \001(\0132#."
-          + "google.datastore.v1.ExplainMetrics\"\203\003\n\032R"
-          + "unAggregationQueryRequest\022\027\n\nproject_id\030"
-          + "\010 \001(\tB\003\340A\002\022\023\n\013database_id\030\t \001(\t\0226\n\014parti"
-          + "tion_id\030\002 \001(\0132 .google.datastore.v1.Part"
-          + "itionId\0226\n\014read_options\030\001 \001(\0132 .google.d"
-          + "atastore.v1.ReadOptions\022B\n\021aggregation_q"
-          + "uery\030\003 \001(\0132%.google.datastore.v1.Aggrega"
-          + "tionQueryH\000\0222\n\tgql_query\030\007 \001(\0132\035.google."
-          + "datastore.v1.GqlQueryH\000\022A\n\017explain_optio"
-          + "ns\030\013 \001(\0132#.google.datastore.v1.ExplainOp"
-          + "tionsB\003\340A\001B\014\n\nquery_type\"\342\001\n\033RunAggregat"
-          + "ionQueryResponse\022:\n\005batch\030\001 \001(\0132+.google"
-          + ".datastore.v1.AggregationResultBatch\0224\n\005"
-          + "query\030\002 \001(\0132%.google.datastore.v1.Aggreg"
-          + "ationQuery\022\023\n\013transaction\030\005 \001(\014\022<\n\017expla"
-          + "in_metrics\030\t \001(\0132#.google.datastore.v1.E"
-          + "xplainMetrics\"\215\001\n\027BeginTransactionReques"
-          + "t\022\027\n\nproject_id\030\010 \001(\tB\003\340A\002\022\023\n\013database_i"
-          + "d\030\t \001(\t\022D\n\023transaction_options\030\n \001(\0132\'.g"
-          + "oogle.datastore.v1.TransactionOptions\"/\n"
-          + "\030BeginTransactionResponse\022\023\n\013transaction"
-          + "\030\001 \001(\014\"Y\n\017RollbackRequest\022\027\n\nproject_id\030"
-          + "\010 \001(\tB\003\340A\002\022\023\n\013database_id\030\t \001(\t\022\030\n\013trans"
-          + "action\030\001 \001(\014B\003\340A\002\"\022\n\020RollbackResponse\"\350\002"
-          + "\n\rCommitRequest\022\027\n\nproject_id\030\010 \001(\tB\003\340A\002"
-          + "\022\023\n\013database_id\030\t \001(\t\0225\n\004mode\030\005 \001(\0162\'.go"
-          + "ogle.datastore.v1.CommitRequest.Mode\022\025\n\013"
-          + "transaction\030\001 \001(\014H\000\022I\n\026single_use_transa"
-          + "ction\030\n \001(\0132\'.google.datastore.v1.Transa"
-          + "ctionOptionsH\000\0220\n\tmutations\030\006 \003(\0132\035.goog"
-          + "le.datastore.v1.Mutation\"F\n\004Mode\022\024\n\020MODE"
-          + "_UNSPECIFIED\020\000\022\021\n\rTRANSACTIONAL\020\001\022\025\n\021NON"
-          + "_TRANSACTIONAL\020\002B\026\n\024transaction_selector"
-          + "\"\227\001\n\016CommitResponse\022=\n\020mutation_results\030"
-          + "\003 \003(\0132#.google.datastore.v1.MutationResu"
-          + "lt\022\025\n\rindex_updates\030\004 \001(\005\022/\n\013commit_time"
-          + "\030\010 \001(\0132\032.google.protobuf.Timestamp\"o\n\022Al"
-          + "locateIdsRequest\022\027\n\nproject_id\030\010 \001(\tB\003\340A"
-          + "\002\022\023\n\013database_id\030\t \001(\t\022+\n\004keys\030\001 \003(\0132\030.g"
-          + "oogle.datastore.v1.KeyB\003\340A\002\"=\n\023AllocateI"
-          + "dsResponse\022&\n\004keys\030\001 \003(\0132\030.google.datast"
-          + "ore.v1.Key\"n\n\021ReserveIdsRequest\022\027\n\nproje"
-          + "ct_id\030\010 \001(\tB\003\340A\002\022\023\n\013database_id\030\t \001(\t\022+\n"
-          + "\004keys\030\001 \003(\0132\030.google.datastore.v1.KeyB\003\340"
-          + "A\002\"\024\n\022ReserveIdsResponse\"\272\002\n\010Mutation\022-\n"
-          + "\006insert\030\004 \001(\0132\033.google.datastore.v1.Enti"
-          + "tyH\000\022-\n\006update\030\005 \001(\0132\033.google.datastore."
-          + "v1.EntityH\000\022-\n\006upsert\030\006 \001(\0132\033.google.dat"
-          + "astore.v1.EntityH\000\022*\n\006delete\030\007 \001(\0132\030.goo"
-          + "gle.datastore.v1.KeyH\000\022\026\n\014base_version\030\010"
-          + " \001(\003H\001\0221\n\013update_time\030\013 \001(\0132\032.google.pro"
-          + "tobuf.TimestampH\001B\013\n\toperationB\035\n\033confli"
-          + "ct_detection_strategy\"\305\001\n\016MutationResult"
-          + "\022%\n\003key\030\003 \001(\0132\030.google.datastore.v1.Key\022"
-          + "\017\n\007version\030\004 \001(\003\022/\n\013create_time\030\007 \001(\0132\032."
-          + "google.protobuf.Timestamp\022/\n\013update_time"
-          + "\030\006 \001(\0132\032.google.protobuf.Timestamp\022\031\n\021co"
-          + "nflict_detected\030\005 \001(\010\"\312\002\n\013ReadOptions\022L\n"
-          + "\020read_consistency\030\001 \001(\01620.google.datasto"
-          + "re.v1.ReadOptions.ReadConsistencyH\000\022\025\n\013t"
-          + "ransaction\030\002 \001(\014H\000\022B\n\017new_transaction\030\003 "
-          + "\001(\0132\'.google.datastore.v1.TransactionOpt"
-          + "ionsH\000\022/\n\tread_time\030\004 \001(\0132\032.google.proto"
-          + "buf.TimestampH\000\"M\n\017ReadConsistency\022 \n\034RE"
-          + "AD_CONSISTENCY_UNSPECIFIED\020\000\022\n\n\006STRONG\020\001"
-          + "\022\014\n\010EVENTUAL\020\002B\022\n\020consistency_type\"\222\002\n\022T"
-          + "ransactionOptions\022G\n\nread_write\030\001 \001(\01321."
-          + "google.datastore.v1.TransactionOptions.R"
-          + "eadWriteH\000\022E\n\tread_only\030\002 \001(\01320.google.d"
-          + "atastore.v1.TransactionOptions.ReadOnlyH"
-          + "\000\032)\n\tReadWrite\022\034\n\024previous_transaction\030\001"
-          + " \001(\014\0329\n\010ReadOnly\022-\n\tread_time\030\001 \001(\0132\032.go"
-          + "ogle.protobuf.TimestampB\006\n\004mode2\341\r\n\tData"
-          + "store\022\300\001\n\006Lookup\022\".google.datastore.v1.L"
-          + "ookupRequest\032#.google.datastore.v1.Looku"
-          + "pResponse\"m\332A\034project_id,read_options,ke"
-          + "ys\202\323\344\223\002%\" /v1/projects/{project_id}:look"
-          + "up:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_id"
-          + "\022\251\001\n\010RunQuery\022$.google.datastore.v1.RunQ"
-          + "ueryRequest\032%.google.datastore.v1.RunQue"
-          + "ryResponse\"P\202\323\344\223\002\'\"\"/v1/projects/{projec"
-          + "t_id}:runQuery:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n"
-          + "\013database_id\022\325\001\n\023RunAggregationQuery\022/.g"
-          + "oogle.datastore.v1.RunAggregationQueryRe"
-          + "quest\0320.google.datastore.v1.RunAggregati"
-          + "onQueryResponse\"[\202\323\344\223\0022\"-/v1/projects/{p"
-          + "roject_id}:runAggregationQuery:\001*\212\323\344\223\002\035\022"
-          + "\014\n\nproject_id\022\r\n\013database_id\022\326\001\n\020BeginTr"
-          + "ansaction\022,.google.datastore.v1.BeginTra"
-          + "nsactionRequest\032-.google.datastore.v1.Be"
-          + "ginTransactionResponse\"e\332A\nproject_id\202\323\344"
-          + "\223\002/\"*/v1/projects/{project_id}:beginTran"
-          + "saction:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013databa"
-          + "se_id\022\346\001\n\006Commit\022\".google.datastore.v1.C"
-          + "ommitRequest\032#.google.datastore.v1.Commi"
-          + "tResponse\"\222\001\332A%project_id,mode,transacti"
-          + "on,mutations\332A\031project_id,mode,mutations"
-          + "\202\323\344\223\002%\" /v1/projects/{project_id}:commit"
-          + ":\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_id\022\302"
-          + "\001\n\010Rollback\022$.google.datastore.v1.Rollba"
-          + "ckRequest\032%.google.datastore.v1.Rollback"
-          + "Response\"i\332A\026project_id,transaction\202\323\344\223\002"
-          + "\'\"\"/v1/projects/{project_id}:rollback:\001*"
-          + "\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_id\022\307\001\n\013"
-          + "AllocateIds\022\'.google.datastore.v1.Alloca"
-          + "teIdsRequest\032(.google.datastore.v1.Alloc"
-          + "ateIdsResponse\"e\332A\017project_id,keys\202\323\344\223\002*"
-          + "\"%/v1/projects/{project_id}:allocateIds:"
-          + "\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_id\022\303\001"
-          + "\n\nReserveIds\022&.google.datastore.v1.Reser"
-          + "veIdsRequest\032\'.google.datastore.v1.Reser"
-          + "veIdsResponse\"d\332A\017project_id,keys\202\323\344\223\002)\""
-          + "$/v1/projects/{project_id}:reserveIds:\001*"
-          + "\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_id\032v\312A\030"
-          + "datastore.googleapis.com\322AXhttps://www.g"
-          + "oogleapis.com/auth/cloud-platform,https:"
-          + "//www.googleapis.com/auth/datastoreB\300\001\n\027"
-          + "com.google.datastore.v1B\016DatastoreProtoP"
-          + "\001Z<google.golang.org/genproto/googleapis"
-          + "/datastore/v1;datastore\252\002\031Google.Cloud.D"
-          + "atastore.V1\312\002\031Google\\Cloud\\Datastore\\V1\352"
-          + "\002\034Google::Cloud::Datastore::V1b\006proto3"
+          + "\003\340A\002\0228\n\rproperty_mask\030\005 \001(\0132!.google.dat"
+          + "astore.v1.PropertyMask\"\346\001\n\016LookupRespons"
+          + "e\0220\n\005found\030\001 \003(\0132!.google.datastore.v1.E"
+          + "ntityResult\0222\n\007missing\030\002 \003(\0132!.google.da"
+          + "tastore.v1.EntityResult\022*\n\010deferred\030\003 \003("
+          + "\0132\030.google.datastore.v1.Key\022\023\n\013transacti"
+          + "on\030\005 \001(\014\022-\n\tread_time\030\007 \001(\0132\032.google.pro"
+          + "tobuf.Timestamp\"\233\003\n\017RunQueryRequest\022\027\n\np"
+          + "roject_id\030\010 \001(\tB\003\340A\002\022\023\n\013database_id\030\t \001("
+          + "\t\0226\n\014partition_id\030\002 \001(\0132 .google.datasto"
+          + "re.v1.PartitionId\0226\n\014read_options\030\001 \001(\0132"
+          + " .google.datastore.v1.ReadOptions\022+\n\005que"
+          + "ry\030\003 \001(\0132\032.google.datastore.v1.QueryH\000\0222"
+          + "\n\tgql_query\030\007 \001(\0132\035.google.datastore.v1."
+          + "GqlQueryH\000\0228\n\rproperty_mask\030\n \001(\0132!.goog"
+          + "le.datastore.v1.PropertyMask\022A\n\017explain_"
+          + "options\030\014 \001(\0132#.google.datastore.v1.Expl"
+          + "ainOptionsB\003\340A\001B\014\n\nquery_type\"\306\001\n\020RunQue"
+          + "ryResponse\0224\n\005batch\030\001 \001(\0132%.google.datas"
+          + "tore.v1.QueryResultBatch\022)\n\005query\030\002 \001(\0132"
+          + "\032.google.datastore.v1.Query\022\023\n\013transacti"
+          + "on\030\005 \001(\014\022<\n\017explain_metrics\030\t \001(\0132#.goog"
+          + "le.datastore.v1.ExplainMetrics\"\203\003\n\032RunAg"
+          + "gregationQueryRequest\022\027\n\nproject_id\030\010 \001("
+          + "\tB\003\340A\002\022\023\n\013database_id\030\t \001(\t\0226\n\014partition"
+          + "_id\030\002 \001(\0132 .google.datastore.v1.Partitio"
+          + "nId\0226\n\014read_options\030\001 \001(\0132 .google.datas"
+          + "tore.v1.ReadOptions\022B\n\021aggregation_query"
+          + "\030\003 \001(\0132%.google.datastore.v1.Aggregation"
+          + "QueryH\000\0222\n\tgql_query\030\007 \001(\0132\035.google.data"
+          + "store.v1.GqlQueryH\000\022A\n\017explain_options\030\013"
+          + " \001(\0132#.google.datastore.v1.ExplainOption"
+          + "sB\003\340A\001B\014\n\nquery_type\"\342\001\n\033RunAggregationQ"
+          + "ueryResponse\022:\n\005batch\030\001 \001(\0132+.google.dat"
+          + "astore.v1.AggregationResultBatch\0224\n\005quer"
+          + "y\030\002 \001(\0132%.google.datastore.v1.Aggregatio"
+          + "nQuery\022\023\n\013transaction\030\005 \001(\014\022<\n\017explain_m"
+          + "etrics\030\t \001(\0132#.google.datastore.v1.Expla"
+          + "inMetrics\"\215\001\n\027BeginTransactionRequest\022\027\n"
+          + "\nproject_id\030\010 \001(\tB\003\340A\002\022\023\n\013database_id\030\t "
+          + "\001(\t\022D\n\023transaction_options\030\n \001(\0132\'.googl"
+          + "e.datastore.v1.TransactionOptions\"/\n\030Beg"
+          + "inTransactionResponse\022\023\n\013transaction\030\001 \001"
+          + "(\014\"Y\n\017RollbackRequest\022\027\n\nproject_id\030\010 \001("
+          + "\tB\003\340A\002\022\023\n\013database_id\030\t \001(\t\022\030\n\013transacti"
+          + "on\030\001 \001(\014B\003\340A\002\"\022\n\020RollbackResponse\"\350\002\n\rCo"
+          + "mmitRequest\022\027\n\nproject_id\030\010 \001(\tB\003\340A\002\022\023\n\013"
+          + "database_id\030\t \001(\t\0225\n\004mode\030\005 \001(\0162\'.google"
+          + ".datastore.v1.CommitRequest.Mode\022\025\n\013tran"
+          + "saction\030\001 \001(\014H\000\022I\n\026single_use_transactio"
+          + "n\030\n \001(\0132\'.google.datastore.v1.Transactio"
+          + "nOptionsH\000\0220\n\tmutations\030\006 \003(\0132\035.google.d"
+          + "atastore.v1.Mutation\"F\n\004Mode\022\024\n\020MODE_UNS"
+          + "PECIFIED\020\000\022\021\n\rTRANSACTIONAL\020\001\022\025\n\021NON_TRA"
+          + "NSACTIONAL\020\002B\026\n\024transaction_selector\"\227\001\n"
+          + "\016CommitResponse\022=\n\020mutation_results\030\003 \003("
+          + "\0132#.google.datastore.v1.MutationResult\022\025"
+          + "\n\rindex_updates\030\004 \001(\005\022/\n\013commit_time\030\010 \001"
+          + "(\0132\032.google.protobuf.Timestamp\"o\n\022Alloca"
+          + "teIdsRequest\022\027\n\nproject_id\030\010 \001(\tB\003\340A\002\022\023\n"
+          + "\013database_id\030\t \001(\t\022+\n\004keys\030\001 \003(\0132\030.googl"
+          + "e.datastore.v1.KeyB\003\340A\002\"=\n\023AllocateIdsRe"
+          + "sponse\022&\n\004keys\030\001 \003(\0132\030.google.datastore."
+          + "v1.Key\"n\n\021ReserveIdsRequest\022\027\n\nproject_i"
+          + "d\030\010 \001(\tB\003\340A\002\022\023\n\013database_id\030\t \001(\t\022+\n\004key"
+          + "s\030\001 \003(\0132\030.google.datastore.v1.KeyB\003\340A\002\"\024"
+          + "\n\022ReserveIdsResponse\"\364\002\n\010Mutation\022-\n\006ins"
+          + "ert\030\004 \001(\0132\033.google.datastore.v1.EntityH\000"
+          + "\022-\n\006update\030\005 \001(\0132\033.google.datastore.v1.E"
+          + "ntityH\000\022-\n\006upsert\030\006 \001(\0132\033.google.datasto"
+          + "re.v1.EntityH\000\022*\n\006delete\030\007 \001(\0132\030.google."
+          + "datastore.v1.KeyH\000\022\026\n\014base_version\030\010 \001(\003"
+          + "H\001\0221\n\013update_time\030\013 \001(\0132\032.google.protobu"
+          + "f.TimestampH\001\0228\n\rproperty_mask\030\t \001(\0132!.g"
+          + "oogle.datastore.v1.PropertyMaskB\013\n\topera"
+          + "tionB\035\n\033conflict_detection_strategy\"\305\001\n\016"
+          + "MutationResult\022%\n\003key\030\003 \001(\0132\030.google.dat"
+          + "astore.v1.Key\022\017\n\007version\030\004 \001(\003\022/\n\013create"
+          + "_time\030\007 \001(\0132\032.google.protobuf.Timestamp\022"
+          + "/\n\013update_time\030\006 \001(\0132\032.google.protobuf.T"
+          + "imestamp\022\031\n\021conflict_detected\030\005 \001(\010\"\035\n\014P"
+          + "ropertyMask\022\r\n\005paths\030\001 \003(\t\"\312\002\n\013ReadOptio"
+          + "ns\022L\n\020read_consistency\030\001 \001(\01620.google.da"
+          + "tastore.v1.ReadOptions.ReadConsistencyH\000"
+          + "\022\025\n\013transaction\030\002 \001(\014H\000\022B\n\017new_transacti"
+          + "on\030\003 \001(\0132\'.google.datastore.v1.Transacti"
+          + "onOptionsH\000\022/\n\tread_time\030\004 \001(\0132\032.google."
+          + "protobuf.TimestampH\000\"M\n\017ReadConsistency\022"
+          + " \n\034READ_CONSISTENCY_UNSPECIFIED\020\000\022\n\n\006STR"
+          + "ONG\020\001\022\014\n\010EVENTUAL\020\002B\022\n\020consistency_type\""
+          + "\222\002\n\022TransactionOptions\022G\n\nread_write\030\001 \001"
+          + "(\01321.google.datastore.v1.TransactionOpti"
+          + "ons.ReadWriteH\000\022E\n\tread_only\030\002 \001(\01320.goo"
+          + "gle.datastore.v1.TransactionOptions.Read"
+          + "OnlyH\000\032)\n\tReadWrite\022\034\n\024previous_transact"
+          + "ion\030\001 \001(\014\0329\n\010ReadOnly\022-\n\tread_time\030\001 \001(\013"
+          + "2\032.google.protobuf.TimestampB\006\n\004mode2\341\r\n"
+          + "\tDatastore\022\300\001\n\006Lookup\022\".google.datastore"
+          + ".v1.LookupRequest\032#.google.datastore.v1."
+          + "LookupResponse\"m\332A\034project_id,read_optio"
+          + "ns,keys\202\323\344\223\002%\" /v1/projects/{project_id}"
+          + ":lookup:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013databa"
+          + "se_id\022\251\001\n\010RunQuery\022$.google.datastore.v1"
+          + ".RunQueryRequest\032%.google.datastore.v1.R"
+          + "unQueryResponse\"P\202\323\344\223\002\'\"\"/v1/projects/{p"
+          + "roject_id}:runQuery:\001*\212\323\344\223\002\035\022\014\n\nproject_"
+          + "id\022\r\n\013database_id\022\325\001\n\023RunAggregationQuer"
+          + "y\022/.google.datastore.v1.RunAggregationQu"
+          + "eryRequest\0320.google.datastore.v1.RunAggr"
+          + "egationQueryResponse\"[\202\323\344\223\0022\"-/v1/projec"
+          + "ts/{project_id}:runAggregationQuery:\001*\212\323"
+          + "\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_id\022\326\001\n\020Be"
+          + "ginTransaction\022,.google.datastore.v1.Beg"
+          + "inTransactionRequest\032-.google.datastore."
+          + "v1.BeginTransactionResponse\"e\332A\nproject_"
+          + "id\202\323\344\223\002/\"*/v1/projects/{project_id}:begi"
+          + "nTransaction:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013d"
+          + "atabase_id\022\346\001\n\006Commit\022\".google.datastore"
+          + ".v1.CommitRequest\032#.google.datastore.v1."
+          + "CommitResponse\"\222\001\332A%project_id,mode,tran"
+          + "saction,mutations\332A\031project_id,mode,muta"
+          + "tions\202\323\344\223\002%\" /v1/projects/{project_id}:c"
+          + "ommit:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database"
+          + "_id\022\302\001\n\010Rollback\022$.google.datastore.v1.R"
+          + "ollbackRequest\032%.google.datastore.v1.Rol"
+          + "lbackResponse\"i\332A\026project_id,transaction"
+          + "\202\323\344\223\002\'\"\"/v1/projects/{project_id}:rollba"
+          + "ck:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_id"
+          + "\022\307\001\n\013AllocateIds\022\'.google.datastore.v1.A"
+          + "llocateIdsRequest\032(.google.datastore.v1."
+          + "AllocateIdsResponse\"e\332A\017project_id,keys\202"
+          + "\323\344\223\002*\"%/v1/projects/{project_id}:allocat"
+          + "eIds:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_"
+          + "id\022\303\001\n\nReserveIds\022&.google.datastore.v1."
+          + "ReserveIdsRequest\032\'.google.datastore.v1."
+          + "ReserveIdsResponse\"d\332A\017project_id,keys\202\323"
+          + "\344\223\002)\"$/v1/projects/{project_id}:reserveI"
+          + "ds:\001*\212\323\344\223\002\035\022\014\n\nproject_id\022\r\n\013database_id"
+          + "\032v\312A\030datastore.googleapis.com\322AXhttps://"
+          + "www.googleapis.com/auth/cloud-platform,h"
+          + "ttps://www.googleapis.com/auth/datastore"
+          + "B\300\001\n\027com.google.datastore.v1B\016DatastoreP"
+          + "rotoP\001Z<google.golang.org/genproto/googl"
+          + "eapis/datastore/v1;datastore\252\002\031Google.Cl"
+          + "oud.Datastore.V1\312\002\031Google\\Cloud\\Datastor"
+          + "e\\V1\352\002\034Google::Cloud::Datastore::V1b\006pro"
+          + "to3"
     };
     descriptor =
         com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
@@ -300,7 +310,7 @@ public final class DatastoreProto {
         new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
             internal_static_google_datastore_v1_LookupRequest_descriptor,
             new java.lang.String[] {
-              "ProjectId", "DatabaseId", "ReadOptions", "Keys",
+              "ProjectId", "DatabaseId", "ReadOptions", "Keys", "PropertyMask",
             });
     internal_static_google_datastore_v1_LookupResponse_descriptor =
         getDescriptor().getMessageTypes().get(1);
@@ -322,6 +332,7 @@ public final class DatastoreProto {
               "ReadOptions",
               "Query",
               "GqlQuery",
+              "PropertyMask",
               "ExplainOptions",
               "QueryType",
             });
@@ -450,6 +461,7 @@ public final class DatastoreProto {
               "Delete",
               "BaseVersion",
               "UpdateTime",
+              "PropertyMask",
               "Operation",
               "ConflictDetectionStrategy",
             });
@@ -461,8 +473,16 @@ public final class DatastoreProto {
             new java.lang.String[] {
               "Key", "Version", "CreateTime", "UpdateTime", "ConflictDetected",
             });
-    internal_static_google_datastore_v1_ReadOptions_descriptor =
+    internal_static_google_datastore_v1_PropertyMask_descriptor =
         getDescriptor().getMessageTypes().get(18);
+    internal_static_google_datastore_v1_PropertyMask_fieldAccessorTable =
+        new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+            internal_static_google_datastore_v1_PropertyMask_descriptor,
+            new java.lang.String[] {
+              "Paths",
+            });
+    internal_static_google_datastore_v1_ReadOptions_descriptor =
+        getDescriptor().getMessageTypes().get(19);
     internal_static_google_datastore_v1_ReadOptions_fieldAccessorTable =
         new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
             internal_static_google_datastore_v1_ReadOptions_descriptor,
@@ -470,7 +490,7 @@ public final class DatastoreProto {
               "ReadConsistency", "Transaction", "NewTransaction", "ReadTime", "ConsistencyType",
             });
     internal_static_google_datastore_v1_TransactionOptions_descriptor =
-        getDescriptor().getMessageTypes().get(19);
+        getDescriptor().getMessageTypes().get(20);
     internal_static_google_datastore_v1_TransactionOptions_fieldAccessorTable =
         new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
             internal_static_google_datastore_v1_TransactionOptions_descriptor,
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequest.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequest.java
index cd95d3a0..88adc120 100644
--- a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequest.java
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequest.java
@@ -299,6 +299,71 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
     return keys_.get(index);
   }
 
+  public static final int PROPERTY_MASK_FIELD_NUMBER = 5;
+  private com.google.datastore.v1.PropertyMask propertyMask_;
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return. Defaults to returning all properties.
+   *
+   * If this field is set and an entity has a property not referenced in the
+   * mask, it will be absent from [LookupResponse.found.entity.properties][].
+   *
+   * The entity's key is always returned.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+   *
+   * @return Whether the propertyMask field is set.
+   */
+  @java.lang.Override
+  public boolean hasPropertyMask() {
+    return ((bitField0_ & 0x00000002) != 0);
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return. Defaults to returning all properties.
+   *
+   * If this field is set and an entity has a property not referenced in the
+   * mask, it will be absent from [LookupResponse.found.entity.properties][].
+   *
+   * The entity's key is always returned.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+   *
+   * @return The propertyMask.
+   */
+  @java.lang.Override
+  public com.google.datastore.v1.PropertyMask getPropertyMask() {
+    return propertyMask_ == null
+        ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+        : propertyMask_;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return. Defaults to returning all properties.
+   *
+   * If this field is set and an entity has a property not referenced in the
+   * mask, it will be absent from [LookupResponse.found.entity.properties][].
+   *
+   * The entity's key is always returned.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+   */
+  @java.lang.Override
+  public com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder() {
+    return propertyMask_ == null
+        ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+        : propertyMask_;
+  }
+
   private byte memoizedIsInitialized = -1;
 
   @java.lang.Override
@@ -319,6 +384,9 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
     for (int i = 0; i < keys_.size(); i++) {
       output.writeMessage(3, keys_.get(i));
     }
+    if (((bitField0_ & 0x00000002) != 0)) {
+      output.writeMessage(5, getPropertyMask());
+    }
     if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(projectId_)) {
       com.google.protobuf.GeneratedMessageV3.writeString(output, 8, projectId_);
     }
@@ -340,6 +408,9 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
     for (int i = 0; i < keys_.size(); i++) {
       size += com.google.protobuf.CodedOutputStream.computeMessageSize(3, keys_.get(i));
     }
+    if (((bitField0_ & 0x00000002) != 0)) {
+      size += com.google.protobuf.CodedOutputStream.computeMessageSize(5, getPropertyMask());
+    }
     if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(projectId_)) {
       size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, projectId_);
     }
@@ -368,6 +439,10 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
       if (!getReadOptions().equals(other.getReadOptions())) return false;
     }
     if (!getKeysList().equals(other.getKeysList())) return false;
+    if (hasPropertyMask() != other.hasPropertyMask()) return false;
+    if (hasPropertyMask()) {
+      if (!getPropertyMask().equals(other.getPropertyMask())) return false;
+    }
     if (!getUnknownFields().equals(other.getUnknownFields())) return false;
     return true;
   }
@@ -391,6 +466,10 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
       hash = (37 * hash) + KEYS_FIELD_NUMBER;
       hash = (53 * hash) + getKeysList().hashCode();
     }
+    if (hasPropertyMask()) {
+      hash = (37 * hash) + PROPERTY_MASK_FIELD_NUMBER;
+      hash = (53 * hash) + getPropertyMask().hashCode();
+    }
     hash = (29 * hash) + getUnknownFields().hashCode();
     memoizedHashCode = hash;
     return hash;
@@ -532,6 +611,7 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
       if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {
         getReadOptionsFieldBuilder();
         getKeysFieldBuilder();
+        getPropertyMaskFieldBuilder();
       }
     }
 
@@ -553,6 +633,11 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
         keysBuilder_.clear();
       }
       bitField0_ = (bitField0_ & ~0x00000008);
+      propertyMask_ = null;
+      if (propertyMaskBuilder_ != null) {
+        propertyMaskBuilder_.dispose();
+        propertyMaskBuilder_ = null;
+      }
       return this;
     }
 
@@ -614,6 +699,11 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
             readOptionsBuilder_ == null ? readOptions_ : readOptionsBuilder_.build();
         to_bitField0_ |= 0x00000001;
       }
+      if (((from_bitField0_ & 0x00000010) != 0)) {
+        result.propertyMask_ =
+            propertyMaskBuilder_ == null ? propertyMask_ : propertyMaskBuilder_.build();
+        to_bitField0_ |= 0x00000002;
+      }
       result.bitField0_ |= to_bitField0_;
     }
 
@@ -702,6 +792,9 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
           }
         }
       }
+      if (other.hasPropertyMask()) {
+        mergePropertyMask(other.getPropertyMask());
+      }
       this.mergeUnknownFields(other.getUnknownFields());
       onChanged();
       return this;
@@ -746,6 +839,12 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
                 }
                 break;
               } // case 26
+            case 42:
+              {
+                input.readMessage(getPropertyMaskFieldBuilder().getBuilder(), extensionRegistry);
+                bitField0_ |= 0x00000010;
+                break;
+              } // case 42
             case 66:
               {
                 projectId_ = input.readStringRequireUtf8();
@@ -1549,6 +1648,236 @@ public final class LookupRequest extends com.google.protobuf.GeneratedMessageV3
       return keysBuilder_;
     }
 
+    private com.google.datastore.v1.PropertyMask propertyMask_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.datastore.v1.PropertyMask,
+            com.google.datastore.v1.PropertyMask.Builder,
+            com.google.datastore.v1.PropertyMaskOrBuilder>
+        propertyMaskBuilder_;
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     *
+     * @return Whether the propertyMask field is set.
+     */
+    public boolean hasPropertyMask() {
+      return ((bitField0_ & 0x00000010) != 0);
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     *
+     * @return The propertyMask.
+     */
+    public com.google.datastore.v1.PropertyMask getPropertyMask() {
+      if (propertyMaskBuilder_ == null) {
+        return propertyMask_ == null
+            ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+            : propertyMask_;
+      } else {
+        return propertyMaskBuilder_.getMessage();
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     */
+    public Builder setPropertyMask(com.google.datastore.v1.PropertyMask value) {
+      if (propertyMaskBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        propertyMask_ = value;
+      } else {
+        propertyMaskBuilder_.setMessage(value);
+      }
+      bitField0_ |= 0x00000010;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     */
+    public Builder setPropertyMask(com.google.datastore.v1.PropertyMask.Builder builderForValue) {
+      if (propertyMaskBuilder_ == null) {
+        propertyMask_ = builderForValue.build();
+      } else {
+        propertyMaskBuilder_.setMessage(builderForValue.build());
+      }
+      bitField0_ |= 0x00000010;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     */
+    public Builder mergePropertyMask(com.google.datastore.v1.PropertyMask value) {
+      if (propertyMaskBuilder_ == null) {
+        if (((bitField0_ & 0x00000010) != 0)
+            && propertyMask_ != null
+            && propertyMask_ != com.google.datastore.v1.PropertyMask.getDefaultInstance()) {
+          getPropertyMaskBuilder().mergeFrom(value);
+        } else {
+          propertyMask_ = value;
+        }
+      } else {
+        propertyMaskBuilder_.mergeFrom(value);
+      }
+      if (propertyMask_ != null) {
+        bitField0_ |= 0x00000010;
+        onChanged();
+      }
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     */
+    public Builder clearPropertyMask() {
+      bitField0_ = (bitField0_ & ~0x00000010);
+      propertyMask_ = null;
+      if (propertyMaskBuilder_ != null) {
+        propertyMaskBuilder_.dispose();
+        propertyMaskBuilder_ = null;
+      }
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     */
+    public com.google.datastore.v1.PropertyMask.Builder getPropertyMaskBuilder() {
+      bitField0_ |= 0x00000010;
+      onChanged();
+      return getPropertyMaskFieldBuilder().getBuilder();
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     */
+    public com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder() {
+      if (propertyMaskBuilder_ != null) {
+        return propertyMaskBuilder_.getMessageOrBuilder();
+      } else {
+        return propertyMask_ == null
+            ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+            : propertyMask_;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return. Defaults to returning all properties.
+     *
+     * If this field is set and an entity has a property not referenced in the
+     * mask, it will be absent from [LookupResponse.found.entity.properties][].
+     *
+     * The entity's key is always returned.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.datastore.v1.PropertyMask,
+            com.google.datastore.v1.PropertyMask.Builder,
+            com.google.datastore.v1.PropertyMaskOrBuilder>
+        getPropertyMaskFieldBuilder() {
+      if (propertyMaskBuilder_ == null) {
+        propertyMaskBuilder_ =
+            new com.google.protobuf.SingleFieldBuilderV3<
+                com.google.datastore.v1.PropertyMask,
+                com.google.datastore.v1.PropertyMask.Builder,
+                com.google.datastore.v1.PropertyMaskOrBuilder>(
+                getPropertyMask(), getParentForChildren(), isClean());
+        propertyMask_ = null;
+      }
+      return propertyMaskBuilder_;
+    }
+
     @java.lang.Override
     public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
       return super.setUnknownFields(unknownFields);
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequestOrBuilder.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequestOrBuilder.java
index 82fe2466..d343eeca 100644
--- a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequestOrBuilder.java
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/LookupRequestOrBuilder.java
@@ -170,4 +170,54 @@ public interface LookupRequestOrBuilder
    * </code>
    */
   com.google.datastore.v1.KeyOrBuilder getKeysOrBuilder(int index);
+
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return. Defaults to returning all properties.
+   *
+   * If this field is set and an entity has a property not referenced in the
+   * mask, it will be absent from [LookupResponse.found.entity.properties][].
+   *
+   * The entity's key is always returned.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+   *
+   * @return Whether the propertyMask field is set.
+   */
+  boolean hasPropertyMask();
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return. Defaults to returning all properties.
+   *
+   * If this field is set and an entity has a property not referenced in the
+   * mask, it will be absent from [LookupResponse.found.entity.properties][].
+   *
+   * The entity's key is always returned.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+   *
+   * @return The propertyMask.
+   */
+  com.google.datastore.v1.PropertyMask getPropertyMask();
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return. Defaults to returning all properties.
+   *
+   * If this field is set and an entity has a property not referenced in the
+   * mask, it will be absent from [LookupResponse.found.entity.properties][].
+   *
+   * The entity's key is always returned.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 5;</code>
+   */
+  com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder();
 }
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/Mutation.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/Mutation.java
index 91895d18..6857d48a 100644
--- a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/Mutation.java
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/Mutation.java
@@ -60,6 +60,7 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
             com.google.datastore.v1.Mutation.class, com.google.datastore.v1.Mutation.Builder.class);
   }
 
+  private int bitField0_;
   private int operationCase_ = 0;
 
   @SuppressWarnings("serial")
@@ -476,6 +477,77 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
     return com.google.protobuf.Timestamp.getDefaultInstance();
   }
 
+  public static final int PROPERTY_MASK_FIELD_NUMBER = 9;
+  private com.google.datastore.v1.PropertyMask propertyMask_;
+  /**
+   *
+   *
+   * <pre>
+   * The properties to write in this mutation.
+   * None of the properties in the mask may have a reserved name, except for
+   * `__key__`.
+   * This field is ignored for `delete`.
+   *
+   * If the entity already exists, only properties referenced in the mask are
+   * updated, others are left untouched.
+   * Properties referenced in the mask but not in the entity are deleted.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+   *
+   * @return Whether the propertyMask field is set.
+   */
+  @java.lang.Override
+  public boolean hasPropertyMask() {
+    return ((bitField0_ & 0x00000001) != 0);
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The properties to write in this mutation.
+   * None of the properties in the mask may have a reserved name, except for
+   * `__key__`.
+   * This field is ignored for `delete`.
+   *
+   * If the entity already exists, only properties referenced in the mask are
+   * updated, others are left untouched.
+   * Properties referenced in the mask but not in the entity are deleted.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+   *
+   * @return The propertyMask.
+   */
+  @java.lang.Override
+  public com.google.datastore.v1.PropertyMask getPropertyMask() {
+    return propertyMask_ == null
+        ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+        : propertyMask_;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The properties to write in this mutation.
+   * None of the properties in the mask may have a reserved name, except for
+   * `__key__`.
+   * This field is ignored for `delete`.
+   *
+   * If the entity already exists, only properties referenced in the mask are
+   * updated, others are left untouched.
+   * Properties referenced in the mask but not in the entity are deleted.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+   */
+  @java.lang.Override
+  public com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder() {
+    return propertyMask_ == null
+        ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+        : propertyMask_;
+  }
+
   private byte memoizedIsInitialized = -1;
 
   @java.lang.Override
@@ -505,6 +577,9 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
     if (conflictDetectionStrategyCase_ == 8) {
       output.writeInt64(8, (long) ((java.lang.Long) conflictDetectionStrategy_));
     }
+    if (((bitField0_ & 0x00000001) != 0)) {
+      output.writeMessage(9, getPropertyMask());
+    }
     if (conflictDetectionStrategyCase_ == 11) {
       output.writeMessage(11, (com.google.protobuf.Timestamp) conflictDetectionStrategy_);
     }
@@ -542,6 +617,9 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
           com.google.protobuf.CodedOutputStream.computeInt64Size(
               8, (long) ((java.lang.Long) conflictDetectionStrategy_));
     }
+    if (((bitField0_ & 0x00000001) != 0)) {
+      size += com.google.protobuf.CodedOutputStream.computeMessageSize(9, getPropertyMask());
+    }
     if (conflictDetectionStrategyCase_ == 11) {
       size +=
           com.google.protobuf.CodedOutputStream.computeMessageSize(
@@ -562,6 +640,10 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
     }
     com.google.datastore.v1.Mutation other = (com.google.datastore.v1.Mutation) obj;
 
+    if (hasPropertyMask() != other.hasPropertyMask()) return false;
+    if (hasPropertyMask()) {
+      if (!getPropertyMask().equals(other.getPropertyMask())) return false;
+    }
     if (!getOperationCase().equals(other.getOperationCase())) return false;
     switch (operationCase_) {
       case 4:
@@ -602,6 +684,10 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
     }
     int hash = 41;
     hash = (19 * hash) + getDescriptor().hashCode();
+    if (hasPropertyMask()) {
+      hash = (37 * hash) + PROPERTY_MASK_FIELD_NUMBER;
+      hash = (53 * hash) + getPropertyMask().hashCode();
+    }
     switch (operationCase_) {
       case 4:
         hash = (37 * hash) + INSERT_FIELD_NUMBER;
@@ -762,10 +848,19 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
     }
 
     // Construct using com.google.datastore.v1.Mutation.newBuilder()
-    private Builder() {}
+    private Builder() {
+      maybeForceBuilderInitialization();
+    }
 
     private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
       super(parent);
+      maybeForceBuilderInitialization();
+    }
+
+    private void maybeForceBuilderInitialization() {
+      if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {
+        getPropertyMaskFieldBuilder();
+      }
     }
 
     @java.lang.Override
@@ -787,6 +882,11 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
       if (updateTimeBuilder_ != null) {
         updateTimeBuilder_.clear();
       }
+      propertyMask_ = null;
+      if (propertyMaskBuilder_ != null) {
+        propertyMaskBuilder_.dispose();
+        propertyMaskBuilder_ = null;
+      }
       operationCase_ = 0;
       operation_ = null;
       conflictDetectionStrategyCase_ = 0;
@@ -827,6 +927,13 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
 
     private void buildPartial0(com.google.datastore.v1.Mutation result) {
       int from_bitField0_ = bitField0_;
+      int to_bitField0_ = 0;
+      if (((from_bitField0_ & 0x00000040) != 0)) {
+        result.propertyMask_ =
+            propertyMaskBuilder_ == null ? propertyMask_ : propertyMaskBuilder_.build();
+        to_bitField0_ |= 0x00000001;
+      }
+      result.bitField0_ |= to_bitField0_;
     }
 
     private void buildPartialOneofs(com.google.datastore.v1.Mutation result) {
@@ -896,6 +1003,9 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
 
     public Builder mergeFrom(com.google.datastore.v1.Mutation other) {
       if (other == com.google.datastore.v1.Mutation.getDefaultInstance()) return this;
+      if (other.hasPropertyMask()) {
+        mergePropertyMask(other.getPropertyMask());
+      }
       switch (other.getOperationCase()) {
         case INSERT:
           {
@@ -994,6 +1104,12 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
                 conflictDetectionStrategyCase_ = 8;
                 break;
               } // case 64
+            case 74:
+              {
+                input.readMessage(getPropertyMaskFieldBuilder().getBuilder(), extensionRegistry);
+                bitField0_ |= 0x00000040;
+                break;
+              } // case 74
             case 90:
               {
                 input.readMessage(getUpdateTimeFieldBuilder().getBuilder(), extensionRegistry);
@@ -2206,6 +2322,254 @@ public final class Mutation extends com.google.protobuf.GeneratedMessageV3
       return updateTimeBuilder_;
     }
 
+    private com.google.datastore.v1.PropertyMask propertyMask_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.datastore.v1.PropertyMask,
+            com.google.datastore.v1.PropertyMask.Builder,
+            com.google.datastore.v1.PropertyMaskOrBuilder>
+        propertyMaskBuilder_;
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     *
+     * @return Whether the propertyMask field is set.
+     */
+    public boolean hasPropertyMask() {
+      return ((bitField0_ & 0x00000040) != 0);
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     *
+     * @return The propertyMask.
+     */
+    public com.google.datastore.v1.PropertyMask getPropertyMask() {
+      if (propertyMaskBuilder_ == null) {
+        return propertyMask_ == null
+            ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+            : propertyMask_;
+      } else {
+        return propertyMaskBuilder_.getMessage();
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     */
+    public Builder setPropertyMask(com.google.datastore.v1.PropertyMask value) {
+      if (propertyMaskBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        propertyMask_ = value;
+      } else {
+        propertyMaskBuilder_.setMessage(value);
+      }
+      bitField0_ |= 0x00000040;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     */
+    public Builder setPropertyMask(com.google.datastore.v1.PropertyMask.Builder builderForValue) {
+      if (propertyMaskBuilder_ == null) {
+        propertyMask_ = builderForValue.build();
+      } else {
+        propertyMaskBuilder_.setMessage(builderForValue.build());
+      }
+      bitField0_ |= 0x00000040;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     */
+    public Builder mergePropertyMask(com.google.datastore.v1.PropertyMask value) {
+      if (propertyMaskBuilder_ == null) {
+        if (((bitField0_ & 0x00000040) != 0)
+            && propertyMask_ != null
+            && propertyMask_ != com.google.datastore.v1.PropertyMask.getDefaultInstance()) {
+          getPropertyMaskBuilder().mergeFrom(value);
+        } else {
+          propertyMask_ = value;
+        }
+      } else {
+        propertyMaskBuilder_.mergeFrom(value);
+      }
+      if (propertyMask_ != null) {
+        bitField0_ |= 0x00000040;
+        onChanged();
+      }
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     */
+    public Builder clearPropertyMask() {
+      bitField0_ = (bitField0_ & ~0x00000040);
+      propertyMask_ = null;
+      if (propertyMaskBuilder_ != null) {
+        propertyMaskBuilder_.dispose();
+        propertyMaskBuilder_ = null;
+      }
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     */
+    public com.google.datastore.v1.PropertyMask.Builder getPropertyMaskBuilder() {
+      bitField0_ |= 0x00000040;
+      onChanged();
+      return getPropertyMaskFieldBuilder().getBuilder();
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     */
+    public com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder() {
+      if (propertyMaskBuilder_ != null) {
+        return propertyMaskBuilder_.getMessageOrBuilder();
+      } else {
+        return propertyMask_ == null
+            ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+            : propertyMask_;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to write in this mutation.
+     * None of the properties in the mask may have a reserved name, except for
+     * `__key__`.
+     * This field is ignored for `delete`.
+     *
+     * If the entity already exists, only properties referenced in the mask are
+     * updated, others are left untouched.
+     * Properties referenced in the mask but not in the entity are deleted.
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.datastore.v1.PropertyMask,
+            com.google.datastore.v1.PropertyMask.Builder,
+            com.google.datastore.v1.PropertyMaskOrBuilder>
+        getPropertyMaskFieldBuilder() {
+      if (propertyMaskBuilder_ == null) {
+        propertyMaskBuilder_ =
+            new com.google.protobuf.SingleFieldBuilderV3<
+                com.google.datastore.v1.PropertyMask,
+                com.google.datastore.v1.PropertyMask.Builder,
+                com.google.datastore.v1.PropertyMaskOrBuilder>(
+                getPropertyMask(), getParentForChildren(), isClean());
+        propertyMask_ = null;
+      }
+      return propertyMaskBuilder_;
+    }
+
     @java.lang.Override
     public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
       return super.setUnknownFields(unknownFields);
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/MutationOrBuilder.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/MutationOrBuilder.java
index e833ed94..e051e600 100644
--- a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/MutationOrBuilder.java
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/MutationOrBuilder.java
@@ -246,6 +246,62 @@ public interface MutationOrBuilder
    */
   com.google.protobuf.TimestampOrBuilder getUpdateTimeOrBuilder();
 
+  /**
+   *
+   *
+   * <pre>
+   * The properties to write in this mutation.
+   * None of the properties in the mask may have a reserved name, except for
+   * `__key__`.
+   * This field is ignored for `delete`.
+   *
+   * If the entity already exists, only properties referenced in the mask are
+   * updated, others are left untouched.
+   * Properties referenced in the mask but not in the entity are deleted.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+   *
+   * @return Whether the propertyMask field is set.
+   */
+  boolean hasPropertyMask();
+  /**
+   *
+   *
+   * <pre>
+   * The properties to write in this mutation.
+   * None of the properties in the mask may have a reserved name, except for
+   * `__key__`.
+   * This field is ignored for `delete`.
+   *
+   * If the entity already exists, only properties referenced in the mask are
+   * updated, others are left untouched.
+   * Properties referenced in the mask but not in the entity are deleted.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+   *
+   * @return The propertyMask.
+   */
+  com.google.datastore.v1.PropertyMask getPropertyMask();
+  /**
+   *
+   *
+   * <pre>
+   * The properties to write in this mutation.
+   * None of the properties in the mask may have a reserved name, except for
+   * `__key__`.
+   * This field is ignored for `delete`.
+   *
+   * If the entity already exists, only properties referenced in the mask are
+   * updated, others are left untouched.
+   * Properties referenced in the mask but not in the entity are deleted.
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 9;</code>
+   */
+  com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder();
+
   com.google.datastore.v1.Mutation.OperationCase getOperationCase();
 
   com.google.datastore.v1.Mutation.ConflictDetectionStrategyCase getConflictDetectionStrategyCase();
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/PropertyMask.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/PropertyMask.java
new file mode 100644
index 00000000..2d9c2caf
--- /dev/null
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/PropertyMask.java
@@ -0,0 +1,848 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/datastore/v1/datastore.proto
+
+// Protobuf Java Version: 3.25.3
+package com.google.datastore.v1;
+
+/**
+ *
+ *
+ * <pre>
+ * The set of arbitrarily nested property paths used to restrict an operation to
+ * only a subset of properties in an entity.
+ * </pre>
+ *
+ * Protobuf type {@code google.datastore.v1.PropertyMask}
+ */
+public final class PropertyMask extends com.google.protobuf.GeneratedMessageV3
+    implements
+    // @@protoc_insertion_point(message_implements:google.datastore.v1.PropertyMask)
+    PropertyMaskOrBuilder {
+  private static final long serialVersionUID = 0L;
+  // Use PropertyMask.newBuilder() to construct.
+  private PropertyMask(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+
+  private PropertyMask() {
+    paths_ = com.google.protobuf.LazyStringArrayList.emptyList();
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(UnusedPrivateParameter unused) {
+    return new PropertyMask();
+  }
+
+  public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+    return com.google.datastore.v1.DatastoreProto
+        .internal_static_google_datastore_v1_PropertyMask_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.google.datastore.v1.DatastoreProto
+        .internal_static_google_datastore_v1_PropertyMask_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.google.datastore.v1.PropertyMask.class,
+            com.google.datastore.v1.PropertyMask.Builder.class);
+  }
+
+  public static final int PATHS_FIELD_NUMBER = 1;
+
+  @SuppressWarnings("serial")
+  private com.google.protobuf.LazyStringArrayList paths_ =
+      com.google.protobuf.LazyStringArrayList.emptyList();
+  /**
+   *
+   *
+   * <pre>
+   * The paths to the properties covered by this mask.
+   *
+   * A path is a list of property names separated by dots (`.`), for example
+   * `foo.bar` means the property `bar` inside the entity property `foo` inside
+   * the entity associated with this path.
+   *
+   * If a property name contains a dot `.` or a backslash `&#92;`, then that
+   * name must be escaped.
+   *
+   * A path must not be empty, and may not reference a value inside an
+   * [array value][google.datastore.v1.Value.array_value].
+   * </pre>
+   *
+   * <code>repeated string paths = 1;</code>
+   *
+   * @return A list containing the paths.
+   */
+  public com.google.protobuf.ProtocolStringList getPathsList() {
+    return paths_;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The paths to the properties covered by this mask.
+   *
+   * A path is a list of property names separated by dots (`.`), for example
+   * `foo.bar` means the property `bar` inside the entity property `foo` inside
+   * the entity associated with this path.
+   *
+   * If a property name contains a dot `.` or a backslash `&#92;`, then that
+   * name must be escaped.
+   *
+   * A path must not be empty, and may not reference a value inside an
+   * [array value][google.datastore.v1.Value.array_value].
+   * </pre>
+   *
+   * <code>repeated string paths = 1;</code>
+   *
+   * @return The count of paths.
+   */
+  public int getPathsCount() {
+    return paths_.size();
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The paths to the properties covered by this mask.
+   *
+   * A path is a list of property names separated by dots (`.`), for example
+   * `foo.bar` means the property `bar` inside the entity property `foo` inside
+   * the entity associated with this path.
+   *
+   * If a property name contains a dot `.` or a backslash `&#92;`, then that
+   * name must be escaped.
+   *
+   * A path must not be empty, and may not reference a value inside an
+   * [array value][google.datastore.v1.Value.array_value].
+   * </pre>
+   *
+   * <code>repeated string paths = 1;</code>
+   *
+   * @param index The index of the element to return.
+   * @return The paths at the given index.
+   */
+  public java.lang.String getPaths(int index) {
+    return paths_.get(index);
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The paths to the properties covered by this mask.
+   *
+   * A path is a list of property names separated by dots (`.`), for example
+   * `foo.bar` means the property `bar` inside the entity property `foo` inside
+   * the entity associated with this path.
+   *
+   * If a property name contains a dot `.` or a backslash `&#92;`, then that
+   * name must be escaped.
+   *
+   * A path must not be empty, and may not reference a value inside an
+   * [array value][google.datastore.v1.Value.array_value].
+   * </pre>
+   *
+   * <code>repeated string paths = 1;</code>
+   *
+   * @param index The index of the value to return.
+   * @return The bytes of the paths at the given index.
+   */
+  public com.google.protobuf.ByteString getPathsBytes(int index) {
+    return paths_.getByteString(index);
+  }
+
+  private byte memoizedIsInitialized = -1;
+
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+    for (int i = 0; i < paths_.size(); i++) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 1, paths_.getRaw(i));
+    }
+    getUnknownFields().writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    {
+      int dataSize = 0;
+      for (int i = 0; i < paths_.size(); i++) {
+        dataSize += computeStringSizeNoTag(paths_.getRaw(i));
+      }
+      size += dataSize;
+      size += 1 * getPathsList().size();
+    }
+    size += getUnknownFields().getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (!(obj instanceof com.google.datastore.v1.PropertyMask)) {
+      return super.equals(obj);
+    }
+    com.google.datastore.v1.PropertyMask other = (com.google.datastore.v1.PropertyMask) obj;
+
+    if (!getPathsList().equals(other.getPathsList())) return false;
+    if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    if (getPathsCount() > 0) {
+      hash = (37 * hash) + PATHS_FIELD_NUMBER;
+      hash = (53 * hash) + getPathsList().hashCode();
+    }
+    hash = (29 * hash) + getUnknownFields().hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(
+      java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(
+      byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(
+      java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+        PARSER, input, extensionRegistry);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseDelimitedFrom(
+      java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(
+        PARSER, input, extensionRegistry);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(
+      com.google.protobuf.CodedInputStream input) throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+  }
+
+  public static com.google.datastore.v1.PropertyMask parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+        PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() {
+    return newBuilder();
+  }
+
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+
+  public static Builder newBuilder(com.google.datastore.v1.PropertyMask prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The set of arbitrarily nested property paths used to restrict an operation to
+   * only a subset of properties in an entity.
+   * </pre>
+   *
+   * Protobuf type {@code google.datastore.v1.PropertyMask}
+   */
+  public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder<Builder>
+      implements
+      // @@protoc_insertion_point(builder_implements:google.datastore.v1.PropertyMask)
+      com.google.datastore.v1.PropertyMaskOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+      return com.google.datastore.v1.DatastoreProto
+          .internal_static_google_datastore_v1_PropertyMask_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.google.datastore.v1.DatastoreProto
+          .internal_static_google_datastore_v1_PropertyMask_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.google.datastore.v1.PropertyMask.class,
+              com.google.datastore.v1.PropertyMask.Builder.class);
+    }
+
+    // Construct using com.google.datastore.v1.PropertyMask.newBuilder()
+    private Builder() {}
+
+    private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+    }
+
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      bitField0_ = 0;
+      paths_ = com.google.protobuf.LazyStringArrayList.emptyList();
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+      return com.google.datastore.v1.DatastoreProto
+          .internal_static_google_datastore_v1_PropertyMask_descriptor;
+    }
+
+    @java.lang.Override
+    public com.google.datastore.v1.PropertyMask getDefaultInstanceForType() {
+      return com.google.datastore.v1.PropertyMask.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.google.datastore.v1.PropertyMask build() {
+      com.google.datastore.v1.PropertyMask result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.google.datastore.v1.PropertyMask buildPartial() {
+      com.google.datastore.v1.PropertyMask result = new com.google.datastore.v1.PropertyMask(this);
+      if (bitField0_ != 0) {
+        buildPartial0(result);
+      }
+      onBuilt();
+      return result;
+    }
+
+    private void buildPartial0(com.google.datastore.v1.PropertyMask result) {
+      int from_bitField0_ = bitField0_;
+      if (((from_bitField0_ & 0x00000001) != 0)) {
+        paths_.makeImmutable();
+        result.paths_ = paths_;
+      }
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+      return super.setField(field, value);
+    }
+
+    @java.lang.Override
+    public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+
+    @java.lang.Override
+    public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field, int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.google.datastore.v1.PropertyMask) {
+        return mergeFrom((com.google.datastore.v1.PropertyMask) other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.google.datastore.v1.PropertyMask other) {
+      if (other == com.google.datastore.v1.PropertyMask.getDefaultInstance()) return this;
+      if (!other.paths_.isEmpty()) {
+        if (paths_.isEmpty()) {
+          paths_ = other.paths_;
+          bitField0_ |= 0x00000001;
+        } else {
+          ensurePathsIsMutable();
+          paths_.addAll(other.paths_);
+        }
+        onChanged();
+      }
+      this.mergeUnknownFields(other.getUnknownFields());
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 10:
+              {
+                java.lang.String s = input.readStringRequireUtf8();
+                ensurePathsIsMutable();
+                paths_.add(s);
+                break;
+              } // case 10
+            default:
+              {
+                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+                  done = true; // was an endgroup tag
+                }
+                break;
+              } // default:
+          } // switch (tag)
+        } // while (!done)
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.unwrapIOException();
+      } finally {
+        onChanged();
+      } // finally
+      return this;
+    }
+
+    private int bitField0_;
+
+    private com.google.protobuf.LazyStringArrayList paths_ =
+        com.google.protobuf.LazyStringArrayList.emptyList();
+
+    private void ensurePathsIsMutable() {
+      if (!paths_.isModifiable()) {
+        paths_ = new com.google.protobuf.LazyStringArrayList(paths_);
+      }
+      bitField0_ |= 0x00000001;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @return A list containing the paths.
+     */
+    public com.google.protobuf.ProtocolStringList getPathsList() {
+      paths_.makeImmutable();
+      return paths_;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @return The count of paths.
+     */
+    public int getPathsCount() {
+      return paths_.size();
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @param index The index of the element to return.
+     * @return The paths at the given index.
+     */
+    public java.lang.String getPaths(int index) {
+      return paths_.get(index);
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @param index The index of the value to return.
+     * @return The bytes of the paths at the given index.
+     */
+    public com.google.protobuf.ByteString getPathsBytes(int index) {
+      return paths_.getByteString(index);
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @param index The index to set the value at.
+     * @param value The paths to set.
+     * @return This builder for chaining.
+     */
+    public Builder setPaths(int index, java.lang.String value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      ensurePathsIsMutable();
+      paths_.set(index, value);
+      bitField0_ |= 0x00000001;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @param value The paths to add.
+     * @return This builder for chaining.
+     */
+    public Builder addPaths(java.lang.String value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      ensurePathsIsMutable();
+      paths_.add(value);
+      bitField0_ |= 0x00000001;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @param values The paths to add.
+     * @return This builder for chaining.
+     */
+    public Builder addAllPaths(java.lang.Iterable<java.lang.String> values) {
+      ensurePathsIsMutable();
+      com.google.protobuf.AbstractMessageLite.Builder.addAll(values, paths_);
+      bitField0_ |= 0x00000001;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @return This builder for chaining.
+     */
+    public Builder clearPaths() {
+      paths_ = com.google.protobuf.LazyStringArrayList.emptyList();
+      bitField0_ = (bitField0_ & ~0x00000001);
+      ;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The paths to the properties covered by this mask.
+     *
+     * A path is a list of property names separated by dots (`.`), for example
+     * `foo.bar` means the property `bar` inside the entity property `foo` inside
+     * the entity associated with this path.
+     *
+     * If a property name contains a dot `.` or a backslash `&#92;`, then that
+     * name must be escaped.
+     *
+     * A path must not be empty, and may not reference a value inside an
+     * [array value][google.datastore.v1.Value.array_value].
+     * </pre>
+     *
+     * <code>repeated string paths = 1;</code>
+     *
+     * @param value The bytes of the paths to add.
+     * @return This builder for chaining.
+     */
+    public Builder addPathsBytes(com.google.protobuf.ByteString value) {
+      if (value == null) {
+        throw new NullPointerException();
+      }
+      checkByteStringIsUtf8(value);
+      ensurePathsIsMutable();
+      paths_.add(value);
+      bitField0_ |= 0x00000001;
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+    // @@protoc_insertion_point(builder_scope:google.datastore.v1.PropertyMask)
+  }
+
+  // @@protoc_insertion_point(class_scope:google.datastore.v1.PropertyMask)
+  private static final com.google.datastore.v1.PropertyMask DEFAULT_INSTANCE;
+
+  static {
+    DEFAULT_INSTANCE = new com.google.datastore.v1.PropertyMask();
+  }
+
+  public static com.google.datastore.v1.PropertyMask getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<PropertyMask> PARSER =
+      new com.google.protobuf.AbstractParser<PropertyMask>() {
+        @java.lang.Override
+        public PropertyMask parsePartialFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+          Builder builder = newBuilder();
+          try {
+            builder.mergeFrom(input, extensionRegistry);
+          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+            throw e.setUnfinishedMessage(builder.buildPartial());
+          } catch (com.google.protobuf.UninitializedMessageException e) {
+            throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+          } catch (java.io.IOException e) {
+            throw new com.google.protobuf.InvalidProtocolBufferException(e)
+                .setUnfinishedMessage(builder.buildPartial());
+          }
+          return builder.buildPartial();
+        }
+      };
+
+  public static com.google.protobuf.Parser<PropertyMask> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<PropertyMask> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.datastore.v1.PropertyMask getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+}
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/PropertyMaskOrBuilder.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/PropertyMaskOrBuilder.java
new file mode 100644
index 00000000..8711d5d8
--- /dev/null
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/PropertyMaskOrBuilder.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/datastore/v1/datastore.proto
+
+// Protobuf Java Version: 3.25.3
+package com.google.datastore.v1;
+
+public interface PropertyMaskOrBuilder
+    extends
+    // @@protoc_insertion_point(interface_extends:google.datastore.v1.PropertyMask)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   *
+   *
+   * <pre>
+   * The paths to the properties covered by this mask.
+   *
+   * A path is a list of property names separated by dots (`.`), for example
+   * `foo.bar` means the property `bar` inside the entity property `foo` inside
+   * the entity associated with this path.
+   *
+   * If a property name contains a dot `.` or a backslash `&#92;`, then that
+   * name must be escaped.
+   *
+   * A path must not be empty, and may not reference a value inside an
+   * [array value][google.datastore.v1.Value.array_value].
+   * </pre>
+   *
+   * <code>repeated string paths = 1;</code>
+   *
+   * @return A list containing the paths.
+   */
+  java.util.List<java.lang.String> getPathsList();
+  /**
+   *
+   *
+   * <pre>
+   * The paths to the properties covered by this mask.
+   *
+   * A path is a list of property names separated by dots (`.`), for example
+   * `foo.bar` means the property `bar` inside the entity property `foo` inside
+   * the entity associated with this path.
+   *
+   * If a property name contains a dot `.` or a backslash `&#92;`, then that
+   * name must be escaped.
+   *
+   * A path must not be empty, and may not reference a value inside an
+   * [array value][google.datastore.v1.Value.array_value].
+   * </pre>
+   *
+   * <code>repeated string paths = 1;</code>
+   *
+   * @return The count of paths.
+   */
+  int getPathsCount();
+  /**
+   *
+   *
+   * <pre>
+   * The paths to the properties covered by this mask.
+   *
+   * A path is a list of property names separated by dots (`.`), for example
+   * `foo.bar` means the property `bar` inside the entity property `foo` inside
+   * the entity associated with this path.
+   *
+   * If a property name contains a dot `.` or a backslash `&#92;`, then that
+   * name must be escaped.
+   *
+   * A path must not be empty, and may not reference a value inside an
+   * [array value][google.datastore.v1.Value.array_value].
+   * </pre>
+   *
+   * <code>repeated string paths = 1;</code>
+   *
+   * @param index The index of the element to return.
+   * @return The paths at the given index.
+   */
+  java.lang.String getPaths(int index);
+  /**
+   *
+   *
+   * <pre>
+   * The paths to the properties covered by this mask.
+   *
+   * A path is a list of property names separated by dots (`.`), for example
+   * `foo.bar` means the property `bar` inside the entity property `foo` inside
+   * the entity associated with this path.
+   *
+   * If a property name contains a dot `.` or a backslash `&#92;`, then that
+   * name must be escaped.
+   *
+   * A path must not be empty, and may not reference a value inside an
+   * [array value][google.datastore.v1.Value.array_value].
+   * </pre>
+   *
+   * <code>repeated string paths = 1;</code>
+   *
+   * @param index The index of the value to return.
+   * @return The bytes of the paths at the given index.
+   */
+  com.google.protobuf.ByteString getPathsBytes(int index);
+}
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequest.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequest.java
index 4420d577..55691cea 100644
--- a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequest.java
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequest.java
@@ -433,6 +433,68 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
     return com.google.datastore.v1.GqlQuery.getDefaultInstance();
   }
 
+  public static final int PROPERTY_MASK_FIELD_NUMBER = 10;
+  private com.google.datastore.v1.PropertyMask propertyMask_;
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return.
+   * This field must not be set for a projection query.
+   *
+   * See
+   * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+   *
+   * @return Whether the propertyMask field is set.
+   */
+  @java.lang.Override
+  public boolean hasPropertyMask() {
+    return ((bitField0_ & 0x00000004) != 0);
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return.
+   * This field must not be set for a projection query.
+   *
+   * See
+   * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+   *
+   * @return The propertyMask.
+   */
+  @java.lang.Override
+  public com.google.datastore.v1.PropertyMask getPropertyMask() {
+    return propertyMask_ == null
+        ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+        : propertyMask_;
+  }
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return.
+   * This field must not be set for a projection query.
+   *
+   * See
+   * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+   */
+  @java.lang.Override
+  public com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder() {
+    return propertyMask_ == null
+        ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+        : propertyMask_;
+  }
+
   public static final int EXPLAIN_OPTIONS_FIELD_NUMBER = 12;
   private com.google.datastore.v1.ExplainOptions explainOptions_;
   /**
@@ -451,7 +513,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
    */
   @java.lang.Override
   public boolean hasExplainOptions() {
-    return ((bitField0_ & 0x00000004) != 0);
+    return ((bitField0_ & 0x00000008) != 0);
   }
   /**
    *
@@ -525,6 +587,9 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       com.google.protobuf.GeneratedMessageV3.writeString(output, 9, databaseId_);
     }
     if (((bitField0_ & 0x00000004) != 0)) {
+      output.writeMessage(10, getPropertyMask());
+    }
+    if (((bitField0_ & 0x00000008) != 0)) {
       output.writeMessage(12, getExplainOptions());
     }
     getUnknownFields().writeTo(output);
@@ -559,6 +624,9 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       size += com.google.protobuf.GeneratedMessageV3.computeStringSize(9, databaseId_);
     }
     if (((bitField0_ & 0x00000004) != 0)) {
+      size += com.google.protobuf.CodedOutputStream.computeMessageSize(10, getPropertyMask());
+    }
+    if (((bitField0_ & 0x00000008) != 0)) {
       size += com.google.protobuf.CodedOutputStream.computeMessageSize(12, getExplainOptions());
     }
     size += getUnknownFields().getSerializedSize();
@@ -586,6 +654,10 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
     if (hasReadOptions()) {
       if (!getReadOptions().equals(other.getReadOptions())) return false;
     }
+    if (hasPropertyMask() != other.hasPropertyMask()) return false;
+    if (hasPropertyMask()) {
+      if (!getPropertyMask().equals(other.getPropertyMask())) return false;
+    }
     if (hasExplainOptions() != other.hasExplainOptions()) return false;
     if (hasExplainOptions()) {
       if (!getExplainOptions().equals(other.getExplainOptions())) return false;
@@ -624,6 +696,10 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       hash = (37 * hash) + READ_OPTIONS_FIELD_NUMBER;
       hash = (53 * hash) + getReadOptions().hashCode();
     }
+    if (hasPropertyMask()) {
+      hash = (37 * hash) + PROPERTY_MASK_FIELD_NUMBER;
+      hash = (53 * hash) + getPropertyMask().hashCode();
+    }
     if (hasExplainOptions()) {
       hash = (37 * hash) + EXPLAIN_OPTIONS_FIELD_NUMBER;
       hash = (53 * hash) + getExplainOptions().hashCode();
@@ -782,6 +858,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {
         getPartitionIdFieldBuilder();
         getReadOptionsFieldBuilder();
+        getPropertyMaskFieldBuilder();
         getExplainOptionsFieldBuilder();
       }
     }
@@ -808,6 +885,11 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       if (gqlQueryBuilder_ != null) {
         gqlQueryBuilder_.clear();
       }
+      propertyMask_ = null;
+      if (propertyMaskBuilder_ != null) {
+        propertyMaskBuilder_.dispose();
+        propertyMaskBuilder_ = null;
+      }
       explainOptions_ = null;
       if (explainOptionsBuilder_ != null) {
         explainOptionsBuilder_.dispose();
@@ -870,9 +952,14 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
         to_bitField0_ |= 0x00000002;
       }
       if (((from_bitField0_ & 0x00000040) != 0)) {
+        result.propertyMask_ =
+            propertyMaskBuilder_ == null ? propertyMask_ : propertyMaskBuilder_.build();
+        to_bitField0_ |= 0x00000004;
+      }
+      if (((from_bitField0_ & 0x00000080) != 0)) {
         result.explainOptions_ =
             explainOptionsBuilder_ == null ? explainOptions_ : explainOptionsBuilder_.build();
-        to_bitField0_ |= 0x00000004;
+        to_bitField0_ |= 0x00000008;
       }
       result.bitField0_ |= to_bitField0_;
     }
@@ -949,6 +1036,9 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       if (other.hasReadOptions()) {
         mergeReadOptions(other.getReadOptions());
       }
+      if (other.hasPropertyMask()) {
+        mergePropertyMask(other.getPropertyMask());
+      }
       if (other.hasExplainOptions()) {
         mergeExplainOptions(other.getExplainOptions());
       }
@@ -1030,10 +1120,16 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
                 bitField0_ |= 0x00000002;
                 break;
               } // case 74
+            case 82:
+              {
+                input.readMessage(getPropertyMaskFieldBuilder().getBuilder(), extensionRegistry);
+                bitField0_ |= 0x00000040;
+                break;
+              } // case 82
             case 98:
               {
                 input.readMessage(getExplainOptionsFieldBuilder().getBuilder(), extensionRegistry);
-                bitField0_ |= 0x00000040;
+                bitField0_ |= 0x00000080;
                 break;
               } // case 98
             default:
@@ -2104,6 +2200,227 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       return gqlQueryBuilder_;
     }
 
+    private com.google.datastore.v1.PropertyMask propertyMask_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.datastore.v1.PropertyMask,
+            com.google.datastore.v1.PropertyMask.Builder,
+            com.google.datastore.v1.PropertyMaskOrBuilder>
+        propertyMaskBuilder_;
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     *
+     * @return Whether the propertyMask field is set.
+     */
+    public boolean hasPropertyMask() {
+      return ((bitField0_ & 0x00000040) != 0);
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     *
+     * @return The propertyMask.
+     */
+    public com.google.datastore.v1.PropertyMask getPropertyMask() {
+      if (propertyMaskBuilder_ == null) {
+        return propertyMask_ == null
+            ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+            : propertyMask_;
+      } else {
+        return propertyMaskBuilder_.getMessage();
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     */
+    public Builder setPropertyMask(com.google.datastore.v1.PropertyMask value) {
+      if (propertyMaskBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        propertyMask_ = value;
+      } else {
+        propertyMaskBuilder_.setMessage(value);
+      }
+      bitField0_ |= 0x00000040;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     */
+    public Builder setPropertyMask(com.google.datastore.v1.PropertyMask.Builder builderForValue) {
+      if (propertyMaskBuilder_ == null) {
+        propertyMask_ = builderForValue.build();
+      } else {
+        propertyMaskBuilder_.setMessage(builderForValue.build());
+      }
+      bitField0_ |= 0x00000040;
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     */
+    public Builder mergePropertyMask(com.google.datastore.v1.PropertyMask value) {
+      if (propertyMaskBuilder_ == null) {
+        if (((bitField0_ & 0x00000040) != 0)
+            && propertyMask_ != null
+            && propertyMask_ != com.google.datastore.v1.PropertyMask.getDefaultInstance()) {
+          getPropertyMaskBuilder().mergeFrom(value);
+        } else {
+          propertyMask_ = value;
+        }
+      } else {
+        propertyMaskBuilder_.mergeFrom(value);
+      }
+      if (propertyMask_ != null) {
+        bitField0_ |= 0x00000040;
+        onChanged();
+      }
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     */
+    public Builder clearPropertyMask() {
+      bitField0_ = (bitField0_ & ~0x00000040);
+      propertyMask_ = null;
+      if (propertyMaskBuilder_ != null) {
+        propertyMaskBuilder_.dispose();
+        propertyMaskBuilder_ = null;
+      }
+      onChanged();
+      return this;
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     */
+    public com.google.datastore.v1.PropertyMask.Builder getPropertyMaskBuilder() {
+      bitField0_ |= 0x00000040;
+      onChanged();
+      return getPropertyMaskFieldBuilder().getBuilder();
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     */
+    public com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder() {
+      if (propertyMaskBuilder_ != null) {
+        return propertyMaskBuilder_.getMessageOrBuilder();
+      } else {
+        return propertyMask_ == null
+            ? com.google.datastore.v1.PropertyMask.getDefaultInstance()
+            : propertyMask_;
+      }
+    }
+    /**
+     *
+     *
+     * <pre>
+     * The properties to return.
+     * This field must not be set for a projection query.
+     *
+     * See
+     * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+     * </pre>
+     *
+     * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+            com.google.datastore.v1.PropertyMask,
+            com.google.datastore.v1.PropertyMask.Builder,
+            com.google.datastore.v1.PropertyMaskOrBuilder>
+        getPropertyMaskFieldBuilder() {
+      if (propertyMaskBuilder_ == null) {
+        propertyMaskBuilder_ =
+            new com.google.protobuf.SingleFieldBuilderV3<
+                com.google.datastore.v1.PropertyMask,
+                com.google.datastore.v1.PropertyMask.Builder,
+                com.google.datastore.v1.PropertyMaskOrBuilder>(
+                getPropertyMask(), getParentForChildren(), isClean());
+        propertyMask_ = null;
+      }
+      return propertyMaskBuilder_;
+    }
+
     private com.google.datastore.v1.ExplainOptions explainOptions_;
     private com.google.protobuf.SingleFieldBuilderV3<
             com.google.datastore.v1.ExplainOptions,
@@ -2125,7 +2442,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
      * @return Whether the explainOptions field is set.
      */
     public boolean hasExplainOptions() {
-      return ((bitField0_ & 0x00000040) != 0);
+      return ((bitField0_ & 0x00000080) != 0);
     }
     /**
      *
@@ -2171,7 +2488,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       } else {
         explainOptionsBuilder_.setMessage(value);
       }
-      bitField0_ |= 0x00000040;
+      bitField0_ |= 0x00000080;
       onChanged();
       return this;
     }
@@ -2194,7 +2511,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
       } else {
         explainOptionsBuilder_.setMessage(builderForValue.build());
       }
-      bitField0_ |= 0x00000040;
+      bitField0_ |= 0x00000080;
       onChanged();
       return this;
     }
@@ -2212,7 +2529,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
      */
     public Builder mergeExplainOptions(com.google.datastore.v1.ExplainOptions value) {
       if (explainOptionsBuilder_ == null) {
-        if (((bitField0_ & 0x00000040) != 0)
+        if (((bitField0_ & 0x00000080) != 0)
             && explainOptions_ != null
             && explainOptions_ != com.google.datastore.v1.ExplainOptions.getDefaultInstance()) {
           getExplainOptionsBuilder().mergeFrom(value);
@@ -2223,7 +2540,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
         explainOptionsBuilder_.mergeFrom(value);
       }
       if (explainOptions_ != null) {
-        bitField0_ |= 0x00000040;
+        bitField0_ |= 0x00000080;
         onChanged();
       }
       return this;
@@ -2241,7 +2558,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
      * </code>
      */
     public Builder clearExplainOptions() {
-      bitField0_ = (bitField0_ & ~0x00000040);
+      bitField0_ = (bitField0_ & ~0x00000080);
       explainOptions_ = null;
       if (explainOptionsBuilder_ != null) {
         explainOptionsBuilder_.dispose();
@@ -2263,7 +2580,7 @@ public final class RunQueryRequest extends com.google.protobuf.GeneratedMessageV
      * </code>
      */
     public com.google.datastore.v1.ExplainOptions.Builder getExplainOptionsBuilder() {
-      bitField0_ |= 0x00000040;
+      bitField0_ |= 0x00000080;
       onChanged();
       return getExplainOptionsFieldBuilder().getBuilder();
     }
diff --git a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequestOrBuilder.java b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequestOrBuilder.java
index 9e7a6f0b..55218e0e 100644
--- a/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequestOrBuilder.java
+++ b/proto-google-cloud-datastore-v1/src/main/java/com/google/datastore/v1/RunQueryRequestOrBuilder.java
@@ -229,6 +229,53 @@ public interface RunQueryRequestOrBuilder
    */
   com.google.datastore.v1.GqlQueryOrBuilder getGqlQueryOrBuilder();
 
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return.
+   * This field must not be set for a projection query.
+   *
+   * See
+   * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+   *
+   * @return Whether the propertyMask field is set.
+   */
+  boolean hasPropertyMask();
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return.
+   * This field must not be set for a projection query.
+   *
+   * See
+   * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+   *
+   * @return The propertyMask.
+   */
+  com.google.datastore.v1.PropertyMask getPropertyMask();
+  /**
+   *
+   *
+   * <pre>
+   * The properties to return.
+   * This field must not be set for a projection query.
+   *
+   * See
+   * [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+   * </pre>
+   *
+   * <code>.google.datastore.v1.PropertyMask property_mask = 10;</code>
+   */
+  com.google.datastore.v1.PropertyMaskOrBuilder getPropertyMaskOrBuilder();
+
   /**
    *
    *
diff --git a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/aggregation_result.proto b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/aggregation_result.proto
index 91c52171..262b61fa 100644
--- a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/aggregation_result.proto
+++ b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/aggregation_result.proto
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// Copyright 2024 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/datastore.proto b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/datastore.proto
index 1a3fbdd1..92b5038e 100644
--- a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/datastore.proto
+++ b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/datastore.proto
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// Copyright 2024 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -173,6 +173,14 @@ message LookupRequest {
 
   // Required. Keys of entities to look up.
   repeated Key keys = 3 [(google.api.field_behavior) = REQUIRED];
+
+  // The properties to return. Defaults to returning all properties.
+  //
+  // If this field is set and an entity has a property not referenced in the
+  // mask, it will be absent from [LookupResponse.found.entity.properties][].
+  //
+  // The entity's key is always returned.
+  PropertyMask property_mask = 5;
 }
 
 // The response for [Datastore.Lookup][google.datastore.v1.Datastore.Lookup].
@@ -234,6 +242,13 @@ message RunQueryRequest {
     GqlQuery gql_query = 7;
   }
 
+  // The properties to return.
+  // This field must not be set for a projection query.
+  //
+  // See
+  // [LookupRequest.property_mask][google.datastore.v1.LookupRequest.property_mask].
+  PropertyMask property_mask = 10;
+
   // Optional. Explain options for the query. If set, additional query
   // statistics will be returned. If not, only query results will be returned.
   ExplainOptions explain_options = 12 [(google.api.field_behavior) = OPTIONAL];
@@ -526,6 +541,16 @@ message Mutation {
     // mutation conflicts.
     google.protobuf.Timestamp update_time = 11;
   }
+
+  // The properties to write in this mutation.
+  // None of the properties in the mask may have a reserved name, except for
+  // `__key__`.
+  // This field is ignored for `delete`.
+  //
+  // If the entity already exists, only properties referenced in the mask are
+  // updated, others are left untouched.
+  // Properties referenced in the mask but not in the entity are deleted.
+  PropertyMask property_mask = 9;
 }
 
 // The result of applying a mutation.
@@ -555,6 +580,23 @@ message MutationResult {
   bool conflict_detected = 5;
 }
 
+// The set of arbitrarily nested property paths used to restrict an operation to
+// only a subset of properties in an entity.
+message PropertyMask {
+  // The paths to the properties covered by this mask.
+  //
+  // A path is a list of property names separated by dots (`.`), for example
+  // `foo.bar` means the property `bar` inside the entity property `foo` inside
+  // the entity associated with this path.
+  //
+  // If a property name contains a dot `.` or a backslash `\`, then that
+  // name must be escaped.
+  //
+  // A path must not be empty, and may not reference a value inside an
+  // [array value][google.datastore.v1.Value.array_value].
+  repeated string paths = 1;
+}
+
 // The options shared by read requests.
 message ReadOptions {
   // The possible values for read consistencies.
diff --git a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/entity.proto b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/entity.proto
index d80dd909..ef442934 100644
--- a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/entity.proto
+++ b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/entity.proto
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// Copyright 2024 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query.proto b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query.proto
index d1f0f8d0..81386d47 100644
--- a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query.proto
+++ b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query.proto
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// Copyright 2024 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
diff --git a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query_profile.proto b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query_profile.proto
index 01c9fc25..f38681c6 100644
--- a/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query_profile.proto
+++ b/proto-google-cloud-datastore-v1/src/main/proto/google/datastore/v1/query_profile.proto
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// Copyright 2024 Google LLC
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index d3672238..4b268da0 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -29,7 +29,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-datastore</artifactId>
-      <version>2.19.1</version>
+      <version>2.20.0</version>
     </dependency>
     <!-- [END datastore_install_without_bom] -->
 
@@ -53,7 +53,7 @@
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
-        <version>3.5.0</version>
+        <version>3.6.0</version>
         <executions>
           <execution>
             <id>add-snippets-source</id>
diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml
index d1d30028..00999bee 100644
--- a/samples/native-image-sample/pom.xml
+++ b/samples/native-image-sample/pom.xml
@@ -28,7 +28,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.38.0</version>
+        <version>26.39.0</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
@@ -86,7 +86,7 @@
         <dependency>
           <groupId>org.graalvm.buildtools</groupId>
           <artifactId>junit-platform-native</artifactId>
-          <version>0.10.1</version>
+          <version>0.10.2</version>
           <scope>test</scope>
         </dependency>
       </dependencies>
@@ -107,7 +107,7 @@
           <plugin>
             <groupId>org.graalvm.buildtools</groupId>
             <artifactId>native-maven-plugin</artifactId>
-            <version>0.10.1</version>
+            <version>0.10.2</version>
             <extensions>true</extensions>
             <configuration>
               <mainClass>com.example.datastore.NativeImageDatastoreSample</mainClass>
diff --git a/samples/pom.xml b/samples/pom.xml
index a2480116..745443d3 100644
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -39,7 +39,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-deploy-plugin</artifactId>
-        <version>3.1.1</version>
+        <version>3.1.2</version>
         <configuration>
           <skip>true</skip>
         </configuration>
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index c701d89f..c9b591ef 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
     <dependency>
       <groupId>com.google.cloud</groupId>
       <artifactId>google-cloud-datastore</artifactId>
-      <version>2.19.2-grpc-experimental-1-SNAPSHOT</version>
+      <version>2.20.0-grpc-experimental-1-SNAPSHOT</version>
     </dependency>
     <!-- {x-version-update-end} -->
 
@@ -52,7 +52,7 @@
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
-        <version>3.5.0</version>
+        <version>3.6.0</version>
         <executions>
           <execution>
             <id>add-snippets-source</id>
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 82f0945a..6ac0109e 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -30,7 +30,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>libraries-bom</artifactId>
-        <version>26.38.0</version>
+        <version>26.39.0</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
diff --git a/versions.txt b/versions.txt
index fe383277..a718ea0c 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,10 +1,10 @@
 # Format:
 # module:released-version:current-version
 
-google-cloud-datastore:2.19.1:2.19.2-grpc-experimental-1-SNAPSHOT
-google-cloud-datastore-bom:2.19.1:2.19.2-grpc-experimental-1-SNAPSHOT
-proto-google-cloud-datastore-v1:0.110.1:0.110.2-grpc-experimental-1-SNAPSHOT
-datastore-v1-proto-client:2.19.1:2.19.2-grpc-experimental-1-SNAPSHOT
-proto-google-cloud-datastore-admin-v1:2.19.1:2.19.2-grpc-experimental-1-SNAPSHOT
-grpc-google-cloud-datastore-admin-v1:2.19.1:2.19.2-grpc-experimental-1-SNAPSHOT
-grpc-google-cloud-datastore-v1:2.19.1:2.19.2-grpc-experimental-1-SNAPSHOT
+google-cloud-datastore:2.20.0:2.20.0-grpc-experimental-1-SNAPSHOT
+google-cloud-datastore-bom:2.20.0:2.20.0-grpc-experimental-1-SNAPSHOT
+proto-google-cloud-datastore-v1:0.111.0:0.111.0-grpc-experimental-1-SNAPSHOT
+datastore-v1-proto-client:2.20.0:2.20.0-grpc-experimental-1-SNAPSHOT
+proto-google-cloud-datastore-admin-v1:2.20.0:2.20.0-grpc-experimental-1-SNAPSHOT
+grpc-google-cloud-datastore-admin-v1:2.20.0:2.20.0-grpc-experimental-1-SNAPSHOT
+grpc-google-cloud-datastore-v1:2.20.0:2.20.0-grpc-experimental-1-SNAPSHOT


Test patch:
diff --git a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/IncompleteKeyTest.java b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/IncompleteKeyTest.java
index a1f8956b..75549e5e 100644
--- a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/IncompleteKeyTest.java
+++ b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/IncompleteKeyTest.java
@@ -25,15 +25,17 @@ import org.junit.Test;
 
 public class IncompleteKeyTest {
 
-  private static IncompleteKey pk1, pk2, pk4;
-  private static Key parent1;
+  private static IncompleteKey pk1, pk2, pk4, pk5;
+  private static Key parent1, parent2;
 
   @Before
   public void setUp() {
     pk1 = IncompleteKey.newBuilder("ds", "kind1").build();
     parent1 = Key.newBuilder("ds", "kind2", 10).setNamespace("ns").build();
+    parent2 = Key.newBuilder("ds", "kind2", 10, "test-db").setNamespace("ns").build();
     pk2 = IncompleteKey.newBuilder(parent1, "kind3").build();
     pk4 = IncompleteKey.newBuilderWithDatabaseId("ds", "kind3", "test-db").build();
+    pk5 = IncompleteKey.newBuilder(parent2, "kind4").build();
   }
 
   @Test
@@ -59,12 +61,18 @@ public class IncompleteKeyTest {
     assertEquals("test-db", pk4.getDatabaseId());
     assertEquals("kind3", pk4.getKind());
     assertTrue(pk4.getAncestors().isEmpty());
+
+    assertEquals("ds", pk5.getProjectId());
+    assertEquals("test-db", pk5.getDatabaseId());
+    assertEquals("kind4", pk5.getKind());
+    assertEquals(parent2.getPath(), pk5.getAncestors());
   }
 
   @Test
   public void testParent() {
     assertNull(pk1.getParent());
     assertEquals(parent1, pk2.getParent());
+    assertEquals(parent2, pk5.getParent());
     Key parent2 = Key.newBuilder("ds", "kind3", "name").setNamespace("ns").build();
     IncompleteKey pk3 = IncompleteKey.newBuilder(parent2, "kind3").build();
     assertEquals(parent2, pk3.getParent());
diff --git a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/AbstractITDatastoreTest.java b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/AbstractITDatastoreTest.java
index c25e87f2..66822bd9 100644
--- a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/AbstractITDatastoreTest.java
+++ b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/AbstractITDatastoreTest.java
@@ -139,6 +139,7 @@ public abstract class AbstractITDatastoreTest {
   private static Key KEY3;
   private static Key KEY4;
   private static Key KEY5;
+  private static Key KEY6;
   private static FullEntity<IncompleteKey> PARTIAL_ENTITY1;
   private static FullEntity<IncompleteKey> PARTIAL_ENTITY2;
   private static FullEntity<IncompleteKey> PARTIAL_ENTITY3;
@@ -196,6 +197,10 @@ public abstract class AbstractITDatastoreTest {
     KEY3 = Key.newBuilder(KEY2).setName("bla").setNamespace(NAMESPACE).build();
     KEY4 = Key.newBuilder(KEY2).setName("newName1").setNamespace(NAMESPACE).build();
     KEY5 = Key.newBuilder(KEY2).setName("newName2").setNamespace(NAMESPACE).build();
+    KEY6 =
+        Key.newBuilder(options.getProjectId(), KIND2, 100, options.getDatabaseId())
+            .setNamespace(NAMESPACE)
+            .build();
 
     LIST_VALUE2 = ListValue.of(Collections.singletonList(KeyValue.of(KEY1)));
 
@@ -1754,6 +1759,21 @@ public abstract class AbstractITDatastoreTest {
     assertFalse(entity.contains("bla"));
   }
 
+  @Test
+  public void testIncompleteKey() {
+    Key parentKey = null;
+    try {
+      IncompleteKey incompleteKey = IncompleteKey.newBuilder(KEY6, KIND1).build();
+      parentKey = incompleteKey.getParent();
+      Entity entity = Entity.newBuilder(parentKey).set("name", "val").build();
+      datastore.put(entity);
+      Entity retrievedEntity = datastore.get(parentKey);
+      assertThat(retrievedEntity).isEqualTo(entity);
+    } finally {
+      datastore.delete(parentKey);
+    }
+  }
+
   @Test
   public void testGetWithReadTime() throws InterruptedException {
     Key key =