diff --git a/en/application-dev/database/data-persistence-by-rdb-store.md b/en/application-dev/database/data-persistence-by-rdb-store.md
index ff37d0fdce056ca143015f39c81892c990f6545d..5879f73dac606c956fa305e9602eb1673f1fb369 100644
--- a/en/application-dev/database/data-persistence-by-rdb-store.md
+++ b/en/application-dev/database/data-persistence-by-rdb-store.md
@@ -50,7 +50,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
## How to Develop
-1. Obtain an **RdbStore** instance.
Example:
+1. Obtain an **RdbStore** instance.
Example:
Stage model:
@@ -97,7 +97,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
store.version = 3;
}
- // Perform operations such as adding, deleting, modifying, and querying data in the RDB store.
+ // Before performing data operations on the database, obtain an RdbStore instance.
});
}
@@ -151,7 +151,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
store.version = 3;
}
- // Perform operations such as adding, deleting, modifying, and querying data in the RDB store.
+ // Before performing data operations on the database, obtain an RdbStore instance.
});
```
@@ -256,7 +256,9 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
5. Delete the RDB store.
- Use **deleteRdbStore()** to delete the RDB store and related database files.
+ Use **deleteRdbStore()** to delete the RDB store and related database files.
+
+ Example:
> **NOTE**
>
@@ -299,4 +301,4 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
store = null;
console.info('Succeeded in deleting RdbStore.');
});
- ```
+ ```
\ No newline at end of file
diff --git a/en/application-dev/reference/apis/js-apis-data-relationalStore.md b/en/application-dev/reference/apis/js-apis-data-relationalStore.md
index 21af7666f861e43b0bc81871308d25f39a07dfae..650be3aed9d4910e7ed656eab7563a09571e6065 100644
--- a/en/application-dev/reference/apis/js-apis-data-relationalStore.md
+++ b/en/application-dev/reference/apis/js-apis-data-relationalStore.md
@@ -216,6 +216,8 @@ FA model:
```js
import featureAbility from '@ohos.ability.featureAbility'
+var store;
+
// Obtain the context.
let context = featureAbility.getContext()
@@ -234,6 +236,8 @@ Stage model:
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
+var store;
+
class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage){
relationalStore.deleteRdbStore(this.context, "RdbTest.db", function (err) {
@@ -287,6 +291,8 @@ FA model:
```js
import featureAbility from '@ohos.ability.featureAbility'
+var store;
+
// Obtain the context.
let context = featureAbility.getContext();
@@ -304,6 +310,8 @@ Stage model:
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
+var store;
+
class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage){
let promise = relationalStore.deleteRdbStore(this.context, "RdbTest.db");
@@ -353,6 +361,8 @@ FA model:
```js
import featureAbility from '@ohos.ability.featureAbility'
+var store;
+
// Obtain the context.
let context = featureAbility.getContext()
const STORE_CONFIG = {
@@ -375,6 +385,8 @@ Stage model:
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
+var store;
+
class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage){
const STORE_CONFIG = {
@@ -434,6 +446,8 @@ FA model:
```js
import featureAbility from '@ohos.ability.featureAbility'
+var store;
+
// Obtain the context.
let context = featureAbility.getContext();
const STORE_CONFIG = {
@@ -455,6 +469,8 @@ Stage model:
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
+var store;
+
class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage){
const STORE_CONFIG = {
@@ -482,7 +498,7 @@ Defines the RDB store configuration.
| ------------- | ------------- | ---- | --------------------------------------------------------- |
| name | string | Yes | Database file name. |
| securityLevel | [SecurityLevel](#securitylevel) | Yes | Security level of the RDB store. |
-| encrypt | boolean | No | Whether to encrypt the RDB store.
The value **true** means to encrypt the RDB store;
the value **false** (default) means the opposite.|
+| encrypt | boolean | No | Whether to encrypt the RDB store.
The value **true** means to encrypt the RDB store;the value **false** (default) means the opposite.|
| dataGroupId10+ | string | No| Application group ID, which needs to be obtained from the AppGallery.
**Model restriction**: This attribute can be used only in the stage model.
This parameter is supported since API version 10. It specifies the **relationalStore** instance created in the sandbox directory corresponding to the **dataGroupId**. If this parameter is not specified, the **relationalStore** instance is created in the sandbox directory of the application.|
## SecurityLevel
@@ -658,8 +674,8 @@ Enumerates the distributed table types. Use the enum names instead of the enum v
| Name | Value | Description |
| ------------------ | --- | -------------------------------------------------------------------------------------------------- |
-| DISTRIBUTED_DEVICE | - | Distributed database table between devices.
**System capability**: SystemCapability.DistributedDataManager.RelationalStore.Core |
-| DISTRIBUTED_CLOUD | - | Distributed database table between the device and the cloud.
**System capability**: SystemCapability.DistributedDataManager.CloudSync.Client|
+| DISTRIBUTED_DEVICE | - | Distributed database table synchronized between devices.
**System capability**: SystemCapability.DistributedDataManager.RelationalStore.Core |
+| DISTRIBUTED_CLOUD | - | Distributed database table synchronized between the device and the cloud.
**System capability**: SystemCapability.DistributedDataManager.CloudSync.Client |
## DistributedConfig10+
@@ -669,7 +685,7 @@ Defines the configuration of the distributed mode of tables.
| Name | Type | Mandatory| Description |
| -------- | ------- | ---- | ------------------------------------------------------------ |
-| autoSync | boolean | Yes | The value **true** means both automatic synchronization and manual synchronization are supported for the table. The value **false** means only manual synchronization is supported for the table.|
+| autoSync | boolean | Yes | The value **true** means both automatic synchronization and manual synchronization are supported for the table.
The value **false** means only manual synchronization is supported for the table. |
## ConflictResolution10+
@@ -704,12 +720,12 @@ Represents the device-cloud synchronization statistics information.
**System capability**: SystemCapability.DistributedDataManager.RelationalStore.Core
-| Name | Type | Mandatory| Description |
-| -------- | ------ | ---- | ---------------------------------------- |
-| total | number | Yes | Total number of rows to be synchronized between the device and cloud in the database table. |
-| success | number | Yes | Number of rows that are successfully synchronized between the device and cloud in the database table. |
-| failed | number | Yes | Number of rows that failed to be synchronized between the device and cloud in the database table. |
-| remained | number | Yes | Number of rows that are not executed for device-cloud synchronization in the database table.|
+| Name | Type | Mandatory| Description |
+| ---------- | ------ | ---- | ---------------------------------------- |
+| total | number | Yes | Total number of rows to be synchronized between the device and cloud in the database table. |
+| successful | number | Yes | Number of rows that are successfully synchronized between the device and cloud in the database table. |
+| failed | number | Yes | Number of rows that failed to be synchronized between the device and cloud in the database table. |
+| remained | number | Yes | Number of rows that are not executed for device-cloud synchronization in the database table.|
## TableDetails10+
@@ -2432,7 +2448,7 @@ store.query(predicates, function (err, resultSet) {
}
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2480,7 +2496,7 @@ store.query(predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"], function (err,
}
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2530,7 +2546,7 @@ let promise = store.query(predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"]);
promise.then((resultSet) => {
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2585,7 +2601,7 @@ store.query("EMPLOYEE", predicates, function (err, resultSet) {
}
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2639,7 +2655,7 @@ store.query("EMPLOYEE", predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"], fu
}
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2695,7 +2711,7 @@ let promise = store.query("EMPLOYEE", predicates, ["ID", "NAME", "AGE", "SALARY"
promise.then((resultSet) => {
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2766,7 +2782,7 @@ store.remoteQuery(deviceId, "EMPLOYEE", predicates, ["ID", "NAME", "AGE", "SALAR
}
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2837,7 +2853,7 @@ let promise = store.remoteQuery(deviceId, "EMPLOYEE", predicates, ["ID", "NAME",
promise.then((resultSet) => {
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2884,7 +2900,7 @@ store.querySql("SELECT * FROM EMPLOYEE CROSS JOIN BOOK WHERE BOOK.NAME = 'sanguo
}
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2930,7 +2946,7 @@ store.querySql("SELECT * FROM EMPLOYEE CROSS JOIN BOOK WHERE BOOK.NAME = ?", ['s
}
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -2978,7 +2994,7 @@ let promise = store.querySql("SELECT * FROM EMPLOYEE CROSS JOIN BOOK WHERE BOOK.
promise.then((resultSet) => {
console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);
// resultSet is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
- while(resultSet.goToNextRow()) {
+ while (resultSet.goToNextRow()) {
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
@@ -3533,7 +3549,46 @@ promise.then(() => {
### setDistributedTables10+
-setDistributedTables(tables: Array<string>, type: number, config: DistributedConfig, callback: AsyncCallback<void>): void
+setDistributedTables(tables: Array<string>, type: DistributedType, callback: AsyncCallback<void>): void
+
+Sets distributed tables. This API uses an asynchronous callback to return the result.
+
+**Required permissions**: ohos.permission.DISTRIBUTED_DATASYNC
+
+**System capability**: SystemCapability.DistributedDataManager.RelationalStore.Core
+
+**Parameters**
+
+| Name | Type | Mandatory| Description |
+| -------- | ------------------------------------- | ---- | ---------------------------- |
+| tables | Array<string> | Yes | Names of the distributed tables to set.|
+| type | [DistributedType](#distributedtype10) | Yes | Distributed type of the tables. |
+| callback | AsyncCallback<void> | Yes | Callback invoked to return the result. |
+
+**Error codes**
+
+For details about the error codes, see [RDB Error Codes](../errorcodes/errorcode-data-rdb.md).
+
+| **ID**| **Error Message**|
+| ------------ | ------------ |
+| 14800000 | Inner error. |
+| 14800051 |The type of the distributed table does not match.|
+
+**Example**
+
+```js
+store.setDistributedTables(["EMPLOYEE"], relationalStore.DistributedType.DISTRIBUTED_CLOUD, function (err) {
+ if (err) {
+ console.error(`SetDistributedTables failed, code is ${err.code},message is ${err.message}`);
+ return;
+ }
+ console.info(`SetDistributedTables successfully.`);
+})
+```
+
+### setDistributedTables10+
+
+setDistributedTables(tables: Array<string>, type: DistributedType, config: DistributedConfig, callback: AsyncCallback<void>): void
Sets distributed tables. This API uses an asynchronous callback to return the result.
@@ -3546,16 +3601,25 @@ Sets distributed tables. This API uses an asynchronous callback to return the re
| Name | Type | Mandatory | Description |
| -------- | ----------------------------------- | --- | --------------- |
| tables | Array<string> | Yes | Names of the distributed tables to set. |
-| type | number | Yes | Distributed type of the tables. Currently, only **relationalStore.DistributedType.DISTRIBUTED_DEVICE** and **relationalStore.DistributedType.DISTRIBUTED_CLOUD** are supported.
The value **relationalStore.DistributedType.DISTRIBUTED_DEVICE** indicates distributed tables across different devices.
The value **relationalStore.DistributedType.DISTRIBUTED_CLOUD** indicates distributed tables between the device and cloud.|
+| type | [DistributedType](#distributedtype10) | Yes | Distributed type of the tables.|
| config | [DistributedConfig](#distributedconfig10) | Yes| Configuration of the distributed mode.|
| callback | AsyncCallback<void> | Yes | Callback invoked to return the result.|
+**Error codes**
+
+For details about the error codes, see [RDB Error Codes](../errorcodes/errorcode-data-rdb.md).
+
+| **ID**| **Error Message** |
+| ------------ | ------------------------------------------------- |
+| 14800000 | Inner error. |
+| 14800051 | The type of the distributed table does not match. |
+
**Example**
```js
-let config = new relationalStore.DistributedConfig();
-config.autoSync = true;
-store.setDistributedTables(["EMPLOYEE"], relationalStore.DistributedType.DISTRIBUTED_CLOUD, config, function (err) {
+store.setDistributedTables(["EMPLOYEE"], relationalStore.DistributedType.DISTRIBUTED_CLOUD, {
+ autoSync: true
+}, function (err) {
if (err) {
console.error(`SetDistributedTables failed, code is ${err.code},message is ${err.message}`);
return;
@@ -3566,7 +3630,7 @@ store.setDistributedTables(["EMPLOYEE"], relationalStore.DistributedType.DISTRIB
### setDistributedTables10+
- setDistributedTables(tables: Array<string>, type?: number, config?: DistributedConfig): Promise<void>
+ setDistributedTables(tables: Array<string>, type?: DistributedType, config?: DistributedConfig): Promise<void>
Sets distributed tables. This API uses a promise to return the result.
@@ -3578,8 +3642,8 @@ Sets distributed tables. This API uses a promise to return the result.
| Name| Type | Mandatory| Description |
| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ |
-| tables | Array<string> | Yes | Names of the distributed tables to set. |
-| type | number | No | Distributed type of the tables. The default value is **relationalStore.DistributedType.DISTRIBUTED_DEVICE**.
Currently, only **relationalStore.DistributedType.DISTRIBUTED_DEVICE** and **relationalStore.DistributedType.DISTRIBUTED_CLOUD** are supported.
The value **relationalStore.DistributedType.DISTRIBUTED_DEVICE** indicates distributed tables across different devices.
The value **relationalStore.DistributedType.DISTRIBUTED_CLOUD** indicates distributed tables between the device and cloud.|
+| tables | Array<string> | Yes | Names of the distributed tables to set. |
+| type | [DistributedType](#distributedtype10) | No | Distributed type of the tables. The default value is **relationalStore.DistributedType.DISTRIBUTED_DEVICE**.|
| config | [DistributedConfig](#distributedconfig10) | No | Configuration of the distributed mode. If this parameter is not specified, the value of **autoSync** is **false** by default, which means only manual synchronization is supported.|
**Return value**
@@ -3588,12 +3652,21 @@ Sets distributed tables. This API uses a promise to return the result.
| ------------------- | ------------------------- |
| Promise<void> | Promise that returns no value.|
+**Error codes**
+
+For details about the error codes, see [RDB Error Codes](../errorcodes/errorcode-data-rdb.md).
+
+| **ID**| **Error Message** |
+| ------------ | ------------------------------------------------- |
+| 14800000 | Inner error. |
+| 14800051 | The type of the distributed table does not match. |
+
**Example**
```js
-let config = new relationalStore.DistributedConfig();
-config.autoSync = true;
-let promise = store.setDistributedTables(["EMPLOYEE"], relationalStore.DistributedType.DISTRIBUTED_CLOUD, config);
+let promise = store.setDistributedTables(["EMPLOYEE"], relationalStore.DistributedType.DISTRIBUTED_CLOUD, {
+ autoSync: true
+});
promise.then(() => {
console.info(`SetDistributedTables successfully.`);
}).catch((err) => {
@@ -3860,7 +3933,7 @@ Manually starts device-cloud synchronization for all distributed tables. This AP
**Example**
```js
-relationalStore.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, function (progressDetails) {
+store.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, function (progressDetails) {
console.info(`Progess: ${progressDetails}`);
}, function (err) {
if (err) {
@@ -3901,7 +3974,7 @@ function progress(progressDetail) {
console.info(`progress: ${progressDetail}`);
}
-relationalStore.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, progress).then(() => {
+store.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, progress).then(() => {
console.info('Cloud sync succeeded');
}).catch((err) => {
console.error(`cloudSync failed, code is ${err.code},message is ${err.message}`);
@@ -3931,7 +4004,7 @@ Manually starts device-cloud synchronization of the specified table. This API us
```js
const tables = ["table1", "table2"];
-relationalStore.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, tables, function (progressDetails) {
+store.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, tables, function (progressDetails) {
console.info(`Progess: ${progressDetails}`);
}, function (err) {
if (err) {
@@ -3974,7 +4047,7 @@ function progress(progressDetail) {
console.info(`progress: ${progressDetail}`);
}
-relationalStore.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, tables, progress).then(() => {
+store.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, tables, progress).then(() => {
console.info('Cloud sync succeeded');
}).catch((err) => {
console.error(`cloudSync failed, code is ${err.code},message is ${err.message}`);
diff --git a/en/application-dev/reference/errorcodes/errorcode-data-rdb.md b/en/application-dev/reference/errorcodes/errorcode-data-rdb.md
index 63ab092c86f4f9102d954f5644dbb6f2179560f7..219a3649fe3790d5ccee9ff472a1885acc4d6cad 100644
--- a/en/application-dev/reference/errorcodes/errorcode-data-rdb.md
+++ b/en/application-dev/reference/errorcodes/errorcode-data-rdb.md
@@ -118,7 +118,7 @@ Data is added, deleted, and modified continuously without closing the read trans
1. Check for unclosed result sets or transactions.
-2. Closes all result sets or transactions.
+2. Close all result sets or transactions.
## 14800050 Failed to Obtain the Subscription Service
@@ -142,7 +142,7 @@ Deploy the subscription service on the platform.
**Error Message**
-Only supported in stage mode.
+ Only supported in stage mode.
**Description**
@@ -173,3 +173,21 @@ The **dataGroupId** is not obtained from the AppGallery.
**Solution**
Obtain **dataGroupId** from the AppGallery and pass it to **storeConfig** correctly.
+
+## 14800051 Inconsistent Distributed Table Type
+
+**Error Message**
+
+The type of the distributed table does not match.
+
+**Description**
+
+Different distributed table types are set for the same database table.
+
+**Possible Causes**
+
+The database table is set with different [distributed table types](../apis/js-apis-data-relationalStore.md#distributedtype10).
+
+**Solution**
+
+A database table can be synchronized either between devices or between device and cloud.