google-pso-data-validator 6.2.0__tar.gz → 6.3.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.3.0}/PKG-INFO +28 -11
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/README.md +27 -10
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/__main__.py +61 -62
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/cli_tools.py +105 -50
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/clients.py +5 -1
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/combiner.py +34 -20
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/config_manager.py +101 -42
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/consts.py +1 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/partition_builder.py +2 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/query_builder/partition_row_builder.py +8 -2
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/query_builder/query_builder.py +5 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/secret_manager.py +9 -5
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/validation_builder.py +0 -2
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/google_pso_data_validator.egg-info/PKG-INFO +28 -11
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/setup.py +6 -6
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_addon/api.py +21 -2
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_addon/operations.py +17 -5
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_db2/registry.py +1 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_oracle/datatypes.py +2 -2
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_oracle/registry.py +9 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_postgres/client.py +7 -1
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_teradata/registry.py +29 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/LICENSE +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/app.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/client_info.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/data_validation.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/exceptions.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/find_tables.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/gcs_helper.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/jellyfish_distance.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/metadata.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/query_builder/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/query_builder/random_row_builder.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/result_handlers/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/result_handlers/bigquery.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/result_handlers/text.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/schema_validation.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/state_manager.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/google_pso_data_validator.egg-info/SOURCES.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/google_pso_data_validator.egg-info/dependency_links.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/google_pso_data_validator.egg-info/entry_points.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/google_pso_data_validator.egg-info/requires.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/google_pso_data_validator.egg-info/top_level.txt +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/setup.cfg +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_addon/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/client.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/registry.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/tests/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/tests/conftest.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_cloud_spanner/to_pandas.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_db2/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_db2/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_db2/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_db2/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_impala/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_impala/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_mssql/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_mssql/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_mssql/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_mssql/registry.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_mysql/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.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.3.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.3.0}/third_party/ibis/ibis_mysql/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_oracle/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_oracle/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_oracle/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_postgres/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_postgres/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_redshift/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_redshift/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_redshift/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_snowflake/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_snowflake/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_snowflake/datatypes.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_teradata/__init__.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_teradata/api.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/third_party/ibis/ibis_teradata/compiler.py +0 -0
- {google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.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.3.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.3.0}/data_validation/__main__.py
RENAMED
|
@@ -160,7 +160,7 @@ def get_aggregate_config(args, config_manager: ConfigManager):
|
|
|
160
160
|
return aggregate_configs
|
|
161
161
|
|
|
162
162
|
|
|
163
|
-
def
|
|
163
|
+
def _get_calculated_config(args, config_manager: ConfigManager) -> List[dict]:
|
|
164
164
|
"""Return list of formatted calculated objects.
|
|
165
165
|
|
|
166
166
|
Args:
|
|
@@ -217,8 +217,41 @@ def get_calculated_config(args, config_manager: ConfigManager) -> List[dict]:
|
|
|
217
217
|
return calculated_configs
|
|
218
218
|
|
|
219
219
|
|
|
220
|
+
def _get_comparison_config(args, config_manager: ConfigManager) -> List[dict]:
|
|
221
|
+
col_list = (
|
|
222
|
+
None
|
|
223
|
+
if config_manager.comparison_fields == "*"
|
|
224
|
+
else cli_tools.get_arg_list(config_manager.comparison_fields)
|
|
225
|
+
)
|
|
226
|
+
comparison_fields = config_manager.build_comp_fields(
|
|
227
|
+
col_list,
|
|
228
|
+
args.exclude_columns,
|
|
229
|
+
)
|
|
230
|
+
# We can't have the PK columns in the comparison SQL twice therefore filter them out here if included.
|
|
231
|
+
comparison_fields = [
|
|
232
|
+
_
|
|
233
|
+
for _ in comparison_fields
|
|
234
|
+
if _ not in cli_tools.get_arg_list(args.primary_keys.casefold())
|
|
235
|
+
]
|
|
236
|
+
|
|
237
|
+
# As per #1190, add rstrip for Teradata string comparison fields
|
|
238
|
+
if (
|
|
239
|
+
config_manager.source_client.name == "teradata"
|
|
240
|
+
or config_manager.target_client.name == "teradata"
|
|
241
|
+
):
|
|
242
|
+
comparison_fields = config_manager.add_rstrip_to_comp_fields(comparison_fields)
|
|
243
|
+
|
|
244
|
+
return config_manager.build_config_comparison_fields(comparison_fields)
|
|
245
|
+
|
|
246
|
+
|
|
220
247
|
def build_config_from_args(args: Namespace, config_manager: ConfigManager):
|
|
221
|
-
"""
|
|
248
|
+
"""This function is used to append build configs to the config manager for all validation commands and generate-table-partitions.
|
|
249
|
+
Instead of having two separate commands, e.g. validate row and validate custom-query row, generate-table-partitions
|
|
250
|
+
uses implicit choice of table or custom-query. A user can specify either tables or source/target query/file,
|
|
251
|
+
but not both. In the case of generate-table-partitions with custom query, the user will not provide
|
|
252
|
+
args.custom_query_type. However, the code will inject args.custom_query_type as 'row' before invoking
|
|
253
|
+
build_config_from_args.
|
|
254
|
+
|
|
222
255
|
|
|
223
256
|
Args:
|
|
224
257
|
args (Namespace): User specified Arguments
|
|
@@ -227,14 +260,14 @@ def build_config_from_args(args: Namespace, config_manager: ConfigManager):
|
|
|
227
260
|
|
|
228
261
|
# Append SCHEMA_VALIDATION configs
|
|
229
262
|
if config_manager.validation_type == consts.SCHEMA_VALIDATION:
|
|
230
|
-
if args.exclusion_columns
|
|
263
|
+
if args.exclusion_columns:
|
|
231
264
|
exclusion_columns = cli_tools.get_arg_list(args.exclusion_columns)
|
|
232
265
|
config_manager.append_exclusion_columns(
|
|
233
266
|
[col.casefold() for col in exclusion_columns]
|
|
234
267
|
)
|
|
235
268
|
config_manager.append_allow_list(args.allow_list, args.allow_list_file)
|
|
236
269
|
|
|
237
|
-
# Append CUSTOM_QUERY
|
|
270
|
+
# Append configs specific to CUSTOM_QUERY (i.e. query strings or strings from files)
|
|
238
271
|
if config_manager.validation_type == consts.CUSTOM_QUERY:
|
|
239
272
|
config_manager.append_custom_query_type(args.custom_query_type)
|
|
240
273
|
|
|
@@ -252,75 +285,37 @@ def build_config_from_args(args: Namespace, config_manager: ConfigManager):
|
|
|
252
285
|
)
|
|
253
286
|
)
|
|
254
287
|
|
|
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:
|
|
288
|
+
# Append COLUMN_VALIDATION configs, including custom-query column validation
|
|
289
|
+
if (
|
|
290
|
+
config_manager.validation_type == consts.COLUMN_VALIDATION
|
|
291
|
+
or config_manager.validation_type == consts.CUSTOM_QUERY
|
|
292
|
+
and args.custom_query_type == consts.COLUMN_VALIDATION.lower()
|
|
293
|
+
):
|
|
293
294
|
config_manager.append_aggregates(get_aggregate_config(args, config_manager))
|
|
294
|
-
if
|
|
295
|
+
if (
|
|
296
|
+
config_manager.validation_type == consts.COLUMN_VALIDATION
|
|
297
|
+
and args.grouped_columns # grouped_columns not supported in custom queries - at least now.
|
|
298
|
+
):
|
|
295
299
|
grouped_columns = cli_tools.get_arg_list(args.grouped_columns)
|
|
296
300
|
config_manager.append_query_groups(
|
|
297
301
|
config_manager.build_column_configs(grouped_columns)
|
|
298
302
|
)
|
|
299
303
|
|
|
300
|
-
# Append ROW_VALIDATION configs
|
|
301
|
-
if
|
|
304
|
+
# Append ROW_VALIDATION configs, including custom-query row validation
|
|
305
|
+
if (
|
|
306
|
+
config_manager.validation_type == consts.ROW_VALIDATION
|
|
307
|
+
or config_manager.validation_type == consts.CUSTOM_QUERY
|
|
308
|
+
and args.custom_query_type == consts.ROW_VALIDATION.lower()
|
|
309
|
+
):
|
|
302
310
|
# Append calculated fields: --hash/--concat
|
|
303
311
|
config_manager.append_calculated_fields(
|
|
304
|
-
|
|
312
|
+
_get_calculated_config(args, config_manager)
|
|
305
313
|
)
|
|
306
314
|
|
|
307
315
|
# 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
|
-
|
|
316
|
+
if args.comparison_fields:
|
|
322
317
|
config_manager.append_comparison_fields(
|
|
323
|
-
config_manager
|
|
318
|
+
_get_comparison_config(args, config_manager)
|
|
324
319
|
)
|
|
325
320
|
|
|
326
321
|
# Append primary_keys
|
|
@@ -599,7 +594,11 @@ def partition_and_store_config_files(args: Namespace) -> None:
|
|
|
599
594
|
None
|
|
600
595
|
"""
|
|
601
596
|
# Default Validate Type
|
|
602
|
-
|
|
597
|
+
if args.tables_list:
|
|
598
|
+
config_managers = build_config_managers_from_args(args, consts.ROW_VALIDATION)
|
|
599
|
+
else:
|
|
600
|
+
setattr(args, "custom_query_type", "row")
|
|
601
|
+
config_managers = build_config_managers_from_args(args, consts.CUSTOM_QUERY)
|
|
603
602
|
partition_builder = PartitionBuilder(config_managers, args)
|
|
604
603
|
partition_builder.partition_configs()
|
|
605
604
|
|
{google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/cli_tools.py
RENAMED
|
@@ -129,7 +129,7 @@ CONNECTION_SOURCE_FIELDS = {
|
|
|
129
129
|
"FileSystem": [
|
|
130
130
|
["table_name", "Table name to use as reference for file data"],
|
|
131
131
|
["file_path", "The local, s3, or GCS file path to the data"],
|
|
132
|
-
["file_type", "The file type of the file. 'csv' or 'json'"],
|
|
132
|
+
["file_type", "The file type of the file. 'csv', 'orc', 'parquet' or 'json'"],
|
|
133
133
|
],
|
|
134
134
|
"Impala": [
|
|
135
135
|
["host", "Desired Impala host"],
|
|
@@ -171,11 +171,45 @@ CONNECTION_SOURCE_FIELDS = {
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
|
|
174
|
+
def _check_custom_query_args(parser: argparse.ArgumentParser, parsed_args: Namespace):
|
|
175
|
+
# This is where we make additional checks if the arguments provided are what we expect
|
|
176
|
+
# For example, only one of -tbls and custom query options can be provided
|
|
177
|
+
if hasattr(parsed_args, "tables_list") and hasattr(
|
|
178
|
+
parsed_args, "source_query"
|
|
179
|
+
): # New Format
|
|
180
|
+
if (
|
|
181
|
+
parsed_args.tables_list
|
|
182
|
+
): # Tables_list is not None - so source and target queries all must be None
|
|
183
|
+
if (
|
|
184
|
+
parsed_args.source_query_file
|
|
185
|
+
or parsed_args.source_query
|
|
186
|
+
or parsed_args.target_query_file
|
|
187
|
+
or parsed_args.target_query
|
|
188
|
+
):
|
|
189
|
+
parser.error(
|
|
190
|
+
f"{parsed_args.command}: when --tables-list/-tbls is specified, --source-query-file/-sqf, --source-query/-sq, --target-query-file/-tqf and --target-query/-tq must not be specified"
|
|
191
|
+
)
|
|
192
|
+
else:
|
|
193
|
+
return
|
|
194
|
+
elif (parsed_args.source_query_file or parsed_args.source_query) and (
|
|
195
|
+
parsed_args.target_query_file or parsed_args.target_query
|
|
196
|
+
):
|
|
197
|
+
return
|
|
198
|
+
else:
|
|
199
|
+
parser.error(
|
|
200
|
+
f"{parsed_args.command}: Must specify both source (--source-query-file/-sqf or --source-query/-sq) and target (--target-query-file/-tqf or --target-query/-tq) - when --tables-list/-tbls is not specified"
|
|
201
|
+
)
|
|
202
|
+
else:
|
|
203
|
+
return # old format - only one of them is present
|
|
204
|
+
|
|
205
|
+
|
|
174
206
|
def get_parsed_args() -> Namespace:
|
|
175
207
|
"""Return ArgParser with configured CLI arguments."""
|
|
176
208
|
parser = configure_arg_parser()
|
|
177
209
|
args = ["--help"] if len(sys.argv) == 1 else None
|
|
178
|
-
|
|
210
|
+
parsed_args = parser.parse_args(args)
|
|
211
|
+
_check_custom_query_args(parser, parsed_args)
|
|
212
|
+
return parsed_args
|
|
179
213
|
|
|
180
214
|
|
|
181
215
|
def configure_arg_parser():
|
|
@@ -225,6 +259,7 @@ def _configure_partition_parser(subparsers):
|
|
|
225
259
|
default=1,
|
|
226
260
|
help="Number of partitions to be validated in a single yaml file.",
|
|
227
261
|
)
|
|
262
|
+
|
|
228
263
|
required_arguments.add_argument(
|
|
229
264
|
"--config-dir",
|
|
230
265
|
"-cdir",
|
|
@@ -242,6 +277,46 @@ def _configure_partition_parser(subparsers):
|
|
|
242
277
|
help="Number of partitions into which the table should be split",
|
|
243
278
|
type=_check_positive,
|
|
244
279
|
)
|
|
280
|
+
# User can provide tables or custom queries, but not both
|
|
281
|
+
# However, Argparse does not support adding an argument_group to an argument_group or adding a
|
|
282
|
+
# mutually_exclusive_group or argument_group to a mutually_exclusive_group since version 3.11.
|
|
283
|
+
# We are only ensuring leaf level mutual exclusivity here and will need to check higher level
|
|
284
|
+
# mutual exclusivity in the code - i.e. a) when --tables-list is present, there can be no custom
|
|
285
|
+
# query parameters and b) when custom query parameters are specified, both source and target must be
|
|
286
|
+
# specified.
|
|
287
|
+
optional_arguments.add_argument(
|
|
288
|
+
"--tables-list",
|
|
289
|
+
"-tbls",
|
|
290
|
+
help=(
|
|
291
|
+
"Comma separated tables list in the form "
|
|
292
|
+
"'schema.table=target_schema.target_table'"
|
|
293
|
+
),
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
source_mutually_exclusive = optional_arguments.add_mutually_exclusive_group()
|
|
297
|
+
source_mutually_exclusive.add_argument(
|
|
298
|
+
"--source-query-file",
|
|
299
|
+
"-sqf",
|
|
300
|
+
help="File containing the source sql query",
|
|
301
|
+
)
|
|
302
|
+
source_mutually_exclusive.add_argument(
|
|
303
|
+
"--source-query",
|
|
304
|
+
"-sq",
|
|
305
|
+
help="Source sql query",
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# Group for mutually exclusive target query arguments. Either must be supplied
|
|
309
|
+
target_mutually_exclusive = optional_arguments.add_mutually_exclusive_group()
|
|
310
|
+
target_mutually_exclusive.add_argument(
|
|
311
|
+
"--target-query-file",
|
|
312
|
+
"-tqf",
|
|
313
|
+
help="File containing the target sql query",
|
|
314
|
+
)
|
|
315
|
+
target_mutually_exclusive.add_argument(
|
|
316
|
+
"--target-query",
|
|
317
|
+
"-tq",
|
|
318
|
+
help="Target sql query",
|
|
319
|
+
)
|
|
245
320
|
|
|
246
321
|
|
|
247
322
|
def _configure_beta_parser(subparsers):
|
|
@@ -443,6 +518,7 @@ def _configure_row_parser(
|
|
|
443
518
|
"--threshold",
|
|
444
519
|
"-th",
|
|
445
520
|
type=threshold_float,
|
|
521
|
+
default=0.0,
|
|
446
522
|
help="Float max threshold for percent difference",
|
|
447
523
|
)
|
|
448
524
|
optional_arguments.add_argument(
|
|
@@ -454,6 +530,8 @@ def _configure_row_parser(
|
|
|
454
530
|
optional_arguments.add_argument(
|
|
455
531
|
"--filters",
|
|
456
532
|
"-filters",
|
|
533
|
+
type=get_filters,
|
|
534
|
+
default=[],
|
|
457
535
|
help="Filters in the format source_filter:target_filter",
|
|
458
536
|
)
|
|
459
537
|
optional_arguments.add_argument(
|
|
@@ -496,9 +574,10 @@ def _configure_row_parser(
|
|
|
496
574
|
"-rbs",
|
|
497
575
|
help="Row batch size used for random row filters (default 10,000).",
|
|
498
576
|
)
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
577
|
+
# Generate table partitions follows a new argument spec where either the table names or queries can be provided, but not both.
|
|
578
|
+
# that is specified in configure_partition_parser. If we use the same spec for row and column validation, the custom query commands
|
|
579
|
+
# may get subsumed by validate and validate commands by specifying tables name or queries. Until this -tbls will be
|
|
580
|
+
# a required argument for validate row, validate column and validate schema.
|
|
502
581
|
required_arguments.add_argument(
|
|
503
582
|
"--tables-list",
|
|
504
583
|
"-tbls",
|
|
@@ -506,6 +585,8 @@ def _configure_row_parser(
|
|
|
506
585
|
required=True,
|
|
507
586
|
help="Comma separated tables list in the form 'schema.table=target_schema.target_table'",
|
|
508
587
|
)
|
|
588
|
+
|
|
589
|
+
# Group required arguments
|
|
509
590
|
required_arguments.add_argument(
|
|
510
591
|
"--primary-keys",
|
|
511
592
|
"-pk",
|
|
@@ -603,24 +684,17 @@ def _configure_column_parser(column_parser):
|
|
|
603
684
|
"--threshold",
|
|
604
685
|
"-th",
|
|
605
686
|
type=threshold_float,
|
|
687
|
+
default=0.0,
|
|
606
688
|
help="Float max threshold for percent difference",
|
|
607
689
|
)
|
|
608
690
|
optional_arguments.add_argument(
|
|
609
691
|
"--filters",
|
|
610
692
|
"-filters",
|
|
693
|
+
type=get_filters,
|
|
694
|
+
default=[],
|
|
611
695
|
help="Filters in the format source_filter:target_filter",
|
|
612
696
|
)
|
|
613
|
-
|
|
614
|
-
"--use-random-row",
|
|
615
|
-
"-rr",
|
|
616
|
-
action="store_true",
|
|
617
|
-
help="Finds a set of random rows of the first primary key supplied.",
|
|
618
|
-
)
|
|
619
|
-
optional_arguments.add_argument(
|
|
620
|
-
"--random-row-batch-size",
|
|
621
|
-
"-rbs",
|
|
622
|
-
help="Row batch size used for random row filters (default 10,000).",
|
|
623
|
-
)
|
|
697
|
+
|
|
624
698
|
optional_arguments.add_argument(
|
|
625
699
|
"--wildcard-include-string-len",
|
|
626
700
|
"-wis",
|
|
@@ -818,25 +892,17 @@ def _configure_custom_query_column_parser(custom_query_column_parser):
|
|
|
818
892
|
optional_arguments.add_argument(
|
|
819
893
|
"--filters",
|
|
820
894
|
"-filters",
|
|
895
|
+
type=get_filters,
|
|
896
|
+
default=[],
|
|
821
897
|
help="Filters in the format source_filter:target_filter",
|
|
822
898
|
)
|
|
823
899
|
optional_arguments.add_argument(
|
|
824
900
|
"--threshold",
|
|
825
901
|
"-th",
|
|
826
902
|
type=threshold_float,
|
|
903
|
+
default=0.0,
|
|
827
904
|
help="Float max threshold for percent difference",
|
|
828
905
|
)
|
|
829
|
-
optional_arguments.add_argument(
|
|
830
|
-
"--use-random-row",
|
|
831
|
-
"-rr",
|
|
832
|
-
action="store_true",
|
|
833
|
-
help="Finds a set of random rows of the first primary key supplied.",
|
|
834
|
-
)
|
|
835
|
-
optional_arguments.add_argument(
|
|
836
|
-
"--random-row-batch-size",
|
|
837
|
-
"-rbs",
|
|
838
|
-
help="Row batch size used for random row filters (default 10,000).",
|
|
839
|
-
)
|
|
840
906
|
|
|
841
907
|
# Group required arguments
|
|
842
908
|
required_arguments = custom_query_column_parser.add_argument_group(
|
|
@@ -910,6 +976,7 @@ def _add_common_arguments(
|
|
|
910
976
|
"-cj",
|
|
911
977
|
help="Store the validation config in the JSON File Path specified to be used for application use cases",
|
|
912
978
|
)
|
|
979
|
+
|
|
913
980
|
optional_arguments.add_argument(
|
|
914
981
|
"--format",
|
|
915
982
|
"-fmt",
|
|
@@ -1080,7 +1147,7 @@ def get_filters(filter_value: str) -> List[Dict]:
|
|
|
1080
1147
|
filter_config = []
|
|
1081
1148
|
if result := re.fullmatch(single_filter, filter_value):
|
|
1082
1149
|
if result.group(0) == "":
|
|
1083
|
-
raise
|
|
1150
|
+
raise argparse.ArgumentTypeError("Empty string not allowed in filter")
|
|
1084
1151
|
filter_dict = {
|
|
1085
1152
|
"type": "custom",
|
|
1086
1153
|
"source": result.group(0),
|
|
@@ -1088,14 +1155,14 @@ def get_filters(filter_value: str) -> List[Dict]:
|
|
|
1088
1155
|
}
|
|
1089
1156
|
elif result := re.fullmatch(double_filter, filter_value):
|
|
1090
1157
|
if result.group("source") == "" or result.group("target") == "":
|
|
1091
|
-
raise
|
|
1158
|
+
raise argparse.ArgumentTypeError("Empty string not allowed in filter")
|
|
1092
1159
|
filter_dict = {
|
|
1093
1160
|
"type": "custom",
|
|
1094
1161
|
"source": result.group("source"),
|
|
1095
1162
|
"target": result.group("target"),
|
|
1096
1163
|
}
|
|
1097
1164
|
else:
|
|
1098
|
-
raise
|
|
1165
|
+
raise argparse.ArgumentTypeError("Unable to parse filter arguments.")
|
|
1099
1166
|
filter_config.append(filter_dict)
|
|
1100
1167
|
return filter_config
|
|
1101
1168
|
|
|
@@ -1315,8 +1382,8 @@ def get_pre_build_configs(args: Namespace, validate_cmd: str) -> List[Dict]:
|
|
|
1315
1382
|
else:
|
|
1316
1383
|
return get_arg_list(concat_arg)
|
|
1317
1384
|
|
|
1318
|
-
#
|
|
1319
|
-
#
|
|
1385
|
+
# validate_cmd will be set to 'row`, or 'Custom-query' if invoked by generate-table-partitions depending
|
|
1386
|
+
# on what is being partitioned. Otherwise validate_cmd will be set to None
|
|
1320
1387
|
if validate_cmd is None:
|
|
1321
1388
|
validate_cmd = args.validate_cmd.capitalize()
|
|
1322
1389
|
|
|
@@ -1339,14 +1406,9 @@ def get_pre_build_configs(args: Namespace, validate_cmd: str) -> List[Dict]:
|
|
|
1339
1406
|
else:
|
|
1340
1407
|
result_handler_config = None
|
|
1341
1408
|
|
|
1342
|
-
#
|
|
1343
|
-
filter_config = []
|
|
1344
|
-
threshold = 0.0
|
|
1345
|
-
if config_type != consts.SCHEMA_VALIDATION:
|
|
1346
|
-
if args.filters:
|
|
1347
|
-
filter_config = get_filters(args.filters)
|
|
1348
|
-
if args.threshold:
|
|
1349
|
-
threshold = args.threshold
|
|
1409
|
+
# Set filter_config and threshold. Not supported in case of schema validation
|
|
1410
|
+
filter_config = getattr(args, "filters", [])
|
|
1411
|
+
threshold = getattr(args, "threshold", 0.0)
|
|
1350
1412
|
|
|
1351
1413
|
# Get labels
|
|
1352
1414
|
if args.labels is None:
|
|
@@ -1362,16 +1424,9 @@ def get_pre_build_configs(args: Namespace, validate_cmd: str) -> List[Dict]:
|
|
|
1362
1424
|
# Get format: text, csv, json, table. Default is table
|
|
1363
1425
|
format = args.format if args.format else "table"
|
|
1364
1426
|
|
|
1365
|
-
# Get random row arguments.
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
random_row_batch_size = None
|
|
1369
|
-
if (
|
|
1370
|
-
args.command != "generate-table-partitions"
|
|
1371
|
-
and config_type != consts.SCHEMA_VALIDATION
|
|
1372
|
-
):
|
|
1373
|
-
use_random_rows = getattr(args, "use_random_row", False)
|
|
1374
|
-
random_row_batch_size = getattr(args, "random_row_batch_size", None)
|
|
1427
|
+
# Get random row arguments. Only in row validations these attributes can be present.
|
|
1428
|
+
use_random_rows = getattr(args, "use_random_row", False)
|
|
1429
|
+
random_row_batch_size = getattr(args, "random_row_batch_size", None)
|
|
1375
1430
|
|
|
1376
1431
|
# Get table list. Not supported in case of custom query validation
|
|
1377
1432
|
is_filesystem = source_client._source_type == "FileSystem"
|
{google_pso_data_validator-6.2.0 → google_pso_data_validator-6.3.0}/data_validation/clients.py
RENAMED
|
@@ -119,12 +119,16 @@ def get_pandas_client(table_name, file_path, file_type):
|
|
|
119
119
|
|
|
120
120
|
table_name (str): Table name to use as reference for file data
|
|
121
121
|
file_path (str): The local, s3, or GCS file path to the data
|
|
122
|
-
file_type (str): The file type of the file (csv or
|
|
122
|
+
file_type (str): The file type of the file (csv, json, orc or parquet)
|
|
123
123
|
"""
|
|
124
124
|
if file_type == "csv":
|
|
125
125
|
df = pandas.read_csv(file_path)
|
|
126
126
|
elif file_type == "json":
|
|
127
127
|
df = pandas.read_json(file_path)
|
|
128
|
+
elif file_type == "orc":
|
|
129
|
+
df = pandas.read_orc(file_path)
|
|
130
|
+
elif file_type == "parquet":
|
|
131
|
+
df = pandas.read_parquet(file_path)
|
|
128
132
|
else:
|
|
129
133
|
raise ValueError(f"Unknown Pandas File Type: {file_type}")
|
|
130
134
|
|