databricks-labs-lakebridge 0.10.0__tar.gz → 0.10.2__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.
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/PKG-INFO +5 -5
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/README.md +1 -1
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/__about__.py +1 -1
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/base_install.py +2 -1
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/cli.py +30 -6
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/config.py +7 -7
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/deployment/recon.py +2 -1
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/helpers/file_utils.py +0 -11
- databricks_labs_lakebridge-0.10.2/databricks/labs/lakebridge/helpers/string_utils.py +28 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/install.py +46 -23
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/intermediate/root_tables.py +5 -7
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/execute.py +60 -46
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/lsp/lsp_engine.py +1 -3
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/uninstall.py +1 -1
- databricks_labs_lakebridge-0.10.2/docs/lakebridge/src/theme/DocSidebarItems/index.tsx +42 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/pyproject.toml +3 -3
- databricks_labs_lakebridge-0.10.0/databricks/labs/lakebridge/helpers/string_utils.py +0 -62
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/.gitignore +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/LICENSE +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/NOTICE +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/assessments/configure_assessment.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/assessments/pipeline.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/assessments/profiler_config.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/connections/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/connections/credential_manager.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/connections/database_manager.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/connections/env_getter.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/contexts/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/contexts/application.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/coverage/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/coverage/commons.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/coverage/lakebridge_snow_transpilation_coverage.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/coverage/local_report.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/coverage/sqlglot_snow_transpilation_coverage.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/coverage/sqlglot_tsql_transpilation_coverage.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/deployment/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/deployment/configurator.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/deployment/dashboard.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/deployment/installation.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/deployment/job.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/deployment/table.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/deployment/upgrade_common.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/discovery/table.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/discovery/table_definition.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/discovery/tsql_table_definition.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/errors/exceptions.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/helpers/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/helpers/db_sql.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/helpers/execution_time.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/helpers/metastore.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/helpers/recon_config_utils.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/helpers/telemetry_utils.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/helpers/validation.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/intermediate/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/intermediate/dag.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/intermediate/engine_adapter.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/jvmproxy.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/lineage.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/compare.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/data_source.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/databricks.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/jdbc_reader.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/oracle.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/secrets.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/snowflake.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/source_adapter.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/connectors/sql_server.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/constants.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/exception.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/execute.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/query_builder/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/query_builder/aggregate_query.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/query_builder/base.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/query_builder/count_query.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/query_builder/expression_generator.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/query_builder/hash_query.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/query_builder/sampling_query.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/query_builder/threshold_query.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/recon_capture.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/recon_config.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/recon_output_config.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/runner.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/sampler.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/reconcile/schema_compare.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/config/credentials.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/00_0_aggregate_recon_header.md +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/01_0_recon_id.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/01_1_executed_by.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/01_2_started_at.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/02_0_source_type.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/02_1_source_table.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/02_2_target_table.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/04_0_aggregate_summary_table.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/05_0_aggregate_recon_drilldown_header.md +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/06_0_recon_id.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/06_1_category.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/06_2_aggregate_type.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/07_0_target_table.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/07_1_source_table.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/08_0_aggregate_details_table.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/09_0_aggregate_missing_mismatch_header.md +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/10_0_aggr_mismatched_records.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/11_0_aggr_missing_in_databricks.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/11_1_aggr_missing_in_source.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/dashboard.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/00_0_recon_main.md +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/01_0_recon_id.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/01_1_report_type.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/01_2_executed_by.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/02_0_source_type.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/02_1_source_table.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/02_2_target_table.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/03_0_started_at.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/05_0_summary_table.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/06_0_schema_comparison_header.md +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/07_0_schema_details_table.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/08_0_drill_down_header.md +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/09_0_recon_id.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/09_1_category.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/10_0_target_table.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/10_1_source_table.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/11_0_recon_details_pivot.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/12_0_daily_data_validation_issue_header.md +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/13_0_success_fail_.filter.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/14_0_failed_recon_ids.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/15_0_total_failed_runs.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/15_1_failed_targets.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/15_2_successful_targets.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/16_0_missing_mismatch_header.md +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/17_0_mismatched_records.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/17_1_threshold_mismatches.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/18_0_missing_in_databricks.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/18_1_missing_in_source.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/dashboard.yml +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/queries/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/queries/installation/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/queries/installation/aggregate_details.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/queries/installation/aggregate_metrics.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/queries/installation/aggregate_rules.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/queries/installation/details.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/queries/installation/main.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/resources/reconcile/queries/installation/metrics.sql +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/lsp/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/dialect_utils.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/generator/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/generator/databricks.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/lca_utils.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/local_expression.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/parsers/__init__.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/parsers/oracle.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/parsers/presto.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/parsers/snowflake.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/sqlglot/sqlglot_engine.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/transpile_engine.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/transpiler/transpile_status.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/upgrades/v0.4.0_add_main_table_operation_name_column.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/databricks/labs/lakebridge/upgrades/v0.6.0_alter_metrics_datatype.py +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/docs/lakebridge/src/components/Button.tsx +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/docs/lakebridge/src/css/custom.css +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/docs/lakebridge/src/css/table.css +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/docs/lakebridge/src/pages/index.tsx +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/docs/lakebridge/src/theme/Footer/index.tsx +0 -0
- {databricks_labs_lakebridge-0.10.0 → databricks_labs_lakebridge-0.10.2}/docs/lakebridge/src/theme/Layout/index.tsx +0 -0
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: databricks-labs-lakebridge
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.2
|
4
4
|
Summary: Fast and predictable migrations to Databricks Lakehouse Platform. This tool is designed to help you migrate your data and workloads to the Databricks Lakehouse Platform in a fast, predictable, and reliable way. It provides a set of tools and utilities to help you reconcile your data and workloads, assess your current state, and plan your migration.
|
5
|
-
Project-URL: Documentation, https://github.
|
5
|
+
Project-URL: Documentation, https://databrickslabs.github.io/lakebridge
|
6
6
|
Project-URL: Issues, https://github.com/databrickslabs/lakebridge/issues
|
7
7
|
Project-URL: Source, https://github.com/databrickslabs/lakebridge
|
8
8
|
Maintainer-email: Databricks Labs <labs-oss@databricks.com>
|
@@ -25,8 +25,8 @@ Classifier: Topic :: Software Development :: Libraries
|
|
25
25
|
Classifier: Topic :: Utilities
|
26
26
|
Requires-Python: >=3.10
|
27
27
|
Requires-Dist: cryptography<45.1.0,>=44.0.2
|
28
|
-
Requires-Dist: databricks-bb-analyzer~=0.1.
|
29
|
-
Requires-Dist: databricks-labs-blueprint[yaml]<0.12.0,>=0.11.
|
28
|
+
Requires-Dist: databricks-bb-analyzer~=0.1.8
|
29
|
+
Requires-Dist: databricks-labs-blueprint[yaml]<0.12.0,>=0.11.1
|
30
30
|
Requires-Dist: databricks-labs-lsql==0.16.0
|
31
31
|
Requires-Dist: databricks-sdk~=0.51.0
|
32
32
|
Requires-Dist: duckdb~=1.2.2
|
@@ -42,7 +42,7 @@ Databricks Labs Lakebridge
|
|
42
42
|

|
43
43
|
|
44
44
|
|
45
|
-
[](https://github.com/databrickslabs/remorph/actions/workflows/push.yml)
|
46
46
|

|
47
47
|
|
48
48
|
-----
|
@@ -3,7 +3,7 @@ Databricks Labs Lakebridge
|
|
3
3
|

|
4
4
|
|
5
5
|
|
6
|
-
[](https://github.com/databrickslabs/remorph/actions/workflows/push.yml)
|
7
7
|

|
8
8
|
|
9
9
|
-----
|
@@ -1,2 +1,2 @@
|
|
1
1
|
# DO NOT MODIFY THIS FILE
|
2
|
-
__version__ = "0.10.
|
2
|
+
__version__ = "0.10.2"
|
@@ -9,4 +9,5 @@ if __name__ == "__main__":
|
|
9
9
|
logger = get_logger(__file__)
|
10
10
|
logger.setLevel("INFO")
|
11
11
|
|
12
|
-
logger.info("Successfully Setup
|
12
|
+
logger.info("Successfully Setup Lakebridge Components Locally")
|
13
|
+
logger.info("For more information, please visit https://databrickslabs.github.io/lakebridge/")
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import asyncio
|
2
2
|
import dataclasses
|
3
|
+
import itertools
|
3
4
|
import json
|
5
|
+
import logging
|
4
6
|
import os
|
5
7
|
import time
|
6
8
|
from pathlib import Path
|
@@ -11,7 +13,7 @@ from databricks.sdk.service.sql import CreateWarehouseRequestWarehouseType
|
|
11
13
|
from databricks.sdk import WorkspaceClient
|
12
14
|
|
13
15
|
from databricks.labs.blueprint.cli import App
|
14
|
-
from databricks.labs.blueprint.entrypoint import get_logger
|
16
|
+
from databricks.labs.blueprint.entrypoint import get_logger, is_in_debug
|
15
17
|
from databricks.labs.blueprint.installation import JsonValue
|
16
18
|
from databricks.labs.blueprint.tui import Prompts
|
17
19
|
|
@@ -40,6 +42,7 @@ from databricks.labs.lakebridge.transpiler.lsp.lsp_engine import LSPConfig
|
|
40
42
|
from databricks.labs.lakebridge.transpiler.sqlglot.sqlglot_engine import SqlglotEngine
|
41
43
|
from databricks.labs.lakebridge.transpiler.transpile_engine import TranspileEngine
|
42
44
|
|
45
|
+
from databricks.labs.lakebridge.transpiler.transpile_status import ErrorSeverity
|
43
46
|
|
44
47
|
lakebridge = App(__file__)
|
45
48
|
logger = get_logger(__file__)
|
@@ -189,7 +192,7 @@ class _TranspileConfigChecker:
|
|
189
192
|
transpiler_name = self._prompts.choice("Select the transpiler:", list(transpiler_names))
|
190
193
|
else:
|
191
194
|
transpiler_name = next(name for name in transpiler_names)
|
192
|
-
logger.info(f"
|
195
|
+
logger.info(f"Lakebridge will use the {transpiler_name} transpiler")
|
193
196
|
transpiler_config_path = str(TranspilerInstaller.transpiler_config_path(transpiler_name))
|
194
197
|
logger.debug(f"Setting transpiler_config_path to '{transpiler_config_path}'")
|
195
198
|
self._config = dataclasses.replace(self._config, transpiler_config_path=cast(str, transpiler_config_path))
|
@@ -306,11 +309,29 @@ async def _transpile(ctx: ApplicationContext, config: TranspileConfig, engine: T
|
|
306
309
|
logger.debug(f"User: {user}")
|
307
310
|
_override_workspace_client_config(ctx, config.sdk_config)
|
308
311
|
status, errors = await do_transpile(ctx.workspace_client, engine, config)
|
309
|
-
|
310
|
-
|
312
|
+
|
313
|
+
logger.debug(f"Transpilation completed with status: {status}")
|
314
|
+
|
315
|
+
for path, errors_by_path in itertools.groupby(errors, key=lambda x: x.path):
|
316
|
+
errs = list(errors_by_path)
|
317
|
+
errors_by_severity = {
|
318
|
+
severity.name: len(list(errors)) for severity, errors in itertools.groupby(errs, key=lambda x: x.severity)
|
319
|
+
}
|
320
|
+
reports = []
|
321
|
+
reported_severities = [ErrorSeverity.ERROR, ErrorSeverity.WARNING]
|
322
|
+
for severity in reported_severities:
|
323
|
+
if severity.name in errors_by_severity:
|
324
|
+
word = str.lower(severity.name) + "s" if errors_by_severity[severity.name] > 1 else ""
|
325
|
+
reports.append(f"{errors_by_severity[severity.name]} {word}")
|
326
|
+
|
327
|
+
msg = ", ".join(reports) + " found"
|
328
|
+
|
329
|
+
if ErrorSeverity.ERROR.name in errors_by_severity:
|
330
|
+
logger.error(f"{path}: {msg}")
|
331
|
+
elif ErrorSeverity.WARNING.name in errors_by_severity:
|
332
|
+
logger.warning(f"{path}: {msg}")
|
311
333
|
|
312
334
|
# Table Template in labs.yml requires the status to be list of dicts Do not change this
|
313
|
-
logger.info(f"lakebridge Transpiler encountered {len(status)} from given {config.input_source} files.")
|
314
335
|
return [status]
|
315
336
|
|
316
337
|
|
@@ -442,8 +463,11 @@ def analyze(w: WorkspaceClient, source_directory: str, report_file: str):
|
|
442
463
|
with_user_agent_extra("analyzer_source_tech", make_alphanum_or_semver(source_tech))
|
443
464
|
user = ctx.current_user
|
444
465
|
logger.debug(f"User: {user}")
|
445
|
-
|
466
|
+
is_debug = logger.getEffectiveLevel() == logging.DEBUG
|
467
|
+
Analyzer.analyze(Path(input_folder), Path(output_file), source_tech, is_debug=is_debug)
|
446
468
|
|
447
469
|
|
448
470
|
if __name__ == "__main__":
|
449
471
|
lakebridge()
|
472
|
+
if is_in_debug():
|
473
|
+
logger.setLevel(logging.DEBUG)
|
@@ -4,7 +4,7 @@ import logging
|
|
4
4
|
from dataclasses import dataclass
|
5
5
|
from enum import Enum, auto
|
6
6
|
from pathlib import Path
|
7
|
-
from typing import Any, cast
|
7
|
+
from typing import Any, Literal, cast
|
8
8
|
|
9
9
|
from databricks.labs.blueprint.installation import JsonValue
|
10
10
|
from databricks.labs.blueprint.tui import Prompts
|
@@ -89,30 +89,30 @@ class TranspileConfig:
|
|
89
89
|
return Path(self.transpiler_config_path) if self.transpiler_config_path is not None else None
|
90
90
|
|
91
91
|
@property
|
92
|
-
def input_path(self):
|
92
|
+
def input_path(self) -> Path:
|
93
93
|
if self.input_source is None:
|
94
94
|
raise ValueError("Missing input source!")
|
95
95
|
return Path(self.input_source)
|
96
96
|
|
97
97
|
@property
|
98
|
-
def output_path(self):
|
98
|
+
def output_path(self) -> Path | None:
|
99
99
|
return None if self.output_folder is None else Path(self.output_folder)
|
100
100
|
|
101
101
|
@property
|
102
|
-
def error_path(self):
|
102
|
+
def error_path(self) -> Path | None:
|
103
103
|
return Path(self.error_file_path) if self.error_file_path else None
|
104
104
|
|
105
105
|
@property
|
106
|
-
def target_dialect(self):
|
106
|
+
def target_dialect(self) -> Literal["databricks"]:
|
107
107
|
return "databricks"
|
108
108
|
|
109
109
|
@classmethod
|
110
|
-
def v1_migrate(cls, raw: dict) -> dict:
|
110
|
+
def v1_migrate(cls, raw: dict[str, Any]) -> dict[str, Any]:
|
111
111
|
raw["version"] = 2
|
112
112
|
return raw
|
113
113
|
|
114
114
|
@classmethod
|
115
|
-
def v2_migrate(cls, raw: dict) -> dict:
|
115
|
+
def v2_migrate(cls, raw: dict[str, Any]) -> dict[str, Any]:
|
116
116
|
del raw["mode"]
|
117
117
|
key_mapping = {"input_sql": "input_source", "output_folder": "output_path", "source": "source_dialect"}
|
118
118
|
raw["version"] = 3
|
@@ -46,7 +46,8 @@ class ReconDeployment:
|
|
46
46
|
logger.info("Installing reconcile components.")
|
47
47
|
self._deploy_tables(recon_config)
|
48
48
|
self._deploy_dashboards(recon_config)
|
49
|
-
|
49
|
+
# TODO INVESTIGATE: Why is this needed?
|
50
|
+
remorph_wheel_path = [whl for whl in wheel_paths if "lakebridge" in whl][0]
|
50
51
|
self._deploy_jobs(recon_config, remorph_wheel_path)
|
51
52
|
self._install_state.save()
|
52
53
|
logger.info("Installation of reconcile components completed successfully.")
|
@@ -51,14 +51,3 @@ def get_sql_file(input_path: str | Path) -> Generator[Path, None, None]:
|
|
51
51
|
for filename in files:
|
52
52
|
if is_sql_file(filename):
|
53
53
|
yield filename
|
54
|
-
|
55
|
-
|
56
|
-
def read_file(filename: str | Path) -> str:
|
57
|
-
"""
|
58
|
-
Reads the contents of the given file and returns it as a string.
|
59
|
-
:param filename: Input File Path
|
60
|
-
:return: File Contents as String
|
61
|
-
"""
|
62
|
-
# pylint: disable=unspecified-encoding
|
63
|
-
with Path(filename).open() as file:
|
64
|
-
return file.read()
|
@@ -0,0 +1,28 @@
|
|
1
|
+
def refactor_hexadecimal_chars(input_string: str) -> str:
|
2
|
+
"""
|
3
|
+
Updates the HexaDecimal characters ( \x1b[\\d+m ) in the given string as below.
|
4
|
+
:param input_string: String with HexaDecimal characters. ex: ( \x1b[4mWHERE\x1b[0m )
|
5
|
+
:return: String with HexaDecimal characters refactored to arrows. ex: ( --> WHERE <--)
|
6
|
+
"""
|
7
|
+
output_string = input_string
|
8
|
+
highlight = {"\x1b[4m": "--> ", "\x1b[0m": " <--"}
|
9
|
+
for key, value in highlight.items():
|
10
|
+
output_string = output_string.replace(key, value)
|
11
|
+
return output_string
|
12
|
+
|
13
|
+
|
14
|
+
def format_error_message(error_type: str, error_message: Exception, error_sql: str) -> str:
|
15
|
+
"""
|
16
|
+
Formats the error message with the error SQL.
|
17
|
+
:param error_type: Error Type
|
18
|
+
:param error_message: Error message
|
19
|
+
:param error_sql: Error SQL
|
20
|
+
:return: Formatted error message
|
21
|
+
"""
|
22
|
+
error_str = (
|
23
|
+
f"------------------------ {error_type} Start:------------------------\n"
|
24
|
+
f"/*\n{str(error_message)}\n*/\n\n"
|
25
|
+
f"/*\nOriginal Query:\n\n{str(error_sql)}\n*/\n"
|
26
|
+
f"------------------------- {error_type} End:-------------------------"
|
27
|
+
).strip()
|
28
|
+
return error_str
|
@@ -558,7 +558,7 @@ class WorkspaceInstaller:
|
|
558
558
|
@classmethod
|
559
559
|
def install_morpheus(cls, artifact: Path | None = None):
|
560
560
|
java_version = cls.get_java_version()
|
561
|
-
if java_version is None or java_version <
|
561
|
+
if java_version is None or java_version < (11, 0, 0, 0):
|
562
562
|
logger.warning(
|
563
563
|
"This software requires Java 11 or above. Please install Java and re-run 'install-transpile'."
|
564
564
|
)
|
@@ -582,25 +582,48 @@ class WorkspaceInstaller:
|
|
582
582
|
logger.fatal(f"Cannot install unsupported artifact: {artifact}")
|
583
583
|
|
584
584
|
@classmethod
|
585
|
-
def get_java_version(cls) -> int | None:
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
return None
|
591
|
-
result = completed.stderr.decode("utf-8")
|
592
|
-
start = result.find(" version ")
|
593
|
-
if start < 0:
|
585
|
+
def get_java_version(cls) -> tuple[int, int, int, int] | None:
|
586
|
+
# Platform-independent way to reliably locate the java executable.
|
587
|
+
# Reference: https://docs.python.org/3.10/library/subprocess.html#popen-constructor
|
588
|
+
java_executable = shutil.which("java")
|
589
|
+
if java_executable is None:
|
594
590
|
return None
|
595
|
-
|
596
|
-
|
591
|
+
try:
|
592
|
+
completed = run([java_executable, "-version"], shell=False, capture_output=True, check=True)
|
593
|
+
except CalledProcessError as e:
|
594
|
+
logger.debug(
|
595
|
+
f"Failed to run {e.args!r} (exit-code={e.returncode}, stdout={e.stdout!r}, stderr={e.stderr!r})",
|
596
|
+
exc_info=e,
|
597
|
+
)
|
597
598
|
return None
|
598
|
-
|
599
|
-
|
599
|
+
# It might not be ascii, but the bits we care about are so this will never fail.
|
600
|
+
java_version_output = completed.stderr.decode("ascii", errors="ignore")
|
601
|
+
java_version = cls._parse_java_version(java_version_output)
|
602
|
+
logger.debug(f"Detected java version: {java_version}")
|
603
|
+
return java_version
|
604
|
+
|
605
|
+
# Pattern to match a Java version string, compiled at import time to ensure it's valid.
|
606
|
+
# Ref: https://docs.oracle.com/en/java/javase/11/install/version-string-format.html
|
607
|
+
_java_version_pattern = re.compile(
|
608
|
+
r' version "(?P<feature>\d+)(?:\.(?P<interim>\d+)(?:\.(?P<update>\d+)(?:\.(?P<patch>\d+))?)?)?"'
|
609
|
+
)
|
610
|
+
|
611
|
+
@classmethod
|
612
|
+
def _parse_java_version(cls, version: str) -> tuple[int, int, int, int] | None:
|
613
|
+
"""Locate and parse the Java version in the output of `java -version`."""
|
614
|
+
# Output looks like this:
|
615
|
+
# openjdk version "24.0.1" 2025-04-15
|
616
|
+
# OpenJDK Runtime Environment Temurin-24.0.1+9 (build 24.0.1+9)
|
617
|
+
# OpenJDK 64-Bit Server VM Temurin-24.0.1+9 (build 24.0.1+9, mixed mode)
|
618
|
+
match = cls._java_version_pattern.search(version)
|
619
|
+
if not match:
|
620
|
+
logger.debug(f"Could not parse java version: {version!r}")
|
600
621
|
return None
|
601
|
-
|
602
|
-
|
603
|
-
|
622
|
+
feature = int(match["feature"])
|
623
|
+
interim = int(match["interim"] or 0)
|
624
|
+
update = int(match["update"] or 0)
|
625
|
+
patch = int(match["patch"] or 0)
|
626
|
+
return feature, interim, update, patch
|
604
627
|
|
605
628
|
def configure(self, module: str) -> RemorphConfigs:
|
606
629
|
match module:
|
@@ -624,10 +647,10 @@ class WorkspaceInstaller:
|
|
624
647
|
|
625
648
|
def _configure_transpile(self) -> TranspileConfig:
|
626
649
|
try:
|
627
|
-
self._installation.load(TranspileConfig)
|
650
|
+
config = self._installation.load(TranspileConfig)
|
628
651
|
logger.info("Lakebridge `transpile` is already installed on this workspace.")
|
629
652
|
if not self._prompts.confirm("Do you want to override the existing installation?"):
|
630
|
-
|
653
|
+
return config
|
631
654
|
except NotFound:
|
632
655
|
logger.info("Couldn't find existing `transpile` installation")
|
633
656
|
except (PermissionDenied, SerdeError, ValueError, AttributeError):
|
@@ -689,8 +712,7 @@ class WorkspaceInstaller:
|
|
689
712
|
transpiler_name = None
|
690
713
|
else:
|
691
714
|
transpiler_name = next(t for t in transpilers)
|
692
|
-
|
693
|
-
logger.info(f"lakebridge will use the {transpiler_name} transpiler")
|
715
|
+
logger.info(f"Lakebridge will use the {transpiler_name} transpiler")
|
694
716
|
if transpiler_name:
|
695
717
|
transpiler_config_path = self._transpiler_config_path(transpiler_name)
|
696
718
|
transpiler_options: dict[str, JsonValue] | None = None
|
@@ -749,10 +771,11 @@ class WorkspaceInstaller:
|
|
749
771
|
def _configure_reconcile(self) -> ReconcileConfig:
|
750
772
|
try:
|
751
773
|
self._installation.load(ReconcileConfig)
|
752
|
-
logger.info("
|
774
|
+
logger.info("Lakebridge `reconcile` is already installed on this workspace.")
|
753
775
|
if not self._prompts.confirm("Do you want to override the existing installation?"):
|
776
|
+
# TODO: Exit gracefully, without raising SystemExit
|
754
777
|
raise SystemExit(
|
755
|
-
"
|
778
|
+
"Lakebridge `reconcile` is already installed and no override has been requested. Exiting..."
|
756
779
|
)
|
757
780
|
except NotFound:
|
758
781
|
logger.info("Couldn't find existing `reconcile` installation")
|
@@ -1,11 +1,9 @@
|
|
1
1
|
import logging
|
2
2
|
from pathlib import Path
|
3
3
|
|
4
|
-
from databricks.labs.
|
5
|
-
|
6
|
-
|
7
|
-
read_file,
|
8
|
-
)
|
4
|
+
from databricks.labs.blueprint.paths import read_text
|
5
|
+
|
6
|
+
from databricks.labs.lakebridge.helpers.file_utils import get_sql_file, is_sql_file
|
9
7
|
from databricks.labs.lakebridge.intermediate.dag import DAG
|
10
8
|
|
11
9
|
from databricks.labs.lakebridge.transpiler.sqlglot.sqlglot_engine import SqlglotEngine
|
@@ -26,14 +24,14 @@ class RootTableAnalyzer:
|
|
26
24
|
# when input is sql file then parse the file
|
27
25
|
if is_sql_file(self.input_path):
|
28
26
|
logger.debug(f"Generating Lineage file: {self.input_path}")
|
29
|
-
sql_content =
|
27
|
+
sql_content = read_text(self.input_path)
|
30
28
|
self._populate_dag(sql_content, self.input_path, dag)
|
31
29
|
return dag # return after processing the file
|
32
30
|
|
33
31
|
# when the input is a directory
|
34
32
|
for path in get_sql_file(self.input_path):
|
35
33
|
logger.debug(f"Generating Lineage file: {path}")
|
36
|
-
sql_content =
|
34
|
+
sql_content = read_text(path)
|
37
35
|
self._populate_dag(sql_content, path, dag)
|
38
36
|
|
39
37
|
return dag
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import asyncio
|
2
2
|
import dataclasses
|
3
3
|
import logging
|
4
|
-
import
|
4
|
+
from email import policy
|
5
5
|
from email.message import Message
|
6
6
|
from email.parser import Parser as EmailParser
|
7
7
|
from pathlib import Path
|
@@ -9,6 +9,7 @@ from typing import cast
|
|
9
9
|
import itertools
|
10
10
|
|
11
11
|
from databricks.labs.blueprint.installation import JsonObject
|
12
|
+
from databricks.labs.blueprint.paths import read_text
|
12
13
|
from databricks.labs.lakebridge.__about__ import __version__
|
13
14
|
from databricks.labs.lakebridge.config import (
|
14
15
|
TranspileConfig,
|
@@ -28,7 +29,6 @@ from databricks.labs.lakebridge.transpiler.transpile_status import (
|
|
28
29
|
ErrorKind,
|
29
30
|
ErrorSeverity,
|
30
31
|
)
|
31
|
-
from databricks.labs.lakebridge.helpers.string_utils import remove_bom
|
32
32
|
from databricks.labs.lakebridge.helpers.validation import Validator
|
33
33
|
from databricks.labs.lakebridge.transpiler.sqlglot.sqlglot_engine import SqlglotEngine
|
34
34
|
from databricks.sdk import WorkspaceClient
|
@@ -62,15 +62,14 @@ async def _process_one_file(context: TranspilingContext) -> tuple[int, list[Tran
|
|
62
62
|
)
|
63
63
|
return 0, [error]
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
context = dataclasses.replace(context, source_code=source_code)
|
65
|
+
source_code = read_text(context.input_path)
|
66
|
+
context = dataclasses.replace(context, source_code=source_code)
|
68
67
|
|
69
68
|
transpile_result = await _transpile(
|
70
69
|
context.transpiler,
|
71
70
|
str(context.config.source_dialect),
|
72
71
|
context.config.target_dialect,
|
73
|
-
|
72
|
+
source_code,
|
74
73
|
context.input_path,
|
75
74
|
)
|
76
75
|
|
@@ -98,7 +97,8 @@ def _is_combined_result(result: TranspileResult):
|
|
98
97
|
|
99
98
|
def _process_combined_result(context: TranspilingContext, _error_list: list[TranspileError]) -> None:
|
100
99
|
# TODO error handling
|
101
|
-
|
100
|
+
# Added policy to process quoted-printable encoded
|
101
|
+
parser = EmailParser(policy=policy.default)
|
102
102
|
transpiled_code: str = cast(str, context.transpiled_code)
|
103
103
|
message: Message = parser.parsestr(transpiled_code)
|
104
104
|
for part in message.walk():
|
@@ -107,18 +107,27 @@ def _process_combined_result(context: TranspilingContext, _error_list: list[Tran
|
|
107
107
|
|
108
108
|
def _process_combined_part(context: TranspilingContext, part: Message) -> None:
|
109
109
|
if part.get_content_type() != "text/plain":
|
110
|
-
return
|
110
|
+
return # TODO Need to handle other content types, e.g., text/binary, application/json, etc.
|
111
111
|
filename = part.get_filename()
|
112
|
-
|
113
|
-
|
114
|
-
|
112
|
+
payload = part.get_payload(decode=True)
|
113
|
+
charset = part.get_content_charset() or "utf-8"
|
114
|
+
if isinstance(payload, bytes):
|
115
|
+
content = payload.decode(charset)
|
116
|
+
else:
|
117
|
+
content = str(payload)
|
118
|
+
logger.debug(f"Processing file: {filename}")
|
119
|
+
|
120
|
+
if not filename:
|
121
|
+
return # TODO Raise exception!!!!
|
122
|
+
filename = Path(filename).name
|
115
123
|
folder = context.output_folder
|
116
124
|
segments = filename.split("/")
|
117
125
|
for segment in segments[:-1]:
|
118
126
|
folder = folder / segment
|
119
127
|
folder.mkdir(parents=True, exist_ok=True)
|
120
128
|
output = folder / segments[-1]
|
121
|
-
|
129
|
+
logger.debug(f"Writing output to: {output}")
|
130
|
+
output.write_text(content)
|
122
131
|
|
123
132
|
|
124
133
|
def _process_single_result(context: TranspilingContext, error_list: list[TranspileError]) -> None:
|
@@ -128,14 +137,6 @@ def _process_single_result(context: TranspilingContext, error_list: list[Transpi
|
|
128
137
|
if any(err.kind == ErrorKind.PARSING for err in error_list):
|
129
138
|
output_code = context.source_code or ""
|
130
139
|
|
131
|
-
if error_list:
|
132
|
-
with_line_numbers = ""
|
133
|
-
lines = output_code.split("\n")
|
134
|
-
line_number_width = math.floor(math.log(len(lines), 10)) + 1
|
135
|
-
for line_number, line in enumerate(lines, start=1):
|
136
|
-
with_line_numbers += f"/* {line_number:{line_number_width}d} */ {line}\n"
|
137
|
-
output_code = with_line_numbers
|
138
|
-
|
139
140
|
elif context.validator:
|
140
141
|
logger.debug(f"Validating transpiled code for file: {context.input_path}")
|
141
142
|
validation_result = _validation(context.validator, context.config, str(context.transpiled_code))
|
@@ -156,38 +157,35 @@ def _process_single_result(context: TranspilingContext, error_list: list[Transpi
|
|
156
157
|
|
157
158
|
output_path = cast(Path, context.output_path)
|
158
159
|
with output_path.open("w") as w:
|
159
|
-
|
160
|
+
# The above adds a java-style comment block at the top of the output file
|
161
|
+
# This would break .py or .json outputs so we disable it for now.
|
162
|
+
# w.write(make_header(context.input_path, error_list))
|
160
163
|
w.write(output_code)
|
161
164
|
|
162
165
|
logger.info(f"Processed file: {context.input_path} (errors: {len(error_list)})")
|
163
166
|
|
164
167
|
|
165
|
-
def
|
168
|
+
def make_header(file_path: Path, errors: list[TranspileError]) -> str:
|
166
169
|
header = ""
|
167
170
|
failed_producing_output = False
|
168
|
-
diag_by_severity = {
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
diag_by_severity[severity] = list(diags)
|
171
|
+
diag_by_severity = {
|
172
|
+
severity.name: list(diags) for severity, diags in itertools.groupby(errors, key=lambda x: x.severity)
|
173
|
+
}
|
174
|
+
line_numbers: dict[int, int] = {}
|
173
175
|
|
174
|
-
if ErrorSeverity.ERROR in diag_by_severity:
|
176
|
+
if ErrorSeverity.ERROR.name in diag_by_severity:
|
175
177
|
header += f"/*\n Failed transpilation of {file_path}\n"
|
176
178
|
header += "\n The following errors were found while transpiling:\n"
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
failed_producing_output = failed_producing_output or diag.kind == ErrorKind.PARSING
|
179
|
+
header += _append_diagnostics(diag_by_severity[ErrorSeverity.ERROR.name], line_numbers)
|
180
|
+
failed_producing_output = failed_producing_output or any(
|
181
|
+
x.kind == ErrorKind.PARSING for x in diag_by_severity[ErrorSeverity.ERROR.name]
|
182
|
+
)
|
182
183
|
else:
|
183
184
|
header += f"/*\n Successfully transpiled from {file_path}\n"
|
184
185
|
|
185
|
-
if ErrorSeverity.WARNING in diag_by_severity:
|
186
|
+
if ErrorSeverity.WARNING.name in diag_by_severity:
|
186
187
|
header += "\n The following warnings were found while transpiling:\n"
|
187
|
-
|
188
|
-
if diag.range:
|
189
|
-
line_numbers[diag.range.start.line] = 0
|
190
|
-
header += _append_diagnostic(diag)
|
188
|
+
header += _append_diagnostics(diag_by_severity[ErrorSeverity.WARNING.name], line_numbers)
|
191
189
|
|
192
190
|
if failed_producing_output:
|
193
191
|
header += "\n\n Parsing errors prevented the converter from translating the input query.\n"
|
@@ -203,13 +201,29 @@ def _make_header(file_path: Path, errors: list[TranspileError]) -> str:
|
|
203
201
|
return header.format(line_numbers=line_numbers)
|
204
202
|
|
205
203
|
|
206
|
-
def
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
204
|
+
def _append_diagnostics(diagnostics: list[TranspileError], line_numbers: dict) -> str:
|
205
|
+
header = ""
|
206
|
+
grouped_by_message = {msg: list(diags) for msg, diags in itertools.groupby(diagnostics, lambda x: x.message)}
|
207
|
+
for msg, occurrences in grouped_by_message.items():
|
208
|
+
for occurrence in occurrences:
|
209
|
+
if occurrence.range:
|
210
|
+
line_numbers.update({occurrence.range.start.line: 0})
|
211
|
+
header += _append_diagnostic(msg, occurrences)
|
212
|
+
return header
|
213
|
+
|
214
|
+
|
215
|
+
def _append_diagnostic(msg: str, diags: list[TranspileError]) -> str:
|
216
|
+
positions = [
|
217
|
+
f"[{{line_numbers[{diag.range.start.line}]}}:{diag.range.start.character + 1}]" for diag in diags if diag.range
|
218
|
+
]
|
219
|
+
message = msg.replace("{", "{{").replace("}", "}}").replace("/n", "\n ")
|
220
|
+
result = f" - {message}\n" if len(positions) != 1 else f" - {positions[0]} {message}\n"
|
221
|
+
if len(positions) > 1:
|
222
|
+
positions_str = ", ".join(positions)
|
223
|
+
result += f" Occurred {len(diags)} times at the following positions: {positions_str}\n"
|
224
|
+
elif len(diags) > 1:
|
225
|
+
result += f" Occurred {len(diags)} times\n"
|
226
|
+
return result
|
213
227
|
|
214
228
|
|
215
229
|
async def _process_many_files(
|
@@ -330,7 +344,7 @@ async def _do_transpile(
|
|
330
344
|
msg = f"{config.input_source} does not exist."
|
331
345
|
logger.error(msg)
|
332
346
|
raise FileNotFoundError(msg)
|
333
|
-
logger.
|
347
|
+
logger.debug(f"Transpiler results: {result}")
|
334
348
|
|
335
349
|
if not config.skip_validation:
|
336
350
|
logger.info(f"SQL validation errors: {result.validation_error_count}")
|
@@ -523,9 +523,7 @@ class LSPEngine(TranspileEngine):
|
|
523
523
|
self.close_document(file_path)
|
524
524
|
return ChangeManager.apply(source_code, response.changes, response.diagnostics, file_path)
|
525
525
|
|
526
|
-
def open_document(self, file_path: Path,
|
527
|
-
if source_code is None:
|
528
|
-
source_code = file_path.read_text(encoding)
|
526
|
+
def open_document(self, file_path: Path, source_code: str) -> None:
|
529
527
|
text_document = TextDocumentItem(
|
530
528
|
uri=file_path.as_uri(), language_id=LanguageKind.Sql, version=1, text=source_code
|
531
529
|
)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import React, {memo, type ReactNode} from 'react';
|
2
|
+
import {useLocation, useHistory} from 'react-router';
|
3
|
+
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs';
|
4
|
+
import {
|
5
|
+
DocSidebarItemsExpandedStateProvider,
|
6
|
+
useVisibleSidebarItems,
|
7
|
+
} from '@docusaurus/plugin-content-docs/client';
|
8
|
+
import DocSidebarItem from '@theme/DocSidebarItem';
|
9
|
+
|
10
|
+
import type {Props} from '@theme/DocSidebarItems';
|
11
|
+
|
12
|
+
function DocSidebarItems({items, onItemClick, ...props}: Props): ReactNode {
|
13
|
+
const location = useLocation();
|
14
|
+
const history = useHistory();
|
15
|
+
const visibleItems = useVisibleSidebarItems(items, props.activePath);
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Additional logic for handling custom UI scenarios
|
19
|
+
*/
|
20
|
+
const onClickHandler = (params: PropSidebarItem) => {
|
21
|
+
if (onItemClick) {
|
22
|
+
onItemClick(params);
|
23
|
+
}
|
24
|
+
|
25
|
+
// show initial page on menu collapse
|
26
|
+
if (params.type === "category") {
|
27
|
+
if (location.pathname !== params.href && location.pathname.includes(params.href)) {
|
28
|
+
history.push(params.href);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
return (
|
34
|
+
<DocSidebarItemsExpandedStateProvider>
|
35
|
+
{visibleItems.map((item, index) => (
|
36
|
+
<DocSidebarItem key={index} item={item} index={index} {...props} onItemClick={onClickHandler} />
|
37
|
+
))}
|
38
|
+
</DocSidebarItemsExpandedStateProvider>
|
39
|
+
);
|
40
|
+
}
|
41
|
+
|
42
|
+
export default memo(DocSidebarItems);
|