1# Persisting RDB Store Data (C/C++) 2 3 4## When to Use 5 6The **RelationalStore** module provides a complete mechanism for local database management. You can use the APIs to add, delete, modify, and query data, and execute SQL statements in complex scenarios. 7 8 9## Basic Concepts 10 11- **Predicates**: a representation of the property or feature of a data entity, or the relationship between data entities, used to define operation conditions. 12 13- **ResultSet**: a set of query results, which allows access to the required data in flexible modes. 14 15 16## Constraints 17 18- By default, the Write Ahead Log (WAL) and the **FULL** flushing mode are used. 19 20- A maximum of four connection pools are used for read operations. 21 22- To ensure data accuracy, only one write operation is allowed at a time. 23 24- Once an application is uninstalled, related database files and temporary files are automatically deleted from the device. 25 26- Before using the device-cloud sync APIs added in API version 11, ensure that the cloud service is available. 27 28 29## Available APIs 30 31For details about the interfaces, see [RDB](../reference/apis-arkdata/capi-rdb.md). 32 33| API| Description| 34| -------- | -------- | 35| OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode) | Obtains an **OH_Rdb_Store** instance for RDB store operations.| 36| OH_Rdb_Execute(OH_Rdb_Store *store, const char *sql) | Executes an SQL statement that contains specified arguments but returns no value.| 37| OH_Rdb_Insert(OH_Rdb_Store *store, const char *table, OH_VBucket *valuesBucket) | Inserts a row of data into a table.| 38| OH_Rdb_Update(OH_Rdb_Store *store, OH_VBucket *valuesBucket, OH_Predicates *predicates) | Updates data in an RDB store.| 39| OH_Rdb_Delete(OH_Rdb_Store *store, OH_Predicates *predicates) | Deletes data from an RDB store.| 40| OH_Rdb_Query(OH_Rdb_Store *store, OH_Predicates *predicates, const char *const *columnNames, int length) | Queries data in an RDB store.| 41| OH_Rdb_DeleteStore(const OH_Rdb_Config *config) | Deletes an RDB store.| 42| OH_VBucket_PutAsset(OH_VBucket *bucket, const char *field, Rdb_Asset *value) | Puts an RDB asset into an **OH_VBucket** object.| 43| OH_VBucket_PutAssets(OH_VBucket *bucket, const char *field, Rdb_Asset *value, uint32_t count) | Puts RDB assets into an **OH_VBucket** object.| 44| OH_Rdb_SetDistributedTables(OH_Rdb_Store *store, const char *tables[], uint32_t count, Rdb_DistributedType type, const Rdb_DistributedConfig *config) | Sets distributed database tables.| 45| OH_Rdb_FindModifyTime(OH_Rdb_Store *store, const char *tableName, const char *columnName, OH_VObject *values) | Obtains the last modification time of the data in the specified column of a table.| 46| OH_Rdb_CloudSync(OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables[], uint32_t count, const Rdb_ProgressObserver *observer) | Manually performs device-cloud sync for a table. The cloud service must be available.| 47| int OH_Data_Asset_SetName(Data_Asset *asset, const char *name) | Sets the name for a data asset.| 48| int OH_Data_Asset_SetUri(Data_Asset *asset, const char *uri) | Sets the absolute path for a data asset.| 49| int OH_Data_Asset_SetPath(Data_Asset *asset, const char *path) | Sets the relative path in the application sandbox directory for a data asset.| 50| int OH_Data_Asset_SetCreateTime(Data_Asset *asset, int64_t createTime) | Sets the creation time for a data asset.| 51| int OH_Data_Asset_SetModifyTime(Data_Asset *asset, int64_t modifyTime) | Sets the last modification time for a data asset.| 52| int OH_Data_Asset_SetSize(Data_Asset *asset, size_t size) | Sets the size of a data asset.| 53| int OH_Data_Asset_SetStatus(Data_Asset *asset, Data_AssetStatus status) | Sets the status for a data asset.| 54| int OH_Data_Asset_GetName(Data_Asset *asset, char *name, size_t *length) | Obtains the name of a data asset.| 55| int OH_Data_Asset_GetUri(Data_Asset *asset, char *uri, size_t *length) | Obtains the absolute path of a data asset.| 56| int OH_Data_Asset_GetPath(Data_Asset *asset, char *path, size_t *length) | Obtains the relative path of a data asset.| 57| int OH_Data_Asset_GetCreateTime(Data_Asset *asset, int64_t *createTime) | Obtains the creation time of a data asset.| 58| int OH_Data_Asset_GetModifyTime(Data_Asset *asset, int64_t *modifyTime) | Obtains the last modification time of a data asset.| 59| int OH_Data_Asset_GetSize(Data_Asset *asset, size_t *size) | Obtains the size of a data asset.| 60| int OH_Data_Asset_GetStatus(Data_Asset *asset, Data_AssetStatus *status) | Obtains the status of a data asset.| 61| Data_Asset *OH_Data_Asset_CreateOne() | Creates a data asset instance. When this data asset is no longer needed, call **OH_Data_Asset_DestroyOne** to destroy it.| 62| int OH_Data_Asset_DestroyOne(Data_Asset *asset) | Destroys a data asset instance to reclaim memory.| 63| Data_Asset **OH_Data_Asset_CreateMultiple(uint32_t count) | Creates an instance for multiple data assets. When the instance is no longer required, call **OH_Data_Asset_DestroyMultiple** to destroy it.| 64| int OH_Data_Asset_DestroyMultiple(Data_Asset **assets, uint32_t count) | Destroys multiple data assets to reclaim memory.| 65| int OH_Rdb_Subscribe(OH_Rdb_Store *store, Rdb_SubscribeType type, const Rdb_DataObserver *observer) | Registers an observer for an RDB store. When the data in the distributed database changes, a callback will be invoked to return the data change.| 66| int OH_Rdb_Unsubscribe(OH_Rdb_Store *store, Rdb_SubscribeType type, const Rdb_DataObserver *observer) | Unregisters the observer of the specified type.| 67| int OH_Rdb_SubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *observer) | Subscribes to the auto sync process of an RDB store. The registered callback will be invoked to return the auto sync progress received.| 68| int OH_Rdb_UnsubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *observer) | Unsubscribes from the auto sync process of an RDB store.| 69 70 71## How to Develop 72 73**Adding the Dynamic Link Library** 74 75Add the following library to **CMakeLists.txt**: 76 77```txt 78libnative_rdb_ndk.z.so 79``` 80 81**Including Header Files** 82 83```c++ 84#include <database/data/data_asset.h> 85#include <database/rdb/oh_cursor.h> 86#include <database/rdb/oh_predicates.h> 87#include <database/rdb/oh_value_object.h> 88#include <database/rdb/oh_values_bucket.h> 89#include <database/rdb/relational_store.h> 90#include <database/rdb/relational_store_error_code.h> 91``` 92 931. Obtain an **OH_Rdb_Store** instance and create a database file.<br>The **dataBaseDir** variable specifies the application sandbox path. In the stage model, you are advised to use the database directory. For details, see the **databaseDir** attribute of [Context](../reference/apis-ability-kit/js-apis-inner-application-context.md). The FA model does not provide any API for obtaining the database sandbox path. Use the application directory instead. For details, see **getFilesDir** of [Context](../reference/apis-ability-kit/js-apis-inner-app-context.md). <br>**area** indicates the security level of the directory for database files. For details, see [contextConstant](../reference/apis-ability-kit/js-apis-app-ability-contextConstant.md). During development, you need to implement the conversion from **AreaMode** to **Rdb_SecurityArea**. <br>Example: 94 95 ```c 96 // Create an OH_Rdb_Config object. 97 OH_Rdb_Config config; 98 // The path is the application sandbox path. 99 config.dataBaseDir = "xxx"; 100 // Database file name. 101 config.storeName = "RdbTest.db"; 102 // Application bundle name. 103 config.bundleName = "xxx"; 104 // Module name. 105 config.moduleName = "xxx"; 106 // Security level of the database file. 107 config.securityLevel = OH_Rdb_SecurityLevel::S3; 108 // Whether the database is encrypted. 109 config.isEncrypt = false; 110 // Memory size occupied by config. 111 config.selfSize = sizeof(OH_Rdb_Config); 112 // Security level of the directory for storing the database file. 113 config.area = RDB_SECURITY_AREA_EL1; 114 115 int errCode = 0; 116 // Obtain an OH_Rdb_Store instance. 117 OH_Rdb_Store *store_ = OH_Rdb_GetOrOpen(&config, &errCode); 118 ``` 119 1202. Call **OH_Rdb_Execute** to create a table, and call **OH_Rdb_Insert** to insert data to the table. <br>Example: 121 122 ```c 123 char createTableSql[] = "CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, " 124 "AGE INTEGER, SALARY REAL, CODES BLOB)"; 125 // Create a table. 126 OH_Rdb_Execute(store_, createTableSql); 127 128 // Create a key-value (KV) pair instance. 129 OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); 130 valueBucket->putText(valueBucket, "NAME", "Lisa"); 131 valueBucket->putInt64(valueBucket, "AGE", 18); 132 valueBucket->putReal(valueBucket, "SALARY", 100.5); 133 uint8_t arr[] = {1, 2, 3, 4, 5}; 134 int len = sizeof(arr) / sizeof(arr[0]); 135 valueBucket->putBlob(valueBucket, "CODES", arr, len); 136 // Insert data. 137 int rowId = OH_Rdb_Insert(store_, "EMPLOYEE", valueBucket); 138 // Destroy the KV pair instance. 139 valueBucket->destroy(valueBucket); 140 ``` 141 142 > **NOTE** 143 > 144 > **RelationalStore** does not provide explicit flush operations for data persistence. The **insert()** API stores data persistently. 145 1463. Modify or delete data based on the conditions specified by **OH_Predicates**.<br> 147 148 Call **OH_Rdb_Update** to modify data, and call **OH_Rdb_Delete** to delete data. <br>Example: 149 150 ```c 151 // Modify data. 152 OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); 153 valueBucket->putText(valueBucket, "NAME", "Rose"); 154 valueBucket->putInt64(valueBucket, "AGE", 22); 155 valueBucket->putReal(valueBucket, "SALARY", 200.5); 156 uint8_t arr[] = {1, 2, 3, 4, 5}; 157 int len = sizeof(arr) / sizeof(arr[0]); 158 valueBucket->putBlob(valueBucket, "CODES", arr, len); 159 160 OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE"); 161 OH_VObject *valueObject = OH_Rdb_CreateValueObject(); 162 const char *name = "Lisa"; 163 valueObject->putText(valueObject, name); 164 predicates->equalTo(predicates, "NAME", valueObject)->andOperate(predicates); 165 uint32_t count = 1; 166 double salary = 100.5; 167 valueObject->putDouble(valueObject, &salary, count); 168 predicates->equalTo(predicates, "SALARY", valueObject); 169 170 int changeRows = OH_Rdb_Update(store_, valueBucket, predicates); 171 valueObject->destroy(valueObject); 172 valueBucket->destroy(valueBucket); 173 predicates->destroy(predicates); 174 ``` 175 176 ```c 177 // Delete data. 178 OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE"); 179 OH_VObject *valueObject = OH_Rdb_CreateValueObject(); 180 const char *name = "Lisa"; 181 valueObject->putText(valueObject, name); 182 predicates->equalTo(predicates, "NAME", valueObject); 183 int deleteRows = OH_Rdb_Delete(store_, predicates); 184 valueObject->destroy(valueObject); 185 predicates->destroy(predicates); 186 ``` 187 1884. Query data based on the conditions specified by **OH_Predicates**.<br> 189 190 Call **OH_Rdb_Query** to query data. The data obtained is returned in an **OH_Cursor** object. <br>Example: 191 192 ```c 193 OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE"); 194 195 const char *columnNames[] = {"NAME", "AGE"}; 196 int len = sizeof(columnNames) / sizeof(columnNames[0]); 197 OH_Cursor *cursor = OH_Rdb_Query(store_, predicates, columnNames, len); 198 199 int columnCount = 0; 200 cursor->getColumnCount(cursor, &columnCount); 201 202 // OH_Cursor is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0. 203 int64_t age; 204 while (cursor->goToNextRow(cursor) == OH_Rdb_ErrCode::RDB_OK) { 205 cursor->getInt64(cursor, 1, &age); 206 } 207 208 // Destroy the OH_Predicates instance. 209 predicates->destroy(predicates); 210 // Destroy the result set. 211 cursor->destroy(cursor); 212 ``` 213 2145. Insert data assets into a table. 215 216 ```c 217 // If the column attribute is a single asset, use asset in the SQL statements. If the column attribute is multiple assets, use assets in the SQL statements. 218 char createAssetTableSql[] = "CREATE TABLE IF NOT EXISTS asset_table (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 asset, data2 assets );"; 219 errCode = OH_Rdb_Execute(store_, createAssetTableSql); 220 Data_Asset *asset = OH_Data_Asset_CreateOne(); 221 OH_Data_Asset_SetName(asset, "name0"); 222 OH_Data_Asset_SetUri(asset, "uri0"); 223 OH_Data_Asset_SetPath(asset, "path0"); 224 OH_Data_Asset_SetCreateTime(asset, 1); 225 OH_Data_Asset_SetModifyTime(asset, 1); 226 OH_Data_Asset_SetSize(asset, 1); 227 OH_Data_Asset_SetStatus(asset, Data_AssetStatus::ASSET_NORMAL); 228 errCode = OH_VBucket_PutAsset(valueBucket, "data1", asset); 229 230 Data_Asset **assets = OH_Data_Asset_CreateMultiple(2); 231 232 OH_Data_Asset_SetName(assets[0], "name0"); 233 OH_Data_Asset_SetUri(assets[0], "uri0"); 234 OH_Data_Asset_SetPath(assets[0], "path0"); 235 OH_Data_Asset_SetCreateTime(assets[0], 1); 236 OH_Data_Asset_SetModifyTime(assets[0], 1); 237 OH_Data_Asset_SetSize(assets[0], 1); 238 OH_Data_Asset_SetStatus(assets[0], Data_AssetStatus::ASSET_NORMAL); 239 240 OH_Data_Asset_SetName(assets[1], "name1"); 241 OH_Data_Asset_SetUri(assets[1], "uri1"); 242 OH_Data_Asset_SetPath(assets[1], "path1"); 243 OH_Data_Asset_SetCreateTime(assets[1], 1); 244 OH_Data_Asset_SetModifyTime(assets[1], 1); 245 OH_Data_Asset_SetSize(assets[1], 1); 246 OH_Data_Asset_SetStatus(assets[1], Data_AssetStatus::ASSET_NORMAL); 247 248 errCode = OH_VBucket_PutAssets(valueBucket, "data2", assets, assetsCount); 249 int rowID = OH_Rdb_Insert(cursorTestRdbStore_, table, valueBucket); 250 // Destroy Data_Asset* and Data_Asset**. 251 OH_Data_Asset_DestroyMultiple(assets, 2); 252 OH_Data_Asset_DestroyOne(asset); 253 ``` 254 2556. Read data assets from the result set. 256 257 ```c 258 OH_Predicates *predicates = OH_Rdb_CreatePredicates("asset_table"); 259 260 OH_Cursor *cursor = OH_Rdb_Query(cursorTestRdbStore_, predicates, NULL, 0); 261 cursor->goToNextRow(cursor); 262 263 uint32_t assetCount = 0; 264 // assetCount is an output parameter that indicates the number of assets in this column. 265 errCode = cursor->getAssets(cursor, 2, nullptr, &assetCount); 266 Data_Asset **assets = OH_Data_Asset_CreateMultiple(assetCount); 267 errCode = cursor->getAssets(cursor, 2, assets, &assetCount); 268 Data_Asset *asset = assets[1]; 269 270 char name[10] = ""; 271 size_t nameLength = 10; 272 errCode = OH_Data_Asset_GetName(asset, name, &nameLength); 273 274 char uri[10] = ""; 275 size_t uriLength = 10; 276 errCode = OH_Data_Asset_GetUri(asset, uri, &uriLength); 277 278 char path[10] = ""; 279 size_t pathLength = 10; 280 errCode = OH_Data_Asset_GetPath(asset, path, &pathLength); 281 282 int64_t createTime = 0; 283 errCode = OH_Data_Asset_GetCreateTime(asset, &createTime); 284 285 int64_t modifyTime = 0; 286 errCode = OH_Data_Asset_GetModifyTime(asset, &modifyTime); 287 288 size_t size = 0; 289 errCode = OH_Data_Asset_GetSize(asset, &size); 290 291 Data_AssetStatus status = Data_AssetStatus::ASSET_NULL; 292 errCode = OH_Data_Asset_GetStatus(asset, &status); 293 294 predicates->destroy(predicates); 295 OH_Data_Asset_DestroyMultiple(assets, assetCount); 296 cursor->destroy(cursor); 297 ``` 298 2997. Obtain the last modification time of data.<br>Call **OH_Rdb_FindModifyTime** to obtain the last modification time of data in the specified column of a table. This API returns an **OH_Cursor** object with two columns of data. The first column is the input primary key or row ID, and the second column is the last modification time. <br>Example: 300 301 ```c 302 OH_VObject *values = OH_Rdb_CreateValueObject(); 303 int64_t keys[] = { 1 }; 304 values->putInt64(values, keys, 1); 305 OH_Cursor *cursor; 306 cursor = OH_Rdb_FindModifyTime(store_, "EMPLOYEE", "ROWID", values); 307 ``` 308 3098. Create distributed tables. <br>Call **OH_Rdb_SetDistributedTables** to set distributed tables for the table (created by using **OH_Rdb_Execute**). Before using this API, ensure that the cloud service is available. <br>Example: 310 311 ```c 312 constexpr int TABLE_COUNT = 1; 313 const char *table[TABLE_COUNT]; 314 table[0] = "EMPLOYEE"; 315 int errcode = OH_Rdb_SetDistributedTables(store_, table, TABLE_COUNT, Rdb_DistributedType::DISTRIBUTED_CLOUD, &config); 316 ``` 317 3189. Manually perform device-cloud sync for the distributed tables.<br>Call **OH_Rdb_CloudSync** to perform device-cloud sync for the tables. Before using this API, ensure that the cloud service is available. <br>Example: 319 320 ```c 321 // Define a callback. 322 void CloudSyncObserverCallback(void *context, Rdb_ProgressDetails *progressDetails) 323 { 324 // Do something. 325 } 326 const Rdb_ProgressObserver observer = { .context = nullptr, .callback = CloudSyncObserverCallback }; 327 OH_Rdb_CloudSync(store_, Rdb_SyncMode::SYNC_MODE_TIME_FIRST, table, TABLE_COUNT, &observer); 328 ``` 329 33010. Register a data observer for the specified event type for an RDB store. When the data changes, the registered callback will be invoked to process the observation. Call **OH_Rdb_Subscribe** to subscribe to data changes. Before using this API, ensure that the cloud service is available. <br>Example: 331 332 ```c 333 // Define a callback. 334 void RdbSubscribeBriefCallback(void *context, const char *values[], uint32_t count) 335 { 336 // Do something. 337 } 338 Rdb_BriefObserver briefObserver; 339 const Rdb_BriefObserver briefObserver = { .context = nullptr, .callback = RdbSubscribeBriefCallback }; 340 // Subscribe to data changes. 341 OH_Rdb_Subscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD, &briefObserver); 342 ``` 343 344 Call **OH_Rdb_Subscribe** to subscribe to local database data changes. <br>Example: 345 346 ```c 347 // Define a callback. 348 void LocalDataChangeObserverCallback1(void *context, const Rdb_ChangeInfo **changeInfo, uint32_t count) 349 { 350 for (uint32_t i = 0; i < count; i++) { 351 EXPECT_EQ(DISTRIBUTED_CHANGE_INFO_VERSION, changeInfo[i]->version); 352 // The table name is employee. 353 changeInfo[i]->tableName; 354 changeInfo[i]->ChangeType; 355 // The number of added rows is 1. 356 changeInfo[i]->inserted.count; 357 // The number of updated rows is 0. 358 changeInfo[i]->updated.count; 359 // The number of deleted rows is 0. 360 changeInfo[i]->deleted.count; 361 } 362 } 363 Rdb_DetailsObserver callback = LocalDataChangeObserverCallback1; 364 Rdb_DataObserver observer = { nullptr, { callback } }; 365 // Subscribe to the local database data changes. 366 OH_Rdb_Subscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS, &observer); 367 368 OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); 369 valueBucket->putText(valueBucket, "NAME", "Lisa"); 370 valueBucket->putInt64(valueBucket, "AGE", 18); 371 valueBucket->putReal(valueBucket, "SALARY", 100.5); 372 uint8_t arr[] = {1, 2, 3, 4, 5}; 373 int len = sizeof(arr) / sizeof(arr[0]); 374 valueBucket->putBlob(valueBucket, "CODES", arr, len); 375 // Insert data. 376 int rowId = OH_Rdb_Insert(store_, "EMPLOYEE", valueBucket); 377 // Destroy the KV pair instance. 378 valueBucket->destroy(valueBucket); 379 ``` 380 38111. Unsubscribe from the events of the specified type for an RDB store. After that, the callback will not be invoked to process the observation. 382 383 Call **OH_Rdb_Unsubscribe** to unsubscribe from data changes. Before using this API, ensure that the cloud service is available. <br>Example: 384 385 ```c 386 // Define a callback. 387 void RdbSubscribeBriefCallback(void *context, const char *values[], uint32_t count) 388 { 389 // Do something. 390 } 391 Rdb_BriefObserver briefObserver = RdbSubscribeBriefCallback; 392 const Rdb_DataObserver briefObs = { .context = nullptr, .callback.briefObserver = briefObserver }; 393 // Unsubscribe from data changes. 394 OH_Rdb_Unsubscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD, &briefObs); 395 ``` 396 Call **OH_Rdb_Unsubscribe** to unsubscribe from local database data changes. <br>Example: 397 ```c 398 // Define a callback. 399 void LocalDataChangeObserverCallback1(void *context, const Rdb_ChangeInfo **changeInfo, uint32_t count) 400 { 401 // Do something. 402 } 403 Rdb_DetailsObserver callback = LocalDataChangeObserverCallback1; 404 Rdb_DataObserver observer = { nullptr, { callback } }; 405 // Unsubscribe from the local database data changes. 406 OH_Rdb_Unsubscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS, &observer); 407 ``` 408 409 41012. Register an observer for auto sync progress of an RDB store. When auto sync is performed on the RDB store, the registered callback will be invoked to process the observation. 411 412 Call **OH_Rdb_SubscribeAutoSyncProgress** to subscribe to the auto sync progress. Before using this API, ensure that the cloud service is available. <br>Example: 413 414 ```c 415 // Define a callback. 416 void RdbProgressObserverCallback(void *context, Rdb_ProgressDetails *progressDetails) 417 { 418 // Do something. 419 } 420 const Rdb_ProgressObserver observer = { .context = nullptr, .callback = RdbProgressObserverCallback }; 421 OH_Rdb_SubscribeAutoSyncProgress(store_, &observer); 422 ``` 423 42413. Unsubscribe from the auto sync progress from an RDB store. After that, the callback will not be invoked to process the observation. 425 426 Call **OH_Rdb_UnsubscribeAutoSyncProgress** to unsubscribe from the auto sync progress. Before using this API, ensure that the cloud service is available. <br>Example: 427 428 ```c 429 // Define a callback. 430 void RdbProgressObserverCallback(void *context, Rdb_ProgressDetails *progressDetails) 431 { 432 // Do something. 433 } 434 const Rdb_ProgressObserver observer = { .context = nullptr, .callback = RdbProgressObserverCallback }; 435 OH_Rdb_UnsubscribeAutoSyncProgress(store_, &observer); 436 ``` 437 43814. Delete the database.<br>Call **OH_Rdb_DeleteStore** to delete the RDB store and related database file. <br>Example: 439 440 ```c 441 // Close the database instance. 442 OH_Rdb_CloseStore(store_); 443 // Delete the database file. 444 OH_Rdb_DeleteStore(&config); 445 ``` 446 447 448 449 450 451 452