Step 6: View the revision history for a document - Amazon Quantum Ledger Database (Amazon QLDB)

Step 6: View the revision history for a document

After modifying registration data for a vehicle in the previous step, you can query the history of all its registered owners and any other updated fields. In this step, you query the revision history of a document in the VehicleRegistration table in your vehicle-registration ledger.

To view the revision history

  1. Review the following program (QueryHistory.java).

    2.x
    /* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial; import java.io.IOException; import java.time.Instant; import java.time.temporal.ChronoUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.amazon.ion.IonValue; import software.amazon.qldb.Result; import software.amazon.qldb.TransactionExecutor; import software.amazon.qldb.tutorial.model.SampleData; import software.amazon.qldb.tutorial.model.VehicleRegistration; /** * Query a table's history for a particular set of documents. * * This code expects that you have AWS credentials setup per: * http://docs.aws.amazon.com/java-sdk/latest/developer-guide/setup-credentials.html */ public final class QueryHistory { public static final Logger log = LoggerFactory.getLogger(QueryHistory.class); private static final int THREE_MONTHS = 90; private QueryHistory() { } /** * In this example, query the 'VehicleRegistration' history table to find all previous primary owners for a VIN. * * @param txn * The {@link TransactionExecutor} for lambda execute. * @param vin * VIN to find previous primary owners for. * @param query * The query to find previous primary owners. * @throws IllegalStateException if failed to convert document ID to an {@link IonValue}. */ public static void previousPrimaryOwners(final TransactionExecutor txn, final String vin, final String query) { try { final String docId = VehicleRegistration.getDocumentIdByVin(txn, vin); log.info("Querying the 'VehicleRegistration' table's history using VIN: {}...", vin); final Result result = txn.execute(query, Constants.MAPPER.writeValueAsIonValue(docId)); ScanTable.printDocuments(result); } catch (IOException ioe) { throw new IllegalStateException(ioe); } } public static void main(final String... args) { final String threeMonthsAgo = Instant.now().minus(THREE_MONTHS, ChronoUnit.DAYS).toString(); final String query = String.format("SELECT data.Owners.PrimaryOwner, metadata.version " + "FROM history(VehicleRegistration, `%s`) " + "AS h WHERE h.metadata.id = ?", threeMonthsAgo); ConnectToLedger.getDriver().execute(txn -> { final String vin = SampleData.VEHICLES.get(0).getVin(); previousPrimaryOwners(txn, vin, query); }); log.info("Successfully queried history."); } }
    1.x
    /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial; import com.amazon.ion.IonValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.qldb.QldbSession; import software.amazon.qldb.Result; import software.amazon.qldb.TransactionExecutor; import software.amazon.qldb.tutorial.model.SampleData; import software.amazon.qldb.tutorial.model.VehicleRegistration; import java.io.IOException; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Collections; import java.util.List; /** * Query a table's history for a particular set of documents. * * This code expects that you have AWS credentials setup per: * http://docs.aws.amazon.com/java-sdk/latest/developer-guide/setup-credentials.html */ public final class QueryHistory { public static final Logger log = LoggerFactory.getLogger(QueryHistory.class); private static final int THREE_MONTHS = 90; private QueryHistory() { } /** * In this example, query the 'VehicleRegistration' history table to find all previous primary owners for a VIN. * * @param txn * The {@link TransactionExecutor} for lambda execute. * @param vin * VIN to find previous primary owners for. * @param query * The query to find previous primary owners. * @throws IllegalStateException if failed to convert document ID to an {@link IonValue}. */ public static void previousPrimaryOwners(final TransactionExecutor txn, final String vin, final String query) { try { final String docId = VehicleRegistration.getDocumentIdByVin(txn, vin); final List<IonValue> parameters = Collections.singletonList(Constants.MAPPER.writeValueAsIonValue(docId)); log.info("Querying the 'VehicleRegistration' table's history using VIN: {}...", vin); final Result result = txn.execute(query, parameters); ScanTable.printDocuments(result); } catch (IOException ioe) { throw new IllegalStateException(ioe); } } public static void main(final String... args) { final String threeMonthsAgo = Instant.now().minus(THREE_MONTHS, ChronoUnit.DAYS).toString(); final String query = String.format("SELECT data.Owners.PrimaryOwner, metadata.version " + "FROM history(VehicleRegistration, `%s`) " + "AS h WHERE h.metadata.id = ?", threeMonthsAgo); ConnectToLedger.getDriver().execute(txn -> { final String vin = SampleData.VEHICLES.get(0).getVin(); previousPrimaryOwners(txn, vin, query); }, (retryAttempt) -> log.info("Retrying due to OCC conflict...")); log.info("Successfully queried history."); } }
    Note
    • You can view the revision history of a document by querying the built-in History function in the following syntax.

      SELECT * FROM history( table_name [, `start-time` [, `end-time` ] ] ) AS h [ WHERE h.metadata.id = 'id' ]
    • The start-time and end-time are both optional. They're Amazon Ion literal values that can be denoted with backticks (`...`). To learn more, see Querying Ion with PartiQL.

    • As a best practice, qualify a history query with both a date range (start-time and end-time) and a document ID (metadata.id). QLDB processes SELECT queries in transactions, which are subject to a transaction timeout limit.

      QLDB history is indexed by document ID, and you can't create additional history indexes at this time. History queries that include a start time and end time gain the benefit of date range qualification.

  2. Compile and run the QueryHistory.java program to query the revision history of the VehicleRegistration document with VIN 1N4AL11D75C109151.

To cryptographically verify a document revision in the vehicle-registration ledger, proceed to Step 7: Verify a document in a ledger.