subsys-data-relational-database-guide.md 12.3 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_wangli 已提交
5
On the basis of the SQLite database, the RDB allows you to operate data with or without native SQL statements. In OpenHarmony, an RDB is also called RDB store.
A
annie_wangli 已提交
6

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

A
annie_wangli 已提交
10
The following table describes APIs available 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_wangli 已提交
16 17 18 19 20 21
| 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 name, storage mode, log mode, synchronization mode, and read-only mode, and encrypting the database. <ul><li> **path**: path of the database. </li> <li> **readOnly**: whether the database is read-only. </li> <li> **storageMode**: storage mode. </li> <li> **encryptKey**: key used for database encryption. </li> <li> **journalMode**: database logging mode. </li> <li> **syncMode**: data synchronization mode. </li> <li> **databaseFileType**: database type. </li> <li> **databaseFileSecurityLevel**: security level. </li></ul>|
| RdbOpenCallback | int OnCreate(RdbStore &rdbStore) | Called when an RDB store is created. You can add the method for initializing the table structure and add initialization data used by your application in the callback.|
| 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.|
| RdbHelper | int DeleteRdbStore(const std::string &path) | Deletes the specified RDB store.|
A
annie_wangli 已提交
22

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

A
annie_wangli 已提交
25
The RDB provides the database encryption capability. 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 28
Table 2 API for changing the key
| Class| API| Description|
A
annie_wangli 已提交
29
|  ----  |  ----  |  ----  |
A
annie_wangli 已提交
30
| RdbStore | int ChangeEncryptKey(const std::vector<uint8_t> &newKey) | Changes the encryption key for an RDB store. <br>Note: The encryption key can be changed only for an encrypted database.|
A
annie_wangli 已提交
31

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

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

A
annie_wangli 已提交
36 37
- **RdbPredicates**: With this class, you do not need to write complex SQL statements. Instead, you can combine SQL statements simply by calling methods in this class, such as **equalTo**, **notEqualTo**, **groupBy**, **orderByAsc**, and **beginsWith**.
- **RawRdbPredicates**: With this class, you can set **whereClause** and **whereArgs**, but cannot call methods such as **equalTo**.
A
annie_wangli 已提交
38

A
annie_wangli 已提交
39 40
  Table 7 APIs for RDB predicates
  | Class| API| Description|
A
annie_wangli 已提交
41
  |  ----  |  ----  |  ----  |
A
annie_wangli 已提交
42 43 44 45 46 47 48
  | RdbPredicates | AbsPredicates *EqualTo(std::string field, std::string value) | Sets the **AbsPredicates** to match the field that is equal to the specified value.|
  | RdbPredicates | AbsPredicates *NotEqualTo(std::string field, std::string value) | Sets the **AbsPredicates** to match the field that is not equal to the specified value.|
  | RdbPredicates | AbsPredicates *BeginsWith(std::string field, std::string value) | Sets the **AbsPredicates** to match the field that starts with the specified value.|
  | RdbPredicates | AbsPredicates *Between(std::string field, std::string low, std::string high) | Sets the **AbsPredicates** to match the field that is within the range specified by **low** and **high**.|
  | RdbPredicates | AbsPredicates *OrderByAsc(std::string field) | Sets the **AbsPredicates** to match the column with values sorted in ascending order.|
  | 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_wangli 已提交
49

A
annie_wangli 已提交
50
### Managing Data in an RDB Store
A
annie_wangli 已提交
51

A
annie_wangli 已提交
52
The RDB provides APIs for inserting, deleting, updating, and querying data in the local RDB store.
A
annie_wangli 已提交
53

A
annie_wangli 已提交
54
- Inserting data
A
annie_wangli 已提交
55

A
annie_wangli 已提交
56
  The RDB provides an API for inserting data through **ValuesBucket** in a data table. If the data is added, the row number of the data inserted is returned; otherwise, **-1** is returned.
A
annie_wangli 已提交
57

A
annie_wangli 已提交
58
  Table 3 API for inserting data to a data table
A
annie_wangli 已提交
59

A
annie_wangli 已提交
60
  | Class| API| Description|
A
annie_wangli 已提交
61
  |  ----  |  ----  |  ----  |
A
annie_wangli 已提交
62
  | 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**. <ul><li>**table**: specifies the name of the target table. </li><li> **initialValues**: specifies the data, stored in **ValuesBucket**, to insert. 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**.</li></ul> |
A
annie_wangli 已提交
63

A
annie_wangli 已提交
64
- Deleting data
A
annie_wangli 已提交
65
  
A
annie_wangli 已提交
66
  Call the **delete()** method to delete data meeting the conditions specified by **AbsRdbPredicates**. If the data is deleted, the row number of the deleted data is returned; otherwise, **0** is returned.
A
annie_wangli 已提交
67

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

A
annie_wangli 已提交
73
- Updating data
A
annie_wangli 已提交
74

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

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

A
annie_wangli 已提交
82
- Querying data
A
annie_wangli 已提交
83

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

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

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

A
annie_wangli 已提交
95
### Using the Result Set
A
annie_wangli 已提交
96

A
annie_wangli 已提交
97
A result set can be regarded as rows of data in the queried results. It allows you to traverse and access the data you have queried. The following table describes the external APIs of **ResultSet**.
A
annie_wangli 已提交
98

A
annie_wangli 已提交
99 100
  Table 8 APIs for using the result set
  | Class| API| Description|
A
annie_wangli 已提交
101
  |  ----  |  ----  |  ----  |
A
annie_wangli 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114
  | ResultSet | int GoTo(int offset) | Moves the result set forwards or backwards by the specified offset relative to its current position.|
  | ResultSet | int GoToRow(int position) | Moves the result set to the specified row.|
  | ResultSet | int GoToNextRow() | Moves the result set to the next row.|
  | ResultSet | int GoToPreviousRow() | Moves the result set to the previous row.|
  | 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.|
  | ResultSet | int GetRowCount(int &count) | Obtains the number of rows in the result set.|
  | ResultSet | int GetColumnCount(int &count) | Obtains the number of columns in the result set.|
  | ResultSet | int GetString(int columnIndex, std::string &value) | Obtains the values in the specified column of the current row, in strings.|
  | ResultSet | int GetBlob(int columnIndex, std::vector\<uint8_t\> &blob) | Obtains the values in the specified column of the current row, in a byte array.|
  | ResultSet | int GetDouble(int columnIndex, double &value) | Obtains the values in the specified column of the current row, in double.|
A
annie_wangli 已提交
115

A
annie_wangli 已提交
116
## Constraints
A
annie_wangli 已提交
117

A
annie_wangli 已提交
118
None.
A
annie_wangli 已提交
119

A
annie_wangli 已提交
120
## How to Develop
A
annie_wangli 已提交
121

A
annie_wangli 已提交
122
1. Create an RDB store.
A
annie_wangli 已提交
123

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

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

A
annie_wangli 已提交
128
    c. Create an RDB store.
A
annie_wangli 已提交
129

A
annie_wangli 已提交
130
    The sample code is as follows:
A
annie_wangli 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    ```
    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 已提交
152
2. Insert data.
A
annie_wangli 已提交
153

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

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

A
annie_wangli 已提交
158
    The sample code is as follows:
A
annie_wangli 已提交
159 160 161 162 163 164 165 166 167 168 169
    ```
    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 已提交
170
3. Query data.
A
annie_wangli 已提交
171

A
annie_wangli 已提交
172
    a. Create a predicate that specifies query conditions.
A
annie_wangli 已提交
173

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

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

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

A
annie_wangli 已提交
180
    The sample code is as follows:
A
annie_wangli 已提交
181 182 183 184 185 186 187 188
    ```
    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();
    ```