• Skip to main content
  • Skip to header right navigation
  • Skip to site footer
CDP Studio logo

CDP Studio

The no-code and full-code software development tool for distributed control systems and HMI

  • Doc
  • Why CDP
    • Software developers
    • Automation engineers
    • Managers
  • Products
    • Automation Designer
    • HMI Designer
    • CDP Linux
  • Services
  • Use cases
  • Pricing
  • Try CDP

CDP Studio Documentation

  • Framework - External Value Types
  • SQLiteValue Handler
  • 5.1.0

EncryptedXMLConf Handler File Handler

SQLiteValue Handler

SQLiteValue Handler

The SQLiteValue handler (ExternalTypes.SQLiteValue) enables CDP properties to store their values in SQLite databases instead of XML configuration.

Use Cases:

  • For nodes whose values should persist between application re-deployments (i.e., XML overwrite)
  • For nodes whose values need to be shared between multiple applications
  • For historical tracking of node value changes (using external database on-change trigger features)
  • For storing sensitive data away from CDP configuration XML files
  • For very large values that would clutter the XML configuration

SQLiteValue handler supports:

  • Automatic database and table creation
  • Configurable SQL statements for full database control (i.e., use any SQL schema needed)
  • Complex key structures using multiple node values
  • Write operation aggregation, i.e., when many value changes happen quickly and are in the write queue, then only the latest value change will be posted to the SQLite database
  • Retry mechanisms for handling database errors

SQLiteValue handler can be configured using the following properties. The properties can be set globally under the CDP.ExternalTypesProvider configuration, or per-node using the ExternalType="SQLiteValue;{semicolon-separated list of key=value configuration parameters}" model attribute. Configuration Properties:

PropertyTypeDefaultDescription
DBNamestringpersistentvalues.sqliteDatabase file name. The name can include environment variables and OS-specific slices as described in External Type Path Resolving. The database file is automatically created if it does not exist yet. The filename can be prepended with a relative (to the path specified in DBLocation) or absolute path as well. Missing directories in the path will be automatically created.
DBLocationstringDatabase file location path (relative to application working directory or absolute), where the database file specified by DBName will be located. The path can include environment variables and OS-specific slices as described in External Type Path Resolving. Empty means the application working directory will be used. Missing directories in the path will be automatically created.
KeyNodesstringSemicolon-separated list of relative node names for database keys. Empty means use the node's full path. Relative names can contain prefixes like "." to refer to some sibling of the current node parent, and ".." to refer to the siblings of the grandparent, etc. Name "Value" refers to the node's internal value (the value stored in XML, i.e., the same value that can be inspected via the "InternalValue" metadata entry).
InitialValueNodestringOptional relative node name containing an initial value for cases when the database does not have an entry for the key yet. Relative name can contain prefixes like "." to refer to some sibling of the current node parent, and ".." to refer to the siblings of the grandparent, etc. When left empty, the node XML value (also shown as the "InternalValue" metadata entry) will be used as an initial value.
CreateSQLstringCREATE TABLE CDPValues (Key TEXT PRIMARY KEY, Value DOUBLE);SQL statement to create the database table in cases when the table does not exist yet
SelectSQLstringSELECT Value FROM CDPValues WHERE Key = ?;SQL statement to fetch the value. All values referred by KeyNodes will be applied here as statement parameters.
UpdateSQLstringINSERT INTO CDPValues (Value, Key) VALUES (?, ?) ON CONFLICT(Key) DO UPDATE SET Value = excluded.Value;SQL statement to update/insert the value in the database. Node value will be added as a first parameter and all values referred by KeyNodes will be added as additional parameters (keys) to this statement.
AutoCommitAfterunsigned int1000Specifies the delta time (in milliseconds) after automatic SQL commits will be executed, even when the worker thread is still alive and the database is still open via the Provider WorkerKeepalive property. Zero means all writes will be committed ASAP.
AutoRetryAttemptsunsigned char5Number of automatic retry attempts for database transient errors like "database is locked" errors. Set to 0 to disable automatic retries.
AutoRetryDelayunsigned int500When AutoRetryAttempts is greater than 0, it specifies the minimum delay in milliseconds to wait before the next retry attempt is made.

Note: Sometimes there may be a need to modify the InternalValue metadata entry, for example, because it is used in a KeyNodes or is an InitialValueNode. It is not possible to edit InternalValue via normal node value update, as then the SQLite external value will always be updated. But InternalValue can be altered in CDP Studio using the value cell context menu Modify External Type "InternalValue"...

Attaching SQLiteValue to a Property

To attach the SQLiteValue handler to a property, set the ExternalType attribute in a model:

<Attribute Name="Value" Type="double" ExternalType="SQLiteValue"/>

Same with custom configuration (can be used to override SQLiteValue global configuration):

<Attribute Name="Value" Type="double" ExternalType="SQLiteValue;KeyNodes=.NodeID;DBName=custom.db"/>

Alternatively, in C++ code, you add the SQLiteValue handler to a node like this:

node->SetExternalType("SQLiteValue");

or

node->SetExternalType("SQLiteValue;KeyNodes=.NodeID;DBName=custom.db");

Note that the initial value from the database is loaded asynchronously, so the property value will be initially invalid at application startup until the external type handler finishes fetching the actual value. Applications should therefore be prepared to handle the situation and wait for the value to become valid (e.g., by listening to node API value change events).

In the CDP C++ node value listener API (in AbstractValueListener class), there are also convenience callbacks that get notified when:

  • the database value has been loaded for a node (after node creation and configuring)
  • there was an error in loading the external value for a node (or also later, e.g., on write errors)

So the simplest C++ value listener API usage looks like this:

class MyValueListener : public CDP::StudioAPI::AbstractValueListener
{
 void ExternalValueLoaded(CDP::StudioAPI::ICDPNode* node) override
 {
   // add code to handle the initial external value for the 'node' loaded event
   // (e.g., start actions that were postponed until the actual value from database is loaded)
 }
 void ExternalTypeError(CDP::StudioAPI::ICDPNode* node, const std::string& error) override
 {
   // add code to handle the external type 'error' event for the 'node'
 }
}

MyValueListener listener;
node->GetNodeAPI()->AddValueListener(&listener);

Best Practices Using SQLiteValue

When using the SQLiteValue handler, consider the following best practices:

  • Set ExternalType="SQLiteValue" for values that should persist across application deployments (i.e., XML overwrite)
  • Design database schemas to support your requirements
  • Monitor the HandlerError alarm for external type issues
  • Use appropriate WorkerCount based on your controller speed and the number of nodes that are using SQLiteValue as a backend.
  • Test external type configurations with your specific data sources

Configuration Example With Value Change Count

SQLiteValue supports advanced database schema configurations. For example, you can extend the schema to track the number of changes made to each value. You can achieve this by modifying the CreateSQL and UpdateSQL properties by adding a ChangeCount column that increments with each update, like this:

Handler Configuration PropertyTypeValue
CreateSQLstringCREATE TABLE CDPValues (Key TEXT PRIMARY KEY, Value DOUBLE, ChangeCount INTEGER NOT NULL DEFAULT 0);
UpdateSQLstringINSERT INTO CDPValues (Value, Key, ChangeCount) VALUES (?, ?, 1) ON CONFLICT(Key) DO UPDATE SET Value = excluded.Value, ChangeCount = ChangeCount + 1;

Similarly, you can even add a separate table to log all historical changes if needed.

Configuration Example With Multiple KeyNodes

SQLiteValue supports using multiple values as a key to identify the value in the database. You can specify multiple relative node names in the KeyNodes property, separated by semicolons. For that, you also need to adjust the CreateSQL, SelectSQL, and UpdateSQL statements accordingly to handle multiple key columns.

Handler Configuration PropertyTypeValue
KeyNodesstring.Tag;Name
CreateSQLstringCREATE TABLE CDPValues (Tag TEXT NOT NULL, Name TEXT NOT NULL, Value DOUBLE, PRIMARY KEY (Tag, Name));
SelectSQLstringSELECT Value FROM CDPValues WHERE Tag = ? AND Name = ?;
UpdateSQLstringINSERT INTO CDPValues (Value, Tag, Name) VALUES (?, ?, ?) ON CONFLICT(Tag, Name) DO UPDATE SET Value = excluded.Value;

This setup identifies each property value in the database using a Tag and Name pair as a key. The SQLiteValue handler uses the values from the specified KeyNodes to form the composite key when performing database operations. In other words, KeyNodes=.Tag;Name expects that the property node has to have a sibling node named "Tag" that provides the Tag part of the key, while the property name itself provides the Name part of the key.

Configuration Example With UID or SUID as a Key

SQLiteValue can also use the CDP unique identifier (UID or SUID) TypeHint feature as a key for storing values in the database. This is beneficial when you want to ensure that the property, once added, is uniquely identified in the database regardless of its position in the configuration, even after the node is renamed or moved around in the application, causing its path (i.e. long-name) to change.

To use UID or SUID as a key, set the KeyNodes property to point to the UID or SUID attribute of the node.

For example, to use UID as a key:

Handler Configuration PropertyTypeValue
KeyNodesstring.UID

In the model XML, attributes should then look like this:

...
 <Attribute Name="Value" Type="double" ExternalType="SQLiteValue;KeyNodes=.UID"/>
 <Attribute Name="UID" Type="string" TypeHint="UID" ReadOnly="1" Required="1"/>
...

or even simpler, assuming the KeyNodes=" .UID" was set globally in SQLiteValue handler configuration, like that:

...
 <Attribute Name="Value" Type="double" ExternalType="SQLiteValue"/>
 <Attribute Name="UID" Type="string" TypeHint="UID" ReadOnly="1" Required="1"/>
...

When a node, having a model like this, is added to the configuration, the "UID" property value will set (at project load or application startup) to an automatically generated unique identifier, and the SQLiteValue handler will then use this UID value as a key to store and retrieve the "Value" property.

Note: Note that the UID or SUID attribute should be created as ReadOnly and Required to ensure it has a value written in the configuration storage (XML) and cannot be accidentally altered by users.

EncryptedXMLConf Handler File Handler

The content of this document is confidential information not to be published without the consent of CDP Technologies AS.

CDP Technologies AS, www.cdpstudio.com

Get started with CDP Studio today

Let us help you take your great ideas and turn them into the products your customer will love.

Try CDP Studio for free
Why CDP Studio?

CDP Technologies AS
Hundsværgata 8,
P.O. Box 144
6001 Ålesund, Norway

Tel: +47 990 80 900
E-mail: info@cdptech.com

Company

About CDP

Contact us

Services

Partners

Blog

Developers

Get started

User manuals

Support

Document download

Release notes

My account

Follow CDP

  • LinkedIn
  • YouTube
  • GitHub

© Copyright 2026 CDP Technologies. Privacy and cookie policy.

Return to top