openmetadata-ingestion 1.5.0.0rc2__py3-none-any.whl → 1.5.2.0__py3-none-any.whl
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.
Potentially problematic release.
This version of openmetadata-ingestion might be problematic. Click here for more details.
- metadata/generated/schema/analytics/__init__.py +1 -1
- metadata/generated/schema/analytics/basic.py +1 -1
- metadata/generated/schema/analytics/reportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/__init__.py +1 -1
- metadata/generated/schema/analytics/reportDataType/aggregatedCostAnalysisReportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/entityReportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/rawCostAnalysisReportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/webAnalyticEntityViewReportData.py +1 -1
- metadata/generated/schema/analytics/reportDataType/webAnalyticUserActivityReportData.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEvent.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEventData.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEventType/__init__.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEventType/customEvent.py +1 -1
- metadata/generated/schema/analytics/webAnalyticEventType/pageViewEvent.py +1 -1
- metadata/generated/schema/api/__init__.py +1 -1
- metadata/generated/schema/api/addGlossaryToAssetsRequest.py +1 -1
- metadata/generated/schema/api/analytics/__init__.py +1 -1
- metadata/generated/schema/api/analytics/createWebAnalyticEvent.py +1 -1
- metadata/generated/schema/api/automations/__init__.py +1 -1
- metadata/generated/schema/api/automations/createWorkflow.py +1 -1
- metadata/generated/schema/api/bulkAssets.py +1 -1
- metadata/generated/schema/api/classification/__init__.py +1 -1
- metadata/generated/schema/api/classification/createClassification.py +1 -1
- metadata/generated/schema/api/classification/createTag.py +1 -1
- metadata/generated/schema/api/classification/loadTags.py +1 -1
- metadata/generated/schema/api/createBot.py +1 -1
- metadata/generated/schema/api/createEventPublisherJob.py +1 -1
- metadata/generated/schema/api/createType.py +1 -1
- metadata/generated/schema/api/data/__init__.py +1 -1
- metadata/generated/schema/api/data/createAPICollection.py +1 -1
- metadata/generated/schema/api/data/createAPIEndpoint.py +1 -1
- metadata/generated/schema/api/data/createChart.py +1 -1
- metadata/generated/schema/api/data/createContainer.py +1 -1
- metadata/generated/schema/api/data/createCustomProperty.py +1 -1
- metadata/generated/schema/api/data/createDashboard.py +1 -1
- metadata/generated/schema/api/data/createDashboardDataModel.py +1 -1
- metadata/generated/schema/api/data/createDatabase.py +1 -1
- metadata/generated/schema/api/data/createDatabaseSchema.py +1 -1
- metadata/generated/schema/api/data/createGlossary.py +1 -1
- metadata/generated/schema/api/data/createGlossaryTerm.py +1 -1
- metadata/generated/schema/api/data/createMlModel.py +1 -1
- metadata/generated/schema/api/data/createPipeline.py +1 -1
- metadata/generated/schema/api/data/createQuery.py +1 -1
- metadata/generated/schema/api/data/createSearchIndex.py +1 -1
- metadata/generated/schema/api/data/createStoredProcedure.py +1 -1
- metadata/generated/schema/api/data/createTable.py +1 -1
- metadata/generated/schema/api/data/createTableProfile.py +1 -1
- metadata/generated/schema/api/data/createTopic.py +1 -1
- metadata/generated/schema/api/data/loadGlossary.py +1 -1
- metadata/generated/schema/api/data/restoreEntity.py +1 -1
- metadata/generated/schema/api/dataInsight/__init__.py +1 -1
- metadata/generated/schema/api/dataInsight/createDataInsightChart.py +1 -1
- metadata/generated/schema/api/dataInsight/custom/__init__.py +1 -1
- metadata/generated/schema/api/dataInsight/custom/createDataInsightCustomChart.py +1 -1
- metadata/generated/schema/api/dataInsight/kpi/__init__.py +1 -1
- metadata/generated/schema/api/dataInsight/kpi/createKpiRequest.py +1 -1
- metadata/generated/schema/api/docStore/__init__.py +1 -1
- metadata/generated/schema/api/docStore/createDocument.py +1 -1
- metadata/generated/schema/api/domains/__init__.py +1 -1
- metadata/generated/schema/api/domains/createDataProduct.py +8 -1
- metadata/generated/schema/api/domains/createDomain.py +1 -1
- metadata/generated/schema/api/feed/__init__.py +1 -1
- metadata/generated/schema/api/feed/closeTask.py +1 -1
- metadata/generated/schema/api/feed/createPost.py +1 -1
- metadata/generated/schema/api/feed/createSuggestion.py +1 -1
- metadata/generated/schema/api/feed/createThread.py +1 -1
- metadata/generated/schema/api/feed/resolveTask.py +1 -1
- metadata/generated/schema/api/feed/threadCount.py +1 -1
- metadata/generated/schema/api/lineage/__init__.py +1 -1
- metadata/generated/schema/api/lineage/addLineage.py +1 -1
- metadata/generated/schema/api/openMetadataServerVersion.py +1 -1
- metadata/generated/schema/api/policies/__init__.py +1 -1
- metadata/generated/schema/api/policies/createPolicy.py +1 -1
- metadata/generated/schema/api/services/__init__.py +1 -1
- metadata/generated/schema/api/services/createApiService.py +1 -1
- metadata/generated/schema/api/services/createDashboardService.py +1 -1
- metadata/generated/schema/api/services/createDatabaseService.py +1 -1
- metadata/generated/schema/api/services/createMessagingService.py +1 -1
- metadata/generated/schema/api/services/createMetadataService.py +1 -1
- metadata/generated/schema/api/services/createMlModelService.py +1 -1
- metadata/generated/schema/api/services/createPipelineService.py +1 -1
- metadata/generated/schema/api/services/createSearchService.py +1 -1
- metadata/generated/schema/api/services/createStorageService.py +1 -1
- metadata/generated/schema/api/services/ingestionPipelines/__init__.py +1 -1
- metadata/generated/schema/api/services/ingestionPipelines/createIngestionPipeline.py +1 -1
- metadata/generated/schema/api/setOwner.py +1 -1
- metadata/generated/schema/api/teams/__init__.py +1 -1
- metadata/generated/schema/api/teams/createPersona.py +1 -1
- metadata/generated/schema/api/teams/createRole.py +1 -1
- metadata/generated/schema/api/teams/createTeam.py +1 -1
- metadata/generated/schema/api/teams/createUser.py +1 -1
- metadata/generated/schema/api/tests/__init__.py +1 -1
- metadata/generated/schema/api/tests/createCustomMetric.py +1 -1
- metadata/generated/schema/api/tests/createLogicalTestCases.py +1 -1
- metadata/generated/schema/api/tests/createTestCase.py +1 -1
- metadata/generated/schema/api/tests/createTestCaseResolutionStatus.py +1 -1
- metadata/generated/schema/api/tests/createTestDefinition.py +1 -1
- metadata/generated/schema/api/tests/createTestSuite.py +1 -1
- metadata/generated/schema/api/voteRequest.py +1 -1
- metadata/generated/schema/auth/__init__.py +1 -1
- metadata/generated/schema/auth/basicAuth.py +1 -1
- metadata/generated/schema/auth/basicLoginRequest.py +1 -1
- metadata/generated/schema/auth/changePasswordRequest.py +1 -1
- metadata/generated/schema/auth/createPersonalToken.py +1 -1
- metadata/generated/schema/auth/emailRequest.py +1 -1
- metadata/generated/schema/auth/emailVerificationToken.py +1 -1
- metadata/generated/schema/auth/generateToken.py +1 -1
- metadata/generated/schema/auth/jwtAuth.py +1 -1
- metadata/generated/schema/auth/loginRequest.py +1 -1
- metadata/generated/schema/auth/logoutRequest.py +1 -1
- metadata/generated/schema/auth/passwordResetRequest.py +1 -1
- metadata/generated/schema/auth/passwordResetToken.py +1 -1
- metadata/generated/schema/auth/personalAccessToken.py +1 -1
- metadata/generated/schema/auth/refreshToken.py +1 -1
- metadata/generated/schema/auth/registrationRequest.py +1 -1
- metadata/generated/schema/auth/revokePersonalToken.py +1 -1
- metadata/generated/schema/auth/revokeToken.py +1 -1
- metadata/generated/schema/auth/serviceTokenEnum.py +1 -1
- metadata/generated/schema/auth/ssoAuth.py +1 -1
- metadata/generated/schema/auth/tokenRefreshRequest.py +1 -1
- metadata/generated/schema/configuration/__init__.py +1 -1
- metadata/generated/schema/configuration/appsPrivateConfiguration.py +1 -1
- metadata/generated/schema/configuration/authConfig.py +1 -1
- metadata/generated/schema/configuration/authenticationConfiguration.py +1 -1
- metadata/generated/schema/configuration/authorizerConfiguration.py +1 -1
- metadata/generated/schema/configuration/changeEventConfiguration.py +1 -1
- metadata/generated/schema/configuration/dataQualityConfiguration.py +1 -1
- metadata/generated/schema/configuration/elasticSearchConfiguration.py +1 -1
- metadata/generated/schema/configuration/eventHandlerConfiguration.py +1 -1
- metadata/generated/schema/configuration/fernetConfiguration.py +1 -1
- metadata/generated/schema/configuration/jwtTokenConfiguration.py +1 -1
- metadata/generated/schema/configuration/kafkaEventConfiguration.py +1 -1
- metadata/generated/schema/configuration/ldapConfiguration.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/__init__.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/customTrustManagerConfig.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/hostNameConfig.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/jvmDefaultConfig.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/trustAllConfig.py +1 -1
- metadata/generated/schema/configuration/ldapTrustStoreConfig/truststoreConfig.py +1 -1
- metadata/generated/schema/configuration/limitsConfiguration.py +1 -1
- metadata/generated/schema/configuration/loginConfiguration.py +1 -1
- metadata/generated/schema/configuration/logoConfiguration.py +1 -1
- metadata/generated/schema/configuration/pipelineServiceClientConfiguration.py +1 -1
- metadata/generated/schema/configuration/profilerConfiguration.py +1 -1
- metadata/generated/schema/configuration/slackAppConfiguration.py +1 -1
- metadata/generated/schema/configuration/taskNotificationConfiguration.py +1 -1
- metadata/generated/schema/configuration/testResultNotificationConfiguration.py +1 -1
- metadata/generated/schema/configuration/themeConfiguration.py +1 -1
- metadata/generated/schema/configuration/uiThemePreference.py +1 -1
- metadata/generated/schema/dataInsight/__init__.py +1 -1
- metadata/generated/schema/dataInsight/custom/__init__.py +1 -1
- metadata/generated/schema/dataInsight/custom/dataInsightCustomChart.py +1 -1
- metadata/generated/schema/dataInsight/custom/dataInsightCustomChartResult.py +1 -1
- metadata/generated/schema/dataInsight/custom/dataInsightCustomChartResultList.py +1 -1
- metadata/generated/schema/dataInsight/custom/formulaHolder.py +1 -1
- metadata/generated/schema/dataInsight/custom/lineChart.py +1 -1
- metadata/generated/schema/dataInsight/custom/summaryCard.py +1 -1
- metadata/generated/schema/dataInsight/dataInsightChart.py +1 -1
- metadata/generated/schema/dataInsight/dataInsightChartResult.py +1 -21
- metadata/generated/schema/dataInsight/kpi/__init__.py +1 -1
- metadata/generated/schema/dataInsight/kpi/basic.py +1 -1
- metadata/generated/schema/dataInsight/kpi/kpi.py +1 -1
- metadata/generated/schema/dataInsight/type/__init__.py +1 -1
- metadata/generated/schema/dataInsight/type/aggregatedUnusedAssetsCount.py +1 -1
- metadata/generated/schema/dataInsight/type/aggregatedUnusedAssetsSize.py +1 -1
- metadata/generated/schema/dataInsight/type/aggregatedUsedVsUnusedAssetsCount.py +1 -1
- metadata/generated/schema/dataInsight/type/aggregatedUsedVsUnusedAssetsSize.py +1 -1
- metadata/generated/schema/dataInsight/type/dailyActiveUsers.py +1 -1
- metadata/generated/schema/dataInsight/type/mostActiveUsers.py +1 -1
- metadata/generated/schema/dataInsight/type/mostViewedEntities.py +1 -1
- metadata/generated/schema/dataInsight/type/pageViewsByEntities.py +1 -1
- metadata/generated/schema/dataInsight/type/unusedAssets.py +1 -1
- metadata/generated/schema/email/__init__.py +1 -1
- metadata/generated/schema/email/emailRequest.py +1 -1
- metadata/generated/schema/email/emailTemplate.py +1 -1
- metadata/generated/schema/email/emailTemplatePlaceholder.py +1 -1
- metadata/generated/schema/email/smtpSettings.py +1 -1
- metadata/generated/schema/email/templateValidationReponse.py +1 -1
- metadata/generated/schema/entity/__init__.py +1 -1
- metadata/generated/schema/entity/applications/__init__.py +1 -1
- metadata/generated/schema/entity/applications/app.py +1 -1
- metadata/generated/schema/entity/applications/appRunRecord.py +1 -1
- metadata/generated/schema/entity/applications/configuration/__init__.py +1 -1
- metadata/generated/schema/entity/applications/configuration/applicationConfig.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/__init__.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/__init__.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/addDescriptionAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/addDomainAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/addOwnerAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/addTagsAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/addTierAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/lineagePropagationAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/mlTaggingAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/removeDescriptionAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/removeDomainAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/removeOwnerAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/removeTagsAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automator/removeTierAction.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/automatorAppConfig.py +1 -1
- metadata/generated/schema/entity/applications/configuration/external/metaPilotAppConfig.py +1 -1
- metadata/generated/schema/entity/applications/configuration/internal/__init__.py +1 -1
- metadata/generated/schema/entity/applications/configuration/internal/dataInsightsAppConfig.py +1 -1
- metadata/generated/schema/entity/applications/configuration/internal/dataInsightsReportAppConfig.py +1 -1
- metadata/generated/schema/entity/applications/configuration/internal/searchIndexingAppConfig.py +1 -1
- metadata/generated/schema/entity/applications/configuration/private/external/__init__.py +1 -1
- metadata/generated/schema/entity/applications/configuration/private/external/metaPilotAppPrivateConfig.py +1 -1
- metadata/generated/schema/entity/applications/createAppRequest.py +1 -1
- metadata/generated/schema/entity/applications/jobStatus.py +1 -1
- metadata/generated/schema/entity/applications/liveExecutionContext.py +1 -1
- metadata/generated/schema/entity/applications/marketplace/__init__.py +1 -1
- metadata/generated/schema/entity/applications/marketplace/appMarketPlaceDefinition.py +1 -1
- metadata/generated/schema/entity/applications/marketplace/createAppMarketPlaceDefinitionReq.py +1 -1
- metadata/generated/schema/entity/applications/scheduledExecutionContext.py +1 -1
- metadata/generated/schema/entity/automations/__init__.py +1 -1
- metadata/generated/schema/entity/automations/testServiceConnection.py +1 -1
- metadata/generated/schema/entity/automations/workflow.py +1 -1
- metadata/generated/schema/entity/bot.py +1 -1
- metadata/generated/schema/entity/classification/__init__.py +1 -1
- metadata/generated/schema/entity/classification/classification.py +1 -1
- metadata/generated/schema/entity/classification/tag.py +1 -1
- metadata/generated/schema/entity/data/__init__.py +1 -1
- metadata/generated/schema/entity/data/apiCollection.py +1 -1
- metadata/generated/schema/entity/data/apiEndpoint.py +1 -1
- metadata/generated/schema/entity/data/chart.py +1 -1
- metadata/generated/schema/entity/data/container.py +1 -1
- metadata/generated/schema/entity/data/dashboard.py +1 -1
- metadata/generated/schema/entity/data/dashboardDataModel.py +1 -1
- metadata/generated/schema/entity/data/database.py +1 -1
- metadata/generated/schema/entity/data/databaseSchema.py +1 -1
- metadata/generated/schema/entity/data/glossary.py +1 -1
- metadata/generated/schema/entity/data/glossaryTerm.py +1 -1
- metadata/generated/schema/entity/data/metrics.py +1 -1
- metadata/generated/schema/entity/data/mlmodel.py +1 -1
- metadata/generated/schema/entity/data/pipeline.py +1 -1
- metadata/generated/schema/entity/data/query.py +1 -1
- metadata/generated/schema/entity/data/report.py +1 -1
- metadata/generated/schema/entity/data/searchIndex.py +1 -1
- metadata/generated/schema/entity/data/storedProcedure.py +1 -1
- metadata/generated/schema/entity/data/table.py +2 -1
- metadata/generated/schema/entity/data/topic.py +1 -1
- metadata/generated/schema/entity/docStore/__init__.py +1 -1
- metadata/generated/schema/entity/docStore/document.py +1 -1
- metadata/generated/schema/entity/domains/__init__.py +1 -1
- metadata/generated/schema/entity/domains/dataProduct.py +8 -1
- metadata/generated/schema/entity/domains/domain.py +1 -1
- metadata/generated/schema/entity/events/__init__.py +1 -1
- metadata/generated/schema/entity/events/webhook.py +1 -1
- metadata/generated/schema/entity/feed/__init__.py +1 -1
- metadata/generated/schema/entity/feed/assets.py +1 -1
- metadata/generated/schema/entity/feed/customProperty.py +1 -1
- metadata/generated/schema/entity/feed/description.py +1 -1
- metadata/generated/schema/entity/feed/domain.py +1 -1
- metadata/generated/schema/entity/feed/entityInfo.py +1 -1
- metadata/generated/schema/entity/feed/owner.py +1 -1
- metadata/generated/schema/entity/feed/suggestion.py +1 -1
- metadata/generated/schema/entity/feed/tag.py +1 -1
- metadata/generated/schema/entity/feed/testCaseResult.py +1 -1
- metadata/generated/schema/entity/feed/thread.py +1 -1
- metadata/generated/schema/entity/policies/__init__.py +1 -1
- metadata/generated/schema/entity/policies/accessControl/__init__.py +1 -1
- metadata/generated/schema/entity/policies/accessControl/resourceDescriptor.py +1 -1
- metadata/generated/schema/entity/policies/accessControl/resourcePermission.py +1 -1
- metadata/generated/schema/entity/policies/accessControl/rule.py +1 -1
- metadata/generated/schema/entity/policies/filters.py +1 -1
- metadata/generated/schema/entity/policies/policy.py +1 -1
- metadata/generated/schema/entity/services/__init__.py +1 -1
- metadata/generated/schema/entity/services/apiService.py +1 -1
- metadata/generated/schema/entity/services/connections/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/apiService/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/apiService/restConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/common/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/common/sslCertPaths.py +1 -1
- metadata/generated/schema/entity/services/connections/common/sslCertValues.py +1 -1
- metadata/generated/schema/entity/services/connections/common/sslConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/connectionBasicType.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/customDashboardConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/domoDashboardConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/lightdashConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/lookerConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/metabaseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/modeConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/mstrConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/powerBIConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/powerbi/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/powerbi/azureConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/powerbi/bucketDetails.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/powerbi/gcsConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/powerbi/s3Config.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/qlikCloudConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/qlikSenseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/quickSightConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/redashConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/supersetConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/dashboard/tableauConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/athenaConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/azureSQLConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/bigQueryConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/bigTableConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/clickhouseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/common/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/common/azureConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/common/basicAuth.py +1 -1
- metadata/generated/schema/entity/services/connections/database/common/iamAuthConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/common/jwtAuth.py +1 -1
- metadata/generated/schema/entity/services/connections/database/couchbaseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/customDatabaseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/databricksConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalake/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalake/azureConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalake/gcsConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalake/s3Config.py +1 -1
- metadata/generated/schema/entity/services/connections/database/datalakeConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/db2Connection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/deltaLakeConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/deltalake/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/deltalake/metastoreConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/deltalake/storageConfig.py +1 -1
- metadata/generated/schema/entity/services/connections/database/domoDatabaseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/dorisConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/druidConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/dynamoDBConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/glueConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/greenplumConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/hiveConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/iceberg/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/iceberg/dynamoDbCatalogConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/iceberg/glueCatalogConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/iceberg/hiveCatalogConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/iceberg/icebergCatalog.py +1 -1
- metadata/generated/schema/entity/services/connections/database/iceberg/icebergFileSystem.py +1 -1
- metadata/generated/schema/entity/services/connections/database/iceberg/restCatalogConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/icebergConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/impalaConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/mariaDBConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/mongoDBConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/mssqlConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/mysqlConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/oracleConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/pinotDBConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/postgresConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/prestoConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/redshiftConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/salesforceConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/sapErpConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/sapHana/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/database/sapHana/sapHanaHDBConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/sapHana/sapHanaSQLConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/sapHanaConnection.py +4 -1
- metadata/generated/schema/entity/services/connections/database/sasConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/singleStoreConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/snowflakeConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/sqliteConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/synapseConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/teradataConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/trinoConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/unityCatalogConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/database/verticaConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/customMessagingConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/kafkaConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/kinesisConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/pulsarConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/redpandaConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/messaging/saslMechanismType.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/alationConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/alationSinkConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/amundsenConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/atlasConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/metadataESConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/metadata/openMetadataConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/customMlModelConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/mlflowConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/sageMakerConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/mlmodel/sklearnConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/airbyteConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/airflowConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/backendConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/customPipelineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/dagsterConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/databricksPipelineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/dbtCloudConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/domoPipelineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/fivetranConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/flinkConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/gluePipelineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/kafkaConnectConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/nifiConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/openLineageConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/sparkConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/pipeline/splineConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/search/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/search/customSearchConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/search/elasticSearch/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/search/elasticSearch/apiAuth.py +1 -1
- metadata/generated/schema/entity/services/connections/search/elasticSearch/basicAuth.py +1 -1
- metadata/generated/schema/entity/services/connections/search/elasticSearchConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/search/openSearchConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/serviceConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/__init__.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/adlsConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/customStorageConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/gcsConnection.py +1 -1
- metadata/generated/schema/entity/services/connections/storage/s3Connection.py +1 -1
- metadata/generated/schema/entity/services/connections/testConnectionDefinition.py +1 -1
- metadata/generated/schema/entity/services/connections/testConnectionResult.py +1 -1
- metadata/generated/schema/entity/services/dashboardService.py +1 -1
- metadata/generated/schema/entity/services/databaseService.py +1 -1
- metadata/generated/schema/entity/services/ingestionPipelines/__init__.py +1 -1
- metadata/generated/schema/entity/services/ingestionPipelines/ingestionPipeline.py +1 -1
- metadata/generated/schema/entity/services/ingestionPipelines/pipelineServiceClientResponse.py +1 -1
- metadata/generated/schema/entity/services/ingestionPipelines/status.py +1 -1
- metadata/generated/schema/entity/services/messagingService.py +1 -1
- metadata/generated/schema/entity/services/metadataService.py +1 -1
- metadata/generated/schema/entity/services/mlmodelService.py +1 -1
- metadata/generated/schema/entity/services/pipelineService.py +1 -1
- metadata/generated/schema/entity/services/searchService.py +1 -1
- metadata/generated/schema/entity/services/serviceType.py +1 -1
- metadata/generated/schema/entity/services/storageService.py +1 -1
- metadata/generated/schema/entity/teams/__init__.py +1 -1
- metadata/generated/schema/entity/teams/persona.py +1 -1
- metadata/generated/schema/entity/teams/role.py +1 -1
- metadata/generated/schema/entity/teams/team.py +1 -1
- metadata/generated/schema/entity/teams/teamHierarchy.py +1 -1
- metadata/generated/schema/entity/teams/user.py +1 -1
- metadata/generated/schema/entity/type.py +1 -1
- metadata/generated/schema/entity/utils/__init__.py +1 -1
- metadata/generated/schema/entity/utils/entitiesCount.py +1 -1
- metadata/generated/schema/entity/utils/servicesCount.py +1 -1
- metadata/generated/schema/entity/utils/supersetApiConnection.py +1 -1
- metadata/generated/schema/events/__init__.py +1 -1
- metadata/generated/schema/events/alertMetrics.py +1 -1
- metadata/generated/schema/events/api/__init__.py +1 -1
- metadata/generated/schema/events/api/createEventSubscription.py +1 -1
- metadata/generated/schema/events/api/testEventSubscriptionDestination.py +1 -1
- metadata/generated/schema/events/emailAlertConfig.py +1 -1
- metadata/generated/schema/events/eventFilterRule.py +1 -1
- metadata/generated/schema/events/eventSubscription.py +1 -1
- metadata/generated/schema/events/eventSubscriptionOffset.py +1 -1
- metadata/generated/schema/events/failedEvent.py +1 -1
- metadata/generated/schema/events/filterResourceDescriptor.py +1 -1
- metadata/generated/schema/events/subscriptionResourceDescriptor.py +1 -1
- metadata/generated/schema/metadataIngestion/__init__.py +1 -1
- metadata/generated/schema/metadataIngestion/application.py +1 -1
- metadata/generated/schema/metadataIngestion/applicationPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/dashboardServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/dataInsightPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/databaseServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/databaseServiceProfilerPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/databaseServiceQueryLineagePipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/databaseServiceQueryUsagePipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/__init__.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtAzureConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtBucketDetails.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtCloudConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtGCSConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtHttpConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtLocalConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/dbtconfig/dbtS3Config.py +1 -1
- metadata/generated/schema/metadataIngestion/messagingServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/metadataToElasticSearchPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/mlmodelServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/pipelineServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/searchServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/__init__.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/containerMetadataConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/manifestMetadataConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageBucketDetails.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageMetadataADLSConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageMetadataGCSConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageMetadataHttpConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageMetadataLocalConfig.py +1 -1
- metadata/generated/schema/metadataIngestion/storage/storageMetadataS3Config.py +1 -1
- metadata/generated/schema/metadataIngestion/storageServiceMetadataPipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/testSuitePipeline.py +1 -1
- metadata/generated/schema/metadataIngestion/workflow.py +1 -1
- metadata/generated/schema/monitoring/__init__.py +1 -1
- metadata/generated/schema/monitoring/eventMonitorProvider.py +1 -1
- metadata/generated/schema/security/__init__.py +1 -1
- metadata/generated/schema/security/client/__init__.py +1 -1
- metadata/generated/schema/security/client/auth0SSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/azureSSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/customOidcSSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/googleSSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/oidcClientConfig.py +1 -1
- metadata/generated/schema/security/client/oktaSSOClientConfig.py +1 -1
- metadata/generated/schema/security/client/openMetadataJWTClientConfig.py +1 -1
- metadata/generated/schema/security/client/samlSSOClientConfig.py +1 -1
- metadata/generated/schema/security/credentials/__init__.py +1 -1
- metadata/generated/schema/security/credentials/accessTokenAuth.py +1 -1
- metadata/generated/schema/security/credentials/apiAccessTokenAuth.py +1 -1
- metadata/generated/schema/security/credentials/awsCredentials.py +1 -1
- metadata/generated/schema/security/credentials/azureCredentials.py +1 -1
- metadata/generated/schema/security/credentials/basicAuth.py +1 -1
- metadata/generated/schema/security/credentials/bitbucketCredentials.py +1 -1
- metadata/generated/schema/security/credentials/gcpCredentials.py +1 -1
- metadata/generated/schema/security/credentials/gcpExternalAccount.py +1 -1
- metadata/generated/schema/security/credentials/gcpValues.py +1 -1
- metadata/generated/schema/security/credentials/gitCredentials.py +1 -1
- metadata/generated/schema/security/credentials/githubCredentials.py +1 -1
- metadata/generated/schema/security/credentials/gitlabCredentials.py +1 -1
- metadata/generated/schema/security/sasl/__init__.py +1 -1
- metadata/generated/schema/security/sasl/saslClientConfig.py +1 -1
- metadata/generated/schema/security/secrets/__init__.py +1 -1
- metadata/generated/schema/security/secrets/secretsManagerClientLoader.py +1 -1
- metadata/generated/schema/security/secrets/secretsManagerConfiguration.py +1 -1
- metadata/generated/schema/security/secrets/secretsManagerProvider.py +1 -1
- metadata/generated/schema/security/securityConfiguration.py +1 -1
- metadata/generated/schema/security/ssl/__init__.py +1 -1
- metadata/generated/schema/security/ssl/validateSSLClientConfig.py +1 -1
- metadata/generated/schema/security/ssl/verifySSLConfig.py +1 -1
- metadata/generated/schema/settings/__init__.py +1 -1
- metadata/generated/schema/settings/settings.py +1 -1
- metadata/generated/schema/system/__init__.py +1 -1
- metadata/generated/schema/system/entityError.py +1 -1
- metadata/generated/schema/system/eventPublisherJob.py +1 -1
- metadata/generated/schema/system/indexingError.py +1 -1
- metadata/generated/schema/system/limitsResponse.py +1 -1
- metadata/generated/schema/system/ui/__init__.py +1 -1
- metadata/generated/schema/system/ui/knowledgePanel.py +1 -1
- metadata/generated/schema/system/ui/page.py +1 -1
- metadata/generated/schema/system/validationResponse.py +1 -1
- metadata/generated/schema/tests/__init__.py +1 -1
- metadata/generated/schema/tests/assigned.py +1 -1
- metadata/generated/schema/tests/basic.py +1 -1
- metadata/generated/schema/tests/customMetric.py +1 -1
- metadata/generated/schema/tests/dataQualityReport.py +1 -1
- metadata/generated/schema/tests/resolved.py +1 -1
- metadata/generated/schema/tests/testCase.py +1 -1
- metadata/generated/schema/tests/testCaseResolutionStatus.py +1 -1
- metadata/generated/schema/tests/testDefinition.py +1 -1
- metadata/generated/schema/tests/testSuite.py +1 -1
- metadata/generated/schema/type/__init__.py +1 -1
- metadata/generated/schema/type/apiSchema.py +1 -1
- metadata/generated/schema/type/auditLog.py +1 -1
- metadata/generated/schema/type/basic.py +1 -1
- metadata/generated/schema/type/bulkOperationResult.py +1 -1
- metadata/generated/schema/type/changeEvent.py +1 -1
- metadata/generated/schema/type/changeEventType.py +1 -1
- metadata/generated/schema/type/collectionDescriptor.py +1 -1
- metadata/generated/schema/type/csvDocumentation.py +1 -1
- metadata/generated/schema/type/csvErrorType.py +1 -1
- metadata/generated/schema/type/csvFile.py +1 -1
- metadata/generated/schema/type/csvImportResult.py +1 -1
- metadata/generated/schema/type/customProperties/__init__.py +1 -1
- metadata/generated/schema/type/customProperties/complexTypes.py +1 -1
- metadata/generated/schema/type/customProperties/enumConfig.py +1 -1
- metadata/generated/schema/type/customProperty.py +1 -1
- metadata/generated/schema/type/dailyCount.py +1 -1
- metadata/generated/schema/type/databaseConnectionConfig.py +1 -1
- metadata/generated/schema/type/entityHierarchy.py +1 -1
- metadata/generated/schema/type/entityHistory.py +1 -1
- metadata/generated/schema/type/entityLineage.py +1 -1
- metadata/generated/schema/type/entityReference.py +1 -1
- metadata/generated/schema/type/entityReferenceList.py +1 -1
- metadata/generated/schema/type/entityRelationship.py +1 -1
- metadata/generated/schema/type/entityUsage.py +1 -1
- metadata/generated/schema/type/filterPattern.py +1 -1
- metadata/generated/schema/type/function.py +1 -1
- metadata/generated/schema/type/include.py +1 -1
- metadata/generated/schema/type/jdbcConnection.py +1 -1
- metadata/generated/schema/type/lifeCycle.py +1 -1
- metadata/generated/schema/type/paging.py +1 -1
- metadata/generated/schema/type/profile.py +1 -1
- metadata/generated/schema/type/queryParserData.py +1 -1
- metadata/generated/schema/type/reaction.py +1 -1
- metadata/generated/schema/type/schedule.py +1 -1
- metadata/generated/schema/type/schema.py +1 -1
- metadata/generated/schema/type/tableQuery.py +1 -1
- metadata/generated/schema/type/tableUsageCount.py +1 -1
- metadata/generated/schema/type/tagLabel.py +1 -1
- metadata/generated/schema/type/usageDetails.py +1 -1
- metadata/generated/schema/type/usageRequest.py +1 -1
- metadata/generated/schema/type/votes.py +1 -1
- metadata/ingestion/connections/builders.py +6 -0
- metadata/ingestion/source/dashboard/tableau/metadata.py +10 -7
- metadata/ingestion/source/database/athena/models.py +4 -4
- metadata/ingestion/source/database/column_type_parser.py +1 -1
- metadata/ingestion/source/database/dbt/metadata.py +1 -1
- metadata/ingestion/source/database/postgres/converter_orm.py +52 -0
- metadata/ingestion/source/database/postgres/metadata.py +6 -0
- metadata/ingestion/source/database/postgres/metrics.py +42 -0
- metadata/ingestion/source/database/postgres/types/money.py +37 -0
- metadata/ingestion/source/database/redshift/connection.py +37 -9
- metadata/ingestion/source/database/redshift/queries.py +4 -5
- metadata/ingestion/source/database/saphana/cdata_parser.py +772 -0
- metadata/ingestion/source/database/saphana/lineage.py +159 -0
- metadata/ingestion/source/database/saphana/models.py +66 -0
- metadata/ingestion/source/database/saphana/queries.py +23 -0
- metadata/profiler/interface/sqlalchemy/profiler_interface.py +22 -9
- metadata/profiler/metrics/static/mean.py +8 -9
- metadata/profiler/orm/functions/median.py +11 -4
- metadata/profiler/orm/registry.py +3 -1
- metadata/utils/importer.py +26 -0
- {openmetadata_ingestion-1.5.0.0rc2.dist-info → openmetadata_ingestion-1.5.2.0.dist-info}/METADATA +339 -339
- {openmetadata_ingestion-1.5.0.0rc2.dist-info → openmetadata_ingestion-1.5.2.0.dist-info}/RECORD +605 -604
- metadata/generated/schema/dataInsight/type/percentageOfEntitiesWithDescriptionByType.py +0 -48
- metadata/generated/schema/dataInsight/type/percentageOfEntitiesWithOwnerByType.py +0 -44
- metadata/generated/schema/dataInsight/type/percentageOfServicesWithDescription.py +0 -46
- metadata/generated/schema/dataInsight/type/percentageOfServicesWithOwner.py +0 -44
- metadata/generated/schema/dataInsight/type/totalEntitiesByTier.py +0 -39
- metadata/generated/schema/dataInsight/type/totalEntitiesByType.py +0 -40
- {openmetadata_ingestion-1.5.0.0rc2.dist-info → openmetadata_ingestion-1.5.2.0.dist-info}/LICENSE +0 -0
- {openmetadata_ingestion-1.5.0.0rc2.dist-info → openmetadata_ingestion-1.5.2.0.dist-info}/WHEEL +0 -0
- {openmetadata_ingestion-1.5.0.0rc2.dist-info → openmetadata_ingestion-1.5.2.0.dist-info}/entry_points.txt +0 -0
- {openmetadata_ingestion-1.5.0.0rc2.dist-info → openmetadata_ingestion-1.5.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,772 @@
|
|
|
1
|
+
# Copyright 2021 Collate
|
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
# you may not use this file except in compliance with the License.
|
|
4
|
+
# You may obtain a copy of the License at
|
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
7
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
8
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
9
|
+
# See the License for the specific language governing permissions and
|
|
10
|
+
# limitations under the License.
|
|
11
|
+
"""
|
|
12
|
+
Parse CDATA XMLs from SAP Hana
|
|
13
|
+
"""
|
|
14
|
+
import itertools
|
|
15
|
+
import re
|
|
16
|
+
import traceback
|
|
17
|
+
import xml.etree.ElementTree as ET
|
|
18
|
+
from collections import defaultdict
|
|
19
|
+
from enum import Enum
|
|
20
|
+
from functools import lru_cache
|
|
21
|
+
from typing import Dict, Iterable, List, NewType, Optional, Set
|
|
22
|
+
|
|
23
|
+
from pydantic import Field, computed_field
|
|
24
|
+
from typing_extensions import Annotated
|
|
25
|
+
|
|
26
|
+
from metadata.generated.schema.api.lineage.addLineage import AddLineageRequest
|
|
27
|
+
from metadata.generated.schema.entity.data.table import Table
|
|
28
|
+
from metadata.generated.schema.entity.services.ingestionPipelines.status import (
|
|
29
|
+
StackTraceError,
|
|
30
|
+
)
|
|
31
|
+
from metadata.generated.schema.type.basic import FullyQualifiedEntityName
|
|
32
|
+
from metadata.generated.schema.type.entityLineage import (
|
|
33
|
+
ColumnLineage,
|
|
34
|
+
EntitiesEdge,
|
|
35
|
+
LineageDetails,
|
|
36
|
+
Source,
|
|
37
|
+
)
|
|
38
|
+
from metadata.generated.schema.type.entityReference import EntityReference
|
|
39
|
+
from metadata.ingestion.api.models import Either
|
|
40
|
+
from metadata.ingestion.lineage.sql_lineage import get_column_fqn
|
|
41
|
+
from metadata.ingestion.models.custom_pydantic import BaseModel
|
|
42
|
+
from metadata.ingestion.ometa.ometa_api import OpenMetadata
|
|
43
|
+
from metadata.ingestion.source.database.saphana.models import (
|
|
44
|
+
SYS_BIC_SCHEMA_NAME,
|
|
45
|
+
ViewType,
|
|
46
|
+
)
|
|
47
|
+
from metadata.utils import fqn
|
|
48
|
+
from metadata.utils.constants import ENTITY_REFERENCE_TYPE_MAP
|
|
49
|
+
from metadata.utils.dispatch import enum_register
|
|
50
|
+
from metadata.utils.logger import ingestion_logger
|
|
51
|
+
|
|
52
|
+
logger = ingestion_logger()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class CDATAParsingError(Exception):
|
|
56
|
+
"""Error parsing CDATA XML"""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
XSI_NS = {"xsi": "http://www.w3.org/2001/XMLSchema-instance"}
|
|
60
|
+
|
|
61
|
+
NAMESPACE_DICT = {
|
|
62
|
+
ViewType.ANALYTIC_VIEW.value: {
|
|
63
|
+
"Cube": "http://www.sap.com/ndb/BiModelCube.ecore",
|
|
64
|
+
**XSI_NS,
|
|
65
|
+
},
|
|
66
|
+
ViewType.CALCULATION_VIEW.value: {
|
|
67
|
+
"Calculation": "http://www.sap.com/ndb/BiModelCalculation.ecore",
|
|
68
|
+
**XSI_NS,
|
|
69
|
+
},
|
|
70
|
+
ViewType.ATTRIBUTE_VIEW.value: {
|
|
71
|
+
"Dimension": "http://www.sap.com/ndb/BiModelDimension.ecore",
|
|
72
|
+
**XSI_NS,
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
FORMULA_PATTERN = re.compile(r"\"(.*?)\"")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class CDATAKeys(Enum):
|
|
80
|
+
"""Keys to access data in CDATA XML files"""
|
|
81
|
+
|
|
82
|
+
COLUMN_OBJECT_NAME = "columnObjectName"
|
|
83
|
+
COLUMN_OBJECT = "columnObject"
|
|
84
|
+
COLUMN_NAME = "columnName"
|
|
85
|
+
SCHEMA_NAME = "schemaName"
|
|
86
|
+
ATTRIBUTES = "attributes"
|
|
87
|
+
ATTRIBUTE = "attribute"
|
|
88
|
+
KEY_MAPPING = "keyMapping"
|
|
89
|
+
MAPPING = "mapping"
|
|
90
|
+
SOURCE = "source"
|
|
91
|
+
TARGET = "target"
|
|
92
|
+
NODE = "node"
|
|
93
|
+
TYPE = "type"
|
|
94
|
+
INPUT = "input"
|
|
95
|
+
CALCULATION_VIEWS = "calculationViews"
|
|
96
|
+
CALCULATION_VIEW = "calculationView"
|
|
97
|
+
CALCULATION_VIEW_ATTRIBUTES = "calculatedViewAttributes"
|
|
98
|
+
CALCULATION_VIEW_ATTRIBUTE = "calculatedViewAttribute"
|
|
99
|
+
RESOURCE_URI = "resourceUri"
|
|
100
|
+
CALCULATED_ATTRS = "calculatedAttributes"
|
|
101
|
+
KEY_CALCULATION = "keyCalculation"
|
|
102
|
+
FORMULA = "formula"
|
|
103
|
+
BASE_MEASURES = "baseMeasures"
|
|
104
|
+
MEASURE = "measure"
|
|
105
|
+
MEASURE_MAPPING = "measureMapping"
|
|
106
|
+
PRIVATE_MEASURE_GROUP = "privateMeasureGroup"
|
|
107
|
+
LOGICAL_MODEL = "logicalModel"
|
|
108
|
+
DATA_SOURCES = "dataSources"
|
|
109
|
+
DATA_SOURCE = "DataSource" # yes, with capital D
|
|
110
|
+
ID = "id"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class CalculatedAttrKey(Enum):
|
|
114
|
+
CALCULATED_ATTRIBUTE = "calculatedAttribute"
|
|
115
|
+
CALCULATED_VIEW_ATTRIBUTE = "calculatedViewAttribute"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class ParentSource(BaseModel):
|
|
119
|
+
"""Parent Source of a given column"""
|
|
120
|
+
|
|
121
|
+
# TODO: Multiple sources from the same parent should be possible
|
|
122
|
+
source: Annotated[
|
|
123
|
+
str, Field(..., description="Column name in the parent Data Source")
|
|
124
|
+
]
|
|
125
|
+
parent: Annotated[str, Field(..., description="Parent ID")]
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class DataSourceMapping(BaseModel):
|
|
129
|
+
"""Column Mapping of DataSources and Logical Calculated Views"""
|
|
130
|
+
|
|
131
|
+
target: Annotated[
|
|
132
|
+
str, Field(..., description="Column name in the provided Data Source")
|
|
133
|
+
]
|
|
134
|
+
parents: Annotated[
|
|
135
|
+
List[ParentSource], Field(..., description="Parent Sources for a target col")
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class DataSource(BaseModel):
|
|
140
|
+
"""Data source from CDATA XML"""
|
|
141
|
+
|
|
142
|
+
name: Annotated[str, Field(..., description="Data Source name")]
|
|
143
|
+
location: Annotated[
|
|
144
|
+
Optional[str], Field(None, description="Schema or project for the Data Source")
|
|
145
|
+
]
|
|
146
|
+
source_type: Annotated[
|
|
147
|
+
Optional[ViewType],
|
|
148
|
+
Field(..., description="Data Source type"),
|
|
149
|
+
]
|
|
150
|
+
mapping: Annotated[
|
|
151
|
+
Optional[Dict[str, DataSourceMapping]],
|
|
152
|
+
Field(
|
|
153
|
+
None,
|
|
154
|
+
description="Logical source column mapping. Key: source column; value: mapping",
|
|
155
|
+
),
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
def get_entity(
|
|
159
|
+
self,
|
|
160
|
+
metadata: OpenMetadata,
|
|
161
|
+
service_name: str,
|
|
162
|
+
) -> Table:
|
|
163
|
+
"""Build the Entity Reference for this DataSource"""
|
|
164
|
+
|
|
165
|
+
if self.source_type == ViewType.LOGICAL:
|
|
166
|
+
raise CDATAParsingError(
|
|
167
|
+
f"We could not find the logical DataSource origin for {self.name}"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
if self.source_type == ViewType.DATA_BASE_TABLE:
|
|
171
|
+
# The source is a table, so the location is the schema
|
|
172
|
+
fqn_ = fqn.build(
|
|
173
|
+
metadata=metadata,
|
|
174
|
+
entity_type=Table,
|
|
175
|
+
service_name=service_name,
|
|
176
|
+
database_name=None, # TODO: Can we assume HXE?
|
|
177
|
+
schema_name=self.location,
|
|
178
|
+
table_name=self.name,
|
|
179
|
+
)
|
|
180
|
+
else:
|
|
181
|
+
# The source is a CalculationView, AttributeView or AnalyticView
|
|
182
|
+
# package from <resourceUri>/SFLIGHT.MODELING/calculationviews/CV_SFLIGHT_SBOOK</resourceUri>
|
|
183
|
+
package = self.location.split("/")[1]
|
|
184
|
+
fqn_ = fqn.build(
|
|
185
|
+
metadata=metadata,
|
|
186
|
+
entity_type=Table,
|
|
187
|
+
service_name=service_name,
|
|
188
|
+
database_name=None,
|
|
189
|
+
schema_name=SYS_BIC_SCHEMA_NAME,
|
|
190
|
+
table_name=f"{package}/{self.name}",
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
return metadata.get_by_name(entity=Table, fqn=fqn_)
|
|
194
|
+
|
|
195
|
+
def __hash__(self):
|
|
196
|
+
return hash(self.location) + hash(self.name) + hash(self.source_type)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
# Given the DataSource ID, get the DataSource from the CDATA XML
|
|
200
|
+
DataSourceMap = NewType("DataSourceMap", Dict[str, DataSource])
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class ColumnMapping(BaseModel):
|
|
204
|
+
"""Column Mapping from CDATA XML"""
|
|
205
|
+
|
|
206
|
+
data_source: Annotated[DataSource, Field(..., description="Source table name")]
|
|
207
|
+
sources: Annotated[List[str], Field(..., description="Source column names")]
|
|
208
|
+
target: Annotated[str, Field(..., description="Destination column name")]
|
|
209
|
+
formula: Annotated[
|
|
210
|
+
Optional[str], Field(None, description="Formula used to derive the column")
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class ParsedLineage(BaseModel):
|
|
215
|
+
"""Parsed Lineage from CDATA XML. For each view, we'll parse the sources"""
|
|
216
|
+
|
|
217
|
+
mappings: Annotated[
|
|
218
|
+
Optional[List[ColumnMapping]], Field([], description="Column mappings")
|
|
219
|
+
]
|
|
220
|
+
|
|
221
|
+
@computed_field
|
|
222
|
+
@property
|
|
223
|
+
def sources(self) -> Set[DataSource]:
|
|
224
|
+
"""Get all the different source tables we'll need to iterate over"""
|
|
225
|
+
return {mapping.data_source for mapping in self.mappings}
|
|
226
|
+
|
|
227
|
+
@lru_cache(maxsize=256)
|
|
228
|
+
def find_target(self, column: str) -> Optional[ColumnMapping]:
|
|
229
|
+
"""Find the column mapping based on the target column"""
|
|
230
|
+
return next(
|
|
231
|
+
(mapping for mapping in self.mappings if mapping.target == column), None
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
def __add__(self, other: "ParsedLineage") -> "ParsedLineage":
|
|
235
|
+
"""Merge two parsed lineages"""
|
|
236
|
+
return ParsedLineage(mappings=self.mappings + other.mappings)
|
|
237
|
+
|
|
238
|
+
def __hash__(self):
|
|
239
|
+
"""
|
|
240
|
+
Note that the LRU Cache require us to implement the __hash__ method, otherwise
|
|
241
|
+
the BaseModel is not hashable. Since we just want a per-instance cache, we'll use the id
|
|
242
|
+
"""
|
|
243
|
+
return id(self)
|
|
244
|
+
|
|
245
|
+
def to_request(
|
|
246
|
+
self, metadata: OpenMetadata, service_name: str, to_entity: Table
|
|
247
|
+
) -> Iterable[Either[AddLineageRequest]]:
|
|
248
|
+
"""Given the target entity, build the AddLineageRequest based on the sources in `self`"""
|
|
249
|
+
for source in self.sources:
|
|
250
|
+
try:
|
|
251
|
+
source_table = source.get_entity(
|
|
252
|
+
metadata=metadata, service_name=service_name
|
|
253
|
+
)
|
|
254
|
+
if not source_table:
|
|
255
|
+
logger.warning(f"Can't find table for source [{source}]")
|
|
256
|
+
continue
|
|
257
|
+
yield Either(
|
|
258
|
+
right=AddLineageRequest(
|
|
259
|
+
edge=EntitiesEdge(
|
|
260
|
+
fromEntity=EntityReference(
|
|
261
|
+
id=source_table.id,
|
|
262
|
+
type=ENTITY_REFERENCE_TYPE_MAP[Table.__name__],
|
|
263
|
+
),
|
|
264
|
+
toEntity=EntityReference(
|
|
265
|
+
id=to_entity.id,
|
|
266
|
+
type=ENTITY_REFERENCE_TYPE_MAP[Table.__name__],
|
|
267
|
+
),
|
|
268
|
+
lineageDetails=LineageDetails(
|
|
269
|
+
source=Source.ViewLineage,
|
|
270
|
+
columnsLineage=[
|
|
271
|
+
ColumnLineage(
|
|
272
|
+
fromColumns=[
|
|
273
|
+
FullyQualifiedEntityName(
|
|
274
|
+
get_column_fqn(
|
|
275
|
+
table_entity=source_table,
|
|
276
|
+
column=source_col,
|
|
277
|
+
)
|
|
278
|
+
)
|
|
279
|
+
for source_col in mapping.sources
|
|
280
|
+
],
|
|
281
|
+
toColumn=FullyQualifiedEntityName(
|
|
282
|
+
get_column_fqn(
|
|
283
|
+
table_entity=to_entity,
|
|
284
|
+
column=mapping.target,
|
|
285
|
+
)
|
|
286
|
+
),
|
|
287
|
+
function=mapping.formula
|
|
288
|
+
if mapping.formula
|
|
289
|
+
else None,
|
|
290
|
+
)
|
|
291
|
+
for mapping in self.mappings
|
|
292
|
+
if mapping.data_source == source
|
|
293
|
+
],
|
|
294
|
+
),
|
|
295
|
+
)
|
|
296
|
+
)
|
|
297
|
+
)
|
|
298
|
+
except Exception as exc:
|
|
299
|
+
yield Either(
|
|
300
|
+
left=StackTraceError(
|
|
301
|
+
name=to_entity.fullyQualifiedName.root,
|
|
302
|
+
error=f"Error trying to get lineage for [{source}] due to [{exc}]",
|
|
303
|
+
stackTrace=traceback.format_exc(),
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def _get_column_datasources(
|
|
309
|
+
entry: ET.Element, datasource_map: Optional[DataSourceMap] = None
|
|
310
|
+
) -> Set[DataSource]:
|
|
311
|
+
"""Read a DataSource from the CDATA XML"""
|
|
312
|
+
if (
|
|
313
|
+
datasource_map
|
|
314
|
+
and entry.get(CDATAKeys.COLUMN_OBJECT_NAME.value) in datasource_map
|
|
315
|
+
):
|
|
316
|
+
# If the datasource is in the map, we'll traverse all intermediate logical
|
|
317
|
+
# datasources until we arrive to a table or view.
|
|
318
|
+
# Note that we can have multiple sources for a single column, e.g., columns
|
|
319
|
+
# coming from a JOIN
|
|
320
|
+
return set(
|
|
321
|
+
_traverse_ds(
|
|
322
|
+
current_column=entry.get(CDATAKeys.COLUMN_NAME.value),
|
|
323
|
+
ds_origin_list=[],
|
|
324
|
+
current_ds=datasource_map[
|
|
325
|
+
entry.get(CDATAKeys.COLUMN_OBJECT_NAME.value)
|
|
326
|
+
],
|
|
327
|
+
datasource_map=datasource_map,
|
|
328
|
+
)
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
# If we don't have any logical sources (projections, aggregations, etc.) We'll stick to
|
|
332
|
+
# a single table origin
|
|
333
|
+
return {
|
|
334
|
+
DataSource(
|
|
335
|
+
name=entry.get(CDATAKeys.COLUMN_OBJECT_NAME.value),
|
|
336
|
+
location=entry.get(CDATAKeys.SCHEMA_NAME.value),
|
|
337
|
+
source_type=ViewType.DATA_BASE_TABLE,
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def _traverse_ds(
|
|
343
|
+
current_column: str,
|
|
344
|
+
ds_origin_list: List[DataSource],
|
|
345
|
+
current_ds: DataSource,
|
|
346
|
+
datasource_map: Optional[DataSourceMap],
|
|
347
|
+
) -> List[DataSource]:
|
|
348
|
+
"""
|
|
349
|
+
Traverse the ds dict jumping from target -> source columns and getting the right parent.
|
|
350
|
+
We keep inspecting current datasources and will append to the origin list the ones
|
|
351
|
+
that are not LOGICAL
|
|
352
|
+
"""
|
|
353
|
+
if current_ds.source_type != ViewType.LOGICAL:
|
|
354
|
+
ds_origin_list.append(current_ds)
|
|
355
|
+
|
|
356
|
+
else:
|
|
357
|
+
# Based on our current column, find the parents from the mappings in the current_ds
|
|
358
|
+
current_ds_mapping: DataSourceMapping = current_ds.mapping.get(current_column)
|
|
359
|
+
|
|
360
|
+
if current_ds_mapping:
|
|
361
|
+
for parent in current_ds_mapping.parents:
|
|
362
|
+
parent_ds = datasource_map.get(parent.parent)
|
|
363
|
+
if not parent_ds:
|
|
364
|
+
raise CDATAParsingError(
|
|
365
|
+
f"Can't find parent [{parent.parent}] for column [{current_column}]"
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
# Traverse from the source column in the parent mapping
|
|
369
|
+
_traverse_ds(
|
|
370
|
+
current_column=parent.source,
|
|
371
|
+
ds_origin_list=ds_origin_list,
|
|
372
|
+
current_ds=parent_ds,
|
|
373
|
+
datasource_map=datasource_map,
|
|
374
|
+
)
|
|
375
|
+
else:
|
|
376
|
+
logger.info(
|
|
377
|
+
f"Can't find mapping for column [{current_column}] in [{current_ds}]. "
|
|
378
|
+
f"We still have to implement `calculatedViewAttributes`."
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
return ds_origin_list
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def _read_attributes(
|
|
385
|
+
tree: ET.Element, ns: dict, datasource_map: Optional[DataSourceMap] = None
|
|
386
|
+
) -> ParsedLineage:
|
|
387
|
+
"""Compute the lineage based from the attributes"""
|
|
388
|
+
lineage = ParsedLineage()
|
|
389
|
+
attribute_list = tree.find(CDATAKeys.ATTRIBUTES.value, ns) if tree else None
|
|
390
|
+
if not attribute_list:
|
|
391
|
+
return lineage
|
|
392
|
+
|
|
393
|
+
for attribute in attribute_list.findall(CDATAKeys.ATTRIBUTE.value, ns):
|
|
394
|
+
key_mapping = attribute.find(CDATAKeys.KEY_MAPPING.value, ns)
|
|
395
|
+
data_sources = _get_column_datasources(
|
|
396
|
+
entry=key_mapping, datasource_map=datasource_map
|
|
397
|
+
)
|
|
398
|
+
attr_lineage = ParsedLineage(
|
|
399
|
+
mappings=[
|
|
400
|
+
ColumnMapping(
|
|
401
|
+
data_source=ds,
|
|
402
|
+
sources=[key_mapping.get(CDATAKeys.COLUMN_NAME.value)],
|
|
403
|
+
target=attribute.get(CDATAKeys.ID.value),
|
|
404
|
+
)
|
|
405
|
+
for ds in data_sources
|
|
406
|
+
]
|
|
407
|
+
)
|
|
408
|
+
lineage += attr_lineage
|
|
409
|
+
|
|
410
|
+
return lineage
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def _read_calculated_attributes(
|
|
414
|
+
tree: ET.Element,
|
|
415
|
+
ns: dict,
|
|
416
|
+
base_lineage: ParsedLineage,
|
|
417
|
+
key: CalculatedAttrKey = CalculatedAttrKey.CALCULATED_ATTRIBUTE,
|
|
418
|
+
) -> ParsedLineage:
|
|
419
|
+
"""Compute the lineage based on the calculated attributes"""
|
|
420
|
+
lineage = ParsedLineage()
|
|
421
|
+
|
|
422
|
+
calculated_attrs = tree.find(CDATAKeys.CALCULATED_ATTRS.value, ns)
|
|
423
|
+
if not calculated_attrs:
|
|
424
|
+
return lineage
|
|
425
|
+
|
|
426
|
+
for calculated_attr in calculated_attrs.findall(key.value, ns):
|
|
427
|
+
formula = (
|
|
428
|
+
calculated_attr.find(CDATAKeys.KEY_CALCULATION.value, ns)
|
|
429
|
+
.find(CDATAKeys.FORMULA.value, ns)
|
|
430
|
+
.text
|
|
431
|
+
)
|
|
432
|
+
lineage += _explode_formula(
|
|
433
|
+
target=calculated_attr.get(CDATAKeys.ID.value),
|
|
434
|
+
formula=formula,
|
|
435
|
+
base_lineage=base_lineage,
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
return lineage
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def _read_base_measures(
|
|
442
|
+
tree: ET.Element, ns: dict, datasource_map: Optional[DataSourceMap] = None
|
|
443
|
+
) -> ParsedLineage:
|
|
444
|
+
"""
|
|
445
|
+
Compute the lineage based on the base measures.
|
|
446
|
+
For CalculationViews, we have a dictionary of pre-defined DataSources. For the rest,
|
|
447
|
+
we'll default to Table DataSources with the given information in the measure.
|
|
448
|
+
|
|
449
|
+
See examples cdata_calculation_view.xml and cdata_attribute_view.xml in test resources.
|
|
450
|
+
"""
|
|
451
|
+
lineage = ParsedLineage()
|
|
452
|
+
|
|
453
|
+
base_measures = tree.find(CDATAKeys.BASE_MEASURES.value, ns)
|
|
454
|
+
if not base_measures:
|
|
455
|
+
return lineage
|
|
456
|
+
|
|
457
|
+
for measure in base_measures.findall(CDATAKeys.MEASURE.value, ns):
|
|
458
|
+
measure_mapping = measure.find(CDATAKeys.MEASURE_MAPPING.value, ns)
|
|
459
|
+
data_sources = _get_column_datasources(
|
|
460
|
+
entry=measure_mapping, datasource_map=datasource_map
|
|
461
|
+
)
|
|
462
|
+
measure_lineage = ParsedLineage(
|
|
463
|
+
mappings=[
|
|
464
|
+
ColumnMapping(
|
|
465
|
+
data_source=ds,
|
|
466
|
+
sources=[measure_mapping.get(CDATAKeys.COLUMN_NAME.value)],
|
|
467
|
+
target=measure.get(CDATAKeys.ID.value),
|
|
468
|
+
)
|
|
469
|
+
for ds in data_sources
|
|
470
|
+
]
|
|
471
|
+
)
|
|
472
|
+
lineage += measure_lineage
|
|
473
|
+
|
|
474
|
+
return lineage
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def _explode_formula(
|
|
478
|
+
target: str, formula: str, base_lineage: ParsedLineage
|
|
479
|
+
) -> ParsedLineage:
|
|
480
|
+
"""
|
|
481
|
+
Explode the formula and extract the columns
|
|
482
|
+
Args:
|
|
483
|
+
formula: formula to extract involved columns from
|
|
484
|
+
base_lineage: parsed lineage of the main attributes. We'll use this to pick up the original lineage columns
|
|
485
|
+
Returns:
|
|
486
|
+
Parsed Lineage from the formula
|
|
487
|
+
"""
|
|
488
|
+
column_ds = {
|
|
489
|
+
match.group(1): base_lineage.find_target(match.group(1)).data_source
|
|
490
|
+
for match in FORMULA_PATTERN.finditer(formula)
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
# Group every datasource (key) with a list of the involved columns (values)
|
|
494
|
+
ds_columns = defaultdict(list)
|
|
495
|
+
for column, ds in column_ds.items():
|
|
496
|
+
ds_columns[ds].append(column)
|
|
497
|
+
|
|
498
|
+
return ParsedLineage(
|
|
499
|
+
mappings=[
|
|
500
|
+
ColumnMapping(
|
|
501
|
+
# We get the source once we find the mapping of the target
|
|
502
|
+
data_source=data_source,
|
|
503
|
+
sources=columns,
|
|
504
|
+
target=target,
|
|
505
|
+
formula=formula,
|
|
506
|
+
)
|
|
507
|
+
for data_source, columns in ds_columns.items()
|
|
508
|
+
]
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
parse_registry = enum_register()
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
@parse_registry.add(ViewType.ANALYTIC_VIEW.value)
|
|
516
|
+
def _(cdata: str) -> ParsedLineage:
|
|
517
|
+
"""Parse the CDATA XML for Analytics View"""
|
|
518
|
+
ns = NAMESPACE_DICT[ViewType.ANALYTIC_VIEW.value]
|
|
519
|
+
tree = ET.fromstring(cdata)
|
|
520
|
+
measure_group = tree.find(CDATAKeys.PRIVATE_MEASURE_GROUP.value, ns)
|
|
521
|
+
# TODO: Handle lineage from calculatedMeasures, restrictedMeasures and sharedDimensions
|
|
522
|
+
return _read_attributes(measure_group, ns)
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
@parse_registry.add(ViewType.ATTRIBUTE_VIEW.value)
|
|
526
|
+
def _(cdata: str) -> ParsedLineage:
|
|
527
|
+
"""Parse the CDATA XML for Analytics View"""
|
|
528
|
+
ns = NAMESPACE_DICT[ViewType.ATTRIBUTE_VIEW.value]
|
|
529
|
+
tree = ET.fromstring(cdata)
|
|
530
|
+
attribute_lineage = _read_attributes(tree=tree, ns=ns)
|
|
531
|
+
calculated_attrs_lineage = _read_calculated_attributes(
|
|
532
|
+
tree=tree, ns=ns, base_lineage=attribute_lineage
|
|
533
|
+
)
|
|
534
|
+
base_measure_lineage = _read_base_measures(tree=tree, ns=ns, datasource_map=None)
|
|
535
|
+
|
|
536
|
+
return attribute_lineage + calculated_attrs_lineage + base_measure_lineage
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
@parse_registry.add(ViewType.CALCULATION_VIEW.value)
|
|
540
|
+
def _(cdata: str) -> ParsedLineage:
|
|
541
|
+
"""
|
|
542
|
+
Parse the CDATA XML for Calculation View
|
|
543
|
+
|
|
544
|
+
We can think of the DataSources in a CV as:
|
|
545
|
+
- "real" sources: they are tables or other views that are used in the calculation
|
|
546
|
+
- "logical" sources: as internal projections, aggregations, etc.
|
|
547
|
+
|
|
548
|
+
The behavior is:
|
|
549
|
+
- The LogicalModel attributes can be linked - transitively - to either a "real" or a "logical" source.
|
|
550
|
+
- The "logical" sources are defined inside each `calculationView`
|
|
551
|
+
- Each `calculationView` can have an `input` node that can either be "real" or "logical"
|
|
552
|
+
- We can identify "real" inputs as their `<input node="#<ID>">` will match the <DataSource id="ID" type="...">
|
|
553
|
+
|
|
554
|
+
When building the dataSources here we need to ensure we iterate over the calculationViews, and during
|
|
555
|
+
the _read_ds we'll iteratively traverse the dataSources to find the actual table.
|
|
556
|
+
|
|
557
|
+
Internally, we'll identify "logical" dataSources by giving them a list of column mappings, which we'll
|
|
558
|
+
use to identify the actual source.
|
|
559
|
+
"""
|
|
560
|
+
# TODO: Handle lineage from calculatedMeasure, restrictedMeasure and sharedDimesions
|
|
561
|
+
ns = NAMESPACE_DICT[ViewType.CALCULATION_VIEW.value]
|
|
562
|
+
tree = ET.fromstring(cdata)
|
|
563
|
+
|
|
564
|
+
# Prepare a dictionary of defined data sources
|
|
565
|
+
datasource_map = _parse_cv_data_sources(tree=tree, ns=ns)
|
|
566
|
+
|
|
567
|
+
# Iterate over the Logical Model attributes
|
|
568
|
+
logical_model = tree.find(CDATAKeys.LOGICAL_MODEL.value, ns)
|
|
569
|
+
attribute_lineage = _read_attributes(
|
|
570
|
+
tree=logical_model, ns=ns, datasource_map=datasource_map
|
|
571
|
+
)
|
|
572
|
+
calculated_attrs_lineage = _read_calculated_attributes(
|
|
573
|
+
tree=tree,
|
|
574
|
+
ns=ns,
|
|
575
|
+
base_lineage=attribute_lineage,
|
|
576
|
+
key=CalculatedAttrKey.CALCULATED_VIEW_ATTRIBUTE,
|
|
577
|
+
)
|
|
578
|
+
base_measure_lineage = _read_base_measures(
|
|
579
|
+
tree=logical_model, ns=ns, datasource_map=datasource_map
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
return attribute_lineage + calculated_attrs_lineage + base_measure_lineage
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
def _parse_cv_data_sources(tree: ET.Element, ns: dict) -> DataSourceMap:
|
|
586
|
+
"""
|
|
587
|
+
Parse the real and logical data sources of a CV
|
|
588
|
+
|
|
589
|
+
The logical (`calculationViews`) have the following shape:
|
|
590
|
+
```
|
|
591
|
+
<calculationViews>
|
|
592
|
+
<calculationView xsi:type="Calculation:AggregationView" id="Aggregation_1">
|
|
593
|
+
<descriptions/>
|
|
594
|
+
<viewAttributes>
|
|
595
|
+
<viewAttribute id="MANDT"/>
|
|
596
|
+
...
|
|
597
|
+
</viewAttributes>
|
|
598
|
+
<calculatedViewAttributes>
|
|
599
|
+
<calculatedViewAttribute datatype="INTEGER" id="USAGE_PCT" expressionLanguage="COLUMN_ENGINE">
|
|
600
|
+
<formula>"SEATSOCC_ALL"/"SEATSMAX_ALL"</formula>
|
|
601
|
+
</calculatedViewAttribute>
|
|
602
|
+
...
|
|
603
|
+
</calculatedViewAttributes>
|
|
604
|
+
<input node="#AT_SFLIGHT">
|
|
605
|
+
<mapping xsi:type="Calculation:AttributeMapping" target="MANDT" source="MANDT"/>
|
|
606
|
+
...
|
|
607
|
+
</input>
|
|
608
|
+
<input emptyUnionBehavior="NO_ROW" node="#Projection_1">
|
|
609
|
+
<mapping xsi:type="Calculation:ConstantAttributeMapping" target="CARRNAME" null="true" value=""/>
|
|
610
|
+
...
|
|
611
|
+
</input>
|
|
612
|
+
...
|
|
613
|
+
</calculationView>
|
|
614
|
+
...
|
|
615
|
+
</calculationViews>
|
|
616
|
+
```
|
|
617
|
+
"""
|
|
618
|
+
datasource_map = DataSourceMap({})
|
|
619
|
+
for ds in tree.find(CDATAKeys.DATA_SOURCES.value, ns).findall(
|
|
620
|
+
CDATAKeys.DATA_SOURCE.value, ns
|
|
621
|
+
):
|
|
622
|
+
column_object = ds.find(CDATAKeys.COLUMN_OBJECT.value, ns)
|
|
623
|
+
# we can't rely on the falsy value of the object even if present in the XML
|
|
624
|
+
# If columnObject is informed, we're talking about a table
|
|
625
|
+
if column_object is not None:
|
|
626
|
+
ds_value = DataSource(
|
|
627
|
+
name=column_object.get(CDATAKeys.COLUMN_OBJECT_NAME.value),
|
|
628
|
+
location=column_object.get(CDATAKeys.SCHEMA_NAME.value),
|
|
629
|
+
source_type=ViewType.DATA_BASE_TABLE,
|
|
630
|
+
)
|
|
631
|
+
# or a package object
|
|
632
|
+
else:
|
|
633
|
+
ds_value = DataSource(
|
|
634
|
+
name=ds.get(CDATAKeys.ID.value),
|
|
635
|
+
location=ds.find(CDATAKeys.RESOURCE_URI.value).text,
|
|
636
|
+
source_type=ViewType.__members__[ds.get(CDATAKeys.TYPE.value)],
|
|
637
|
+
)
|
|
638
|
+
datasource_map[ds.get(CDATAKeys.ID.value)] = ds_value
|
|
639
|
+
|
|
640
|
+
calculation_views = tree.find(CDATAKeys.CALCULATION_VIEWS.value, ns)
|
|
641
|
+
if calculation_views is None:
|
|
642
|
+
return datasource_map
|
|
643
|
+
|
|
644
|
+
for cv in calculation_views.findall(CDATAKeys.CALCULATION_VIEW.value, ns):
|
|
645
|
+
mappings = _build_mappings(calculation_view=cv, ns=ns)
|
|
646
|
+
datasource_map[cv.get(CDATAKeys.ID.value)] = DataSource(
|
|
647
|
+
name=cv.get(CDATAKeys.ID.value),
|
|
648
|
+
location=None,
|
|
649
|
+
mapping={mapping.target: mapping for mapping in mappings},
|
|
650
|
+
source_type=ViewType.LOGICAL,
|
|
651
|
+
)
|
|
652
|
+
|
|
653
|
+
return datasource_map
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
def _build_mappings(calculation_view: ET.Element, ns: dict) -> List[DataSourceMapping]:
|
|
657
|
+
"""
|
|
658
|
+
Build the DataSourceMappings from each `input` inside a Calculation View tree.
|
|
659
|
+
|
|
660
|
+
Note how we can have:
|
|
661
|
+
```
|
|
662
|
+
<input emptyUnionBehavior="NO_ROW" node="#Aggregation_1">
|
|
663
|
+
<mapping xsi:type="Calculation:AttributeMapping" target="MANDT" source="MANDT"/>
|
|
664
|
+
...
|
|
665
|
+
</input>
|
|
666
|
+
<input emptyUnionBehavior="NO_ROW" node="#Projection_1">
|
|
667
|
+
<mapping xsi:type="Calculation:AttributeMapping" target="MANDT" source="MANDT"/>
|
|
668
|
+
...
|
|
669
|
+
</input>
|
|
670
|
+
```
|
|
671
|
+
Where a single target column `MANDT` comes from multiple sources. We need to consider
|
|
672
|
+
this when building the `parent` field in DataSourceMapping.
|
|
673
|
+
|
|
674
|
+
1. First, create a single list of all the mappings from all the inputs independently
|
|
675
|
+
2. Then, group by `target` and listagg the `parent`s
|
|
676
|
+
|
|
677
|
+
TODO: We still need to take care of mappings without source, since those come from
|
|
678
|
+
`calculatedViewAttributes` where we should handle the formula. Check `cdata_calculation_view.xml`
|
|
679
|
+
and take the `USAGE_PCT` as an example.
|
|
680
|
+
"""
|
|
681
|
+
|
|
682
|
+
input_mappings = _build_input_mappings(calculation_view=calculation_view, ns=ns)
|
|
683
|
+
# calculated_view_attrs = _build_cv_attributes(
|
|
684
|
+
# calculation_view=calculation_view, ns=ns, input_mappings=input_mappings
|
|
685
|
+
# )
|
|
686
|
+
|
|
687
|
+
return input_mappings
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
def _build_input_mappings(
|
|
691
|
+
calculation_view: ET.Element, ns: dict
|
|
692
|
+
) -> List[DataSourceMapping]:
|
|
693
|
+
"""Map input nodes"""
|
|
694
|
+
mappings = []
|
|
695
|
+
for input_node in calculation_view.findall(CDATAKeys.INPUT.value, ns):
|
|
696
|
+
for mapping in input_node.findall(CDATAKeys.MAPPING.value, ns):
|
|
697
|
+
if mapping.get(CDATAKeys.SOURCE.value) and mapping.get(
|
|
698
|
+
CDATAKeys.TARGET.value
|
|
699
|
+
):
|
|
700
|
+
mappings.append(
|
|
701
|
+
DataSourceMapping(
|
|
702
|
+
target=mapping.get(CDATAKeys.TARGET.value),
|
|
703
|
+
parents=[
|
|
704
|
+
ParentSource(
|
|
705
|
+
source=mapping.get(CDATAKeys.SOURCE.value),
|
|
706
|
+
parent=input_node.get(CDATAKeys.NODE.value).replace(
|
|
707
|
+
"#", ""
|
|
708
|
+
),
|
|
709
|
+
)
|
|
710
|
+
],
|
|
711
|
+
)
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
return _group_mappings(mappings)
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
def _build_cv_attributes(
|
|
718
|
+
calculation_view: ET.Element, ns: dict, input_mappings: List[DataSourceMapping]
|
|
719
|
+
) -> List[DataSourceMapping]:
|
|
720
|
+
"""Extract mapping from `calculatedViewAttribute` formulas"""
|
|
721
|
+
mappings = []
|
|
722
|
+
view_attrs = calculation_view.find(CDATAKeys.CALCULATION_VIEW_ATTRIBUTES.value, ns)
|
|
723
|
+
if view_attrs is None:
|
|
724
|
+
return mappings
|
|
725
|
+
|
|
726
|
+
for view_attr in view_attrs.findall(CDATAKeys.CALCULATION_VIEW_ATTRIBUTE.value, ns):
|
|
727
|
+
formula = (
|
|
728
|
+
view_attr.find(CDATAKeys.FORMULA.value, ns).text
|
|
729
|
+
if view_attr.find(CDATAKeys.FORMULA.value, ns) is not None
|
|
730
|
+
else None
|
|
731
|
+
)
|
|
732
|
+
if not formula:
|
|
733
|
+
logger.debug(f"Skipping formula without expression at {view_attr}")
|
|
734
|
+
continue
|
|
735
|
+
|
|
736
|
+
involved_columns = FORMULA_PATTERN.findall(formula)
|
|
737
|
+
for col in involved_columns:
|
|
738
|
+
# Find the mapping for the involved column
|
|
739
|
+
mapping = next(
|
|
740
|
+
(mapping for mapping in input_mappings if mapping.target == col), None
|
|
741
|
+
)
|
|
742
|
+
if not mapping:
|
|
743
|
+
logger.debug(
|
|
744
|
+
f"Can't find mapping for column [{col}] in [{input_mappings}]"
|
|
745
|
+
)
|
|
746
|
+
continue
|
|
747
|
+
|
|
748
|
+
mappings.append(
|
|
749
|
+
DataSourceMapping(
|
|
750
|
+
target=view_attr.get(CDATAKeys.ID.value),
|
|
751
|
+
parents=mapping.parents,
|
|
752
|
+
)
|
|
753
|
+
)
|
|
754
|
+
|
|
755
|
+
return _group_mappings(mappings)
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
def _group_mappings(mappings: List[DataSourceMapping]) -> List[DataSourceMapping]:
|
|
759
|
+
"""Group the mappings by target column and listagg the parents"""
|
|
760
|
+
# Sort the data by the target field
|
|
761
|
+
mappings.sort(key=lambda x: x.target)
|
|
762
|
+
|
|
763
|
+
# Use groupby to group by the target field
|
|
764
|
+
grouped_data = [
|
|
765
|
+
DataSourceMapping(
|
|
766
|
+
target=target,
|
|
767
|
+
parents=list(itertools.chain.from_iterable(item.parents for item in group)),
|
|
768
|
+
)
|
|
769
|
+
for target, group in itertools.groupby(mappings, key=lambda x: x.target)
|
|
770
|
+
]
|
|
771
|
+
|
|
772
|
+
return grouped_data
|