1# RelationalStore Development (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/_r_d_b.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, use **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, use **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. 94 95 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). 96 97 **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**. 98 99 Example: 100 101 ```c 102 // Create an OH_Rdb_Config object. 103 OH_Rdb_Config config; 104 // The path is the application sandbox path. 105 config.dataBaseDir = "xxx"; 106 // Database file name. 107 config.storeName = "RdbTest.db"; 108 // Application bundle name. 109 config.bundleName = "xxx"; 110 // Module name. 111 config.moduleName = "xxx"; 112 // Security level of the database file. 113 config.securityLevel = OH_Rdb_SecurityLevel::S3; 114 // Whether the database is encrypted. 115 config.isEncrypt = false; 116 // Memory size occupied by config. 117 config.selfSize = sizeof(OH_Rdb_Config); 118 // Security level of the directory for storing the database file. 119 config.area = RDB_SECURITY_AREA_EL1; 120 121 int errCode = 0; 122 // Obtain an OH_Rdb_Store instance. 123 OH_Rdb_Store *store_ = OH_Rdb_GetOrOpen(&config, &errCode); 124 ``` 125 1262. Call **OH_Rdb_Execute** to create a table, and call **OH_Rdb_Insert** to insert data to the table. <br>Example: 127 128 ```c 129 char createTableSql[] = "CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, " 130 "AGE INTEGER, SALARY REAL, CODES BLOB)"; 131 // Create a table. 132 OH_Rdb_Execute(store_, createTableSql); 133 134 // Create a key-value (KV) pair instance. 135 OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); 136 valueBucket->putText(valueBucket, "NAME", "Lisa"); 137 valueBucket->putInt64(valueBucket, "AGE", 18); 138 valueBucket->putReal(valueBucket, "SALARY", 100.5); 139 uint8_t arr[] = {1, 2, 3, 4, 5}; 140 int len = sizeof(arr) / sizeof(arr[0]); 141 valueBucket->putBlob(valueBucket, "CODES", arr, len); 142 // Insert data. 143 int rowId = OH_Rdb_Insert(store_, "EMPLOYEE", valueBucket); 144 // Destroy the KV pair instance. 145 valueBucket->destroy(valueBucket); 146 ``` 147 148 > **NOTE** 149 > 150 > **RelationalStore** does not provide explicit flush operations for data persistence. The **insert()** API stores data persistently. 151 1523. Modify or delete data based on the conditions specified by **OH_Predicates**. 153 154 Call **OH_Rdb_Update** to modify data, and call **OH_Rdb_Delete** to delete data. <br>Example: 155 156 ```c 157 // Modify data. 158 OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); 159 valueBucket->putText(valueBucket, "NAME", "Rose"); 160 valueBucket->putInt64(valueBucket, "AGE", 22); 161 valueBucket->putReal(valueBucket, "SALARY", 200.5); 162 uint8_t arr[] = {1, 2, 3, 4, 5}; 163 int len = sizeof(arr) / sizeof(arr[0]); 164 valueBucket->putBlob(valueBucket, "CODES", arr, len); 165 166 OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE"); 167 OH_VObject *valueObject = OH_Rdb_CreateValueObject(); 168 const char *name = "Lisa"; 169 valueObject->putText(valueObject, name); 170 predicates->equalTo(predicates, "NAME", valueObject)->andOperate(predicates); 171 uint32_t count = 1; 172 double salary = 100.5; 173 valueObject->putDouble(valueObject, &salary, count); 174 predicates->equalTo(predicates, "SALARY", valueObject); 175 176 int changeRows = OH_Rdb_Update(store_, valueBucket, predicates); 177 valueObject->destroy(valueObject); 178 valueBucket->destroy(valueBucket); 179 predicates->destroy(predicates); 180 ``` 181 182 ```c 183 // Delete data. 184 OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE"); 185 OH_VObject *valueObject = OH_Rdb_CreateValueObject(); 186 const char *name = "Lisa"; 187 valueObject->putText(valueObject, name); 188 predicates->equalTo(predicates, "NAME", valueObject); 189 int deleteRows = OH_Rdb_Delete(store_, predicates); 190 valueObject->destroy(valueObject); 191 predicates->destroy(predicates); 192 ``` 193 1944. Query data based on the conditions specified by **OH_Predicates**. 195 196 Call **OH_Rdb_Query** to query data. The data obtained is returned in an **OH_Cursor** object. <br>Example: 197 198 ```c 199 OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE"); 200 201 const char *columnNames[] = {"NAME", "AGE"}; 202 int len = sizeof(columnNames) / sizeof(columnNames[0]); 203 OH_Cursor *cursor = OH_Rdb_Query(store_, predicates, columnNames, len); 204 205 int columnCount = 0; 206 cursor->getColumnCount(cursor, &columnCount); 207 208 // OH_Cursor is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0. 209 int64_t age; 210 while (cursor->goToNextRow(cursor) == OH_Rdb_ErrCode::RDB_OK) { 211 cursor->getInt64(cursor, 1, &age); 212 } 213 214 // Destroy the OH_Predicates instance. 215 predicates->destroy(predicates); 216 // Destroy the result set. 217 cursor->destroy(cursor); 218 ``` 219 2205. Insert data assets into a table. 221 222 ```c 223 // 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. 224 char createAssetTableSql[] = "CREATE TABLE IF NOT EXISTS asset_table (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 asset, data2 assets );"; 225 errCode = OH_Rdb_Execute(store_, createAssetTableSql); 226 Data_Asset *asset = OH_Data_Asset_CreateOne(); 227 OH_Data_Asset_SetName(asset, "name0"); 228 OH_Data_Asset_SetUri(asset, "uri0"); 229 OH_Data_Asset_SetPath(asset, "path0"); 230 OH_Data_Asset_SetCreateTime(asset, 1); 231 OH_Data_Asset_SetModifyTime(asset, 1); 232 OH_Data_Asset_SetSize(asset, 1); 233 OH_Data_Asset_SetStatus(asset, Data_AssetStatus::ASSET_NORMAL); 234 errCode = OH_VBucket_PutAsset(valueBucket, "data1", asset); 235 236 Data_Asset **assets = OH_Data_Asset_CreateMultiple(2); 237 238 OH_Data_Asset_SetName(assets[0], "name0"); 239 OH_Data_Asset_SetUri(assets[0], "uri0"); 240 OH_Data_Asset_SetPath(assets[0], "path0"); 241 OH_Data_Asset_SetCreateTime(assets[0], 1); 242 OH_Data_Asset_SetModifyTime(assets[0], 1); 243 OH_Data_Asset_SetSize(assets[0], 1); 244 OH_Data_Asset_SetStatus(assets[0], Data_AssetStatus::ASSET_NORMAL); 245 246 OH_Data_Asset_SetName(assets[1], "name1"); 247 OH_Data_Asset_SetUri(assets[1], "uri1"); 248 OH_Data_Asset_SetPath(assets[1], "path1"); 249 OH_Data_Asset_SetCreateTime(assets[1], 1); 250 OH_Data_Asset_SetModifyTime(assets[1], 1); 251 OH_Data_Asset_SetSize(assets[1], 1); 252 OH_Data_Asset_SetStatus(assets[1], Data_AssetStatus::ASSET_NORMAL); 253 254 errCode = OH_VBucket_PutAssets(valueBucket, "data2", assets, assetsCount); 255 int rowID = OH_Rdb_Insert(cursorTestRdbStore_, table, valueBucket); 256 // Destroy Data_Asset* and Data_Asset**. 257 OH_Data_Asset_DestroyMultiple(assets, 2); 258 OH_Data_Asset_DestroyOne(asset); 259 ``` 260 2616. Read data assets from the result set. 262 263 ```c 264 OH_Predicates *predicates = OH_Rdb_CreatePredicates("asset_table"); 265 266 OH_Cursor *cursor = OH_Rdb_Query(cursorTestRdbStore_, predicates, NULL, 0); 267 cursor->goToNextRow(cursor); 268 269 uint32_t assetCount = 0; 270 // assetCount is an output parameter that indicates the number of assets in this column. 271 errCode = cursor->getAssets(cursor, 2, nullptr, &assetCount); 272 Data_Asset **assets = OH_Data_Asset_CreateMultiple(assetCount); 273 errCode = cursor->getAssets(cursor, 2, assets, &assetCount); 274 Data_Asset *asset = assets[1]; 275 276 char name[10] = ""; 277 size_t nameLength = 10; 278 errCode = OH_Data_Asset_GetName(asset, name, &nameLength); 279 280 char uri[10] = ""; 281 size_t uriLength = 10; 282 errCode = OH_Data_Asset_GetUri(asset, uri, &uriLength); 283 284 char path[10] = ""; 285 size_t pathLength = 10; 286 errCode = OH_Data_Asset_GetPath(asset, path, &pathLength); 287 288 int64_t createTime = 0; 289 errCode = OH_Data_Asset_GetCreateTime(asset, &createTime); 290 291 int64_t modifyTime = 0; 292 errCode = OH_Data_Asset_GetModifyTime(asset, &modifyTime); 293 294 size_t size = 0; 295 errCode = OH_Data_Asset_GetSize(asset, &size); 296 297 Data_AssetStatus status = Data_AssetStatus::ASSET_NULL; 298 errCode = OH_Data_Asset_GetStatus(asset, &status); 299 300 predicates->destroy(predicates); 301 OH_Data_Asset_DestroyMultiple(assets, assetCount); 302 cursor->destroy(cursor); 303 ``` 304 3057. Obtain the last modification time of data. 306 307 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. 308 309 Example: 310 311 ```c 312 OH_VObject *values = OH_Rdb_CreateValueObject(); 313 int64_t keys[] = { 1 }; 314 values->putInt64(values, keys, 1); 315 OH_Cursor *cursor; 316 cursor = OH_Rdb_FindModifyTime(store_, "EMPLOYEE", "ROWID", values); 317 ``` 318 3198. Create distributed tables. 320 321 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. 322 323 Example: 324 325 ```c 326 constexpr int TABLE_COUNT = 1; 327 const char *table[TABLE_COUNT]; 328 table[0] = "EMPLOYEE"; 329 int errcode = OH_Rdb_SetDistributedTables(store_, table, TABLE_COUNT, Rdb_DistributedType::DISTRIBUTED_CLOUD, &config); 330 ``` 331 3329. Manually perform device-cloud sync for the distributed tables. 333 334 Call **OH_Rdb_CloudSync** to perform device-cloud sync for the tables. Before using this API, ensure that the cloud service is available. 335 336 Example: 337 338 ```c 339 // Define a callback. 340 void CloudSyncObserverCallback(void *context, Rdb_ProgressDetails *progressDetails) 341 { 342 // Do something. 343 } 344 const Rdb_ProgressObserver observer = { .context = nullptr, .callback = CloudSyncObserverCallback }; 345 OH_Rdb_CloudSync(store_, Rdb_SyncMode::SYNC_MODE_TIME_FIRST, table, TABLE_COUNT, &observer); 346 ``` 347 34810. 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. 349 350 Call **OH_Rdb_Subscribe** to subscribe to data changes. Before using this API, ensure that the cloud service is available. 351 352 Example: 353 354 ```c 355 // Define a callback. 356 void RdbSubscribeBriefCallback(void *context, const char *values[], uint32_t count) 357 { 358 // Do something. 359 } 360 Rdb_BriefObserver briefObserver; 361 const Rdb_BriefObserver briefObserver = { .context = nullptr, .callback = RdbSubscribeBriefCallback }; 362 // Subscribe to data changes. 363 OH_Rdb_Subscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD, &briefObserver); 364 ``` 365 366 Call **OH_Rdb_Subscribe** to subscribe to local database data changes. <br>Example: 367 368 ```c 369 // Define a callback. 370 void LocalDataChangeObserverCallback1(void *context, const Rdb_ChangeInfo **changeInfo, uint32_t count) 371 { 372 for (uint32_t i = 0; i < count; i++) { 373 EXPECT_EQ(DISTRIBUTED_CHANGE_INFO_VERSION, changeInfo[i]->version); 374 // The table name is employee. 375 changeInfo[i]->tableName; 376 changeInfo[i]->ChangeType; 377 // The number of added rows is 1. 378 changeInfo[i]->inserted.count; 379 // The number of updated rows is 0. 380 changeInfo[i]->updated.count; 381 // The number of deleted rows is 0. 382 changeInfo[i]->deleted.count; 383 } 384 } 385 Rdb_DetailsObserver callback = LocalDataChangeObserverCallback1; 386 Rdb_DataObserver observer = { nullptr, { callback } }; 387 // Subscribe to the local database data changes. 388 OH_Rdb_Subscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS, &observer); 389 390 OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); 391 valueBucket->putText(valueBucket, "NAME", "Lisa"); 392 valueBucket->putInt64(valueBucket, "AGE", 18); 393 valueBucket->putReal(valueBucket, "SALARY", 100.5); 394 uint8_t arr[] = {1, 2, 3, 4, 5}; 395 int len = sizeof(arr) / sizeof(arr[0]); 396 valueBucket->putBlob(valueBucket, "CODES", arr, len); 397 // Insert data. 398 int rowId = OH_Rdb_Insert(store_, "EMPLOYEE", valueBucket); 399 // Destroy the KV pair instance. 400 valueBucket->destroy(valueBucket); 401 ``` 402 40311. Unsubscribe from the events of the specified type for an RDB store. After that, the callback will not be invoked to process the observation. 404 405 Call **OH_Rdb_Unsubscribe** to unsubscribe from data changes. Before using this API, ensure that the cloud service is available. 406 407 Example: 408 409 ```c 410 // Define a callback. 411 void RdbSubscribeBriefCallback(void *context, const char *values[], uint32_t count) 412 { 413 // Do something. 414 } 415 Rdb_BriefObserver briefObserver = RdbSubscribeBriefCallback; 416 const Rdb_DataObserver briefObs = { .context = nullptr, .callback.briefObserver = briefObserver }; 417 // Unsubscribe from data changes. 418 OH_Rdb_Unsubscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD, &briefObs); 419 ``` 420 Call **OH_Rdb_Unsubscribe** to unsubscribe from local database data changes. 421 422 Example: 423 424 ```c 425 // Define a callback. 426 void LocalDataChangeObserverCallback1(void *context, const Rdb_ChangeInfo **changeInfo, uint32_t count) 427 { 428 // Do something. 429 } 430 Rdb_DetailsObserver callback = LocalDataChangeObserverCallback1; 431 Rdb_DataObserver observer = { nullptr, { callback } }; 432 // Unsubscribe from the local database data changes. 433 OH_Rdb_Unsubscribe(store_, Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS, &observer); 434 ``` 435 436 43712. 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. 438 439 Call **OH_Rdb_SubscribeAutoSyncProgress** to subscribe to the auto sync progress. Before using this API, ensure that the cloud service is available. 440 441 Example: 442 443 ```c 444 // Define a callback. 445 void RdbProgressObserverCallback(void *context, Rdb_ProgressDetails *progressDetails) 446 { 447 // Do something. 448} 449 const Rdb_ProgressObserver observer = { .context = nullptr, .callback = RdbProgressObserverCallback }; 450 OH_Rdb_SubscribeAutoSyncProgress(store_, &observer); 451 ``` 452 45313. Unsubscribe from the auto sync progress from an RDB store. After that, the callback will not be invoked to process the observation. 454 455 Call **OH_Rdb_UnsubscribeAutoSyncProgress** to unsubscribe from the auto sync progress. Before using this API, ensure that the cloud service is available. 456 457 Example: 458 459 ```c 460 // Define a callback. 461 void RdbProgressObserverCallback(void *context, Rdb_ProgressDetails *progressDetails) 462 { 463 // Do something. 464 } 465 const Rdb_ProgressObserver observer = { .context = nullptr, .callback = RdbProgressObserverCallback }; 466 OH_Rdb_UnsubscribeAutoSyncProgress(store_, &observer); 467 ``` 468 46914. Delete an RDB store. 470 471 Call **OH_Rdb_DeleteStore** to delete the RDB store and related database file. 472 473 Example: 474 475 ```c 476 // Close the database instance. 477 OH_Rdb_CloseStore(store_); 478 // Delete the database file. 479 OH_Rdb_DeleteStore(&config); 480 ``` 481 482 483 484 485 486 487