google-pso-data-validator 6.2.0__tar.gz → 6.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/PKG-INFO +28 -11
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/README.md +27 -10
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/__main__.py +96 -91
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/cli_tools.py +128 -60
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/clients.py +5 -1
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/combiner.py +34 -20
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/config_manager.py +108 -42
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/consts.py +8 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/data_validation.py +21 -7
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/exceptions.py +5 -1
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/metadata.py +1 -3
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/partition_builder.py +2 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/query_builder/partition_row_builder.py +8 -2
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/query_builder/query_builder.py +5 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/secret_manager.py +9 -5
- google_pso_data_validator-6.4.0/data_validation/util.py +24 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/validation_builder.py +0 -2
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/google_pso_data_validator.egg-info/PKG-INFO +28 -11
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/google_pso_data_validator.egg-info/SOURCES.txt +1 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/setup.py +6 -6
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_addon/api.py +21 -2
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_addon/operations.py +17 -5
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_db2/registry.py +1 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_oracle/__init__.py +10 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_oracle/datatypes.py +2 -2
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_oracle/registry.py +9 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_postgres/client.py +7 -1
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_teradata/registry.py +29 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/LICENSE +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/app.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/client_info.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/find_tables.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/gcs_helper.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/jellyfish_distance.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/query_builder/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/query_builder/random_row_builder.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/result_handlers/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/result_handlers/bigquery.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/result_handlers/text.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/schema_validation.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/state_manager.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/google_pso_data_validator.egg-info/dependency_links.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/google_pso_data_validator.egg-info/entry_points.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/google_pso_data_validator.egg-info/requires.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/google_pso_data_validator.egg-info/top_level.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/setup.cfg +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_addon/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/client.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/registry.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/tests/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/tests/conftest.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_cloud_spanner/to_pandas.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_db2/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_db2/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_db2/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_db2/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_impala/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_impala/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_mssql/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_mssql/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_mssql/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_mssql/registry.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_mysql/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_mysql/base_sql_compiler/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_mysql/base_sql_compiler/select_builder.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_mysql/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_oracle/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_oracle/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_postgres/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_postgres/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_redshift/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_redshift/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_redshift/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_snowflake/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_snowflake/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_snowflake/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_teradata/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_teradata/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_teradata/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/third_party/ibis/ibis_teradata/datatypes.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: google-pso-data-validator
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.4.0
|
|
4
4
|
Summary: A package to enable easy data validation
|
|
5
5
|
Author: PSO DVT Engineering team
|
|
6
6
|
Author-email: data-validator-eng@google.com
|
|
@@ -267,13 +267,13 @@ data-validation
|
|
|
267
267
|
[--case-insensitive-match, -cim]
|
|
268
268
|
Performs a case insensitive match by adding an UPPER() before comparison.
|
|
269
269
|
```
|
|
270
|
-
#### Generate
|
|
270
|
+
#### Generate Partitions for Large Row Validations
|
|
271
271
|
|
|
272
|
-
When performing row validations, Data Validation Tool brings each row into memory and can run into MemoryError. Below is the command syntax for generating
|
|
272
|
+
When performing row validations, Data Validation Tool brings each row into memory and can run into MemoryError. Below is the command syntax for generating partitions in order to perform row validations on large dataset (table or custom-query) to alleviate MemoryError. Each partition contains a range of primary key(s) and the ranges of keys across partitions are distinct. The partitions have nearly equal number of rows. See *Primary Keys* section
|
|
273
273
|
|
|
274
|
-
The command generates and stores multiple YAML validations each representing a chunk of the large
|
|
274
|
+
The command generates and stores multiple YAML validations each representing a chunk of the large dataset using filters (`WHERE primary_key(s) >= X AND primary_key(s) < Y`) in YAML files. The parameter parts-per-file, specifies the number of validations in one YAML file. Each yaml file will have parts-per-file validations in it - except the last one which will contain the remaining partitions (i.e. parts-per-file may not divide partition-num evenly). You can then run the validations in the directory serially (or in parallel in multiple containers, VMs) with the `data-validation configs run --config-dir PATH` command as described [here](https://github.com/GoogleCloudPlatform/professional-services-data-validator#yaml-configuration-files).
|
|
275
275
|
|
|
276
|
-
The command takes the same parameters as required for `Row Validation` *plus* a few parameters to support partitioning. Single and multiple primary keys are supported and keys can be of any indexable type, except for date and timestamp type. A parameter used in earlier versions, ```partition-key``` is no longer supported.
|
|
276
|
+
The command takes the same parameters as required for `Row Validation` *plus* a few parameters to support partitioning. Single and multiple primary keys are supported and keys can be of any indexable type, except for date and timestamp type. You can specify tables that are being validated or the source and target custom query. A parameter used in earlier versions, ```partition-key``` is no longer supported.
|
|
277
277
|
|
|
278
278
|
```
|
|
279
279
|
data-validation
|
|
@@ -292,6 +292,17 @@ data-validation
|
|
|
292
292
|
Comma separated list of tables in the form schema.table=target_schema.target_table
|
|
293
293
|
Target schema name and table name are optional.
|
|
294
294
|
i.e 'bigquery-public-data.new_york_citibike.citibike_trips'
|
|
295
|
+
Either --tables-list or --source-query (or file) and --target-query (or file) must be provided
|
|
296
|
+
--source-query SOURCE_QUERY, -sq SOURCE_QUERY
|
|
297
|
+
Source sql query
|
|
298
|
+
Either --tables-list or --source-query (or file) and --target-query (or file) must be provided
|
|
299
|
+
--source-query-file SOURCE_QUERY_FILE, -sqf SOURCE_QUERY_FILE
|
|
300
|
+
File containing the source sql command. Supports GCS and local paths.
|
|
301
|
+
--target-query TARGET_QUERY, -tq TARGET_QUERY
|
|
302
|
+
Target sql query
|
|
303
|
+
Either --tables-list or --source-query (or file) and --target-query (or file) must be provided
|
|
304
|
+
--target-query-file TARGET_QUERY_FILE, -tqf TARGET_QUERY_FILE
|
|
305
|
+
File containing the target sql command. Supports GCS and local paths.
|
|
295
306
|
--primary-keys PRIMARY_KEYS, -pk PRIMARY_KEYS
|
|
296
307
|
Comma separated list of primary key columns 'col_a,col_b'. See *Primary Keys* section
|
|
297
308
|
--comparison-fields or -comp-fields FIELDS
|
|
@@ -303,6 +314,7 @@ data-validation
|
|
|
303
314
|
Directory Path to store YAML Config Files
|
|
304
315
|
GCS: Provide a full gs:// path of the target directory. Eg: `gs://<BUCKET>/partitions_dir`
|
|
305
316
|
Local: Provide a relative path of the target directory. Eg: `partitions_dir`
|
|
317
|
+
If invoked with -tbls parameter, the validations are stored in a directory named <schema>.<table>, otherwise the directory is named `custom.<random_string>`
|
|
306
318
|
--partition-num INT, -pn INT
|
|
307
319
|
Number of partitions into which the table should be split, e.g. 1000 or 10000
|
|
308
320
|
In case this value exceeds the row count of the source/target table, it will be decreased to max(source_row_count, target_row_count)
|
|
@@ -581,10 +593,10 @@ View the complete YAML file for a Grouped Column validation on the
|
|
|
581
593
|
|
|
582
594
|
### Scaling DVT
|
|
583
595
|
|
|
584
|
-
You can scale DVT for large
|
|
596
|
+
You can scale DVT for large validations by running the tool in a distributed manner. To optimize the validation speed for large tables, you can use GKE Jobs ([Google Kubernetes Jobs](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-workloads-overview#batch_jobs)) or [Cloud Run Jobs](https://cloud.google.com/run/docs/create-jobs). If you are not familiar with Kubernetes or Cloud Run Jobs, see [Scaling DVT with Distributed Jobs](https://github.com/GoogleCloudPlatform/professional-services-data-validator/blob/develop/docs/internal/distributed_jobs.md) for a detailed overview.
|
|
585
597
|
|
|
586
598
|
|
|
587
|
-
We recommend first generating
|
|
599
|
+
We recommend first generating partitions with the `generate-table-partitions` command for your large datasets (tables or queries). Then, use Cloud Run or GKE to distribute the validation of each chunk in parallel. See the [Cloud Run Jobs Quickstart sample](https://github.com/GoogleCloudPlatform/professional-services-data-validator/tree/develop/samples/cloud_run_jobs) to get started.
|
|
588
600
|
|
|
589
601
|
When running DVT in a distributed fashion, both the `--kube-completions` and `--config-dir` flags are required. The `--kube-completions` flag specifies that the validation is being run in indexed completion mode in Kubernetes or as multiple independent tasks in Cloud Run. If the `-kc` option is used and you are not running in indexed mode, you will receive a warning and the container will process all the validations sequentially. If the `-kc` option is used and a config directory is not provided (i.e. a `--config-file` is provided instead), a warning is issued.
|
|
590
602
|
|
|
@@ -719,10 +731,15 @@ resultset that breaks down the count of rows per calendar date.
|
|
|
719
731
|
Row level validations can involve either a hash/checksum, concat, or comparison fields.
|
|
720
732
|
A hash validation (`--hash '*'`) will first sanitize the data with the following
|
|
721
733
|
operations on all or selected columns: CAST to string, IFNULL replace with a default
|
|
722
|
-
replacement string
|
|
723
|
-
and run a SHA256() hash and compare the source and target results.
|
|
724
|
-
|
|
725
|
-
|
|
734
|
+
replacement string and RSTRIP. Then, it will CONCAT() the results
|
|
735
|
+
and run a SHA256() hash and compare the source and target results.
|
|
736
|
+
|
|
737
|
+
When there are data type mismatches for columns, for example dates compared to timestamps and
|
|
738
|
+
booleans compared with numeric columns, you may see other expressions in SQL statements which
|
|
739
|
+
ensure that consistent values are used to build comparison values.
|
|
740
|
+
|
|
741
|
+
Since each row will be returned in the result set if is recommended recommended to validate a
|
|
742
|
+
subset of the table. The `--filters` and `--use-random-row` options can be used for this purpose.
|
|
726
743
|
|
|
727
744
|
Please note that SHA256 is not a supported function on Teradata systems. If you wish to perform
|
|
728
745
|
this comparison on Teradata you will need to [deploy a UDF to perform the conversion](https://github.com/akuroda/teradata-udf-sha2/blob/master/src/sha256.c).
|
|
@@ -226,13 +226,13 @@ data-validation
|
|
|
226
226
|
[--case-insensitive-match, -cim]
|
|
227
227
|
Performs a case insensitive match by adding an UPPER() before comparison.
|
|
228
228
|
```
|
|
229
|
-
#### Generate
|
|
229
|
+
#### Generate Partitions for Large Row Validations
|
|
230
230
|
|
|
231
|
-
When performing row validations, Data Validation Tool brings each row into memory and can run into MemoryError. Below is the command syntax for generating
|
|
231
|
+
When performing row validations, Data Validation Tool brings each row into memory and can run into MemoryError. Below is the command syntax for generating partitions in order to perform row validations on large dataset (table or custom-query) to alleviate MemoryError. Each partition contains a range of primary key(s) and the ranges of keys across partitions are distinct. The partitions have nearly equal number of rows. See *Primary Keys* section
|
|
232
232
|
|
|
233
|
-
The command generates and stores multiple YAML validations each representing a chunk of the large
|
|
233
|
+
The command generates and stores multiple YAML validations each representing a chunk of the large dataset using filters (`WHERE primary_key(s) >= X AND primary_key(s) < Y`) in YAML files. The parameter parts-per-file, specifies the number of validations in one YAML file. Each yaml file will have parts-per-file validations in it - except the last one which will contain the remaining partitions (i.e. parts-per-file may not divide partition-num evenly). You can then run the validations in the directory serially (or in parallel in multiple containers, VMs) with the `data-validation configs run --config-dir PATH` command as described [here](https://github.com/GoogleCloudPlatform/professional-services-data-validator#yaml-configuration-files).
|
|
234
234
|
|
|
235
|
-
The command takes the same parameters as required for `Row Validation` *plus* a few parameters to support partitioning. Single and multiple primary keys are supported and keys can be of any indexable type, except for date and timestamp type. A parameter used in earlier versions, ```partition-key``` is no longer supported.
|
|
235
|
+
The command takes the same parameters as required for `Row Validation` *plus* a few parameters to support partitioning. Single and multiple primary keys are supported and keys can be of any indexable type, except for date and timestamp type. You can specify tables that are being validated or the source and target custom query. A parameter used in earlier versions, ```partition-key``` is no longer supported.
|
|
236
236
|
|
|
237
237
|
```
|
|
238
238
|
data-validation
|
|
@@ -251,6 +251,17 @@ data-validation
|
|
|
251
251
|
Comma separated list of tables in the form schema.table=target_schema.target_table
|
|
252
252
|
Target schema name and table name are optional.
|
|
253
253
|
i.e 'bigquery-public-data.new_york_citibike.citibike_trips'
|
|
254
|
+
Either --tables-list or --source-query (or file) and --target-query (or file) must be provided
|
|
255
|
+
--source-query SOURCE_QUERY, -sq SOURCE_QUERY
|
|
256
|
+
Source sql query
|
|
257
|
+
Either --tables-list or --source-query (or file) and --target-query (or file) must be provided
|
|
258
|
+
--source-query-file SOURCE_QUERY_FILE, -sqf SOURCE_QUERY_FILE
|
|
259
|
+
File containing the source sql command. Supports GCS and local paths.
|
|
260
|
+
--target-query TARGET_QUERY, -tq TARGET_QUERY
|
|
261
|
+
Target sql query
|
|
262
|
+
Either --tables-list or --source-query (or file) and --target-query (or file) must be provided
|
|
263
|
+
--target-query-file TARGET_QUERY_FILE, -tqf TARGET_QUERY_FILE
|
|
264
|
+
File containing the target sql command. Supports GCS and local paths.
|
|
254
265
|
--primary-keys PRIMARY_KEYS, -pk PRIMARY_KEYS
|
|
255
266
|
Comma separated list of primary key columns 'col_a,col_b'. See *Primary Keys* section
|
|
256
267
|
--comparison-fields or -comp-fields FIELDS
|
|
@@ -262,6 +273,7 @@ data-validation
|
|
|
262
273
|
Directory Path to store YAML Config Files
|
|
263
274
|
GCS: Provide a full gs:// path of the target directory. Eg: `gs://<BUCKET>/partitions_dir`
|
|
264
275
|
Local: Provide a relative path of the target directory. Eg: `partitions_dir`
|
|
276
|
+
If invoked with -tbls parameter, the validations are stored in a directory named <schema>.<table>, otherwise the directory is named `custom.<random_string>`
|
|
265
277
|
--partition-num INT, -pn INT
|
|
266
278
|
Number of partitions into which the table should be split, e.g. 1000 or 10000
|
|
267
279
|
In case this value exceeds the row count of the source/target table, it will be decreased to max(source_row_count, target_row_count)
|
|
@@ -540,10 +552,10 @@ View the complete YAML file for a Grouped Column validation on the
|
|
|
540
552
|
|
|
541
553
|
### Scaling DVT
|
|
542
554
|
|
|
543
|
-
You can scale DVT for large
|
|
555
|
+
You can scale DVT for large validations by running the tool in a distributed manner. To optimize the validation speed for large tables, you can use GKE Jobs ([Google Kubernetes Jobs](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-workloads-overview#batch_jobs)) or [Cloud Run Jobs](https://cloud.google.com/run/docs/create-jobs). If you are not familiar with Kubernetes or Cloud Run Jobs, see [Scaling DVT with Distributed Jobs](https://github.com/GoogleCloudPlatform/professional-services-data-validator/blob/develop/docs/internal/distributed_jobs.md) for a detailed overview.
|
|
544
556
|
|
|
545
557
|
|
|
546
|
-
We recommend first generating
|
|
558
|
+
We recommend first generating partitions with the `generate-table-partitions` command for your large datasets (tables or queries). Then, use Cloud Run or GKE to distribute the validation of each chunk in parallel. See the [Cloud Run Jobs Quickstart sample](https://github.com/GoogleCloudPlatform/professional-services-data-validator/tree/develop/samples/cloud_run_jobs) to get started.
|
|
547
559
|
|
|
548
560
|
When running DVT in a distributed fashion, both the `--kube-completions` and `--config-dir` flags are required. The `--kube-completions` flag specifies that the validation is being run in indexed completion mode in Kubernetes or as multiple independent tasks in Cloud Run. If the `-kc` option is used and you are not running in indexed mode, you will receive a warning and the container will process all the validations sequentially. If the `-kc` option is used and a config directory is not provided (i.e. a `--config-file` is provided instead), a warning is issued.
|
|
549
561
|
|
|
@@ -678,10 +690,15 @@ resultset that breaks down the count of rows per calendar date.
|
|
|
678
690
|
Row level validations can involve either a hash/checksum, concat, or comparison fields.
|
|
679
691
|
A hash validation (`--hash '*'`) will first sanitize the data with the following
|
|
680
692
|
operations on all or selected columns: CAST to string, IFNULL replace with a default
|
|
681
|
-
replacement string
|
|
682
|
-
and run a SHA256() hash and compare the source and target results.
|
|
683
|
-
|
|
684
|
-
|
|
693
|
+
replacement string and RSTRIP. Then, it will CONCAT() the results
|
|
694
|
+
and run a SHA256() hash and compare the source and target results.
|
|
695
|
+
|
|
696
|
+
When there are data type mismatches for columns, for example dates compared to timestamps and
|
|
697
|
+
booleans compared with numeric columns, you may see other expressions in SQL statements which
|
|
698
|
+
ensure that consistent values are used to build comparison values.
|
|
699
|
+
|
|
700
|
+
Since each row will be returned in the result set if is recommended recommended to validate a
|
|
701
|
+
subset of the table. The `--filters` and `--use-random-row` options can be used for this purpose.
|
|
685
702
|
|
|
686
703
|
Please note that SHA256 is not a supported function on Teradata systems. If you wish to perform
|
|
687
704
|
this comparison on Teradata you will need to [deploy a UDF to perform the conversion](https://github.com/akuroda/teradata-udf-sha2/blob/master/src/sha256.c).
|
{google_pso_data_validator-6.2.0 → google_pso_data_validator-6.4.0}/data_validation/__main__.py
RENAMED
|
@@ -24,7 +24,9 @@ from data_validation import (
|
|
|
24
24
|
cli_tools,
|
|
25
25
|
clients,
|
|
26
26
|
consts,
|
|
27
|
+
exceptions,
|
|
27
28
|
state_manager,
|
|
29
|
+
util,
|
|
28
30
|
)
|
|
29
31
|
from data_validation.config_manager import ConfigManager
|
|
30
32
|
from data_validation.data_validation import DataValidation
|
|
@@ -160,7 +162,7 @@ def get_aggregate_config(args, config_manager: ConfigManager):
|
|
|
160
162
|
return aggregate_configs
|
|
161
163
|
|
|
162
164
|
|
|
163
|
-
def
|
|
165
|
+
def _get_calculated_config(args, config_manager: ConfigManager) -> List[dict]:
|
|
164
166
|
"""Return list of formatted calculated objects.
|
|
165
167
|
|
|
166
168
|
Args:
|
|
@@ -217,8 +219,41 @@ def get_calculated_config(args, config_manager: ConfigManager) -> List[dict]:
|
|
|
217
219
|
return calculated_configs
|
|
218
220
|
|
|
219
221
|
|
|
222
|
+
def _get_comparison_config(args, config_manager: ConfigManager) -> List[dict]:
|
|
223
|
+
col_list = (
|
|
224
|
+
None
|
|
225
|
+
if args.comparison_fields == "*"
|
|
226
|
+
else cli_tools.get_arg_list(args.comparison_fields)
|
|
227
|
+
)
|
|
228
|
+
comparison_fields = config_manager.build_comp_fields(
|
|
229
|
+
col_list,
|
|
230
|
+
args.exclude_columns,
|
|
231
|
+
)
|
|
232
|
+
# We can't have the PK columns in the comparison SQL twice therefore filter them out here if included.
|
|
233
|
+
comparison_fields = [
|
|
234
|
+
_
|
|
235
|
+
for _ in comparison_fields
|
|
236
|
+
if _ not in cli_tools.get_arg_list(args.primary_keys.casefold())
|
|
237
|
+
]
|
|
238
|
+
|
|
239
|
+
# As per #1190, add rstrip for Teradata string comparison fields
|
|
240
|
+
if (
|
|
241
|
+
config_manager.source_client.name == "teradata"
|
|
242
|
+
or config_manager.target_client.name == "teradata"
|
|
243
|
+
):
|
|
244
|
+
comparison_fields = config_manager.add_rstrip_to_comp_fields(comparison_fields)
|
|
245
|
+
|
|
246
|
+
return config_manager.build_config_comparison_fields(comparison_fields)
|
|
247
|
+
|
|
248
|
+
|
|
220
249
|
def build_config_from_args(args: Namespace, config_manager: ConfigManager):
|
|
221
|
-
"""
|
|
250
|
+
"""This function is used to append build configs to the config manager for all validation commands and generate-table-partitions.
|
|
251
|
+
Instead of having two separate commands, e.g. validate row and validate custom-query row, generate-table-partitions
|
|
252
|
+
uses implicit choice of table or custom-query. A user can specify either tables or source/target query/file,
|
|
253
|
+
but not both. In the case of generate-table-partitions with custom query, the user will not provide
|
|
254
|
+
args.custom_query_type. However, the code will inject args.custom_query_type as 'row' before invoking
|
|
255
|
+
build_config_from_args.
|
|
256
|
+
|
|
222
257
|
|
|
223
258
|
Args:
|
|
224
259
|
args (Namespace): User specified Arguments
|
|
@@ -227,14 +262,14 @@ def build_config_from_args(args: Namespace, config_manager: ConfigManager):
|
|
|
227
262
|
|
|
228
263
|
# Append SCHEMA_VALIDATION configs
|
|
229
264
|
if config_manager.validation_type == consts.SCHEMA_VALIDATION:
|
|
230
|
-
if args.exclusion_columns
|
|
265
|
+
if args.exclusion_columns:
|
|
231
266
|
exclusion_columns = cli_tools.get_arg_list(args.exclusion_columns)
|
|
232
267
|
config_manager.append_exclusion_columns(
|
|
233
268
|
[col.casefold() for col in exclusion_columns]
|
|
234
269
|
)
|
|
235
270
|
config_manager.append_allow_list(args.allow_list, args.allow_list_file)
|
|
236
271
|
|
|
237
|
-
# Append CUSTOM_QUERY
|
|
272
|
+
# Append configs specific to CUSTOM_QUERY (i.e. query strings or strings from files)
|
|
238
273
|
if config_manager.validation_type == consts.CUSTOM_QUERY:
|
|
239
274
|
config_manager.append_custom_query_type(args.custom_query_type)
|
|
240
275
|
|
|
@@ -252,75 +287,37 @@ def build_config_from_args(args: Namespace, config_manager: ConfigManager):
|
|
|
252
287
|
)
|
|
253
288
|
)
|
|
254
289
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
# Append Comparison fields
|
|
262
|
-
if args.comparison_fields is not None:
|
|
263
|
-
comparison_fields = cli_tools.get_arg_list(
|
|
264
|
-
args.comparison_fields, default_value=[]
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
# As per #1190, add rstrip for Teradata string comparison fields
|
|
268
|
-
if (
|
|
269
|
-
config_manager.source_client.name == "teradata"
|
|
270
|
-
or config_manager.target_client.name == "teradata"
|
|
271
|
-
):
|
|
272
|
-
comparison_fields = config_manager.add_rstrip_to_comp_fields(
|
|
273
|
-
comparison_fields
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
config_manager.append_comparison_fields(
|
|
277
|
-
config_manager.build_config_comparison_fields(comparison_fields)
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
# Append calculated fields: --hash/--concat
|
|
281
|
-
config_manager.append_calculated_fields(
|
|
282
|
-
get_calculated_config(args, config_manager)
|
|
283
|
-
)
|
|
284
|
-
|
|
285
|
-
# Append primary_keys
|
|
286
|
-
primary_keys = cli_tools.get_arg_list(args.primary_keys)
|
|
287
|
-
config_manager.append_primary_keys(
|
|
288
|
-
config_manager.build_column_configs(primary_keys)
|
|
289
|
-
)
|
|
290
|
-
|
|
291
|
-
# Append COLUMN_VALIDATION configs
|
|
292
|
-
if config_manager.validation_type == consts.COLUMN_VALIDATION:
|
|
290
|
+
# Append COLUMN_VALIDATION configs, including custom-query column validation
|
|
291
|
+
if (
|
|
292
|
+
config_manager.validation_type == consts.COLUMN_VALIDATION
|
|
293
|
+
or config_manager.validation_type == consts.CUSTOM_QUERY
|
|
294
|
+
and args.custom_query_type == consts.COLUMN_VALIDATION.lower()
|
|
295
|
+
):
|
|
293
296
|
config_manager.append_aggregates(get_aggregate_config(args, config_manager))
|
|
294
|
-
if
|
|
297
|
+
if (
|
|
298
|
+
config_manager.validation_type == consts.COLUMN_VALIDATION
|
|
299
|
+
and args.grouped_columns # grouped_columns not supported in custom queries - at least now.
|
|
300
|
+
):
|
|
295
301
|
grouped_columns = cli_tools.get_arg_list(args.grouped_columns)
|
|
296
302
|
config_manager.append_query_groups(
|
|
297
303
|
config_manager.build_column_configs(grouped_columns)
|
|
298
304
|
)
|
|
299
305
|
|
|
300
|
-
# Append ROW_VALIDATION configs
|
|
301
|
-
if
|
|
306
|
+
# Append ROW_VALIDATION configs, including custom-query row validation
|
|
307
|
+
if (
|
|
308
|
+
config_manager.validation_type == consts.ROW_VALIDATION
|
|
309
|
+
or config_manager.validation_type == consts.CUSTOM_QUERY
|
|
310
|
+
and args.custom_query_type == consts.ROW_VALIDATION.lower()
|
|
311
|
+
):
|
|
302
312
|
# Append calculated fields: --hash/--concat
|
|
303
313
|
config_manager.append_calculated_fields(
|
|
304
|
-
|
|
314
|
+
_get_calculated_config(args, config_manager)
|
|
305
315
|
)
|
|
306
316
|
|
|
307
317
|
# Append Comparison fields
|
|
308
|
-
if args.comparison_fields
|
|
309
|
-
comparison_fields = cli_tools.get_arg_list(
|
|
310
|
-
args.comparison_fields, default_value=[]
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
# As per #1190, add rstrip for Teradata string comparison fields
|
|
314
|
-
if (
|
|
315
|
-
config_manager.source_client.name == "teradata"
|
|
316
|
-
or config_manager.target_client.name == "teradata"
|
|
317
|
-
):
|
|
318
|
-
comparison_fields = config_manager.add_rstrip_to_comp_fields(
|
|
319
|
-
comparison_fields
|
|
320
|
-
)
|
|
321
|
-
|
|
318
|
+
if args.comparison_fields:
|
|
322
319
|
config_manager.append_comparison_fields(
|
|
323
|
-
config_manager
|
|
320
|
+
_get_comparison_config(args, config_manager)
|
|
324
321
|
)
|
|
325
322
|
|
|
326
323
|
# Append primary_keys
|
|
@@ -336,22 +333,25 @@ def build_config_managers_from_args(
|
|
|
336
333
|
args: Namespace, validate_cmd: str = None
|
|
337
334
|
) -> List[ConfigManager]:
|
|
338
335
|
"""Return a list of config managers ready to execute."""
|
|
339
|
-
configs = []
|
|
340
336
|
|
|
341
|
-
|
|
342
|
-
|
|
337
|
+
def _build_configs():
|
|
338
|
+
configs = []
|
|
339
|
+
|
|
340
|
+
# Get pre build configs to build ConfigManager objects
|
|
341
|
+
pre_build_configs_list = cli_tools.get_pre_build_configs(args, validate_cmd)
|
|
343
342
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
343
|
+
# Build a list of ConfigManager objects
|
|
344
|
+
for pre_build_configs in pre_build_configs_list:
|
|
345
|
+
config_manager = ConfigManager.build_config_manager(**pre_build_configs)
|
|
347
346
|
|
|
348
|
-
|
|
349
|
-
|
|
347
|
+
# Append post build configs to ConfigManager object
|
|
348
|
+
config_manager = build_config_from_args(args, config_manager)
|
|
350
349
|
|
|
351
|
-
|
|
352
|
-
|
|
350
|
+
# Append ConfigManager object to configs list
|
|
351
|
+
configs.append(config_manager)
|
|
352
|
+
return configs
|
|
353
353
|
|
|
354
|
-
return
|
|
354
|
+
return util.timed_call("Build config", _build_configs)
|
|
355
355
|
|
|
356
356
|
|
|
357
357
|
def config_runner(args):
|
|
@@ -393,9 +393,26 @@ def config_runner(args):
|
|
|
393
393
|
)
|
|
394
394
|
config_file_names = cli_tools.list_validations(config_dir=args.config_dir)
|
|
395
395
|
config_managers = []
|
|
396
|
+
errors = False
|
|
396
397
|
for file in config_file_names:
|
|
397
398
|
config_managers = build_config_managers_from_yaml(args, file)
|
|
398
|
-
|
|
399
|
+
try:
|
|
400
|
+
logging.info(
|
|
401
|
+
"Currently running the validation for YAML file: %s",
|
|
402
|
+
file,
|
|
403
|
+
)
|
|
404
|
+
run_validations(args, config_managers)
|
|
405
|
+
except Exception as e:
|
|
406
|
+
errors = True
|
|
407
|
+
logging.error(
|
|
408
|
+
"Error '%s' occurred while running config file %s. Skipping it for now.",
|
|
409
|
+
str(e),
|
|
410
|
+
file,
|
|
411
|
+
)
|
|
412
|
+
if errors:
|
|
413
|
+
raise exceptions.ValidationException(
|
|
414
|
+
"Some of the validations raised an exception"
|
|
415
|
+
)
|
|
399
416
|
else:
|
|
400
417
|
if args.kube_completions:
|
|
401
418
|
logging.warning(
|
|
@@ -548,23 +565,7 @@ def run_validations(args, config_managers):
|
|
|
548
565
|
"""
|
|
549
566
|
# TODO(issue/31): Add parallel execution logic
|
|
550
567
|
for config_manager in config_managers:
|
|
551
|
-
|
|
552
|
-
logging.info(
|
|
553
|
-
"Currently running the validation for YAML file: %s",
|
|
554
|
-
config_manager.config[consts.CONFIG_FILE],
|
|
555
|
-
)
|
|
556
|
-
try:
|
|
557
|
-
run_validation(
|
|
558
|
-
config_manager, dry_run=args.dry_run, verbose=args.verbose
|
|
559
|
-
)
|
|
560
|
-
except Exception as e:
|
|
561
|
-
logging.error(
|
|
562
|
-
"Error %s occurred while running config file %s. Skipping it for now.",
|
|
563
|
-
str(e),
|
|
564
|
-
config_manager.config[consts.CONFIG_FILE],
|
|
565
|
-
)
|
|
566
|
-
else:
|
|
567
|
-
run_validation(config_manager, dry_run=args.dry_run, verbose=args.verbose)
|
|
568
|
+
run_validation(config_manager, dry_run=args.dry_run, verbose=args.verbose)
|
|
568
569
|
|
|
569
570
|
|
|
570
571
|
def store_yaml_config_file(args, config_managers):
|
|
@@ -599,7 +600,11 @@ def partition_and_store_config_files(args: Namespace) -> None:
|
|
|
599
600
|
None
|
|
600
601
|
"""
|
|
601
602
|
# Default Validate Type
|
|
602
|
-
|
|
603
|
+
if args.tables_list:
|
|
604
|
+
config_managers = build_config_managers_from_args(args, consts.ROW_VALIDATION)
|
|
605
|
+
else:
|
|
606
|
+
setattr(args, "custom_query_type", "row")
|
|
607
|
+
config_managers = build_config_managers_from_args(args, consts.CUSTOM_QUERY)
|
|
603
608
|
partition_builder = PartitionBuilder(config_managers, args)
|
|
604
609
|
partition_builder.partition_configs()
|
|
605
610
|
|