subsys-data-relational-database-guide.md 19.2 KB
Newer Older
A
annie_wangli 已提交
1
# RDB Development
A
annie_wangli 已提交
2

A
annie_wangli 已提交
3
## When to Use
A
annie_wangli 已提交
4

A
Annie_wang 已提交
5
A relational database (RDB) store allows you to operate local data with or without native SQL statements based on SQLite.
A
annie_wangli 已提交
6

A
annie_wangli 已提交
7 8
## Available APIs
### Creating and Deleting an RDB Store
A
annie_wangli 已提交
9

A
Annie_wang 已提交
10
The table below describes the APIs for creating and deleting an RDB store.
A
annie_wangli 已提交
11

A
annie_wangli 已提交
12
**Table 1** APIs for creating and deleting an RDB store
A
annie_wangli 已提交
13

A
annie_wangli 已提交
14
| Class| API| Description|
A
annie_wangli 已提交
15
|  ----  |  ----  |  ----  |
A
Annie_wang 已提交
16 17
| RdbStoreConfig | RdbStoreConfig(const std::string &path, <br> StorageMode storageMode = StorageMode::MODE_DISK, <br> bool readOnly = false, <br> const std::vector<uint8_t> &encryptKey = std::vector<uint8_t>(), <br> const std::string &journalMode = "", <br> const std::string &syncMode = "", <br> const std::string &databaseFileType = "", <br> const std::string &databaseFileSecurityLevel = "") | Configures an RDB store, including setting the RDB store name, storage mode, log mode, synchronization mode, and read-only mode, and whether to encrypt the RDB store.<br/> - **path**: path of the RDB store. <br>- **readOnly**: whether the RDB store is read-only. <br>- **storageMode**: storage mode. <br>- **encryptKey**: key used to encrypt the RDB store. <br>- **journalMode**: logging mode. <br>- **syncMode**: data synchronization mode. <br>- **databaseFileType**: RDB store type. <br>- **databaseFileSecurityLevel**: security level of the RDB store.|
| RdbOpenCallback | int OnCreate(RdbStore &rdbStore) | Called when an RDB store is created. You can add the method for initializing the table structure and initialization data used by your application in this callback.|
A
annie_wangli 已提交
18 19 20
| RdbOpenCallback | int OnUpgrade(RdbStore &rdbStore, int currentVersion, int targetVersion) | Called when the RDB store is upgraded.|
| RdbOpenCallback | int OnDowngrade(RdbStore &rdbStore, int currentVersion, int targetVersion) | Called when the RDB store is downgraded.|
| RdbHelper | std::shared_ptr\<RdbStore\> GetRdbStore(const RdbStoreConfig &config, int version, RdbOpenCallback &openCallback, int &errCode) | Creates or obtains an RDB store.|
A
Annie_wang 已提交
21
| RdbHelper | int DeleteRdbStore(const std::string &path) | Deletes an RDB store.|
A
annie_wangli 已提交
22

A
annie_wangli 已提交
23
### Encrypting an RDB Store
A
annie_wangli 已提交
24

A
Annie_wang 已提交
25
When creating an RDB store, you can add a key for security purposes. After that, the RDB store can be accessed only with the correct key.
A
annie_wangli 已提交
26

A
annie_wangli 已提交
27
**Table 2** API for changing the key
A
annie_wangli 已提交
28
| Class| API| Description|
A
annie_wangli 已提交
29
|  ----  |  ----  |  ----  |
A
Annie_wang 已提交
30
| RdbStore | int ChangeEncryptKey(const std::vector<uint8_t> &newKey) | Changes the encryption key for an RDB store. <br>Note that the encryption key can be changed only for an encrypted RDB store.|
A
annie_wangli 已提交
31

A
annie_wangli 已提交
32
### Using Predicates
A
annie_wangli 已提交
33

A
Annie_wang 已提交
34
The RDB store provides **AbsRdbPredicates** for you to set database operation conditions. The **AbsRdbPredicates** class has the following child classes:
A
annie_wangli 已提交
35

A
Annie_wang 已提交
36 37
- **RdbPredicates**: allows you to combine SQL statements by simply calling methods in this class, such as **equalTo**, **notEqualTo**, **groupBy**, **orderByAsc**, and **beginsWith**. With this class, you do not need to write complex SQL statements.
- **RawRdbPredicates**: allows you to write complex SQL statements, such as setting **whereClause** and **whereArgs**. However, this class does not support APIs such as **equalTo**.
A
annie_wangli 已提交
38

A
Annie_wang 已提交
39
  **Table 3** APIs for setting RDB predicates 
A
annie_wangli 已提交
40
  | Class| API| Description|
A
annie_wangli 已提交
41
  |  ----  |  ----  |  ----  |
A
Annie_wang 已提交
42 43 44 45 46
  | RdbPredicates | AbsPredicates *EqualTo(std::string field, std::string value) | Sets an **AbsPredicates** to match the field that is equal to the specified value.|
  | RdbPredicates | AbsPredicates *NotEqualTo(std::string field, std::string value) | Sets an **AbsPredicates** to match the field that is not equal to the specified value.|
  | RdbPredicates | AbsPredicates *BeginsWith(std::string field, std::string value) | Sets an **AbsPredicates** to match the field that starts with the specified value.|
  | RdbPredicates | AbsPredicates *Between(std::string field, std::string low, std::string high) | Sets an **AbsPredicates** to match the field that is within the range specified by **low** and **high**.|
  | RdbPredicates | AbsPredicates *OrderByAsc(std::string field) | Sets an **AbsPredicates** that sorts values in ascending order.|
A
annie_wangli 已提交
47 48
  | RdbPredicates | void SetWhereClause(std::string whereClause) | Sets **whereClause**.|
  | RdbPredicates | void SetWhereArgs(std::vector\<std::string\> whereArgs) | Sets **whereArgs**, which indicates the value of the placeholder in **whereClause**.|
A
Annie_wang 已提交
49 50
  | RdbPredicates | AbsRdbPredicates *InDevices(std::vector<std::string>& devices) | Sets an **AbsPredicates** to specify the remote devices on the network with databases to be synchronized.|
  | RdbPredicates | AbsRdbPredicates *InAllDevices() | Sets an **AbsPredicates** to connect to all remote devices on the network when synchronizing distributed databases.|
A
annie_wangli 已提交
51

A
annie_wangli 已提交
52

A
annie_wangli 已提交
53
### Managing Data in an RDB Store
A
annie_wangli 已提交
54

A
Annie_wang 已提交
55
You can use the APIs provided by the RDB to insert, delete, update, and query local data.
A
annie_wangli 已提交
56

A
annie_wangli 已提交
57
- Inserting data
A
annie_wangli 已提交
58

A
Annie_wang 已提交
59
  Call **int Insert()** to insert data through **ValuesBucket**. If data is inserted, the row number of the data inserted is returned; otherwise, **-1** is returned.
A
annie_wangli 已提交
60

A
Annie_wang 已提交
61
  **Table 4** API for inserting data
A
annie_wangli 已提交
62

A
annie_wangli 已提交
63
  | Class| API| Description|
A
annie_wangli 已提交
64
  |  ----  |  ----  |  ----  |
A
Annie_wang 已提交
65
  | RdbStore | int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) | Inserts data based on the passed table name and data in **ValuesBucket**. <br/>- **table**: name of the target table. <br/>- **initialValues**: data to insert. The data is stored in **ValuesBucket**. A series of **put()** methods, such as **PutString(const std::string &columnName, const std::string &value)** and **PutDouble(const std::string &columnName, double value)**, are provided to add data to **ValuesBucket**. |
A
annie_wangli 已提交
66

A
annie_wangli 已提交
67
- Deleting data
A
annie_wangli 已提交
68
  
A
Annie_wang 已提交
69
  Call **delete()** to delete the data that meets the conditions specified by **AbsRdbPredicates**. If data is deleted, the row number of the deleted data is returned; otherwise, **0** is returned.
A
annie_wangli 已提交
70

A
annie_wangli 已提交
71
  **Table 5** API for deleting data
A
annie_wangli 已提交
72
  | Class| API| Description|
A
annie_wangli 已提交
73
  |  ----  |  ----  |  ----  |
A
Annie_wang 已提交
74
  | RdbStore | int Delete(int &deletedRows, const AbsRdbPredicates &predicates) | Deletes data.<br> - **deletedRows**: number of rows to delete.<br> - **predicates**: table name and conditions for deleting the data. **AbsRdbPredicates** has the following classes:<br> - **RdbPredicates**: specifies query conditions by calling its methods, such as **equalTo**.<br> - **RawRdbPredicates**: specifies the table name, **whereClause**, and **whereArgs** only. |
A
annie_wangli 已提交
75

A
annie_wangli 已提交
76
- Updating data
A
annie_wangli 已提交
77

A
Annie_wang 已提交
78
  Call **update()** to update data based on the passed data and the conditions specified by **AbsRdbPredicates**. If data is updated, the row number of the updated data is returned; otherwise, **0** is returned.
A
annie_wangli 已提交
79

A
annie_wangli 已提交
80
  **Table 6** API for updating data
A
annie_wangli 已提交
81
  | Class| API| Description|
A
annie_wangli 已提交
82
  |  ----  |  ----  |  ----  |
A
Annie_wang 已提交
83
  | RdbStore | int Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) | Updates the data that meets the conditions specified by predicates.<br> - **changedRows**: number of rows to update.<br> - **values**: new data stored in **ValuesBucket**.<br> - **predicates**: table name and conditions for the update operation. **AbsRdbPredicates** has the following classes:<br> - **RdbPredicates**: specifies update conditions by calling its methods, such as **equalTo**.<br> - **RawRdbPredicates**: specifies the table name, **whereClause**, and **whereArgs** only. |
A
annie_wangli 已提交
84

A
annie_wangli 已提交
85
- Querying data
A
annie_wangli 已提交
86

A
annie_wangli 已提交
87
  You can query data in an RDB store in either of the following ways:
A
annie_wangli 已提交
88

A
annie_wangli 已提交
89 90
  - Call the **query()** method to query data based on the predicates, without passing any SQL statement.
  - Run the native SQL statement.
A
annie_wangli 已提交
91

A
annie_wangli 已提交
92
  **Table 7** APIs for querying data
A
annie_wangli 已提交
93
  | Class| API| Description|
A
annie_wangli 已提交
94
  |  ----  |  ----  |  ----  |
A
Annie_wang 已提交
95 96
  | RdbStore | std::unique_ptr<AbsSharedResultSet> Query(const AbsRdbPredicates &predicates, const std::vector\<std::string\> columns) | Queries data.<br> - **predicates**: query conditions. **AbsRdbPredicates** has the following classes:<br> - **RdbPredicates**: specifies query conditions by calling its methods, such as **equalTo**.<br> - **RawRdbPredicates**: specifies the table name, **whereClause**, and **whereArgs** only.<br> - **columns**: number of columns returned. |
  | RdbStore | std::unique_ptr<AbsSharedResultSet> QuerySql(const std::string &sql, const std::vector\<std::string\> &selectionArgs = std::vector\<std::string\>()) | Executes the native SQL statements to query data.<br> - **sql**: native SQL statement.<br> - **selectionArgs**: parameter values corresponding to the placeholders in the SQL statements. Set it to **null** if the **select** statement has no placeholder. |
A
annie_wangli 已提交
97

A
Annie_wang 已提交
98
### Obtaining the Query Result
A
annie_wangli 已提交
99

A
Annie_wang 已提交
100
You can use the APIs provided by **ResultSet** to traverse and access the data you have queried. A result set can be regarded as a row of data in the queried result. The table below describes the APIs of **ResultSet**.
A
annie_wangli 已提交
101

A
Annie_wang 已提交
102
**Table 8** APIs of **ResultSet**
A
annie_wangli 已提交
103 104
| Class| API| Description|
|  ----  |  ----  |  ----  |
A
Annie_wang 已提交
105 106 107 108
| ResultSet | int GoTo(int offset) | Moves forwards or backwards by the specified offset relative to its current position.|
| ResultSet | int GoToRow(int position) | Moves to the specified row.|
| ResultSet | int GoToNextRow() | Moves to the next row.|
| ResultSet | int GoToPreviousRow() | Moves to the previous row.|
A
annie_wangli 已提交
109 110 111 112
| ResultSet | int IsStarted(bool &result) | Checks whether the result set has been moved.|
| ResultSet | int IsEnded(bool &result) | Checks whether the result set is moved after the last line.|
| ResultSet | int IsAtFirstRow(bool &result) | Checks whether the result set is located in the first row.|
| ResultSet | int IsAtLastRow(bool &result) | Checks whether the result set is located in the last row.|
A
Annie_wang 已提交
113 114 115 116 117
| ResultSet | int GetRowCount(int &count) | Obtains the number of rows of this result set.|
| ResultSet | int GetColumnCount(int &count) | Obtains the number of columns of this result set.|
| ResultSet | int GetString(int columnIndex, std::string &value) | Obtains the value in the specified column of the current row, in strings.|
| ResultSet | int GetBlob(int columnIndex, std::vector\<uint8_t\> &blob) | Obtains the value in the specified column of the current row, in a byte array.|
| ResultSet | int GetDouble(int columnIndex, double &value) | Obtains the value in the specified column of the current row, in double.|
A
annie_wangli 已提交
118

A
Annie_wang 已提交
119
### Setting Distributed Tables
A
annie_wangli 已提交
120

A
Annie_wang 已提交
121
Call **bool SetDistributedTables()** to set distributed tables for data operations across devices.
A
annie_wangli 已提交
122

A
Annie_wang 已提交
123
**Table 9** API for setting distributed tables
A
annie_wangli 已提交
124 125
| Class| API| Description|
|  ----  |  ----  |  ----  |
A
Annie_wang 已提交
126
| RdbStore | bool SetDistributedTables(const std::vector<std::string>& tables) | Sets distributed tables.<br> **tables**: names of the distributed tables to set. |
A
annie_wangli 已提交
127 128 129

### Obtaining the Distributed Table Name for a Remote Device

A
Annie_wang 已提交
130
You can obtain the distributed table name for a remote device based on the local table name. The distributed table name can be used to query the RDB store of the remote device.<br>
A
annie_wangli 已提交
131 132 133 134

**Table 10** API for obtaining the distributed table name of a remote device
| Class| API| Description|
|  ----  |  ----  |  ----  |
A
Annie_wang 已提交
135
| RdbStore | std::string ObtainDistributedTableName(const std::string& device, const std::string& table) | Obtains the distributed table name of a remote device based on the local table name. The distributed table name can be used to query the RDB store of the remote device.<br> - **device**: ID of the remote device. <br>- **table**: name of the local table.|
A
annie_wangli 已提交
136 137 138

### Synchronizing Data Between Devices

A
Annie_wang 已提交
139
**Table 11** API for synchronizing data between devices
A
annie_wangli 已提交
140 141
| Class| API| Description|
|  ----  |  ----  |  ----  |
A
Annie_wang 已提交
142
| RdbStore | bool Sync(const SyncOption& option, const AbsRdbPredicates& predicate, const SyncCallback& callback) | Synchronizes data between devices. <br/>- **option**: synchronization options, which include **mode** and **isBlock**. **mode** specifies how data is synchronized. The value **push** means to push data from the local device to the remote device; the value **pull** means to pull data from the remote device to the local device. **isBlock** specifies whether the invocation of this function is blocked. <br>- **callback**: callback used to return the result. |
A
annie_wangli 已提交
143 144 145 146 147 148

### Registering an RDB Store Observer

**Table 12** API for registering an observer
| Class| API| Description|
|  ----  |  ----  |  ----  |
A
Annie_wang 已提交
149
| RdbStore | bool Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) | Registers an observer for this RDB store to listen for distributed data changes. When data in the RDB store changes, a callback will be invoked to return the data changes. <br/>- **option**: subscription type.<br>- **observer**: observer that listens for data changes in the RDB store. |
A
annie_wangli 已提交
150 151 152 153 154 155

### Unregistering an RDB Store Observer

**Table 13** API for unregistering an observer
| Class| API| Description|
|  ----  |  ----  |  ----  |
A
Annie_wang 已提交
156
| RdbStore | bool UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) | Unregisters the observer of the specified type. <br/>- **option**: subscription type to unregister.<br>- **observer**: observer to unregister. |
A
Annie_wang 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169

### Backing Up and Restoring an RDB Store

You can use the APIs provided by **rdbStore** to back up and restore local database files.

- Backing up an RDB store

  Call **int Backup()** to back up the current database file. **databasePath** specifies the name or path of the backup file to be generated. If the backup is successful, **0** is returned; otherwise, an error code is returned.

  Table 14 API for backing up an RDB store

  | Class| API| Description|
  |  ----  |  ----  |  ----  |
A
Annie_wang 已提交
170 171 172
  | RdbStore | int Backup(const std::string databasePath, const std::vector&lt;uint8_t&gt; destEncryptKey) | Backs up the current database file.<br>- **databasePath**: name or path of the backup file to generate.<br>- **destEncryptKey**: key used to encrypt the RDB store. Currently, only non-encrypted RDB stores can be backed up. |

  
A
Annie_wang 已提交
173 174 175 176 177 178 179 180 181 182

- Restoring an RDB store

  Call **int Restore()** to restore an RDB from the backup file. **backupPath** specifies the name or path of the backup file. If the restore is successful, **0** is returned; otherwise, an error code is returned.

  Table 15 API for restoring an RDB store

  | Class| API| Description|
  |  ----  |  ----  |  ----  |
  | RdbStore | int Restore(const std::string backupPath, const std::vector&lt;uint8_t&gt; &newKey) | Restore an RDB store.<br> - **backupPath**: name or path of the backup file.<br> - **newKey**: key used to encrypt the RDB store. Currently, only non-encrypted RDB stores can be restored. |
A
annie_wangli 已提交
183

A
Annie_wang 已提交
184 185 186 187 188 189 190 191 192 193 194 195
### Transaction

  A transaction is a unit of work performed in a database. If a transaction is successful, **0** is returned. Otherwise, an error code is returned.

  Table 16 Transaction APIs

| Class| API| Description|
|  ----  |  ----  |  ----  |
| RdbStore | int BeginTransaction() | Starts a transaction.|
| RdbStore | int Commit() | Commits the changes.|
| RdbStore | int RollBack() | Rolls back the changes.|

A
annie_wangli 已提交
196
## Constraints
A
annie_wangli 已提交
197

A
annie_wangli 已提交
198
None.
A
annie_wangli 已提交
199

A
annie_wangli 已提交
200
## How to Develop
A
annie_wangli 已提交
201

A
annie_wangli 已提交
202
1. Create an RDB store.
A
annie_wangli 已提交
203

A
annie_wangli 已提交
204
    a. Configure the RDB store attributes, including the RDB store name, storage mode, and read-only mode.
A
annie_wangli 已提交
205

A
annie_wangli 已提交
206
    b. Initialize the table structure and related data in the RDB store.
A
annie_wangli 已提交
207

A
annie_wangli 已提交
208
    c. Create an RDB store.
A
annie_wangli 已提交
209

A
annie_wangli 已提交
210
    The sample code is as follows:
A
annie_wangli 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    ```
    const std::string DATABASE_NAME = RDB_TEST_PATH + "RdbStoreTest.db";
    const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, salary REAL, blobType BLOB)";

    class OpenCallback : public RdbOpenCallback {
    public:
        int OnCreate(RdbStore &rdbStore) override;
        int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override;
    };

    int OpenCallback::OnCreate(RdbStore &store)
    {
        return store.ExecuteSql(CREATE_TABLE_TEST);
    }

    RdbStoreConfig config(DATABASE_NAME);
    OpenCallback callback;

    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, callback, 0); 
    ```

A
annie_wangli 已提交
232
2. Insert data.
A
annie_wangli 已提交
233

A
annie_wangli 已提交
234
    a. Create a **ValuesBucket** to store the data you need to insert.
A
annie_wangli 已提交
235

A
annie_wangli 已提交
236
    b. Call the **insert()** method to insert data into the RDB store.
A
annie_wangli 已提交
237

A
annie_wangli 已提交
238 239
    c. Create an RDB store.

A
annie_wangli 已提交
240
    The sample code is as follows:
A
annie_wangli 已提交
241 242 243 244 245 246 247 248 249 250 251
    ```
    ValuesBucket values;

    values.PutInt("id", 1);
    values.PutString("name", std::string("Tom"));
    values.PutInt("age", 18);
    values.PutDouble("salary", 100.5);
    values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
    store->Insert(id, "test", values);
    ```

A
annie_wangli 已提交
252
3. Query data.
A
annie_wangli 已提交
253

A
annie_wangli 已提交
254
    a. Create a predicate that specifies query conditions.
A
annie_wangli 已提交
255

A
annie_wangli 已提交
256
    b. Specify the data columns to return in the result set.
A
annie_wangli 已提交
257

A
annie_wangli 已提交
258
    c. Call the **query()** method to query data.
A
annie_wangli 已提交
259

A
annie_wangli 已提交
260
    d. Call the **ResultSet** APIs to traverse data in the result set.
A
annie_wangli 已提交
261

A
annie_wangli 已提交
262
    The sample code is as follows:
A
annie_wangli 已提交
263 264 265 266 267 268 269 270
    ```
    std::vector<std::string> columns = {"id", "name", "age", "salary"};

    RdbPredicates predicates("test");
    predicates.EqualTo("age", "25")->OrderByAsc("salary");
    std::unique_ptr<ResultSet> resultSet  = store->Query(predicates, columns)
    resultSet.goToNextRow();
    ```
A
annie_wangli 已提交
271 272 273

4. Set the distributed tables to be synchronized.

A
Annie_wang 已提交
274
    Call the **SetDistributedTables()** method to set the distributed tables to be synchronized.
A
annie_wangli 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343

    The sample code is as follows:

    ```
    store->SetDistributedTables("test");
    ```

5. Synchronize data.

    a. Set the data synchronization mode and block status.

    b. Constructs an **AbsPredicates** object to specify remote devices within the network to be synchronized.

    c. Call the **Sync()** method to synchronize data.

    The sample code is as follows:

    ```
    SyncOption option;
    option.mode = PUSH;
    option.isBlock = true;
    AbsRdbPredicates predicate("test");
    predicate.InAllDevices();
    store->Sync(option, predicate, [] (const SyncResult& result) {
        for (const auto& [device, status] : result) {
            LogI("device=%s status=%d", device.c_str(), status);
        }
    });
    ```

6. Subscribe to distributed data.

    a. Override the **OnChange()** function.

    b. Define the distributed data subscription type.

    c. Call APIs to subscribe to or unsubscribe from distributed data.

    The sample code is as follows:

    ```
    class MyObserver : public RdbStoreObserver {
    public:
        void OnChange(const std::vector<std::string>& devices) override {
            for (const auto& device : devices) {
                LOGI("device=%s data change", device.c_str());
            }
        }
    };

    SubscribeOption option;
    option.mode = SubscribeMode::REMOTE;
    MyObserver observer;
    store->Subscribe(option, &observer); // Subscribe to distributed data.

    store->UnSubscribe(option, &observer); // Unsubscribe from distributed data.
    ```

7. Query data across devices.

   a. Obtain the distributed table name for a remote device based on the local table name.

   b. Run SQL statements to query data in the RDB store of the remote device.

   The sample code is as follows:
   ```
    std::string tableName = store->ObtainDistributedTableName("123456789abcd", "test");
    auto resultSet = store->QuerySql("SELECT * from ?;", tableName);
   ```
A
Annie_wang 已提交
344 345 346 347 348 349 350 351 352 353 354 355 356 357

8. Back up and restore an RDB store.

   a. Back up the current RDB store.

   b. Restore the RDB store from the specified backup file.

   The sample code is as follows:
   ```
    std::string backupName = "backup.db"; // Name of the database backup file to generate.
    std::vector<uint8_t> key; // Key used to encrypt the RDB store.
    int errno = store->Backup(backupName, key);
    errno = store->Restore(backupName, key);
   ```