{*
 *******************************************************************************
 *
 *  Copyright 2026 RIEGL Laser Measurement Systems
 *
 *  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
 *
 *      http://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.
 *
 *  SPDX-License-Identifier: Apache-2.0
 *
 *******************************************************************************
 *}
{*!
 *******************************************************************************
 *
 * \file    riegl.rdb.pointcloud.transactions.pas
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Manage point cloud transactions (Pascal wrapper code)
 * \version 2015-10-14/AW: Initial version
 * \version 2020-07-03/AW: Changelog management interface added (#3614)
 * \version 2021-11-17/AW: New function to discard transaction data (#3843)
 * \version 2021-11-18/AW: New function to estimate transaction size (#3837)
 *
 *******************************************************************************
 *}

unit riegl.rdb.pointcloud.transactions;

{******************************************************************************}
{***} INTERFACE {**************************************************************}
{******************************************************************************}

//---< INCLUDES >---------------------------------------------------------------

uses
  Types,
  riegl.rdb,
  riegl.rdb.context,
  riegl.rdb.progress,
  riegl.rdb.pointcloud.transaction;

//---< RDB LIBRARY IMPORTS >----------------------------------------------------

type
  TRDBPointcloudTransactionIDList = array of TRDBPointcloudTransactionID;

//______________________________________________________________________________
{*!
 * \brief Create new transaction
 *
 * Whenever you are going to modify the point cloud, you must create a
 * transaction by using this function. Without a transaction, any function
 * that modifies the point cloud will fail (i.e. it throws an exception).
 *
 * A transaction automatically locks the database so that other users
 * can query data but can __NOT__ add or modify data. Please note that
 * only __one transaction at a time__ is allowed. If there is already
 * a transaction pending, this function will raise an exception (see
 * Error::TransactionPending).
 *
 * To finish a transaction either call commit() or rollback().
 *
 * \note Parameters 'title' and 'agent' are required - i.e. creating
 *       a new transaction will fail if empty strings are provided.
 *       All other parameters are optional.
 *
 * \note Parameters 'comments' and 'settings' serve the user and client
 *       application for information, e.g. to repeat processing steps
 *       later on. They have no influence on the transaction itself. The
 *       client application is free to store information in any format
 *       that is string-compatible (e.g. plain text, INI, XML, JSON).
 *
 * \note The total size of the 'title', 'agent', 'comments' and 'settings'
 *       strings must not exceed 500 MB (bytes, not characters).
 *}
function rdb_pointcloud_transaction_begin(
  Context    : TRDBContextHandle;                //!< [in] library context
  Pointcloud : TRDBPointcloudHandle;             //!< [in] point cloud handle
  Title      : TRDBString;                       //!< [in] short description, e.g. "Import"
  Agent      : TRDBString;                       //!< [in] software name, e.g. "rdbimport v1.0"
  Comments   : TRDBString = nil;                 //!< [in] e.g. process details for humans
  Settings   : TRDBString = nil;                 //!< [in] e.g. process settings for software
  ID         : PRDBPointcloudTransactionID = nil //!< [out] optional transaction ID output
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Commit current transaction
 *
 * This function commits the current transaction. All changes made by the
 * transaction become visible to others.
 *}
function rdb_pointcloud_transaction_commit(
  Context    : TRDBContextHandle;   //!< [in] library context
  Pointcloud : TRDBPointcloudHandle //!< [in] point cloud handle
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Commit current transaction
 *
 * This function acts like rdb_pointcloud_transaction_commit() and additionally
 * accepts a pointer to a callback function to provide progress information.
 *}
function rdb_pointcloud_transaction_commit_with_progress(
  Context    : TRDBContextHandle;    //!< [in] library context
  Pointcloud : TRDBPointcloudHandle; //!< [in] point cloud handle
  Progress   : TRDBProgress;         //!< [in] commit progress callback function
  Userdata   : Pointer               //!< [in] progress callback function user data
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Commit current transaction
 *
 * This function acts like rdb_pointcloud_transaction_commit_with_progress()
 * and additionally accepts a transaction signature method and encryption key.
 *}
function rdb_pointcloud_transaction_commit_with_signature(
  Context    : TRDBContextHandle;    //!< [in] library context
  Pointcloud : TRDBPointcloudHandle; //!< [in] point cloud handle
  Progress   : TRDBProgress;         //!< [in] commit progress callback function
  Userdata   : Pointer;              //!< [in] progress callback function user data
  Signature  : TRDBUInt32;           //!< [in] signature method (0: none, 1: default)
  KeySize    : TRDBUInt32;           //!< [in] signature encryption key size (at least 32 byte)
  KeyData    : Pointer               //!< [in] signature encryption key buffer
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Abort current transaction
 *
 * This function rolls back the current transaction and causes all changes
 * made by the transaction to be discarded.
 *}
function rdb_pointcloud_transaction_rollback(
  Context    : TRDBContextHandle;   //!< [in] library context
  Pointcloud : TRDBPointcloudHandle //!< [in] point cloud handle
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Get list of transactions
 *
 * The database keeps a log (journal) of all transactions. This function
 * returns a list of identifiers (IDs) for all recorded transactions.
 *}
function rdb_pointcloud_transaction_list(
  Context    : TRDBContextHandle;          //!< [in] library context
  Pointcloud : TRDBPointcloudHandle;       //!< [in] point cloud handle
  var Count  : TRDBUInt32;                 //!< [out] number of transactions
  List       : PRDBPointcloudTransactionID //!< [out] list of transaction IDs
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief ID of current transaction
 *
 * This function returns the ID of the current transaction. Usually this
 * is the transaction that was committed at last. However, if restore() is
 * used to return to a previous database state, the current transaction is
 * the restored transaction.
 *
 * \note This function does not return the ID of a pending transaction.
 *}
function rdb_pointcloud_transaction_current(
  Context     : TRDBContextHandle;          //!< [in] library context
  Pointcloud  : TRDBPointcloudHandle;       //!< [in] point cloud handle
  var Current : TRDBPointcloudTransactionID //!< [out] ID of current transaction
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Check if transaction is pending
 *
 * This function checks whether there is a pending transaction that was
 * started by __this__ database instance. This function does __not__ check
 * whether a transaction was started by a different database instance of
 * the current or different thread or process.
 *}
function rdb_pointcloud_transaction_pending(
  Context     : TRDBContextHandle;          //!< [in] library context
  Pointcloud  : TRDBPointcloudHandle;       //!< [in] point cloud handle
  var Pending : TRDBUInt32                  //!< [out] 0: false, 1: true
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Query transaction details
 *}
function rdb_pointcloud_transaction_details(
  Context     : TRDBContextHandle;              //!< [in] library context
  Pointcloud  : TRDBPointcloudHandle;           //!< [in] point cloud handle
  ID          : TRDBPointcloudTransactionID;    //!< [in] transaction identifier
  Transaction : TRDBPointcloudTransactionHandle //!< [out] transaction details
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Restore database state
 *
 * This function restores the database state that was current at the end
 * of the transaction. Those transactions that were created after the
 * restored transaction remain valid until a new transaction is created.
 * This offers some simple undo/redo functionality.
 *}
function rdb_pointcloud_transaction_restore(
  Context     : TRDBContextHandle;          //!< [in] library context
  Pointcloud  : TRDBPointcloudHandle;       //!< [in] point cloud handle
  ID          : TRDBPointcloudTransactionID //!< [in] transaction identifier
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Discard transaction data
 *
 * This function deletes the given transaction(s). Please note that this
 * operation only removes the transaction(s) from the database history and
 * releases the related data blocks in the database file so that they can
 * be re-used by subsequent transactions. However the database file size
 * will not decrease unless you call vacuum().
 *
 * \note The first (database creation) and the current transaction
 *       (last committed or restored) can not be deleted.
 *
 * \see riegl::rdb::pointcloud::Management::finalize()
 * \see riegl::rdb::pointcloud::Management::vacuum()
 *}
function rdb_pointcloud_transaction_discard(
  Context    : TRDBContextHandle;          //!< [in] library context
  Pointcloud : TRDBPointcloudHandle;       //!< [in] point cloud handle
  Count      : TRDBUInt32;                 //!< [in] number of transactions
  List       : PRDBPointcloudTransactionID //!< [in] list of transaction IDs
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//______________________________________________________________________________
{*!
 * \brief Estimate database size
 *
 * This function returns the size (in bytes) of all data of the specified
 * transactions, which is approximately the file size of a database that
 * contains only these transactions (and no gaps).
 *
 * \note Data blocks may be shared among multiple transactions and size()
 *       returns the total size of the union of all used data blocks. That
 *       is why size(1) + size(2) is not necessarily equal to size(1, 2).
 *
 * \see riegl::rdb::pointcloud::Transactions::discard()
 * \see riegl::rdb::pointcloud::Management::finalize()
 * \see riegl::rdb::pointcloud::Management::vacuum()
 *}
function rdb_pointcloud_transaction_size(
  Context    : TRDBContextHandle;           //!< [in] library context
  Pointcloud : TRDBPointcloudHandle;        //!< [in] point cloud handle
  Count      : TRDBUInt32;                  //!< [in] number of transactions
  List       : PRDBPointcloudTransactionID; //!< [in] list of transaction IDs
  var Result : TRDBUInt64                   //!< [out] estimated data size [byte]
) : TRDBResult; cdecl; external riegl.rdb.RDB_LIBRARY_FILENAME;

//---< CLASS TRDBPointcloudTransactions >---------------------------------------
{*!
 * \brief Manage point cloud transactions
 *
 * Modifying the point cloud database means to execute a transaction.
 *
 * This class allows to start new transactions (see BeginTransaction())
 * and to browse past (already executed) transactions.
 *
 * \see riegl::rdb::Pointcloud::transaction()
 *}
type
  TRDBPointcloudTransactions = class(System.TObject)
  public
    {*!
     * \brief Constructor
     * \note  You cannot create new TRDBPointcloudTransactions objects directly,
     *        use riegl::rdb::Pointcloud::transaction() instead.
     *}
    constructor Create(Parent : System.TObject); reintroduce;
    destructor  Destroy(); override;

    {*!
     * \brief Create new transaction
     *
     * Whenever you are going to modify the point cloud, you must create a
     * transaction by using this function. Without a transaction, any function
     * that modifies the point cloud will fail (i.e. it throws an exception).
     *
     * A transaction automatically locks the database so that other users
     * can query data but can __NOT__ add or modify data. Please note that
     * only __one transaction at a time__ is allowed. If there is already
     * a transaction pending, this function will raise an exception (see
     * Error::TransactionPending).
     *
     * To finish a transaction either call commit() or rollback().
     *
     * \note Parameters 'title' and 'agent' are required - i.e. creating
     *       a new transaction will fail if empty strings are provided.
     *       All other parameters are optional.
     *
     * \note Parameters 'comments' and 'settings' serve the user and client
     *       application for information, e.g. to repeat processing steps
     *       later on. They have no influence on the transaction itself. The
     *       client application is free to store information in any format
     *       that is string-compatible (e.g. plain text, INI, XML, JSON).
     *
     * \note The total size of the 'title', 'agent', 'comments' and 'settings'
     *       strings must not exceed 500 MB (bytes, not characters).
     *}
    function BeginTransaction(
        const Title    : System.String;      //!< [in] short description, e.g. "Import"
        const Agent    : System.String;      //!< [in] software name, e.g. "rdbimport v1.0"
        const Comments : System.String = ''; //!< [in] e.g. process details for humans
        const Settings : System.String = ''  //!< [in] e.g. process settings for software
    ) : TRDBPointcloudTransactionID;

    {*!
     * \brief Commit current transaction
     *
     * This function commits the current transaction. All changes made by the
     * transaction become visible to others.
     *}
    procedure Commit(
      Progress  : TRDBProgressFunction = nil; //!< [in] commit progress callback function
      Userdata  : Pointer              = nil; //!< [in] progress callback function user data
      Signature : TRDBUInt32           = 0;   //!< [in] signature method (0: none, 1: default)
      KeySize   : TRDBUInt32           = 0;   //!< [in] signature encryption key size (at least 32 byte)
      KeyData   : Pointer              = nil  //!< [in] signature encryption key buffer
    ); overload;
    procedure Commit(
      Progress  : TRDBProgressMethod; //!< [in] commit progress callback method
      Signature : TRDBUInt32 = 0;     //!< [in] signature method (0: none, 1: default)
      KeySize   : TRDBUInt32 = 0;     //!< [in] signature encryption key size (at least 32 byte)
      KeyData   : Pointer    = nil    //!< [in] signature encryption key buffer
    ); overload;
    procedure Commit(
      Signature : TRDBUInt32; //!< [in] signature method (0: none, 1: default)
      KeySize   : TRDBUInt32; //!< [in] signature encryption key size (at least 32 byte)
      KeyData   : Pointer     //!< [in] signature encryption key buffer
    ); overload;

    {*!
     * \brief Abort current transaction
     *
     * This function rolls back the current transaction and causes all changes
     * made by the transaction to be discarded.
     *}
    procedure Rollback();

    {*!
     * \brief Get list of transactions
     *
     * The database keeps a log (journal) of all transactions. This function
     * returns a list of identifiers (IDs) for all recorded transactions.
     *}
    function List() : TRDBPointcloudTransactionIDList;

    {*!
     * \brief ID of current transaction
     *
     * This function returns the ID of the current transaction. Usually this
     * is the transaction that was committed at last. However, if restore() is
     * used to return to a previous database state, the current transaction is
     * the restored transaction.
     *
     * \note This function does not return the ID of a pending transaction.
     *}
    function Current() : TRDBPointcloudTransactionID;

    {*!
     * \brief Check if transaction is pending
     *
     * This function checks whether there is a pending transaction that was
     * started by __this__ database instance. This function does __not__ check
     * whether a transaction was started by a different database instance of
     * the current or different thread or process.
     *}
    function Pending() : Boolean;

    {*!
     * \brief Query transaction details
     *}
    function Details(
      const Transaction : TRDBPointcloudTransactionID //!< [in] transaction identifier
    ) : TRDBPointcloudTransaction;

    {*!
     * \brief Restore database state
     *
     * This function restores the database state that was current at the end
     * of the transaction. Those transactions that were created after the
     * restored transaction remain valid until a new transaction is created.
     * This offers some simple undo/redo functionality.
     *}
    procedure Restore(
      const Transaction : TRDBPointcloudTransactionID //!< [in] transaction identifier
    );

    {*!
     * \brief Discard transaction data
     *
     * This function deletes the given transaction(s). Please note that this
     * operation only removes the transaction(s) from the database history and
     * releases the related data blocks in the database file so that they can
     * be re-used by subsequent transactions. However the database file size
     * will not decrease unless you call vacuum().
     *
     * \note The first (database creation) and the current transaction
     *       (last committed or restored) can not be deleted.
     *
     * \see riegl::rdb::pointcloud::Management::finalize()
     * \see riegl::rdb::pointcloud::Management::vacuum()
     *}
    procedure Discard(
      const Transaction : TRDBPointcloudTransactionID //!< [in] transaction identifier
    ); overload;
    procedure Discard(
      const Transactions : TRDBPointcloudTransactionIDList//!< [in] transaction identifiers
    ); overload;

    {*!
     * \brief Estimate database size
     *
     * This function returns the size (in bytes) of all data of the specified
     * transactions, which is approximately the file size of a database that
     * contains only these transactions (and no gaps).
     *
     * \note Data blocks may be shared among multiple transactions and size()
     *       returns the total size of the union of all used data blocks. That
     *       is why size(1) + size(2) is not necessarily equal to size(1, 2).
     *
     * \see riegl::rdb::pointcloud::Transactions::discard()
     * \see riegl::rdb::pointcloud::Management::finalize()
     * \see riegl::rdb::pointcloud::Management::vacuum()
     *}
    function Size(
      const Transaction : TRDBPointcloudTransactionID //!< [in] transaction identifier
    ) : TRDBUInt64; overload;
    function Size(
      const Transactions : TRDBPointcloudTransactionIDList//!< [in] transaction identifiers
    ) : TRDBUInt64; overload;

  private
    FContext    : TRDBContext;
    FPointcloud : TRDBPointcloudHandle;
  end;

{******************************************************************************}
{***} IMPLEMENTATION {*********************************************************}
{******************************************************************************}

//---< INCLUDES >---------------------------------------------------------------

uses
  SysUtils,
  riegl.rdb.pointcloud;

//---< LOCAL TOOLS >------------------------------------------------------------

type
  TFunctionProgressWrapper = class(TObject)
  public
    ProgressUserdata : Pointer;
    ProgressFunction : TRDBProgressFunction;
    ProgressMethod   : TRDBProgressMethod;

    constructor Create; reintroduce;
    procedure Execute(Progress : TRDBUInt8);
  end;

  constructor TFunctionProgressWrapper.Create;
  begin
    inherited Create;
    ProgressUserdata := nil;
    ProgressFunction := nil;
    ProgressMethod   := nil;
  end;

  procedure TFunctionProgressWrapper.Execute(Progress : TRDBUInt8);
  begin
    if Assigned(ProgressFunction) then
    begin
      ProgressFunction(Progress, ProgressUserdata);
    end
    else if Assigned(ProgressMethod) then
    begin
      ProgressMethod(Progress);
    end;
  end;

  procedure FunctionProgressWrapperExecute(Progress : TRDBUInt8; Userdata : Pointer) cdecl;
  begin
    try
      TFunctionProgressWrapper(Userdata).Execute(Progress);
    except
      on E:Exception do; // ignore all errors
    end;
  end;

//---< TRDBPointcloudTransactions::PUBLIC >-------------------------------------

constructor TRDBPointcloudTransactions.Create(Parent : System.TObject);
begin
  inherited Create;
  FContext    := (Parent as TRDBPointcloud).Context;
  FPointcloud := (Parent as TRDBPointcloud).Pointcloud;
end; // Create()

destructor TRDBPointcloudTransactions.Destroy();
begin
  inherited;
end; // Destroy()

function TRDBPointcloudTransactions.BeginTransaction(
  const Title    : System.String;
  const Agent    : System.String;
  const Comments : System.String;
  const Settings : System.String
) : TRDBPointcloudTransactionID;
begin
  FContext.Check(rdb_pointcloud_transaction_begin(
    FContext.Handle,       FPointcloud,
    TRDBString(AnsiToUtf8(Title)),    TRDBString(AnsiToUtf8(Agent)),
    TRDBString(AnsiToUtf8(Comments)), TRDBString(AnsiToUtf8(Settings)),
    @Result
  ));
end; // BeginTransaction()

procedure TRDBPointcloudTransactions.Commit(
  Progress  : TRDBProgressFunction;
  Userdata  : Pointer;
  Signature : TRDBUInt32;
  KeySize   : TRDBUInt32;
  KeyData   : Pointer
);
var
  Wrapper : TFunctionProgressWrapper;
begin
  Wrapper := TFunctionProgressWrapper.Create;
  try
    Wrapper.ProgressUserdata := Userdata;
    Wrapper.ProgressFunction := Progress;
    FContext.Check(rdb_pointcloud_transaction_commit_with_signature(
      FContext.Handle, FPointcloud, FunctionProgressWrapperExecute, Wrapper,
      Signature, KeySize, KeyData
    ));
  finally
    FreeAndNil(Wrapper);
  end; // try..finally
end; // Commit()

procedure TRDBPointcloudTransactions.Commit(
  Progress  : TRDBProgressMethod;
  Signature : TRDBUInt32;
  KeySize   : TRDBUInt32;
  KeyData   : Pointer
);
var
  Wrapper : TFunctionProgressWrapper;
begin
  Wrapper := TFunctionProgressWrapper.Create;
  try
    Wrapper.ProgressMethod := Progress;
    FContext.Check(rdb_pointcloud_transaction_commit_with_signature(
      FContext.Handle, FPointcloud, FunctionProgressWrapperExecute, Wrapper,
      Signature, KeySize, KeyData
    ));
  finally
    FreeAndNil(Wrapper);
  end; // try..finally
end; // Commit()

procedure TRDBPointcloudTransactions.Commit(
  Signature : TRDBUInt32;
  KeySize   : TRDBUInt32;
  KeyData   : Pointer
);
begin
  Commit(nil, nil, Signature, KeySize, KeyData);
end;

procedure TRDBPointcloudTransactions.Rollback();
begin
  FContext.Check(rdb_pointcloud_transaction_rollback(
    FContext.Handle, FPointcloud
  ));
end; // Rollback()

function TRDBPointcloudTransactions.List() : TRDBPointcloudTransactionIDList;
var
  Count : TRDBUInt32;
begin
  Count := 0;
  FContext.Check(rdb_pointcloud_transaction_list(
    FContext.Handle, FPointcloud, Count, nil // = query count
  ));
  SetLength(Result, Count);
  FContext.Check(rdb_pointcloud_transaction_list(
    FContext.Handle, FPointcloud, Count, @Result[0]
  ));
end; // List()

function TRDBPointcloudTransactions.Current() : TRDBPointcloudTransactionID;
begin
  FContext.Check(rdb_pointcloud_transaction_current(
    FContext.Handle, FPointcloud, Result
  ));
end; // Current()

function TRDBPointcloudTransactions.Pending() : Boolean;
var
  Pending : TRDBUInt32;
begin
  Pending := 0;
  FContext.Check(rdb_pointcloud_transaction_pending(
    FContext.Handle, FPointcloud, Pending
  ));
  Result := (Pending <> 0);
end; // Pending()

function TRDBPointcloudTransactions.Details(
  const Transaction : TRDBPointcloudTransactionID
) : TRDBPointcloudTransaction;
var
  Return : TRDBPointcloudTransaction;
  Handle : TRDBPointcloudTransactionHandle;
begin
  Return := nil; // no result yet
  FContext.Check(rdb_pointcloud_transaction_new(FContext.Handle, Handle));
  try
    FContext.Check(rdb_pointcloud_transaction_details(
      FContext.Handle, FPointcloud, Transaction, Handle
    ));
    Return := TRDBPointcloudTransaction.Create(FContext);
    PointcloudTransactionRead(FContext, Handle, Return);
    Result := Return; Return := nil; // success
  finally
    FContext.Check(rdb_pointcloud_transaction_delete(FContext.Handle, Handle));
    FreeAndNil(Return); // in case of troubles...
  end; // try..finally
end; // Details()

procedure TRDBPointcloudTransactions.Restore(
  const Transaction : TRDBPointcloudTransactionID
);
begin
  FContext.Check(rdb_pointcloud_transaction_restore(
    FContext.Handle, FPointcloud, Transaction
  ));
end; // Restore()

procedure TRDBPointcloudTransactions.Discard(
  const Transaction : TRDBPointcloudTransactionID
);
begin
  FContext.Check(rdb_pointcloud_transaction_discard(
    FContext.Handle, FPointcloud, 1, @Transaction
  ));
end; // Discard()

procedure TRDBPointcloudTransactions.Discard(
  const Transactions : TRDBPointcloudTransactionIDList
);
begin
  FContext.Check(rdb_pointcloud_transaction_discard(
    FContext.Handle, FPointcloud, Length(Transactions), @Transactions[0]
  ));
end; // Discard()

function TRDBPointcloudTransactions.Size(
  const Transaction : TRDBPointcloudTransactionID
) : TRDBUInt64;
begin
  Result := 0;
  FContext.Check(rdb_pointcloud_transaction_size(
    FContext.Handle, FPointcloud, 1, @Transaction, Result
  ));
end; // Size()

function TRDBPointcloudTransactions.Size(
  const Transactions : TRDBPointcloudTransactionIDList
) : TRDBUInt64;
begin
  Result := 0;
  FContext.Check(rdb_pointcloud_transaction_size(
    FContext.Handle, FPointcloud, Length(Transactions), @Transactions[0], Result
  ));
end; // Size()

end.
