databricks-labs-lakebridge 0.10.5__tar.gz → 0.10.7__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.
Files changed (185) hide show
  1. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/PKG-INFO +1 -1
  2. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/__about__.py +1 -1
  3. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/analyzer/lakebridge_analyzer.py +95 -0
  4. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/base_install.py +34 -0
  5. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/cli.py +57 -72
  6. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/config.py +1 -1
  7. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/contexts/application.py +11 -4
  8. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/deployment/dashboard.py +2 -1
  9. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/deployment/installation.py +11 -11
  10. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/deployment/job.py +2 -2
  11. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/helpers/file_utils.py +36 -0
  12. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/install.py +228 -278
  13. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/compare.py +70 -33
  14. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/connectors/data_source.py +19 -0
  15. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/connectors/databricks.py +11 -1
  16. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/connectors/dialect_utils.py +126 -0
  17. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/connectors/models.py +7 -0
  18. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/connectors/oracle.py +11 -1
  19. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/connectors/snowflake.py +14 -2
  20. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/connectors/tsql.py +27 -2
  21. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/constants.py +4 -3
  22. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/execute.py +119 -0
  23. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/normalize_recon_config_service.py +133 -0
  24. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/query_builder/base.py +3 -7
  25. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/recon_config.py +3 -0
  26. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/recon_output_config.py +2 -1
  27. databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/reconcile/execute.py → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/reconciliation.py +48 -460
  28. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/schema_compare.py +26 -19
  29. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/trigger_recon_aggregate_service.py +98 -0
  30. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/trigger_recon_service.py +253 -0
  31. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/utils.py +38 -0
  32. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/lsp/lsp_engine.py +48 -63
  33. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/transpiler/repository.py +123 -0
  34. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/sqlglot/dialect_utils.py +2 -0
  35. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/transpiler/sqlglot/parsers/__init__.py +0 -0
  36. databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/transpiler/transpile_engine.py +29 -0
  37. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/pyproject.toml +4 -2
  38. databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/base_install.py +0 -13
  39. databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/transpiler/transpile_engine.py +0 -47
  40. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/.gitignore +0 -0
  41. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/LICENSE +0 -0
  42. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/NOTICE +0 -0
  43. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/README.md +0 -0
  44. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/__init__.py +0 -0
  45. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/__init__.py +0 -0
  46. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/__init__.py +0 -0
  47. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/connections → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/analyzer}/__init__.py +0 -0
  48. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/assessments/configure_assessment.py +0 -0
  49. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/assessments/pipeline.py +0 -0
  50. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/assessments/profiler_config.py +0 -0
  51. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/contexts → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/connections}/__init__.py +0 -0
  52. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/connections/credential_manager.py +0 -0
  53. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/connections/database_manager.py +0 -0
  54. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/connections/env_getter.py +0 -0
  55. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/coverage → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/contexts}/__init__.py +0 -0
  56. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/deployment → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/coverage}/__init__.py +0 -0
  57. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/coverage/commons.py +0 -0
  58. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/coverage/lakebridge_snow_transpilation_coverage.py +0 -0
  59. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/coverage/local_report.py +0 -0
  60. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/coverage/sqlglot_snow_transpilation_coverage.py +0 -0
  61. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/coverage/sqlglot_tsql_transpilation_coverage.py +0 -0
  62. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/helpers → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/deployment}/__init__.py +0 -0
  63. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/deployment/configurator.py +0 -0
  64. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/deployment/recon.py +0 -0
  65. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/deployment/table.py +0 -0
  66. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/deployment/upgrade_common.py +0 -0
  67. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/discovery/table.py +0 -0
  68. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/discovery/table_definition.py +0 -0
  69. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/discovery/tsql_table_definition.py +0 -0
  70. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/errors/exceptions.py +0 -0
  71. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/intermediate → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/helpers}/__init__.py +0 -0
  72. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/helpers/db_sql.py +0 -0
  73. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/helpers/execution_time.py +0 -0
  74. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/helpers/metastore.py +0 -0
  75. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/helpers/recon_config_utils.py +0 -0
  76. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/helpers/string_utils.py +0 -0
  77. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/helpers/telemetry_utils.py +0 -0
  78. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/helpers/validation.py +0 -0
  79. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/reconcile → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/intermediate}/__init__.py +0 -0
  80. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/intermediate/dag.py +0 -0
  81. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/intermediate/engine_adapter.py +0 -0
  82. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/intermediate/root_tables.py +0 -0
  83. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/jvmproxy.py +0 -0
  84. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/lineage.py +0 -0
  85. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/reconcile/connectors → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile}/__init__.py +0 -0
  86. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/reconcile/query_builder → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/connectors}/__init__.py +0 -0
  87. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/connectors/jdbc_reader.py +0 -0
  88. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/connectors/secrets.py +0 -0
  89. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/connectors/source_adapter.py +0 -0
  90. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/exception.py +0 -0
  91. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/resources → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/reconcile/query_builder}/__init__.py +0 -0
  92. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/query_builder/aggregate_query.py +0 -0
  93. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/query_builder/count_query.py +0 -0
  94. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/query_builder/expression_generator.py +0 -0
  95. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/query_builder/hash_query.py +0 -0
  96. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/query_builder/sampling_query.py +0 -0
  97. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/query_builder/threshold_query.py +0 -0
  98. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/recon_capture.py +0 -0
  99. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/runner.py +0 -0
  100. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/reconcile/sampler.py +0 -0
  101. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/resources/reconcile → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/resources}/__init__.py +0 -0
  102. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/config/credentials.yml +0 -0
  103. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/resources/reconcile/dashboards → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/resources/reconcile}/__init__.py +0 -0
  104. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/resources/reconcile/queries → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/resources/reconcile/dashboards}/__init__.py +0 -0
  105. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/00_0_aggregate_recon_header.md +0 -0
  106. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/01_0_recon_id.filter.yml +0 -0
  107. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/01_1_executed_by.filter.yml +0 -0
  108. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/01_2_started_at.filter.yml +0 -0
  109. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/02_0_source_type.filter.yml +0 -0
  110. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/02_1_source_table.filter.yml +0 -0
  111. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/02_2_target_table.filter.yml +0 -0
  112. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/04_0_aggregate_summary_table.sql +0 -0
  113. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/05_0_aggregate_recon_drilldown_header.md +0 -0
  114. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/06_0_recon_id.filter.yml +0 -0
  115. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/06_1_category.filter.yml +0 -0
  116. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/06_2_aggregate_type.filter.yml +0 -0
  117. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/07_0_target_table.filter.yml +0 -0
  118. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/07_1_source_table.filter.yml +0 -0
  119. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/08_0_aggregate_details_table.sql +0 -0
  120. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/09_0_aggregate_missing_mismatch_header.md +0 -0
  121. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/10_0_aggr_mismatched_records.sql +0 -0
  122. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/11_0_aggr_missing_in_databricks.sql +0 -0
  123. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/11_1_aggr_missing_in_source.sql +0 -0
  124. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/aggregate_reconciliation_metrics/dashboard.yml +0 -0
  125. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/00_0_recon_main.md +0 -0
  126. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/01_0_recon_id.filter.yml +0 -0
  127. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/01_1_report_type.filter.yml +0 -0
  128. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/01_2_executed_by.filter.yml +0 -0
  129. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/02_0_source_type.filter.yml +0 -0
  130. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/02_1_source_table.filter.yml +0 -0
  131. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/02_2_target_table.filter.yml +0 -0
  132. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/03_0_started_at.filter.yml +0 -0
  133. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/05_0_summary_table.sql +0 -0
  134. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/06_0_schema_comparison_header.md +0 -0
  135. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/07_0_schema_details_table.sql +0 -0
  136. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/08_0_drill_down_header.md +0 -0
  137. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/09_0_recon_id.filter.yml +0 -0
  138. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/09_1_category.filter.yml +0 -0
  139. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/10_0_target_table.filter.yml +0 -0
  140. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/10_1_source_table.filter.yml +0 -0
  141. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/11_0_recon_details_pivot.sql +0 -0
  142. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/12_0_daily_data_validation_issue_header.md +0 -0
  143. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/13_0_success_fail_.filter.yml +0 -0
  144. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/14_0_failed_recon_ids.sql +0 -0
  145. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/15_0_total_failed_runs.sql +0 -0
  146. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/15_1_failed_targets.sql +0 -0
  147. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/15_2_successful_targets.sql +0 -0
  148. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/16_0_missing_mismatch_header.md +0 -0
  149. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/17_0_mismatched_records.sql +0 -0
  150. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/17_1_threshold_mismatches.sql +0 -0
  151. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/18_0_missing_in_databricks.sql +0 -0
  152. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/18_1_missing_in_source.sql +0 -0
  153. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/dashboards/reconciliation_metrics/dashboard.yml +0 -0
  154. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/resources/reconcile/queries/installation → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/resources/reconcile/queries}/__init__.py +0 -0
  155. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/transpiler → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/resources/reconcile/queries/installation}/__init__.py +0 -0
  156. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/queries/installation/aggregate_details.sql +0 -0
  157. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/queries/installation/aggregate_metrics.sql +0 -0
  158. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/queries/installation/aggregate_rules.sql +0 -0
  159. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/queries/installation/details.sql +0 -0
  160. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/queries/installation/main.sql +0 -0
  161. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/resources/reconcile/queries/installation/metrics.sql +0 -0
  162. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/transpiler/lsp → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/transpiler}/__init__.py +0 -0
  163. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/execute.py +0 -0
  164. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/transpiler/sqlglot → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/transpiler/lsp}/__init__.py +0 -0
  165. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/transpiler/sqlglot/generator → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/transpiler/sqlglot}/__init__.py +0 -0
  166. {databricks_labs_lakebridge-0.10.5/databricks/labs/lakebridge/transpiler/sqlglot/parsers → databricks_labs_lakebridge-0.10.7/databricks/labs/lakebridge/transpiler/sqlglot/generator}/__init__.py +0 -0
  167. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/sqlglot/generator/databricks.py +0 -0
  168. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/sqlglot/lca_utils.py +0 -0
  169. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/sqlglot/local_expression.py +0 -0
  170. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/sqlglot/parsers/oracle.py +0 -0
  171. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/sqlglot/parsers/presto.py +0 -0
  172. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/sqlglot/parsers/snowflake.py +0 -0
  173. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/sqlglot/sqlglot_engine.py +0 -0
  174. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/transpiler/transpile_status.py +0 -0
  175. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/uninstall.py +0 -0
  176. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/upgrades/v0.4.0_add_main_table_operation_name_column.py +0 -0
  177. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/databricks/labs/lakebridge/upgrades/v0.6.0_alter_metrics_datatype.py +0 -0
  178. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/docs/lakebridge/src/components/Button.tsx +0 -0
  179. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/docs/lakebridge/src/components/ReconcileTabs.tsx +0 -0
  180. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/docs/lakebridge/src/css/custom.css +0 -0
  181. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/docs/lakebridge/src/css/table.css +0 -0
  182. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/docs/lakebridge/src/pages/index.tsx +0 -0
  183. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/docs/lakebridge/src/theme/DocSidebarItems/index.tsx +0 -0
  184. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/docs/lakebridge/src/theme/Footer/index.tsx +0 -0
  185. {databricks_labs_lakebridge-0.10.5 → databricks_labs_lakebridge-0.10.7}/docs/lakebridge/src/theme/Layout/index.tsx +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databricks-labs-lakebridge
3
- Version: 0.10.5
3
+ Version: 0.10.7
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
5
  Project-URL: Documentation, https://databrickslabs.github.io/lakebridge
6
6
  Project-URL: Issues, https://github.com/databrickslabs/lakebridge/issues
@@ -1,2 +1,2 @@
1
1
  # DO NOT MODIFY THIS FILE
2
- __version__ = "0.10.5"
2
+ __version__ = "0.10.7"
@@ -0,0 +1,95 @@
1
+ import tempfile
2
+ from pathlib import Path
3
+
4
+ from databricks.sdk.service.iam import User
5
+ from databricks.sdk.core import with_user_agent_extra
6
+
7
+ from databricks.labs.blueprint.entrypoint import get_logger
8
+ from databricks.labs.blueprint.tui import Prompts
9
+
10
+ from databricks.labs.bladespector.analyzer import Analyzer, _PLATFORM_TO_SOURCE_TECHNOLOGY
11
+
12
+ from databricks.labs.lakebridge.helpers.telemetry_utils import make_alphanum_or_semver
13
+ from databricks.labs.lakebridge.helpers.file_utils import check_path, move_tmp_file
14
+
15
+ logger = get_logger(__file__)
16
+
17
+
18
+ class LakebridgeAnalyzer(Analyzer):
19
+ def __init__(self, current_user: User, prompts: Prompts, is_debug: bool = False):
20
+ self._current_user = current_user
21
+ self._prompts = prompts
22
+ self._is_debug = is_debug
23
+ super().__init__()
24
+
25
+ def _get_source_directory(self) -> Path:
26
+ """Get and validate the source directory from user input."""
27
+ directory_str = self._prompts.question(
28
+ "Enter full path to the source directory",
29
+ default=Path.cwd().as_posix(),
30
+ validate=check_path,
31
+ )
32
+ return Path(directory_str).resolve()
33
+
34
+ def _get_result_file_path(self, directory: Path) -> Path:
35
+ """Get the result file path - accepts either filename or full path."""
36
+ filename = self._prompts.question(
37
+ "Enter report file name or custom export path including file name without extension",
38
+ default=f"{directory.as_posix()}/lakebridge-analyzer-results.xlsx",
39
+ validate=check_path,
40
+ )
41
+ return directory / Path(filename) if len(filename.split("/")) == 1 else Path(filename)
42
+
43
+ def _get_source_tech(self, platform: str | None = None) -> str:
44
+ """Validate source technology or prompt for a valid source"""
45
+ if platform is None or platform not in self.supported_source_technologies():
46
+ if platform is not None:
47
+ logger.warning(f"Invalid source technology {platform}")
48
+ platform = self._prompts.choice("Select the source technology", self.supported_source_technologies())
49
+ with_user_agent_extra("analyzer_source_tech", make_alphanum_or_semver(platform))
50
+ logger.debug(f"User: {self._current_user}")
51
+ return _PLATFORM_TO_SOURCE_TECHNOLOGY[platform]
52
+
53
+ @staticmethod
54
+ def _temp_xlsx_path(results_dir: Path | str) -> Path:
55
+ return (Path(tempfile.mkdtemp()) / Path(results_dir).name).with_suffix(".xlsx")
56
+
57
+ def _run_prompt_analyzer(self):
58
+ """Run the analyzer: prompt guided"""
59
+ source_dir = self._get_source_directory()
60
+ results_dir = self._get_result_file_path(source_dir)
61
+ tmp_dir = self._temp_xlsx_path(results_dir)
62
+ technology = self._get_source_tech()
63
+
64
+ self._run_binary(source_dir, tmp_dir, technology, self._is_debug)
65
+
66
+ move_tmp_file(tmp_dir, results_dir)
67
+
68
+ logger.info(f"Successfully Analyzed files in ${source_dir} for ${technology} and saved report to {results_dir}")
69
+
70
+ def _run_arg_analyzer(self, source_dir: str | None, results_dir: str | None, technology: str | None):
71
+ """Run the analyzer: arg guided"""
72
+ if source_dir is None or results_dir is None or technology is None:
73
+ logger.error("All arguments (--source-directory, --report-file, --source-tech) must be provided")
74
+ return
75
+
76
+ if check_path(source_dir) and check_path(results_dir):
77
+ tmp_dir = self._temp_xlsx_path(results_dir)
78
+ technology = self._get_source_tech(technology)
79
+ self._run_binary(Path(source_dir), tmp_dir, technology, self._is_debug)
80
+
81
+ move_tmp_file(tmp_dir, Path(results_dir))
82
+
83
+ logger.info(
84
+ f"Successfully Analyzed files in ${source_dir} for ${technology} and saved report to {results_dir}"
85
+ )
86
+
87
+ def run_analyzer(
88
+ self, source_dir: str | None = None, results_dir: str | None = None, technology: str | None = None
89
+ ):
90
+ """Run the analyzer."""
91
+ if not any([source_dir, results_dir, technology]):
92
+ self._run_prompt_analyzer()
93
+ return
94
+
95
+ self._run_arg_analyzer(source_dir, results_dir, technology)
@@ -0,0 +1,34 @@
1
+ from databricks.labs.blueprint.logger import install_logger
2
+ from databricks.labs.blueprint.entrypoint import get_logger
3
+ from databricks.sdk import WorkspaceClient
4
+ from databricks.sdk.core import with_user_agent_extra
5
+
6
+ from databricks.labs.lakebridge import __version__
7
+ from databricks.labs.lakebridge.install import installer as _installer
8
+ from databricks.labs.lakebridge.transpiler.repository import TranspilerRepository
9
+
10
+
11
+ def main() -> None:
12
+ install_logger()
13
+ with_user_agent_extra("cmd", "install")
14
+
15
+ logger = get_logger(__file__)
16
+ logger.setLevel("INFO")
17
+
18
+ installer = _installer(
19
+ WorkspaceClient(product="lakebridge", product_version=__version__),
20
+ transpiler_repository=TranspilerRepository.user_home(),
21
+ )
22
+ if installer.has_installed_transpilers():
23
+ logger.warning(
24
+ "Detected existing Lakebridge transpilers; run 'databricks labs lakebridge install-transpile' to upgrade them."
25
+ )
26
+ else:
27
+ logger.debug("No existing Lakebridge transpilers detected; assuming fresh installation.")
28
+
29
+ logger.info("Successfully Setup Lakebridge Components Locally")
30
+ logger.info("For more information, please visit https://databrickslabs.github.io/lakebridge/")
31
+
32
+
33
+ if __name__ == "__main__":
34
+ main()
@@ -19,28 +19,23 @@ from databricks.labs.blueprint.entrypoint import get_logger, is_in_debug
19
19
  from databricks.labs.blueprint.installation import RootJsonValue
20
20
  from databricks.labs.blueprint.tui import Prompts
21
21
 
22
- from databricks.labs.bladespector.analyzer import Analyzer
23
-
24
22
 
25
23
  from databricks.labs.lakebridge.assessments.configure_assessment import (
26
24
  create_assessment_configurator,
27
25
  PROFILER_SOURCE_SYSTEM,
28
26
  )
29
27
 
30
- from databricks.labs.lakebridge.__about__ import __version__
31
28
  from databricks.labs.lakebridge.config import TranspileConfig
32
29
  from databricks.labs.lakebridge.contexts.application import ApplicationContext
33
30
  from databricks.labs.lakebridge.helpers.recon_config_utils import ReconConfigPrompts
34
31
  from databricks.labs.lakebridge.helpers.telemetry_utils import make_alphanum_or_semver
35
- from databricks.labs.lakebridge.install import WorkspaceInstaller
36
- from databricks.labs.lakebridge.install import TranspilerInstaller
32
+ from databricks.labs.lakebridge.install import installer
37
33
  from databricks.labs.lakebridge.reconcile.runner import ReconcileRunner
38
34
  from databricks.labs.lakebridge.lineage import lineage_generator
39
35
  from databricks.labs.lakebridge.reconcile.recon_config import RECONCILE_OPERATION_NAME, AGG_RECONCILE_OPERATION_NAME
40
36
  from databricks.labs.lakebridge.transpiler.execute import transpile as do_transpile
41
-
42
-
43
37
  from databricks.labs.lakebridge.transpiler.lsp.lsp_engine import LSPEngine
38
+ from databricks.labs.lakebridge.transpiler.repository import TranspilerRepository
44
39
  from databricks.labs.lakebridge.transpiler.sqlglot.sqlglot_engine import SqlglotEngine
45
40
  from databricks.labs.lakebridge.transpiler.transpile_engine import TranspileEngine
46
41
 
@@ -54,19 +49,6 @@ def raise_validation_exception(msg: str) -> NoReturn:
54
49
  raise ValueError(msg)
55
50
 
56
51
 
57
- def _installer(ws: WorkspaceClient) -> WorkspaceInstaller:
58
- app_context = ApplicationContext(_verify_workspace_client(ws))
59
- return WorkspaceInstaller(
60
- app_context.workspace_client,
61
- app_context.prompts,
62
- app_context.installation,
63
- app_context.install_state,
64
- app_context.product_info,
65
- app_context.resource_configurator,
66
- app_context.workspace_installation,
67
- )
68
-
69
-
70
52
  def _create_warehouse(ws: WorkspaceClient) -> str:
71
53
 
72
54
  dbsql = ws.warehouses.create_and_wait(
@@ -90,19 +72,6 @@ def _remove_warehouse(ws: WorkspaceClient, warehouse_id: str):
90
72
  logger.info(f"Removed warehouse post installation with id: {warehouse_id}")
91
73
 
92
74
 
93
- def _verify_workspace_client(ws: WorkspaceClient) -> WorkspaceClient:
94
- """
95
- [Private] Verifies and updates the workspace client configuration.
96
- """
97
-
98
- # Using reflection to set right value for _product_info for telemetry
99
- product_info = getattr(ws.config, '_product_info')
100
- if product_info[0] != "lakebridge":
101
- setattr(ws.config, '_product_info', ('lakebridge', __version__))
102
-
103
- return ws
104
-
105
-
106
75
  @lakebridge.command
107
76
  def transpile(
108
77
  w: WorkspaceClient,
@@ -114,12 +83,13 @@ def transpile(
114
83
  skip_validation: str | None = None,
115
84
  catalog_name: str | None = None,
116
85
  schema_name: str | None = None,
86
+ transpiler_repository: TranspilerRepository = TranspilerRepository.user_home(),
117
87
  ):
118
88
  """Transpiles source dialect to databricks dialect"""
119
89
  ctx = ApplicationContext(w)
120
90
  logger.debug(f"Preconfigured transpiler config: {ctx.transpile_config!r}")
121
91
  with_user_agent_extra("cmd", "execute-transpile")
122
- checker = _TranspileConfigChecker(ctx.transpile_config, ctx.prompts)
92
+ checker = _TranspileConfigChecker(ctx.transpile_config, ctx.prompts, transpiler_repository)
123
93
  checker.use_transpiler_config_path(transpiler_config_path)
124
94
  checker.use_source_dialect(source_dialect)
125
95
  checker.use_input_source(input_source)
@@ -188,14 +158,19 @@ class _TranspileConfigChecker:
188
158
 
189
159
  _config: TranspileConfig
190
160
  """The workspace configuration for transpiling, updated from command-line arguments."""
191
- # _engine: TranspileEngine | None
192
- # """The transpiler engine to use for transpiling, lazily loaded based on the configuration."""
193
161
  _prompts: Prompts
194
162
  """Prompting system, for requesting configuration that hasn't been provided."""
195
163
  _source_dialect_override: str | None = None
196
164
  """The source dialect provided on the command-line, if any."""
197
-
198
- def __init__(self, config: TranspileConfig | None, prompts: Prompts) -> None:
165
+ _transpiler_repository: TranspilerRepository
166
+ """The repository where available transpilers are installed."""
167
+
168
+ def __init__(
169
+ self,
170
+ config: TranspileConfig | None,
171
+ prompts: Prompts,
172
+ transpiler_repository: TranspilerRepository,
173
+ ) -> None:
199
174
  if config is None:
200
175
  logger.warning(
201
176
  "No workspace transpile configuration, use 'install-transpile' to (re)install and configure; using defaults for now."
@@ -203,6 +178,7 @@ class _TranspileConfigChecker:
203
178
  config = TranspileConfig()
204
179
  self._config = config
205
180
  self._prompts = prompts
181
+ self._transpiler_repository = transpiler_repository
206
182
  self._source_dialect_override = None
207
183
 
208
184
  @staticmethod
@@ -334,7 +310,7 @@ class _TranspileConfigChecker:
334
310
  def _configure_transpiler_config_path(self, source_dialect: str) -> TranspileEngine | None:
335
311
  """Configure the transpiler config path based on the requested source dialect."""
336
312
  # Names of compatible transpiler engines for the given dialect.
337
- compatible_transpilers = TranspilerInstaller.transpilers_with_dialect(source_dialect)
313
+ compatible_transpilers = self._transpiler_repository.transpilers_with_dialect(source_dialect)
338
314
  match len(compatible_transpilers):
339
315
  case 0:
340
316
  # Nothing found for the specified dialect, fail.
@@ -349,10 +325,10 @@ class _TranspileConfigChecker:
349
325
  f"Multiple transpilers available for dialect {source_dialect!r}: {compatible_transpilers!r}"
350
326
  )
351
327
  transpiler_name = self._prompts.choice("Select the transpiler:", list(compatible_transpilers))
352
- transpiler_config_path = TranspilerInstaller.transpiler_config_path(transpiler_name)
328
+ transpiler_config_path = self._transpiler_repository.transpiler_config_path(transpiler_name)
353
329
  logger.info(f"Lakebridge will use the {transpiler_name} transpiler.")
354
330
  self._config = dataclasses.replace(self._config, transpiler_config_path=str(transpiler_config_path))
355
- return TranspileEngine.load_engine(transpiler_config_path)
331
+ return LSPEngine.from_config_path(transpiler_config_path)
356
332
 
357
333
  def _configure_source_dialect(
358
334
  self, source_dialect: str, engine: TranspileEngine | None, msg_prefix: str
@@ -361,7 +337,7 @@ class _TranspileConfigChecker:
361
337
  if engine is None:
362
338
  engine = self._configure_transpiler_config_path(source_dialect)
363
339
  if engine is None:
364
- supported_dialects = ", ".join(TranspilerInstaller.all_dialects())
340
+ supported_dialects = ", ".join(self._transpiler_repository.all_dialects())
365
341
  msg = f"{msg_prefix}: {source_dialect!r} (supported dialects: {supported_dialects})"
366
342
  raise_validation_exception(msg)
367
343
  else:
@@ -375,7 +351,7 @@ class _TranspileConfigChecker:
375
351
 
376
352
  def _prompt_source_dialect(self) -> TranspileEngine:
377
353
  # This is similar to the post-install prompting for the source dialect.
378
- supported_dialects = TranspilerInstaller.all_dialects()
354
+ supported_dialects = self._transpiler_repository.all_dialects()
379
355
  match len(supported_dialects):
380
356
  case 0:
381
357
  msg = "No transpilers are available, install using 'install-transpile' or use --transpiler-conf-path'."
@@ -420,14 +396,15 @@ class _TranspileConfigChecker:
420
396
  #
421
397
 
422
398
  # Step 1: Check the transpiler config path.
399
+ engine: TranspileEngine | None
423
400
  transpiler_config_path = self._config.transpiler_config_path
424
401
  if transpiler_config_path is not None:
425
402
  self._validate_transpiler_config_path(
426
403
  transpiler_config_path,
427
- f"Invalid transpiler path configured, path does not exist: {transpiler_config_path}",
404
+ f"Error: Invalid value for '--transpiler-config-path': '{str(transpiler_config_path)}', file does not exist.",
428
405
  )
429
406
  path = Path(transpiler_config_path)
430
- engine = TranspileEngine.load_engine(path)
407
+ engine = LSPEngine.from_config_path(path)
431
408
  else:
432
409
  engine = None
433
410
  del transpiler_config_path
@@ -522,7 +499,7 @@ async def _transpile(ctx: ApplicationContext, config: TranspileConfig, engine: T
522
499
  return [status]
523
500
 
524
501
 
525
- def _override_workspace_client_config(ctx: ApplicationContext, overrides: dict[str, str] | None):
502
+ def _override_workspace_client_config(ctx: ApplicationContext, overrides: dict[str, str] | None) -> None:
526
503
  """
527
504
  Override the Workspace client's SDK config with the user provided SDK config.
528
505
  Users can provide the cluster_id and warehouse_id during the installation.
@@ -541,7 +518,7 @@ def _override_workspace_client_config(ctx: ApplicationContext, overrides: dict[s
541
518
 
542
519
 
543
520
  @lakebridge.command
544
- def reconcile(w: WorkspaceClient):
521
+ def reconcile(w: WorkspaceClient) -> None:
545
522
  """[EXPERIMENTAL] Reconciles source to Databricks datasets"""
546
523
  with_user_agent_extra("cmd", "execute-reconcile")
547
524
  ctx = ApplicationContext(w)
@@ -557,7 +534,7 @@ def reconcile(w: WorkspaceClient):
557
534
 
558
535
 
559
536
  @lakebridge.command
560
- def aggregates_reconcile(w: WorkspaceClient):
537
+ def aggregates_reconcile(w: WorkspaceClient) -> None:
561
538
  """[EXPERIMENTAL] Reconciles Aggregated source to Databricks datasets"""
562
539
  with_user_agent_extra("cmd", "execute-aggregates-reconcile")
563
540
  ctx = ApplicationContext(w)
@@ -574,7 +551,13 @@ def aggregates_reconcile(w: WorkspaceClient):
574
551
 
575
552
 
576
553
  @lakebridge.command
577
- def generate_lineage(w: WorkspaceClient, *, source_dialect: str | None = None, input_source: str, output_folder: str):
554
+ def generate_lineage(
555
+ w: WorkspaceClient,
556
+ *,
557
+ source_dialect: str | None = None,
558
+ input_source: str,
559
+ output_folder: str,
560
+ ) -> None:
578
561
  """[Experimental] Generates a lineage of source SQL files or folder"""
579
562
  ctx = ApplicationContext(w)
580
563
  logger.debug(f"User: {ctx.current_user}")
@@ -595,7 +578,7 @@ def generate_lineage(w: WorkspaceClient, *, source_dialect: str | None = None, i
595
578
 
596
579
 
597
580
  @lakebridge.command
598
- def configure_secrets(w: WorkspaceClient):
581
+ def configure_secrets(w: WorkspaceClient) -> None:
599
582
  """Setup reconciliation connection profile details as Secrets on Databricks Workspace"""
600
583
  recon_conf = ReconConfigPrompts(w)
601
584
 
@@ -607,7 +590,7 @@ def configure_secrets(w: WorkspaceClient):
607
590
 
608
591
 
609
592
  @lakebridge.command(is_unauthenticated=True)
610
- def configure_database_profiler():
593
+ def configure_database_profiler() -> None:
611
594
  """[Experimental] Install the lakebridge Assessment package"""
612
595
  prompts = Prompts()
613
596
 
@@ -622,19 +605,26 @@ def configure_database_profiler():
622
605
 
623
606
 
624
607
  @lakebridge.command()
625
- def install_transpile(w: WorkspaceClient, artifact: str | None = None):
626
- """Install the Lakebridge transpilers"""
608
+ def install_transpile(
609
+ w: WorkspaceClient,
610
+ artifact: str | None = None,
611
+ transpiler_repository: TranspilerRepository = TranspilerRepository.user_home(),
612
+ ) -> None:
613
+ """Install or upgrade the Lakebridge transpilers."""
627
614
  with_user_agent_extra("cmd", "install-transpile")
628
615
  if artifact:
629
616
  with_user_agent_extra("artifact-overload", Path(artifact).name)
630
617
  user = w.current_user
631
618
  logger.debug(f"User: {user}")
632
- installer = _installer(w)
633
- installer.run(module="transpile", artifact=artifact)
619
+ transpile_installer = installer(w, transpiler_repository)
620
+ transpile_installer.run(module="transpile", artifact=artifact)
634
621
 
635
622
 
636
623
  @lakebridge.command(is_unauthenticated=False)
637
- def configure_reconcile(w: WorkspaceClient):
624
+ def configure_reconcile(
625
+ w: WorkspaceClient,
626
+ transpiler_repository: TranspilerRepository = TranspilerRepository.user_home(),
627
+ ) -> None:
638
628
  """Configure the Lakebridge reconciliation module"""
639
629
  with_user_agent_extra("cmd", "configure-reconcile")
640
630
  user = w.current_user
@@ -643,28 +633,23 @@ def configure_reconcile(w: WorkspaceClient):
643
633
  dbsql_id = _create_warehouse(w)
644
634
  w.config.warehouse_id = dbsql_id
645
635
  logger.debug(f"Warehouse ID used for configuring reconcile: {w.config.warehouse_id}.")
646
- installer = _installer(w)
647
- installer.run(module="reconcile")
636
+ reconcile_installer = installer(w, transpiler_repository)
637
+ reconcile_installer.run(module="reconcile")
648
638
 
649
639
 
650
640
  @lakebridge.command()
651
- def analyze(w: WorkspaceClient, source_directory: str, report_file: str, source_tech: str | None = None):
641
+ def analyze(
642
+ w: WorkspaceClient,
643
+ source_directory: str | None = None,
644
+ report_file: str | None = None,
645
+ source_tech: str | None = None,
646
+ ):
652
647
  """Run the Analyzer"""
653
648
  with_user_agent_extra("cmd", "analyze")
654
649
  ctx = ApplicationContext(w)
655
- prompts = ctx.prompts
656
- output_file = report_file
657
- input_folder = source_directory
658
- if source_tech is None:
659
- source_tech = prompts.choice("Select the source technology", Analyzer.supported_source_technologies())
660
- with_user_agent_extra("analyzer_source_tech", make_alphanum_or_semver(source_tech))
661
- user = ctx.current_user
662
- logger.debug(f"User: {user}")
663
- is_debug = logger.getEffectiveLevel() == logging.DEBUG
664
- Analyzer.analyze(Path(input_folder), Path(output_file), source_tech, is_debug=is_debug)
665
- logger.info(
666
- f"Successfully Analyzed files in ${source_directory} for ${source_tech} and saved report to {report_file}"
667
- )
650
+
651
+ logger.debug(f"User: {ctx.current_user}")
652
+ ctx.analyzer.run_analyzer(source_directory, report_file, source_tech)
668
653
 
669
654
 
670
655
  if __name__ == "__main__":
@@ -185,6 +185,6 @@ class ReconcileConfig:
185
185
 
186
186
 
187
187
  @dataclass
188
- class RemorphConfigs:
188
+ class LakebridgeConfiguration:
189
189
  transpile: TranspileConfig | None = None
190
190
  reconcile: ReconcileConfig | None = None
@@ -12,7 +12,8 @@ from databricks.sdk.config import Config
12
12
  from databricks.sdk.errors import NotFound
13
13
  from databricks.sdk.service.iam import User
14
14
 
15
- from databricks.labs.lakebridge.config import TranspileConfig, ReconcileConfig, RemorphConfigs
15
+ from databricks.labs.lakebridge.analyzer.lakebridge_analyzer import LakebridgeAnalyzer
16
+ from databricks.labs.lakebridge.config import TranspileConfig, ReconcileConfig, LakebridgeConfiguration
16
17
  from databricks.labs.lakebridge.deployment.configurator import ResourceConfigurator
17
18
  from databricks.labs.lakebridge.deployment.dashboard import DashboardDeployment
18
19
  from databricks.labs.lakebridge.deployment.installation import WorkspaceInstallation
@@ -22,6 +23,7 @@ from databricks.labs.lakebridge.helpers.metastore import CatalogOperations
22
23
  logger = logging.getLogger(__name__)
23
24
 
24
25
 
26
+ # pylint: disable=too-many-public-methods
25
27
  class ApplicationContext:
26
28
  def __init__(self, ws: WorkspaceClient):
27
29
  self._ws = ws
@@ -42,7 +44,7 @@ class ApplicationContext:
42
44
 
43
45
  @cached_property
44
46
  def product_info(self) -> ProductInfo:
45
- return ProductInfo.from_class(RemorphConfigs)
47
+ return ProductInfo.from_class(LakebridgeConfiguration)
46
48
 
47
49
  @cached_property
48
50
  def installation(self) -> Installation:
@@ -65,8 +67,8 @@ class ApplicationContext:
65
67
  return None
66
68
 
67
69
  @cached_property
68
- def remorph_config(self) -> RemorphConfigs:
69
- return RemorphConfigs(transpile=self.transpile_config, reconcile=self.recon_config)
70
+ def remorph_config(self) -> LakebridgeConfiguration:
71
+ return LakebridgeConfiguration(transpile=self.transpile_config, reconcile=self.recon_config)
70
72
 
71
73
  @cached_property
72
74
  def connect_config(self) -> Config:
@@ -131,3 +133,8 @@ class ApplicationContext:
131
133
  @cached_property
132
134
  def upgrades(self):
133
135
  return Upgrades(self.product_info, self.installation)
136
+
137
+ @cached_property
138
+ def analyzer(self):
139
+ is_debug = logger.getEffectiveLevel() == logging.DEBUG
140
+ return LakebridgeAnalyzer(self.current_user, self.prompts, is_debug)
@@ -54,7 +54,8 @@ class DashboardDeployment:
54
54
 
55
55
  valid_dashboard_refs = set()
56
56
  for dashboard_folder in folder.iterdir():
57
- if not dashboard_folder.is_dir():
57
+ # Make sure the directory contains a dashboard
58
+ if not (dashboard_folder.is_dir() and dashboard_folder.joinpath("dashboard.yml").exists()):
58
59
  continue
59
60
  valid_dashboard_refs.add(self._dashboard_reference(dashboard_folder))
60
61
  dashboard = self._update_or_create_dashboard(dashboard_folder, parent_path, config.metadata_config)
@@ -11,7 +11,7 @@ from databricks.sdk.errors import NotFound
11
11
  from databricks.sdk.mixins.compute import SemVer
12
12
  from databricks.sdk.errors.platform import InvalidParameterValue, ResourceDoesNotExist
13
13
 
14
- from databricks.labs.lakebridge.config import RemorphConfigs
14
+ from databricks.labs.lakebridge.config import LakebridgeConfiguration
15
15
  from databricks.labs.lakebridge.deployment.recon import ReconDeployment
16
16
 
17
17
  logger = logging.getLogger("databricks.labs.lakebridge.install")
@@ -54,14 +54,14 @@ class WorkspaceInstallation:
54
54
  return Version(
55
55
  version=local_installed_version,
56
56
  date=local_installed_date,
57
- wheel=f"databricks_labs_remorph-{local_installed_version}-py3-none-any.whl",
57
+ wheel=f"databricks_labs_lakebridge-{local_installed_version}-py3-none-any.whl",
58
58
  )
59
59
 
60
60
  def _get_ws_version(self):
61
61
  try:
62
62
  return self._installation.load(Version)
63
- except ResourceDoesNotExist as err:
64
- logger.warning(f"Unable to get Workspace Version due to: {err}")
63
+ except ResourceDoesNotExist:
64
+ logger.debug("No existing version found in workspace; assuming fresh installation.")
65
65
  return None
66
66
 
67
67
  def _apply_upgrades(self):
@@ -91,21 +91,21 @@ class WorkspaceInstallation:
91
91
  wheel_paths = [f"/Workspace{wheel}" for wheel in wheel_paths]
92
92
  return wheel_paths
93
93
 
94
- def install(self, config: RemorphConfigs):
94
+ def install(self, config: LakebridgeConfiguration):
95
95
  self._apply_upgrades()
96
96
  wheel_paths: list[str] = self._upload_wheel()
97
97
  if config.reconcile:
98
- logger.info("Installing Remorph reconcile Metadata components.")
98
+ logger.info("Installing Lakebridge reconcile Metadata components.")
99
99
  self._recon_deployment.install(config.reconcile, wheel_paths)
100
100
 
101
- def uninstall(self, config: RemorphConfigs):
102
- # This will remove all the Remorph modules
101
+ def uninstall(self, config: LakebridgeConfiguration):
102
+ # This will remove all the Lakebridge modules
103
103
  if not self._prompts.confirm(
104
- "Do you want to uninstall Remorph from the workspace too, this would "
105
- "remove Remorph project folder, jobs, metadata and dashboards"
104
+ "Do you want to uninstall Lakebridge from the workspace too, this would "
105
+ "remove Lakebridge project folder, jobs, metadata and dashboards"
106
106
  ):
107
107
  return
108
- logger.info(f"Uninstalling Remorph from {self._ws.config.host}.")
108
+ logger.info(f"Uninstalling Lakebridge from {self._ws.config.host}.")
109
109
  try:
110
110
  self._installation.files()
111
111
  except NotFound:
@@ -112,8 +112,8 @@ class JobDeployment:
112
112
  libraries = [
113
113
  compute.Library(whl=remorph_wheel_path),
114
114
  ]
115
- source = recon_config.data_source
116
- if source == ReconSourceType.ORACLE.value:
115
+
116
+ if recon_config.data_source == ReconSourceType.ORACLE.value:
117
117
  # TODO: Automatically fetch a version list for `ojdbc8`
118
118
  oracle_driver_version = "23.4.0.24.05"
119
119
  libraries.append(
@@ -1,8 +1,13 @@
1
1
  import contextlib
2
+ import logging
2
3
  import os
3
4
  from pathlib import Path
5
+ from shutil import move, Error
6
+ from datetime import datetime
4
7
  from collections.abc import Generator
5
8
 
9
+ logger = logging.getLogger(__name__)
10
+
6
11
 
7
12
  def is_sql_file(file: str | Path) -> bool:
8
13
  """
@@ -63,3 +68,34 @@ def chdir(new_path: Path) -> Generator[None, None, None]:
63
68
  yield
64
69
  finally:
65
70
  os.chdir(saved_path)
71
+
72
+
73
+ def check_path(path: str) -> bool:
74
+ """Validates a path for both existing files and writable files."""
75
+ try:
76
+ path_obj = Path(path) if not isinstance(path, Path) else path
77
+
78
+ if path_obj.exists():
79
+ return os.access(path_obj, os.W_OK)
80
+
81
+ parent = path_obj.parent
82
+ return parent.exists() and os.access(parent, os.W_OK)
83
+
84
+ except OSError as e:
85
+ logger.warning(f"Could not validate path: {path}, error: {e}")
86
+ return False
87
+
88
+
89
+ def move_tmp_file(tmp_path: Path, output_path: Path) -> None:
90
+ """Process file from a temp directory"""
91
+ try:
92
+ move(tmp_path, output_path.parent)
93
+ except (FileExistsError, Error):
94
+ timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
95
+ new_output_path = output_path.parent / timestamp
96
+ new_output_path.mkdir(exist_ok=True)
97
+
98
+ move(tmp_path, new_output_path)
99
+ finally:
100
+ tmp_path.parent.rmdir()
101
+ logger.info(f"Results store at {output_path}")