diff --git a/v1.13.x/api-reference/data-quality/test-cases/create.mdx b/v1.13.x/api-reference/data-quality/test-cases/create.mdx index 888bb4bb..78661b7c 100644 --- a/v1.13.x/api-reference/data-quality/test-cases/create.mdx +++ b/v1.13.x/api-reference/data-quality/test-cases/create.mdx @@ -18,7 +18,7 @@ The server associates the test case with the basic suite of the table in `entity - Fully qualified name (FQN) of the test definition to use. For example, `columnValueMaxToBeBetween`. + Fully qualified name (FQN) of the test definition to use. For example, `columnValueMaxToBeBetween`. For a custom SQL test (the **Custom SQL Query** test type in the UI), use `tableCustomSQLQuery`. For a test case on a custom test definition you created, use that definition's name, such as `columnValuesMaxLength`. For more information, see [Custom SQL Test Cases](#custom-sql-test-cases). @@ -140,6 +140,39 @@ curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ "description": "Validates shop_id max value stays between 1 and 100" }' ``` + +```bash POST /v1/dataQuality/testCases (custom SQL) +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "orders_no_negative_amounts", + "testDefinition": "tableCustomSQLQuery", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.orders>", + "parameterValues": [ + {"name": "sqlExpression", "value": "SELECT * FROM orders WHERE amount < 0"}, + {"name": "strategy", "value": "ROWS"}, + {"name": "operator", "value": "=="}, + {"name": "threshold", "value": "0"} + ], + "computePassedFailedRowCount": true + }' +``` + +```bash POST /v1/dataQuality/testCases (custom test definition) +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "email_max_length", + "testDefinition": "columnValuesMaxLength", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.dim_address::columns::email>", + "parameterValues": [ + {"name": "maxLength", "value": "50"} + ], + "computePassedFailedRowCount": true + }' +``` @@ -294,8 +327,15 @@ curl -X PUT "{base_url}/api/v1/dataQuality/testCases" \ ## Custom SQL Test Cases +OpenMetadata has two ways to run SQL in a test case: + +- **Custom SQL test**: the **Custom SQL Query** test type in the UI. The test case uses the built-in `tableCustomSQLQuery` test definition and carries the SQL itself in `parameterValues`. You don't create a test definition. +- **Custom test definition**: a reusable SQL template you create once, with `{{ paramName }}` placeholders. Test cases then reference it by name. For more information, see [Test Cases for a Custom Test Definition](#test-cases-for-a-custom-test-definition). + A test case passes values to a SQL-based test definition through `parameterValues`. The server rejects any parameter that the test definition doesn't declare in `parameterDefinition`, and requires every parameter marked `required`. +### Custom SQL Test + The built-in `tableCustomSQLQuery` test definition runs a SQL query against a table. It accepts these parameters: | Parameter | Required | Description | @@ -316,13 +356,37 @@ curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.orders>", "parameterValues": [ {"name": "sqlExpression", "value": "SELECT * FROM orders WHERE amount < 0"}, - {"name": "strategy", "value": "ROWS"} + {"name": "strategy", "value": "ROWS"}, + {"name": "operator", "value": "=="}, + {"name": "threshold", "value": "0"} + ], + "computePassedFailedRowCount": true + }' +``` + +### Test Cases for a Custom Test Definition + +A test case for a custom SQL test definition sets `testDefinition` to the definition's name and passes one `parameterValues` entry per `{{ paramName }}` placeholder. The following request uses a custom `columnValuesMaxLength` definition, which declares `maxLength`: + +```bash +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "email_max_length", + "testDefinition": "columnValuesMaxLength", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.dim_address::columns::email>", + "parameterValues": [ + {"name": "maxLength", "value": "50"} ], "computePassedFailedRowCount": true }' ``` -For a custom test definition that uses `{{ paramName }}` placeholders, pass one `parameterValues` entry per placeholder. For more information, see [Create a Test Definition](/v1.13.x/api-reference/data-quality/test-definitions/create#custom-sql-test-definitions). +- **Pass condition**: The test case passes only when the number of rows the SQL returns is 0. +- **Row counts**: Set `computePassedFailedRowCount` to `true` to report passed and failed row counts. + +For more information, see [Create a Test Definition](/v1.13.x/api-reference/data-quality/test-definitions/create#custom-sql-test-definitions). ## Error Handling diff --git a/v1.13.x/api-reference/data-quality/test-definitions/create.mdx b/v1.13.x/api-reference/data-quality/test-definitions/create.mdx index 7ff8a65a..80effe97 100644 --- a/v1.13.x/api-reference/data-quality/test-definitions/create.mdx +++ b/v1.13.x/api-reference/data-quality/test-definitions/create.mdx @@ -68,7 +68,12 @@ Create a custom test definition to define organization-specific data quality val - Name of the validator that runs the test. For custom SQL-based tests, defaults to `ruleLibrarySqlExpressionValidator` when omitted. + Class name of the validator that runs the test. For a custom SQL test definition, set one of the following values. The OpenMetadata UI sets the same values when you create a custom SQL test definition: + + - `ColumnRuleLibrarySqlExpressionValidator`: use when `entityType` is `COLUMN`. + - `TableRuleLibrarySqlExpressionValidator`: use when `entityType` is `TABLE`. + + Built-in test definitions use their own validators, which you can't select for a custom definition. The server accepts any string for this field, so always set it explicitly for SQL-based definitions. @@ -113,24 +118,21 @@ configure( ) request = CreateTestDefinitionRequest( - name="columnValuesToMatchBusinessRule", - displayName="Column Values To Match Business Rule", - description="Validates that column values conform to a custom business rule regex pattern", + name="columnValuesMaxLength", + displayName="Column Values Max Length", + description="Fails when a value is longer than the allowed length", entityType="COLUMN", testPlatforms=["OpenMetadata"], + dataQualityDimension="SQL", supportedDataTypes=["STRING", "VARCHAR", "TEXT"], + sqlExpression="SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + validatorClass="ColumnRuleLibrarySqlExpressionValidator", parameterDefinition=[ { - "name": "regexPattern", - "dataType": "STRING", - "required": True, - "description": "The regex pattern to match against" - }, - { - "name": "threshold", + "name": "maxLength", "dataType": "INT", - "required": False, - "description": "Maximum number of non-matching values allowed" + "required": True, + "description": "Maximum allowed length" } ] ) @@ -177,25 +179,17 @@ curl -X POST "{base_url}/api/v1/dataQuality/testDefinitions" \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '{ - "name": "columnValuesToMatchBusinessRule", - "displayName": "Column Values To Match Business Rule", - "description": "Validates that column values conform to a custom business rule regex pattern", + "name": "columnValuesMaxLength", + "displayName": "Column Values Max Length", + "description": "Fails when a value is longer than the allowed length", "entityType": "COLUMN", "testPlatforms": ["OpenMetadata"], + "dataQualityDimension": "SQL", "supportedDataTypes": ["STRING", "VARCHAR", "TEXT"], + "sqlExpression": "SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + "validatorClass": "ColumnRuleLibrarySqlExpressionValidator", "parameterDefinition": [ - { - "name": "regexPattern", - "dataType": "STRING", - "required": true, - "description": "The regex pattern to match against" - }, - { - "name": "threshold", - "dataType": "INT", - "required": false, - "description": "Maximum number of non-matching values allowed" - } + {"name": "maxLength", "dataType": "INT", "required": true, "description": "Maximum allowed length"} ] }' ``` @@ -321,6 +315,8 @@ Returns the created test definition object with all specified properties and sys ## Custom SQL Test Definitions +A custom test definition is a reusable SQL template. To run a one-off SQL query on a single table, such as the **Custom SQL Query** test type in the UI, create a test case with the built-in `tableCustomSQLQuery` definition instead. For more information, see [Custom SQL Test Cases](/v1.13.x/api-reference/data-quality/test-cases/create#custom-sql-test-cases). + To create a test definition that runs your own SQL, set `sqlExpression` and declare every `{{ paramName }}` placeholder in `parameterDefinition`. The following request creates a column-level test that fails when any value in the column is longer than a limit: ```bash @@ -336,13 +332,9 @@ curl -X POST "{base_url}/api/v1/dataQuality/testDefinitions" \ "dataQualityDimension": "SQL", "supportedDataTypes": ["STRING", "VARCHAR", "TEXT"], "sqlExpression": "SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + "validatorClass": "ColumnRuleLibrarySqlExpressionValidator", "parameterDefinition": [ - { - "name": "maxLength", - "dataType": "INT", - "required": true, - "description": "Maximum allowed length" - } + {"name": "maxLength", "dataType": "INT", "required": true, "description": "Maximum allowed length"} ] }' ``` diff --git a/v2.0.x/api-reference/data-quality/test-cases/create.mdx b/v2.0.x/api-reference/data-quality/test-cases/create.mdx index f049557c..15544a75 100644 --- a/v2.0.x/api-reference/data-quality/test-cases/create.mdx +++ b/v2.0.x/api-reference/data-quality/test-cases/create.mdx @@ -18,7 +18,7 @@ The server associates the test case with the basic suite of the table in `entity - Fully qualified name (FQN) of the test definition to use. For example, `columnValueMaxToBeBetween`. + Fully qualified name (FQN) of the test definition to use. For example, `columnValueMaxToBeBetween`. For a custom SQL test (the **Custom SQL Query** test type in the UI), use `tableCustomSQLQuery`. For a test case on a custom test definition you created, use that definition's name, such as `columnValuesMaxLength`. For more information, see [Custom SQL Test Cases](#custom-sql-test-cases). @@ -140,6 +140,39 @@ curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ "description": "Validates shop_id max value stays between 1 and 100" }' ``` + +```bash POST /v1/dataQuality/testCases (custom SQL) +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "orders_no_negative_amounts", + "testDefinition": "tableCustomSQLQuery", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.orders>", + "parameterValues": [ + {"name": "sqlExpression", "value": "SELECT * FROM orders WHERE amount < 0"}, + {"name": "strategy", "value": "ROWS"}, + {"name": "operator", "value": "=="}, + {"name": "threshold", "value": "0"} + ], + "computePassedFailedRowCount": true + }' +``` + +```bash POST /v1/dataQuality/testCases (custom test definition) +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "email_max_length", + "testDefinition": "columnValuesMaxLength", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.dim_address::columns::email>", + "parameterValues": [ + {"name": "maxLength", "value": "50"} + ], + "computePassedFailedRowCount": true + }' +``` @@ -294,8 +327,15 @@ curl -X PUT "{base_url}/api/v1/dataQuality/testCases" \ ## Custom SQL Test Cases +OpenMetadata has two ways to run SQL in a test case: + +- **Custom SQL test**: the **Custom SQL Query** test type in the UI. The test case uses the built-in `tableCustomSQLQuery` test definition and carries the SQL itself in `parameterValues`. You don't create a test definition. +- **Custom test definition**: a reusable SQL template you create once, with `{{ paramName }}` placeholders. Test cases then reference it by name. For more information, see [Test Cases for a Custom Test Definition](#test-cases-for-a-custom-test-definition). + A test case passes values to a SQL-based test definition through `parameterValues`. The server rejects any parameter that the test definition doesn't declare in `parameterDefinition`, and requires every parameter marked `required`. +### Custom SQL Test + The built-in `tableCustomSQLQuery` test definition runs a SQL query against a table. It accepts these parameters: | Parameter | Required | Description | @@ -316,13 +356,37 @@ curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.orders>", "parameterValues": [ {"name": "sqlExpression", "value": "SELECT * FROM orders WHERE amount < 0"}, - {"name": "strategy", "value": "ROWS"} + {"name": "strategy", "value": "ROWS"}, + {"name": "operator", "value": "=="}, + {"name": "threshold", "value": "0"} + ], + "computePassedFailedRowCount": true + }' +``` + +### Test Cases for a Custom Test Definition + +A test case for a custom SQL test definition sets `testDefinition` to the definition's name and passes one `parameterValues` entry per `{{ paramName }}` placeholder. The following request uses a custom `columnValuesMaxLength` definition, which declares `maxLength`: + +```bash +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "email_max_length", + "testDefinition": "columnValuesMaxLength", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.dim_address::columns::email>", + "parameterValues": [ + {"name": "maxLength", "value": "50"} ], "computePassedFailedRowCount": true }' ``` -For a custom test definition that uses `{{ paramName }}` placeholders, pass one `parameterValues` entry per placeholder. For more information, see [Create a Test Definition](/v2.0.x/api-reference/data-quality/test-definitions/create#custom-sql-test-definitions). +- **Pass condition**: The test case passes only when the number of rows the SQL returns is 0. +- **Row counts**: Set `computePassedFailedRowCount` to `true` to report passed and failed row counts. + +For more information, see [Create a Test Definition](/v2.0.x/api-reference/data-quality/test-definitions/create#custom-sql-test-definitions). ## Error Handling diff --git a/v2.0.x/api-reference/data-quality/test-definitions/create.mdx b/v2.0.x/api-reference/data-quality/test-definitions/create.mdx index 312936df..a65a5e68 100644 --- a/v2.0.x/api-reference/data-quality/test-definitions/create.mdx +++ b/v2.0.x/api-reference/data-quality/test-definitions/create.mdx @@ -68,7 +68,12 @@ Create a custom test definition to define organization-specific data quality val - Name of the validator that runs the test. For custom SQL-based tests, defaults to `ruleLibrarySqlExpressionValidator` when omitted. + Class name of the validator that runs the test. For a custom SQL test definition, set one of the following values. The OpenMetadata UI sets the same values when you create a custom SQL test definition: + + - `ColumnRuleLibrarySqlExpressionValidator`: use when `entityType` is `COLUMN`. + - `TableRuleLibrarySqlExpressionValidator`: use when `entityType` is `TABLE`. + + Built-in test definitions use their own validators, which you can't select for a custom definition. The server accepts any string for this field, so always set it explicitly for SQL-based definitions. @@ -113,24 +118,21 @@ configure( ) request = CreateTestDefinitionRequest( - name="columnValuesToMatchBusinessRule", - displayName="Column Values To Match Business Rule", - description="Validates that column values conform to a custom business rule regex pattern", + name="columnValuesMaxLength", + displayName="Column Values Max Length", + description="Fails when a value is longer than the allowed length", entityType="COLUMN", testPlatforms=["OpenMetadata"], + dataQualityDimension="SQL", supportedDataTypes=["STRING", "VARCHAR", "TEXT"], + sqlExpression="SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + validatorClass="ColumnRuleLibrarySqlExpressionValidator", parameterDefinition=[ { - "name": "regexPattern", - "dataType": "STRING", - "required": True, - "description": "The regex pattern to match against" - }, - { - "name": "threshold", + "name": "maxLength", "dataType": "INT", - "required": False, - "description": "Maximum number of non-matching values allowed" + "required": True, + "description": "Maximum allowed length" } ] ) @@ -177,25 +179,17 @@ curl -X POST "{base_url}/api/v1/dataQuality/testDefinitions" \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '{ - "name": "columnValuesToMatchBusinessRule", - "displayName": "Column Values To Match Business Rule", - "description": "Validates that column values conform to a custom business rule regex pattern", + "name": "columnValuesMaxLength", + "displayName": "Column Values Max Length", + "description": "Fails when a value is longer than the allowed length", "entityType": "COLUMN", "testPlatforms": ["OpenMetadata"], + "dataQualityDimension": "SQL", "supportedDataTypes": ["STRING", "VARCHAR", "TEXT"], + "sqlExpression": "SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + "validatorClass": "ColumnRuleLibrarySqlExpressionValidator", "parameterDefinition": [ - { - "name": "regexPattern", - "dataType": "STRING", - "required": true, - "description": "The regex pattern to match against" - }, - { - "name": "threshold", - "dataType": "INT", - "required": false, - "description": "Maximum number of non-matching values allowed" - } + {"name": "maxLength", "dataType": "INT", "required": true, "description": "Maximum allowed length"} ] }' ``` @@ -321,6 +315,8 @@ Returns the created test definition object with all specified properties and sys ## Custom SQL Test Definitions +A custom test definition is a reusable SQL template. To run a one-off SQL query on a single table, such as the **Custom SQL Query** test type in the UI, create a test case with the built-in `tableCustomSQLQuery` definition instead. For more information, see [Custom SQL Test Cases](/v2.0.x/api-reference/data-quality/test-cases/create#custom-sql-test-cases). + To create a test definition that runs your own SQL, set `sqlExpression` and declare every `{{ paramName }}` placeholder in `parameterDefinition`. The following request creates a column-level test that fails when any value in the column is longer than a limit: ```bash @@ -336,13 +332,9 @@ curl -X POST "{base_url}/api/v1/dataQuality/testDefinitions" \ "dataQualityDimension": "SQL", "supportedDataTypes": ["STRING", "VARCHAR", "TEXT"], "sqlExpression": "SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + "validatorClass": "ColumnRuleLibrarySqlExpressionValidator", "parameterDefinition": [ - { - "name": "maxLength", - "dataType": "INT", - "required": true, - "description": "Maximum allowed length" - } + {"name": "maxLength", "dataType": "INT", "required": true, "description": "Maximum allowed length"} ] }' ``` diff --git a/v2.1.x-SNAPSHOT/api-reference/data-quality/test-cases/create.mdx b/v2.1.x-SNAPSHOT/api-reference/data-quality/test-cases/create.mdx index b800da98..20591182 100644 --- a/v2.1.x-SNAPSHOT/api-reference/data-quality/test-cases/create.mdx +++ b/v2.1.x-SNAPSHOT/api-reference/data-quality/test-cases/create.mdx @@ -18,7 +18,7 @@ The server associates the test case with the basic suite of the table in `entity - Fully qualified name (FQN) of the test definition to use. For example, `columnValueMaxToBeBetween`. + Fully qualified name (FQN) of the test definition to use. For example, `columnValueMaxToBeBetween`. For a custom SQL test (the **Custom SQL Query** test type in the UI), use `tableCustomSQLQuery`. For a test case on a custom test definition you created, use that definition's name, such as `columnValuesMaxLength`. For more information, see [Custom SQL Test Cases](#custom-sql-test-cases). @@ -144,6 +144,41 @@ curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ "description": "Validates shop_id max value stays between 1 and 100" }' ``` + +```bash POST /v1/dataQuality/testCases (custom SQL) +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "orders_no_negative_amounts", + "testDefinition": "tableCustomSQLQuery", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.orders>", + "parameterValues": [ + {"name": "sqlExpression", "value": "SELECT * FROM orders WHERE amount < 0"}, + {"name": "strategy", "value": "ROWS"}, + {"name": "operator", "value": "=="}, + {"name": "threshold", "value": "0"} + ], + "computePassedFailedRowCount": true + }' +``` + +```bash POST /v1/dataQuality/testCases (custom test definition) +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "email_max_length", + "testDefinition": "columnValuesMaxLength", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.dim_address::columns::email>", + "parameterValues": [ + {"name": "maxLength", "value": "50"}, + {"name": "threshold", "value": "5"}, + {"name": "thresholdUnit", "value": "PERCENTAGE"} + ], + "computePassedFailedRowCount": true + }' +``` @@ -298,8 +333,15 @@ curl -X PUT "{base_url}/api/v1/dataQuality/testCases" \ ## Custom SQL Test Cases +OpenMetadata has two ways to run SQL in a test case: + +- **Custom SQL test**: the **Custom SQL Query** test type in the UI. The test case uses the built-in `tableCustomSQLQuery` test definition and carries the SQL itself in `parameterValues`. You don't create a test definition. +- **Custom test definition**: a reusable SQL template you create once, with `{{ paramName }}` placeholders. Test cases then reference it by name. For more information, see [Test Cases for a Custom Test Definition](#test-cases-for-a-custom-test-definition). + A test case passes values to a SQL-based test definition through `parameterValues`. The server rejects any parameter that the test definition doesn't declare in `parameterDefinition`, and requires every parameter marked `required`. +### Custom SQL Test + The built-in `tableCustomSQLQuery` test definition runs a SQL query against a table. It accepts these parameters: | Parameter | Required | Description | @@ -321,13 +363,40 @@ curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.orders>", "parameterValues": [ {"name": "sqlExpression", "value": "SELECT * FROM orders WHERE amount < 0"}, - {"name": "strategy", "value": "ROWS"} + {"name": "strategy", "value": "ROWS"}, + {"name": "operator", "value": "=="}, + {"name": "threshold", "value": "0"} + ], + "computePassedFailedRowCount": true + }' +``` + +### Test Cases for a Custom Test Definition + +A test case for a custom SQL test definition sets `testDefinition` to the definition's name and passes one `parameterValues` entry per `{{ paramName }}` placeholder. The following request uses a custom `columnValuesMaxLength` definition, which declares `maxLength`, `threshold`, and `thresholdUnit`: + +```bash +curl -X POST "{base_url}/api/v1/dataQuality/testCases" \ + -H "Authorization: Bearer {access_token}" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "email_max_length", + "testDefinition": "columnValuesMaxLength", + "entityLink": "<#E::table::sample_data.ecommerce_db.shopify.dim_address::columns::email>", + "parameterValues": [ + {"name": "maxLength", "value": "50"}, + {"name": "threshold", "value": "5"}, + {"name": "thresholdUnit", "value": "PERCENTAGE"} ], "computePassedFailedRowCount": true }' ``` -For a custom test definition that uses `{{ paramName }}` placeholders, pass one `parameterValues` entry per placeholder. For more information, see [Create a Test Definition](/v2.1.x-SNAPSHOT/api-reference/data-quality/test-definitions/create#custom-sql-test-definitions). +- **Pass condition**: The test case passes when the number of rows the SQL returns is within the tolerance. With no `threshold`, any returned row fails the test case. +- **Threshold**: `threshold` and `thresholdUnit` apply only if the test definition declares `thresholdUnit`. With `ABSOLUTE`, `threshold` is a row count. With `PERCENTAGE`, it is a share of the evaluated rows and can't exceed `100`. A negative or non-numeric `threshold` returns a `400` error. +- **Row counts**: Set `computePassedFailedRowCount` to `true` to report passed and failed row counts. + +For more information, see [Create a Test Definition](/v2.1.x-SNAPSHOT/api-reference/data-quality/test-definitions/create#custom-sql-test-definitions). ## Error Handling diff --git a/v2.1.x-SNAPSHOT/api-reference/data-quality/test-definitions/create.mdx b/v2.1.x-SNAPSHOT/api-reference/data-quality/test-definitions/create.mdx index c792908f..f645daf1 100644 --- a/v2.1.x-SNAPSHOT/api-reference/data-quality/test-definitions/create.mdx +++ b/v2.1.x-SNAPSHOT/api-reference/data-quality/test-definitions/create.mdx @@ -64,11 +64,16 @@ Create a custom test definition to define organization-specific data quality val - `{{ column_name }}`: the column the test case runs against. Available only when `entityType` is `COLUMN`. - `{{ paramName }}`: the value of a parameter declared in `parameterDefinition`. - OpenMetadata doesn't substitute single-brace placeholders, which produce invalid SQL. The test passes only when the rendered query returns 0 rows. `table_name` is reserved for all definitions, and `column_name` is also reserved when `entityType` is `COLUMN`. Don't use reserved names as parameter names. For more information, see [Custom SQL Test Definitions](#custom-sql-test-definitions). + OpenMetadata doesn't substitute single-brace placeholders, which produce invalid SQL. By default, the test passes only when the rendered query returns 0 rows. To tolerate some violating rows, set a failure threshold. `table_name` is reserved for all definitions, and `column_name` is also reserved when `entityType` is `COLUMN`. Don't use reserved names as parameter names. For more information, see [Custom SQL Test Definitions](#custom-sql-test-definitions). - Name of the validator that runs the test. For custom SQL-based tests, defaults to `ruleLibrarySqlExpressionValidator` when omitted. + Class name of the validator that runs the test. For a custom SQL test definition, set one of the following values. The OpenMetadata UI sets the same values when you create a custom SQL test definition: + + - `ColumnRuleLibrarySqlExpressionValidator`: use when `entityType` is `COLUMN`. + - `TableRuleLibrarySqlExpressionValidator`: use when `entityType` is `TABLE`. + + Built-in test definitions use their own validators, which you can't select for a custom definition. The server accepts any string for this field, so always set it explicitly for SQL-based definitions. @@ -113,24 +118,33 @@ configure( ) request = CreateTestDefinitionRequest( - name="columnValuesToMatchBusinessRule", - displayName="Column Values To Match Business Rule", - description="Validates that column values conform to a custom business rule regex pattern", + name="columnValuesMaxLength", + displayName="Column Values Max Length", + description="Fails when a value is longer than the allowed length", entityType="COLUMN", testPlatforms=["OpenMetadata"], + dataQualityDimension="SQL", supportedDataTypes=["STRING", "VARCHAR", "TEXT"], + sqlExpression="SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + validatorClass="ColumnRuleLibrarySqlExpressionValidator", parameterDefinition=[ { - "name": "regexPattern", - "dataType": "STRING", + "name": "maxLength", + "dataType": "INT", "required": True, - "description": "The regex pattern to match against" + "description": "Maximum allowed length" }, { "name": "threshold", - "dataType": "INT", + "dataType": "NUMBER", "required": False, - "description": "Maximum number of non-matching values allowed" + "description": "Number of failing rows to tolerate before the test fails" + }, + { + "name": "thresholdUnit", + "dataType": "STRING", + "required": False, + "description": "ABSOLUTE for a row count or PERCENTAGE for a share of rows" } ] ) @@ -177,25 +191,19 @@ curl -X POST "{base_url}/api/v1/dataQuality/testDefinitions" \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '{ - "name": "columnValuesToMatchBusinessRule", - "displayName": "Column Values To Match Business Rule", - "description": "Validates that column values conform to a custom business rule regex pattern", + "name": "columnValuesMaxLength", + "displayName": "Column Values Max Length", + "description": "Fails when a value is longer than the allowed length", "entityType": "COLUMN", "testPlatforms": ["OpenMetadata"], + "dataQualityDimension": "SQL", "supportedDataTypes": ["STRING", "VARCHAR", "TEXT"], + "sqlExpression": "SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + "validatorClass": "ColumnRuleLibrarySqlExpressionValidator", "parameterDefinition": [ - { - "name": "regexPattern", - "dataType": "STRING", - "required": true, - "description": "The regex pattern to match against" - }, - { - "name": "threshold", - "dataType": "INT", - "required": false, - "description": "Maximum number of non-matching values allowed" - } + {"name": "maxLength", "dataType": "INT", "required": true, "description": "Maximum allowed length"}, + {"name": "threshold", "dataType": "NUMBER", "required": false, "description": "Number of failing rows to tolerate before the test fails"}, + {"name": "thresholdUnit", "dataType": "STRING", "required": false, "description": "ABSOLUTE for a row count or PERCENTAGE for a share of rows"} ] }' ``` @@ -321,6 +329,8 @@ Returns the created test definition object with all specified properties and sys ## Custom SQL Test Definitions +A custom test definition is a reusable SQL template. To run a one-off SQL query on a single table, such as the **Custom SQL Query** test type in the UI, create a test case with the built-in `tableCustomSQLQuery` definition instead. For more information, see [Custom SQL Test Cases](/v2.1.x-SNAPSHOT/api-reference/data-quality/test-cases/create#custom-sql-test-cases). + To create a test definition that runs your own SQL, set `sqlExpression` and declare every `{{ paramName }}` placeholder in `parameterDefinition`. The following request creates a column-level test that fails when any value in the column is longer than a limit: ```bash @@ -336,23 +346,33 @@ curl -X POST "{base_url}/api/v1/dataQuality/testDefinitions" \ "dataQualityDimension": "SQL", "supportedDataTypes": ["STRING", "VARCHAR", "TEXT"], "sqlExpression": "SELECT * FROM {{ table_name }} WHERE LENGTH({{ column_name }}) > {{ maxLength }}", + "validatorClass": "ColumnRuleLibrarySqlExpressionValidator", "parameterDefinition": [ - { - "name": "maxLength", - "dataType": "INT", - "required": true, - "description": "Maximum allowed length" - } + {"name": "maxLength", "dataType": "INT", "required": true, "description": "Maximum allowed length"}, + {"name": "threshold", "dataType": "NUMBER", "required": false, "description": "Number of failing rows to tolerate before the test fails"}, + {"name": "thresholdUnit", "dataType": "STRING", "required": false, "description": "ABSOLUTE for a row count or PERCENTAGE for a share of rows"} ] }' ``` How OpenMetadata evaluates the SQL: -- **Pass condition**: The test case passes only when the rendered query returns 0 rows. Write the query so that it returns the rows that violate the rule. +- **Pass condition**: By default, the test case passes only when the rendered query returns 0 rows. Write the query so that it returns the rows that violate the rule. +- **Failure threshold**: To let a test case tolerate some violating rows, declare both `threshold` and `thresholdUnit` in `parameterDefinition`. The server ignores `threshold` unless the definition declares `thresholdUnit`. For more information, see [Failure Thresholds](#failure-thresholds). - **Reserved names**: `table_name` is reserved for table-level definitions. `table_name` and `column_name` are reserved for column-level definitions. Do not declare them in `parameterDefinition`, because the validator supplies their values at runtime. - **Parameters**: A test case supplies values for `{{ paramName }}` through `parameterValues`. For more information, see [Create a Test Case](/v2.1.x-SNAPSHOT/api-reference/data-quality/test-cases/create#custom-sql-test-cases). +### Failure Thresholds + +A failure threshold is the number of violating rows a test case tolerates before it fails. It turns the default "fail on any row" pass condition into a tolerance. + +| Parameter | Data type | Description | +|-----------|-----------|-------------| +| `threshold` | `NUMBER` | Tolerated violations. Must be a non-negative number. Defaults to `0`. | +| `thresholdUnit` | `STRING` | `ABSOLUTE` reads `threshold` as a row count. `PERCENTAGE` reads it as a share of the evaluated rows, up to `100`. | + +The test case supplies the values in `parameterValues`. For more information, see [Create a Test Case](/v2.1.x-SNAPSHOT/api-reference/data-quality/test-cases/create#custom-sql-test-cases) and [Failure Thresholds](/v2.1.x-SNAPSHOT/how-to-guides/data-quality-observability/quality/failure-thresholds). + ## Create or Update (PUT) Use `PUT /v1/dataQuality/testDefinitions` instead of `POST` to perform an upsert. If a test definition with the same name already exists, it will be updated; otherwise, a new test definition is created. The request body is the same as `POST`.