Historical Access
Historical Access: the engine that answers HistoryRead and HistoryUpdate, the store interface behind it, the SQLite store that implements one, and the annotations property.
ua::history::HistoryEngine
class
Storage-agnostic Historical Access semantics (OPC 10000-11 section 6.4 / section 6.8).
The engine implements the normative read/update behaviour - half-open windowing, returnBounds with Bad_BoundNotFound placeholders, forward/reverse direction, the numValuesPerNode cap with continuation points, single-instant reads, ReadModified, Insert/Replace/Update status fan-out, Delete, modification-record creation - over an abstract HistoryStore. It performs no I/O and owns no threads, so it is unit-tested directly against an in-memory store. The NamespaceHistoryDelegate (see history_delegate.h) wraps the engine with a strand + worker thread and a HistoryStore instance.
All methods are pure functions of (store, item): they are invoked one item at a time from the delegate's worker, after the SDK service layer has already performed request-level validation.
Member types
ua::NamespaceHistoryDelegate::ReadRawItem ReadRawItem
Request item for a ReadRaw / ReadModified operation (re-exported from the delegate seam so callers can spell these types as HistoryEngine::ReadRawItem).
ua::NamespaceHistoryDelegate::ReadRawItemResult ReadRawItemResult
Per-node result of a ReadRaw / ReadModified operation.
ua::NamespaceHistoryDelegate::Cursor Cursor
Continuation cursor carried between paginated raw reads.
ua::NamespaceHistoryDelegate::ReadAtTimeItem ReadAtTimeItem
Request item for a ReadAtTime operation.
ua::NamespaceHistoryDelegate::ReadAtTimeItemResult ReadAtTimeItemResult
Per-node result of a ReadAtTime operation.
ua::NamespaceHistoryDelegate::ReadEventsItem ReadEventsItem
Request item for a ReadEvents operation.
ua::NamespaceHistoryDelegate::ReadEventsItemResult ReadEventsItemResult
Per-node result of a ReadEvents operation.
ua::NamespaceHistoryDelegate::ReadAnnotationItem ReadAnnotationItem
Request item for a ReadAnnotationData operation.
ua::NamespaceHistoryDelegate::ReadAnnotationItemResult ReadAnnotationItemResult
Per-node result of a ReadAnnotationData operation.
ua::NamespaceHistoryDelegate::UpdateDataItem UpdateDataItem
Request item for an UpdateData (Insert / Replace / Update) operation.
ua::NamespaceHistoryDelegate::UpdateDataItemResult UpdateDataItemResult
Per-node result of an UpdateData operation.
ua::NamespaceHistoryDelegate::UpdateEventsItem UpdateEventsItem
Request item for an UpdateEvents operation.
ua::NamespaceHistoryDelegate::UpdateEventsItemResult UpdateEventsItemResult
Per-node result of an UpdateEvents operation.
ua::NamespaceHistoryDelegate::UpdateStructureDataItem UpdateStructureDataItem
Request item for an UpdateStructureData (Annotation) operation.
ua::NamespaceHistoryDelegate::UpdateStructureDataItemResult UpdateStructureDataItemResult
Per-node result of an UpdateStructureData operation.
ua::NamespaceHistoryDelegate::DeleteRawItem DeleteRawItem
Request item for a DeleteRaw operation.
ua::NamespaceHistoryDelegate::DeleteAtTimeItem DeleteAtTimeItem
Request item for a DeleteAtTime operation.
ua::NamespaceHistoryDelegate::DeleteEventsItem DeleteEventsItem
Request item for a DeleteEvents operation.
ua::NamespaceHistoryDelegate::DeleteItemResult DeleteItemResult
Per-node result shared by the delete operations.
Static functions
ReadRawItemResult read_raw(HistoryStore &store, ReadRawItem &item)
Read raw or modified values for one operation (OPC 10000-11 section 6.4.3).
store(HistoryStore &) - the history store queried for raw / modified values.item(ReadRawItem &) - the ReadRaw / ReadModified operation; carries the request window and flags, and its continuation cursor is updated in place when a page boundary is hit.
Returns: the per-node result: the values (or modification infos) and a continuation point when the numValuesPerNode cap is reached.
ReadAtTimeItemResult read_at_time(HistoryStore &store, const ReadAtTimeItem &item)
Read values at specific timestamps (OPC 10000-11 section 6.4.5).
store(HistoryStore &) - the history store queried for exact and surrounding raw values.item(const ReadAtTimeItem &) - the ReadAtTime operation; carries the requested timestamps and the use_simple_bounds flag.
Returns: the per-node result: one DataValue per requested timestamp, in request order.
ReadEventsItemResult read_events(HistoryStore &store, ReadEventsItem &item)
Read historical Events for one operation (OPC 10000-11 section 6.4.2).
store(HistoryStore &) - the history store queried for stored events.item(ReadEventsItem &) - the ReadEvents operation; carries the time window, the event filter select clauses, and its continuation cursor is updated in place when a page boundary is hit.
Returns: the per-node result: the projected event field lists, with a continuation point when the numValuesPerNode cap is reached.
std::string field_key(const ua::SimpleAttributeOperand &operand)
The storage field key for a select clause: its browse-path names joined with '/'.
operand(const ua::SimpleAttributeOperand &) - the select clause whose browse-path names form the key.
Returns: the storage field key: the operand's browse-path names joined with '/'.
UpdateDataItemResult update_data(HistoryStore &store, const UpdateDataItem &item, std::string_view userName={})
Insert / Replace / Update one operation's values (OPC 10000-11 section 6.8.2).
store(HistoryStore &) - the history store the values are written to.item(const UpdateDataItem &) - the UpdateData operation; carries the Insert / Replace / Update mode and the values.userName(std::string_view) - identity recorded in each generated modification record's ModificationInfo; empty when no user identity is available.
Returns: the per-value operation results.
DeleteItemResult delete_raw(HistoryStore &store, const DeleteRawItem &item, std::string_view userName={})
Delete raw values in the [startTime, endTime] interval (OPC 10000-11 section 6.8.5).
store(HistoryStore &) - the history store the values are deleted from.item(const DeleteRawItem &) - the DeleteRaw operation; carries the [startTime, endTime] interval to delete.userName(std::string_view) - identity stamped on the generated Delete modification records.
Returns: the operation result (always Good; an empty range is not an error).
DeleteItemResult delete_at_time(HistoryStore &store, const DeleteAtTimeItem &item, std::string_view userName={})
Delete raw values at specific timestamps (OPC 10000-11 section 6.8.5).
store(HistoryStore &) - the history store the values are deleted from.item(const DeleteAtTimeItem &) - the DeleteAtTime operation; carries the specific timestamps to delete.userName(std::string_view) - identity stamped on the generated Delete modification records.
Returns: the per-timestamp operation results (Good when a value was deleted, else Bad_NoEntryExists).
UpdateEventsItemResult update_events(HistoryStore &store, const UpdateEventsItem &item)
Insert / Replace / Update historical events (OPC 10000-11 section 6.8.4).
store(HistoryStore &) - the history store the events are written to.item(const UpdateEventsItem &) - the UpdateEvents operation; carries the Insert / Replace / Update mode, the event filter, and the event field values.
Returns: the per-event operation results.
DeleteItemResult delete_events(HistoryStore &store, const DeleteEventsItem &item)
Delete historical events by EventId (OPC 10000-11 section 6.8.5).
store(HistoryStore &) - the history store the events are deleted from.item(const DeleteEventsItem &) - the DeleteEvents operation; carries the EventIds to delete.
Returns: the per-EventId operation results.
ReadAnnotationItemResult read_annotations(HistoryStore &store, const ReadAnnotationItem &item)
Read history Annotations at specific timestamps (OPC 10000-11 section 6.4.6).
store(HistoryStore &) - the history store queried for stored Annotations.item(const ReadAnnotationItem &) - the ReadAnnotationData operation; carries the requested timestamps.
Returns: the per-node result: one DataValue per requested timestamp, in request order.
UpdateStructureDataItemResult update_structure_data(HistoryStore &store, const UpdateStructureDataItem &item)
Insert / Replace / Update / Remove structured history - Annotations (OPC 10000-11 section 6.8.3).
store(HistoryStore &) - the history store the Annotations are written to.item(const UpdateStructureDataItem &) - the UpdateStructureData operation; carries the Insert / Replace / Update / Remove mode and the Annotation entries.
Returns: the per-entry operation results.
ua::history::HistoryEngine::RawCursor
struct
Continuation state: the not-yet-returned tail of an already-ordered result plus the page size to slice on each resume.
Stored opaquely in the SDK's HistoryContinuationPoint. For a modified read remaining_infos runs parallel to remaining; for a raw read it is empty.
Public attributes
std::vector< ua::DataValue > remaining
std::vector< ua::ModificationInfo > remaining_infos
uint32_t page_size
ua::history::HistoryEngine::EventsCursor
struct
Continuation state for a paged event read: the not-yet-returned tail plus the page size.
Public attributes
std::vector< ua::HistoryEventFieldList > remaining
uint32_t page_size
ua::history::HistoryDelegate
class
Canonical reference NamespaceHistoryDelegate.
Owns a dedicated single-thread pool + strand so the (potentially blocking) store I/O never runs on the server's async threads, and drives the storage-agnostic HistoryEngine over an injected HistoryStore. The store is touched only from the worker strand, so it needs no internal synchronisation.
The store is injected (dependency injection) rather than hard-wired to SQLite so one delegate serves any backend, and so the engine can be exercised over an in-memory store in tests.
Functions
HistoryDelegate(std::unique_ptr< HistoryStore > store)
Take ownership of store, the storage backend the wrapped HistoryEngine drives.
store(std::unique_ptr< HistoryStore >) - the storage backend that the wrapped HistoryEngine reads from and writes to.
Capabilities capabilities() const noexcept override
Declares which history operations this delegate supports.
Returns: The supported-operation flags. The default returns all-false (no operations supported).
void read_raw_async(const ReadContext &context, std::vector< ReadRawItem > items, ReadRawCallback callback) noexcept override
Reads raw or modified value history for a batch of nodes.
context(const ReadContext &) - Read context, including cancellation flag and timestamp preference.items(std::vector< ReadRawItem >) - Per-node read requests, taken by value so the delegate may retain them.callback(ReadRawCallback) - Receives a BatchResult whose batch status reports whether the request was accepted, and each per-item Result holds the node's values or an ErrorDetail. This method never throws.
void read_at_time_async(const ReadContext &context, std::vector< ReadAtTimeItem > items, ReadAtTimeCallback callback) noexcept override
Reads values at specific timestamps for a batch of nodes.
context(const ReadContext &) - Read context, including cancellation flag and timestamp preference.items(std::vector< ReadAtTimeItem >) - Per-node read requests, taken by value so the delegate may retain them.callback(ReadAtTimeCallback) - Receives a BatchResult whose per-item Result holds the node's values or an ErrorDetail. This method never throws.
void read_events_async(const ReadContext &context, std::vector< ReadEventsItem > items, ReadEventsCallback callback) noexcept override
Reads historical events for a batch of event-source nodes.
context(const ReadContext &) - Read context, including cancellation flag and timestamp preference.items(std::vector< ReadEventsItem >) - Per-node read requests, taken by value so the delegate may retain them.callback(ReadEventsCallback) - Receives a BatchResult whose per-item Result holds the matching events or an ErrorDetail. This method never throws.
void read_annotations_async(const ReadContext &context, std::vector< ReadAnnotationItem > items, ReadAnnotationCallback callback) noexcept override
Reads history annotations for a batch of nodes.
context(const ReadContext &) - Read context, including cancellation flag and timestamp preference.items(std::vector< ReadAnnotationItem >) - Per-node read requests, taken by value so the delegate may retain them.callback(ReadAnnotationCallback) - Receives a BatchResult whose per-item Result holds the annotation values or an ErrorDetail. This method never throws.
void update_data_async(const UpdateContext &context, std::vector< UpdateDataItem > items, UpdateDataCallback callback) noexcept override
Inserts or replaces historical values for a batch of nodes.
context(const UpdateContext &) - Update context, including the cancellation flag.items(std::vector< UpdateDataItem >) - Per-node update requests, taken by value so the delegate may retain them.callback(UpdateDataCallback) - Receives a BatchResult whose per-item Result holds the per-value status codes or an ErrorDetail. This method never throws.
void update_events_async(const UpdateContext &context, std::vector< UpdateEventsItem > items, UpdateEventsCallback callback) noexcept override
Inserts, replaces, or updates historical events for a batch of event-source nodes.
context(const UpdateContext &) - Update context, including the cancellation flag.items(std::vector< UpdateEventsItem >) - Per-node update requests, taken by value so the delegate may retain them.callback(UpdateEventsCallback) - Receives a BatchResult whose per-item Result holds the per-event status codes or an ErrorDetail. This method never throws.
void update_structure_data_async(const UpdateContext &context, std::vector< UpdateStructureDataItem > items, UpdateStructureDataCallback callback) noexcept override
Inserts, replaces, updates, or removes structured history (e.g.
context(const UpdateContext &) - Update context, including the cancellation flag.items(std::vector< UpdateStructureDataItem >) - Per-node update requests, taken by value so the delegate may retain them.callback(UpdateStructureDataCallback) - Receives a BatchResult whose per-item Result holds the per-entry status codes or an ErrorDetail. This method never throws.
void delete_raw_async(const UpdateContext &context, std::vector< DeleteRawItem > items, DeleteRawCallback callback) noexcept override
Deletes raw or modified value history over a time range for a batch of nodes.
context(const UpdateContext &) - Update context, including the cancellation flag.items(std::vector< DeleteRawItem >) - Per-node delete requests, taken by value so the delegate may retain them.callback(DeleteRawCallback) - Receives a BatchResult whose per-item Result holds the outcome or an ErrorDetail. This method never throws.
void delete_at_time_async(const UpdateContext &context, std::vector< DeleteAtTimeItem > items, DeleteAtTimeCallback callback) noexcept override
Deletes values at specific timestamps for a batch of nodes.
context(const UpdateContext &) - Update context, including the cancellation flag.items(std::vector< DeleteAtTimeItem >) - Per-node delete requests, taken by value so the delegate may retain them.callback(DeleteAtTimeCallback) - Receives a BatchResult whose per-item Result holds the outcome or an ErrorDetail. This method never throws.
void delete_events_async(const UpdateContext &context, std::vector< DeleteEventsItem > items, DeleteEventsCallback callback) noexcept override
Deletes historical events for a batch of event-source nodes.
context(const UpdateContext &) - Update context, including the cancellation flag.items(std::vector< DeleteEventsItem >) - Per-node delete requests, taken by value so the delegate may retain them.callback(DeleteEventsCallback) - Receives a BatchResult whose per-item Result holds the outcome or an ErrorDetail. This method never throws.
ua::history::HistoryNamespace
class
Forwarding wrapper around an SDK-provided Namespace that attaches a history delegate without changing the underlying address-space behaviour.
Functions
HistoryNamespace(ua::shared_ptr< ua::Namespace > inner, ua::shared_ptr< ua::NamespaceHistoryDelegate > delegate)
Wrap inner, attaching delegate as the namespace's history delegate.
inner(ua::shared_ptr< ua::Namespace >) - the SDK-provided namespace whose non-history behaviour is forwarded unchanged.delegate(ua::shared_ptr< ua::NamespaceHistoryDelegate >) - the history delegate attached to the wrapped namespace.
ua::String uri() const override
Returns the namespace URI that uniquely identifies this namespace.
Returns: The namespace URI, the string form used to register and look this namespace up in the server's namespace array.
void set_index(uint16_t index) override
Assigns the namespace index this namespace occupies in the server's namespace array.
index(uint16_t) - Zero-based candidate namespace-array slot.
void shutdown_async(std::function< void(ua::VoidResult)> callback) noexcept override
Forwards the shutdown to the wrapped namespace: this wrapper arms nothing of its own.
callback(std::function< void(ua::VoidResult)>) - invoked once the wrapped namespace has stopped its background work.
void find_node(const ua::NodeId &nodeId, FindNodeCompleteCallback callback) override
Resolves a node owned by this namespace to an accessor.
nodeId(const ua::NodeId &) - Identifier of the node to resolve. Its namespace index is assumed to belong to this namespace.callback(FindNodeCompleteCallback) - Receives a NodeAccessorResult - on success an accessor for the node; on failure a bad StatusCode carrying any ErrorDetail (e.g. BadNodeIdUnknown). Never throws.
Creates a node of the given class in this namespace, with its initial attributes.
nodeId(const ua::NodeId &) - Identifier for the new node; must not already exist in this namespace.nodeClass(ua::NodeClass) - OPC UA node class to instantiate.initialAttributes(ua::InitialAttributes) - Standard attributes (id + wire-form value) to apply atomically as the node is created; may be empty for a bare node. A Variable's live value is not a creation attribute (use a value source / write_value); a VariableType's static default Value may be supplied here.callback(CreateNodeCompleteCallback) - Receives a NodeAccessorResult - on success an accessor for the created node; on failure a bad StatusCode carrying any ErrorDetail (BadNotSupported from the base default). Never throws.
void delete_node(const ua::NodeId &nodeId, bool deleteForwardHierarchicalRefs, DeleteNodeCompleteCallback callback) override
Deletes a node and its intra-namespace references from this namespace.
nodeId(const ua::NodeId &) - Identifier of the node to delete.deleteForwardHierarchicalRefs(bool) - When true, also delete nodes reachable by forward hierarchical references from this node (recursive subtree delete).callback(DeleteNodeCompleteCallback) - Receives a DeleteNodeResult - on success the ExternalReference entries needing cross-namespace cleanup; on failure a bad StatusCode carrying any ErrorDetail. Never throws.
void create_monitoring(std::span< const ua::MonitoringCreateItem > items, CreateMonitoringCallback callback) override
Forwards monitored-item creation to the wrapped namespace.
items(std::span< const ua::MonitoringCreateItem >) - the monitored items to create on the wrapped namespace.callback(CreateMonitoringCallback) - invoked with the per-item creation results.
void delete_monitoring(std::span< const ua::MonitoringHandle > handles, DeleteMonitoringCallback callback) override
Forwards monitored-item removal to the wrapped namespace.
handles(std::span< const ua::MonitoringHandle >) - the monitored-item handles to remove from the wrapped namespace.callback(DeleteMonitoringCallback) - invoked with the per-handle removal results.
void modify_monitoring(std::span< const ua::MonitoringModifyItem > items, ModifyMonitoringCallback callback) override
Forwards monitored-item modification to the wrapped namespace.
items(std::span< const ua::MonitoringModifyItem >) - the monitored-item modifications to apply on the wrapped namespace.callback(ModifyMonitoringCallback) - invoked with the per-item modification results.
ua::shared_ptr< ua::NamespaceHistoryDelegate > history_delegate() noexcept override
Returns the delegate that provides historical-access for nodes in this namespace.
Returns: The history delegate, or nullptr if this namespace has no history support.
ua::SemanticChangeSource * semantic_change_source() noexcept override
Optional capability for SemanticsChanged delivery (CTT Data Access Analog 008).
Returns: The namespace's SemanticChangeSource used to signal SemanticsChanged data-changes, or nullptr when the namespace does not track semantic changes.
std::optional< ua::PermissionType > effective_permissions(const ua::AccessIdentity &identity, std::optional< ua::NodeAccessor > node) const override
Forwards the wrapped namespace's access-control answer unchanged.
identity(const ua::AccessIdentity &) - the identity whose permissions are being resolved.node(std::optional< ua::NodeAccessor >) - the node the permissions are wanted for, or nullopt for the namespace itself.
Returns: the wrapped namespace's answer, unchanged.
void effective_permissions_async(ua::shared_ptr< const ua::AccessIdentity > identity, std::optional< std::vector< ua::NodeId > > nodes, ua::EffectivePermissionsCallback callback) override
Forwards asynchronous effective-permission resolution to the wrapped namespace.
identity(ua::shared_ptr< const ua::AccessIdentity >) - the identity whose permissions are being resolved.nodes(std::optional< std::vector< ua::NodeId > >) - the nodes the permissions are wanted for, or nullopt for the namespace itself.callback(ua::EffectivePermissionsCallback) - invoked with the resolved permissions.
void validate_role_permissions_update_async(ua::NodeId nodeId, std::optional< std::vector< ua::RolePermissionType > > proposedRolePermissions, std::function< void(ua::VoidResult)> callback) noexcept override
Forwards prospective RolePermissions operability validation to the wrapped namespace.
nodeId(ua::NodeId) - the node whose RolePermissions the caller proposes to change.proposedRolePermissions(std::optional< std::vector< ua::RolePermissionType > >) - the mask the caller proposes, or nullopt to clear it.callback(std::function< void(ua::VoidResult)>) - invoked with the wrapped namespace's verdict.
std::optional< std::vector< ua::RolePermissionType > > default_role_permissions() const override
Forwards the wrapped namespace's Part-18 default.
Returns: the wrapped namespace's default RolePermissions, or nullopt when it declares none.
std::optional< ua::AccessRestrictionType > default_access_restrictions() const override
Forwards the wrapped namespace's channel default.
Returns: the wrapped namespace's default AccessRestrictions, or nullopt when it declares none.
void on_identity_released(const ua::AccessIdentityKey &key) noexcept override
Forwards the identity-lifetime notification to the wrapped namespace.
key(const ua::AccessIdentityKey &) - the identity that has been released.
std::optional< ua::NodeId > metadata_object() const override
Forwards the metadata Object already served by the wrapped namespace.
Returns: the wrapped namespace's NamespaceMetadata Object, or nullopt when it serves none.
ua::history::SqliteConnection
class
RAII wrapper around a sqlite3* connection handle.
Opens or creates a SQLite database at the given path.
Functions
SqliteConnection(const std::string &dbPath)
Open (or create) the SQLite database at dbPath.
dbPath(const std::string &) - filesystem path of the SQLite database to open or create.
SqliteConnection(SqliteConnection &&) noexcept=default
Move-constructible; ownership of the underlying sqlite3* handle transfers.
SqliteConnection & operator=(SqliteConnection &&) noexcept=default
Move-assignable; ownership of the underlying sqlite3* handle transfers.
Returns: reference to this connection.
ua::VoidResult execute(const char *sql)
Execute a SQL statement that returns no results (CREATE TABLE, etc.).
sql(const char *) - the SQL statement to run (expected to produce no result rows).
Returns: a VoidResult that carries an error if the statement fails.
sqlite3 * handle() noexcept
Access the raw handle for statement preparation.
Returns: the underlying sqlite3* connection handle.
ua::history::SqliteStatement
class
RAII wrapper around a sqlite3_stmt* prepared statement.
Functions
SqliteStatement(SqliteConnection &connection, const char *sql)
Prepare sql against connection.
connection(SqliteConnection &) - the open connection the statement is prepared against.sql(const char *) - the SQL text to compile into a prepared statement.
SqliteStatement(SqliteStatement &&) noexcept=default
Move-constructible; ownership of the prepared sqlite3_stmt* transfers.
SqliteStatement & operator=(SqliteStatement &&) noexcept=default
Move-assignable; ownership of the prepared sqlite3_stmt* transfers.
Returns: reference to this statement.
void bind_text(int index, std::string_view value)
Bind a text value to parameter index.
index(int) - the 1-based parameter position to bind.value(std::string_view) - the text value to bind.
void bind_int64(int index, int64_t value)
Bind a 64-bit integer to parameter index.
index(int) - the 1-based parameter position to bind.value(int64_t) - the 64-bit integer value to bind.
void bind_double(int index, double value)
Bind a floating-point value to parameter index.
index(int) - the 1-based parameter position to bind.value(double) - the floating-point value to bind.
void bind_blob(int index, std::span< const uint8_t > data)
Bind a binary blob to parameter index.
index(int) - the 1-based parameter position to bind.data(std::span< const uint8_t >) - the binary blob to bind.
void bind_null(int index)
Bind SQL NULL to parameter index.
index(int) - the 1-based parameter position to set to SQL NULL.
bool step()
Returns true if a row is available (SQLITE_ROW), false on SQLITE_DONE.
Returns: true if a row is available (SQLITE_ROW), false on SQLITE_DONE.
void reset()
Reset the statement and clear bindings for reuse.
int64_t column_int64(int index) const
Read column index of the current row as a 64-bit integer.
index(int) - the 0-based column position to read.
Returns: the column value as a 64-bit integer.
double column_double(int index) const
Read column index of the current row as a floating-point value.
index(int) - the 0-based column position to read.
Returns: the column value as a floating-point number.
std::string_view column_text(int index) const
Read column index of the current row as text (valid until the next step/reset).
index(int) - the 0-based column position to read.
Returns: the column text, valid until the next step/reset.
std::span< const uint8_t > column_blob(int index) const
Read column index of the current row as a binary blob (valid until the next step/reset).
index(int) - the 0-based column position to read.
Returns: the column blob, valid until the next step/reset.
int column_bytes(int index) const
Byte length of column index in the current row.
index(int) - the 0-based column position to measure.
Returns: the byte length of the column value.
bool column_is_null(int index) const
Whether column index of the current row is SQL NULL.
index(int) - the 0-based column position to test.
Returns: true if the column value is SQL NULL.
ua::history::StatementResetGuard
class
Ensures a SqliteStatement is reset on scope exit.
Functions
Capture stmt, resetting it on scope exit.
stmt(SqliteStatement &) - the statement to reset when this guard goes out of scope.
ua::history::SqliteHistoryStore
class
SQLite-backed HistoryStore - the real persistence layer for the reference Historical Access implementation.
Raw values live in history_values keyed by (node_id, source_time); the full DataValue (value + status + timestamps) is stored as a UA-Binary BLOB via the SDK codec. Modification records live in history_modifications. Annotations are stored decomposed into their own fields rather than as an encoded Variant, so no structure-resolving codec is required (this is a store-implementation choice; the seam only requires that an annotation DataValue round-trips, see history_store.h). All access is single-threaded (driven from the delegate's worker strand), so no internal synchronisation is needed.
Per the HistoryStore failure contract, every method returns a ua::Result and never throws: SQLite/codec errors raised internally as ua::UaException are caught at the seam boundary and converted to an error Result carrying an ErrorDetail.
Range/bound queries map the engine's exclusive bounds to inclusive integer-tick bounds (+/-1 tick) so a single prepared BETWEEN statement serves every inclusivity combination.
Functions
SqliteHistoryStore(const std::string &dbPath, ua::shared_ptr< const ua::UaBinaryDataValueCodec > codec)
Open (or create) the SQLite-backed store at dbPath, using codec to serialise and deserialise stored DataValues.
dbPath(const std::string &) - filesystem path of the SQLite database to open or create.codec(ua::shared_ptr< const ua::UaBinaryDataValueCodec >) - codec used to serialise and deserialise stored DataValues.
Raw values whose SourceTimestamp lies in the (lower, upper) interval with the given inclusivity, ordered ascending by SourceTimestamp (ties broken by insertion order).
node(const ua::NodeId &) - The Variable node whose raw history is queried.lower(std::optional< ua::DateTime >) - Lower time bound, or std::nullopt for unbounded below.lower_inclusive(bool) - Whether a value exactly at lower is included.upper(std::optional< ua::DateTime >) - Upper time bound, or std::nullopt for unbounded above.upper_inclusive(bool) - Whether a value exactly at upper is included.limit(uint32_t) - Maximum number of values to return; 0 means no limit.
Returns: The matching raw values ascending by SourceTimestamp, or an error Result on storage failure.
The nearest raw value at/around reference in the given direction.
node(const ua::NodeId &) - The Variable node whose raw history is queried.reference(ua::DateTime) - Reference timestamp the search is relative to.direction(Direction) - Whether to search towards earlier (Before) or later (After) timestamps.inclusive(bool) - Whether a value exactly at reference qualifies.
Returns: The nearest matching value, a good empty optional if none exists, or an error Result on storage failure.
The raw value whose SourceTimestamp exactly equals timestamp, if any (collision detection for Insert/Replace/Update and exact-match for AtTime / DeleteAtTime).
node(const ua::NodeId &) - The Variable node whose raw history is queried.timestamp(ua::DateTime) - The exact SourceTimestamp to match.
Returns: The value at timestamp, a good empty optional if none exists, or an error Result on storage failure.
Insert or overwrite the value at its SourceTimestamp.
node(const ua::NodeId &) - The Variable node whose raw history is written.value(const ua::DataValue &) - The value to insert or overwrite, keyed by its SourceTimestamp.
Returns: A good VoidResult on success, or an error carrying the storage failure.
Remove the value whose SourceTimestamp exactly equals timestamp.
node(const ua::NodeId &) - The Variable node whose raw history is modified.timestamp(ua::DateTime) - The exact SourceTimestamp of the value to remove.
Returns: A good VoidResult on success, or an error carrying the storage failure.
Remove all values whose SourceTimestamp lies in the [start, end] closed interval.
node(const ua::NodeId &) - The Variable node whose raw history is modified.start(ua::DateTime) - Inclusive start of the SourceTimestamp interval to delete.end(ua::DateTime) - Inclusive end of the SourceTimestamp interval to delete.
Returns: The number of values removed, or an error Result on storage failure.
ua::VoidResult insert_modification(const ua::NodeId &node, const ua::DataValue &value, const ua::ModificationInfo &info) override
Record a modification (Insert/Replace/Update/Delete) of the value at its SourceTimestamp.
node(const ua::NodeId &) - The Variable node whose modification history is written.value(const ua::DataValue &) - The value the modification applies to, keyed by its SourceTimestamp.info(const ua::ModificationInfo &) - The modification record (update type, time, user) to store.
Returns: A good VoidResult on success, or an error carrying the storage failure.
ua::Result< std::vector< ModifiedValue > > read_modifications(const ua::NodeId &node, std::optional< ua::DateTime > lower, bool lower_inclusive, std::optional< ua::DateTime > upper, bool upper_inclusive, uint32_t limit) override
Modification records whose SourceTimestamp lies in (lower, upper) with the given inclusivity, ordered ascending by SourceTimestamp (ties broken by modification order).
node(const ua::NodeId &) - The Variable node whose modification history is queried.lower(std::optional< ua::DateTime >) - Lower time bound, or std::nullopt for unbounded below.lower_inclusive(bool) - Whether a record exactly at lower is included.upper(std::optional< ua::DateTime >) - Upper time bound, or std::nullopt for unbounded above.upper_inclusive(bool) - Whether a record exactly at upper is included.limit(uint32_t) - Maximum number of records to return; 0 means no limit.
Returns: The matching modification records ascending by SourceTimestamp, or an error Result on storage failure.
Whether a modification record exists at exactly timestamp (drives the Raw-read ExtraData bit).
node(const ua::NodeId &) - The Variable node whose modification history is queried.timestamp(ua::DateTime) - The exact SourceTimestamp to test.
Returns: True if a modification record exists at timestamp, or an error Result on storage failure.
ua::VoidResult insert_event(const ua::NodeId &node, const StoredEvent &event) override
Store a historical Event.
node(const ua::NodeId &) - The notifier node the event is stored under.event(const StoredEvent &) - The historical event to store.
Returns: A good VoidResult on success, or an error carrying the storage failure.
ua::Result< std::vector< StoredEvent > > read_events(const ua::NodeId &node, std::optional< ua::DateTime > lower, bool lower_inclusive, std::optional< ua::DateTime > upper, bool upper_inclusive, uint32_t limit) override
Events whose Time lies in (lower, upper) with the given inclusivity, ordered ascending by Time (ties broken by insertion order).
node(const ua::NodeId &) - The notifier node whose event history is queried.lower(std::optional< ua::DateTime >) - Lower time bound, or std::nullopt for unbounded below.lower_inclusive(bool) - Whether an event exactly at lower is included.upper(std::optional< ua::DateTime >) - Upper time bound, or std::nullopt for unbounded above.upper_inclusive(bool) - Whether an event exactly at upper is included.limit(uint32_t) - Maximum number of events to return; 0 means no limit.
Returns: The matching events ascending by Time, or an error Result on storage failure.
ua::Result< std::optional< StoredEvent > > read_event(const ua::NodeId &node, const ua::ByteString &eventId) override
The stored Event with the given EventId, if any (for Replace/Update).
node(const ua::NodeId &) - The notifier node whose event history is queried.eventId(const ua::ByteString &) - The EventId identifying the stored event.
Returns: The event with eventId, a good empty optional if none exists, or an error Result on storage failure.
ua::Result< bool > delete_event(const ua::NodeId &node, const ua::ByteString &eventId) override
Delete the Event with the given EventId.
node(const ua::NodeId &) - The notifier node whose event history is modified.eventId(const ua::ByteString &) - The EventId identifying the event to delete.
Returns: True if an event was removed, false if none matched, or an error Result on storage failure.
Insert or overwrite the annotation at its SourceTimestamp.
node(const ua::NodeId &) - The Variable node the annotation is stored under.annotation(const ua::DataValue &) - The annotation as a DataValue whose Value is an Annotation, keyed by its SourceTimestamp.
Returns: A good VoidResult on success, or an error carrying the storage failure.
The annotation at exactly timestamp, if any (as a DataValue whose Value is an Annotation).
node(const ua::NodeId &) - The Variable node whose annotations are queried.timestamp(ua::DateTime) - The exact SourceTimestamp to match.
Returns: The annotation at timestamp, a good empty optional if none exists, or an error Result on storage failure.
Remove the annotation at exactly timestamp.
node(const ua::NodeId &) - The Variable node whose annotations are modified.timestamp(ua::DateTime) - The exact SourceTimestamp of the annotation to remove.
Returns: A good VoidResult on success, or an error carrying the storage failure.
ua::history::ModifiedValue
struct
A raw historical value together with the modification record that produced it.
Returned by read_modifications for ReadModified.
Public attributes
ua::DataValue value
The historical value as stored.
ua::ModificationInfo info
The modification record (update type, time, user) that produced it.
ua::history::StoredEvent
struct
A stored historical Event.
fields maps an opaque field key to that field's value. The key is a token the engine assigns (see HistoryEngine::field_key); a store MUST persist and return keys byte-for-byte and MUST NOT parse or interpret them. This lets a backend keep event fields in a generic key/value table without understanding OPC UA browse paths, and lets the engine change the key format without breaking any store.
time (the event's Time field) and event_id (its EventId field) are derived views the store windows and identifies on: they are the canonical copy the store indexes by, and the engine also keeps them inside fields so a read can project the Time/EventId select clauses. A store reads time/event_id for ordering and lookup and round-trips fields opaquely.
Public attributes
ua::DateTime time
The event's Time field; the store windows and orders on this.
ua::ByteString event_id
The event's EventId field; the store identifies the event by this.
std::map< std::string, ua::Variant > fields
All event fields, keyed by the engine's opaque field key.
ua::history::HistoryStore
class
Storage backend seam for the Historical Access reference implementation.
The Part-11 semantics (windowing, bounds, continuation, status fan-out, interpolation, modification-record construction) live in HistoryEngine, which is storage-agnostic and drives a HistoryStore. A customer plugs in their own backend (a historian, an RDBMS, a time-series DB) by implementing this seam; SqliteHistoryStore is the bundled reference implementation, and works against an in-memory SQLite database as well as a file.
Failure contract. Every method returns a ua::Result<T> / ua::VoidResult and never throws: a storage failure is reported as an error Result carrying a StatusCode and an ErrorDetail, which the engine forwards into the per-item history result. A successful read that simply finds nothing is a good Result holding an empty std::optional / empty vector - it is not an error. (This is why a lookup returns Result<optional<...>> rather than optional<...>.)
All methods are invoked from the delegate's single worker strand, so implementations do not need to be internally synchronised.
Functions
~HistoryStore()=default
Raw values whose SourceTimestamp lies in the (lower, upper) interval with the given inclusivity, ordered ascending by SourceTimestamp (ties broken by insertion order).
node(const ua::NodeId &) - The Variable node whose raw history is queried.lower(std::optional< ua::DateTime >) - Lower time bound, or std::nullopt for unbounded below.lower_inclusive(bool) - Whether a value exactly at lower is included.upper(std::optional< ua::DateTime >) - Upper time bound, or std::nullopt for unbounded above.upper_inclusive(bool) - Whether a value exactly at upper is included.limit(uint32_t) - Maximum number of values to return; 0 means no limit.
Returns: The matching raw values ascending by SourceTimestamp, or an error Result on storage failure.
The nearest raw value at/around reference in the given direction.
node(const ua::NodeId &) - The Variable node whose raw history is queried.reference(ua::DateTime) - Reference timestamp the search is relative to.direction(Direction) - Whether to search towards earlier (Before) or later (After) timestamps.inclusive(bool) - Whether a value exactly at reference qualifies.
Returns: The nearest matching value, a good empty optional if none exists, or an error Result on storage failure.
The raw value whose SourceTimestamp exactly equals timestamp, if any (collision detection for Insert/Replace/Update and exact-match for AtTime / DeleteAtTime).
node(const ua::NodeId &) - The Variable node whose raw history is queried.timestamp(ua::DateTime) - The exact SourceTimestamp to match.
Returns: The value at timestamp, a good empty optional if none exists, or an error Result on storage failure.
Insert or overwrite the value at its SourceTimestamp.
node(const ua::NodeId &) - The Variable node whose raw history is written.value(const ua::DataValue &) - The value to insert or overwrite, keyed by its SourceTimestamp.
Returns: A good VoidResult on success, or an error carrying the storage failure.
Remove the value whose SourceTimestamp exactly equals timestamp.
node(const ua::NodeId &) - The Variable node whose raw history is modified.timestamp(ua::DateTime) - The exact SourceTimestamp of the value to remove.
Returns: A good VoidResult on success, or an error carrying the storage failure.
Remove all values whose SourceTimestamp lies in the [start, end] closed interval.
node(const ua::NodeId &) - The Variable node whose raw history is modified.start(ua::DateTime) - Inclusive start of the SourceTimestamp interval to delete.end(ua::DateTime) - Inclusive end of the SourceTimestamp interval to delete.
Returns: The number of values removed, or an error Result on storage failure.
ua::VoidResult insert_modification(const ua::NodeId &node, const ua::DataValue &value, const ua::ModificationInfo &info)=0
Record a modification (Insert/Replace/Update/Delete) of the value at its SourceTimestamp.
node(const ua::NodeId &) - The Variable node whose modification history is written.value(const ua::DataValue &) - The value the modification applies to, keyed by its SourceTimestamp.info(const ua::ModificationInfo &) - The modification record (update type, time, user) to store.
Returns: A good VoidResult on success, or an error carrying the storage failure.
ua::Result< std::vector< ModifiedValue > > read_modifications(const ua::NodeId &node, std::optional< ua::DateTime > lower, bool lower_inclusive, std::optional< ua::DateTime > upper, bool upper_inclusive, uint32_t limit)=0
Modification records whose SourceTimestamp lies in (lower, upper) with the given inclusivity, ordered ascending by SourceTimestamp (ties broken by modification order).
node(const ua::NodeId &) - The Variable node whose modification history is queried.lower(std::optional< ua::DateTime >) - Lower time bound, or std::nullopt for unbounded below.lower_inclusive(bool) - Whether a record exactly at lower is included.upper(std::optional< ua::DateTime >) - Upper time bound, or std::nullopt for unbounded above.upper_inclusive(bool) - Whether a record exactly at upper is included.limit(uint32_t) - Maximum number of records to return; 0 means no limit.
Returns: The matching modification records ascending by SourceTimestamp, or an error Result on storage failure.
Whether a modification record exists at exactly timestamp (drives the Raw-read ExtraData bit).
node(const ua::NodeId &) - The Variable node whose modification history is queried.timestamp(ua::DateTime) - The exact SourceTimestamp to test.
Returns: True if a modification record exists at timestamp, or an error Result on storage failure.
ua::VoidResult insert_event(const ua::NodeId &node, const StoredEvent &event)=0
Store a historical Event.
node(const ua::NodeId &) - The notifier node the event is stored under.event(const StoredEvent &) - The historical event to store.
Returns: A good VoidResult on success, or an error carrying the storage failure.
ua::Result< std::vector< StoredEvent > > read_events(const ua::NodeId &node, std::optional< ua::DateTime > lower, bool lower_inclusive, std::optional< ua::DateTime > upper, bool upper_inclusive, uint32_t limit)=0
Events whose Time lies in (lower, upper) with the given inclusivity, ordered ascending by Time (ties broken by insertion order).
node(const ua::NodeId &) - The notifier node whose event history is queried.lower(std::optional< ua::DateTime >) - Lower time bound, or std::nullopt for unbounded below.lower_inclusive(bool) - Whether an event exactly at lower is included.upper(std::optional< ua::DateTime >) - Upper time bound, or std::nullopt for unbounded above.upper_inclusive(bool) - Whether an event exactly at upper is included.limit(uint32_t) - Maximum number of events to return; 0 means no limit.
Returns: The matching events ascending by Time, or an error Result on storage failure.
ua::Result< std::optional< StoredEvent > > read_event(const ua::NodeId &node, const ua::ByteString &eventId)=0
The stored Event with the given EventId, if any (for Replace/Update).
node(const ua::NodeId &) - The notifier node whose event history is queried.eventId(const ua::ByteString &) - The EventId identifying the stored event.
Returns: The event with eventId, a good empty optional if none exists, or an error Result on storage failure.
ua::Result< bool > delete_event(const ua::NodeId &node, const ua::ByteString &eventId)=0
Delete the Event with the given EventId.
node(const ua::NodeId &) - The notifier node whose event history is modified.eventId(const ua::ByteString &) - The EventId identifying the event to delete.
Returns: True if an event was removed, false if none matched, or an error Result on storage failure.
Insert or overwrite the annotation at its SourceTimestamp.
node(const ua::NodeId &) - The Variable node the annotation is stored under.annotation(const ua::DataValue &) - The annotation as a DataValue whose Value is an Annotation, keyed by its SourceTimestamp.
Returns: A good VoidResult on success, or an error carrying the storage failure.
The annotation at exactly timestamp, if any (as a DataValue whose Value is an Annotation).
node(const ua::NodeId &) - The Variable node whose annotations are queried.timestamp(ua::DateTime) - The exact SourceTimestamp to match.
Returns: The annotation at timestamp, a good empty optional if none exists, or an error Result on storage failure.
Remove the annotation at exactly timestamp.
node(const ua::NodeId &) - The Variable node whose annotations are modified.timestamp(ua::DateTime) - The exact SourceTimestamp of the annotation to remove.
Returns: A good VoidResult on success, or an error carrying the storage failure.
Enumerations
ua::history::Direction
enum
Direction of a nearest-value lookup relative to a reference timestamp.

