From 20e508973b05b851b86d10bea3a17bd9aafdf8b9 Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Mon, 9 Dec 2024 22:10:40 +0530 Subject: [PATCH 01/10] Reporting the Advisory locks, XML Functions and System columsn on the DDLs in the unsupported_features in analyze --- yb-voyager/src/queryissue/queryissue.go | 50 ++++++++++++++++--------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/yb-voyager/src/queryissue/queryissue.go b/yb-voyager/src/queryissue/queryissue.go index 6f9b31436..b9451db27 100644 --- a/yb-voyager/src/queryissue/queryissue.go +++ b/yb-voyager/src/queryissue/queryissue.go @@ -94,16 +94,12 @@ func (p *ParserIssueDetector) getAllIssues(query string) ([]issue.IssueInstance, if err != nil { return nil, fmt.Errorf("error getting plpgsql issues: %v", err) } - - dmlIssues, err := p.getDMLIssues(query) - if err != nil { - return nil, fmt.Errorf("error getting dml issues: %v", err) - } ddlIssues, err := p.getDDLIssues(query) if err != nil { return nil, fmt.Errorf("error getting ddl issues: %v", err) } - return lo.Flatten([][]issue.IssueInstance{plpgsqlIssues, dmlIssues, ddlIssues}), nil + issues := lo.Flatten([][]issue.IssueInstance{plpgsqlIssues, ddlIssues}) + return issues, nil } func (p *ParserIssueDetector) getIssuesNotFixedInTargetDbVersion(issues []issue.IssueInstance, targetDbVersion *ybversion.YBVersion) ([]issue.IssueInstance, error) { @@ -173,7 +169,7 @@ func (p *ParserIssueDetector) getPLPGSQLIssues(query string) ([]issue.IssueInsta if err != nil { return nil, fmt.Errorf("error deparsing a select stmt: %v", err) } - issues, err := p.getDMLIssues(selectStmtQuery) + issues, err := p.genericIssues(selectStmtQuery) if err != nil { return nil, err } @@ -290,6 +286,23 @@ func (p *ParserIssueDetector) getDDLIssues(query string) ([]issue.IssueInstance, issues[i].SqlStatement = query } } + + if ddlObj.GetObjectType() == queryparser.MVIEW_OBJECT_TYPE || ddlObj.GetObjectType() == queryparser.VIEW_OBJECT_TYPE { + //Already reporting these generic issues in plpgsql section on MVIEW/VIEW + return issues, nil + } + + genericIssues, err := p.genericIssues(query) + if err != nil { + return nil, fmt.Errorf("error getting generic issues: %w", err) + } + + for _, i := range genericIssues { + //In case of genericIssues we don't populate the proper obj type and obj name + i.ObjectType = ddlObj.GetObjectType() + i.ObjectName = ddlObj.GetObjectName() + issues = append(issues, i) + } return issues, nil } @@ -324,16 +337,6 @@ func (p *ParserIssueDetector) GetPercentTypeSyntaxIssues(query string) ([]issue. } func (p *ParserIssueDetector) GetDMLIssues(query string, targetDbVersion *ybversion.YBVersion) ([]issue.IssueInstance, error) { - issues, err := p.getDMLIssues(query) - if err != nil { - return issues, err - } - - return p.getIssuesNotFixedInTargetDbVersion(issues, targetDbVersion) -} - -// TODO: in future when we will DDL issues detection here we need `GetDDLIssues` -func (p *ParserIssueDetector) getDMLIssues(query string) ([]issue.IssueInstance, error) { parseTree, err := queryparser.Parse(query) if err != nil { return nil, fmt.Errorf("error parsing query: %w", err) @@ -346,6 +349,19 @@ func (p *ParserIssueDetector) getDMLIssues(query string) ([]issue.IssueInstance, //Skip all the DDLs coming to this function return nil, nil } + issues, err := p.genericIssues(query) + if err != nil { + return issues, err + } + + return p.getIssuesNotFixedInTargetDbVersion(issues, targetDbVersion) +} + +func (p *ParserIssueDetector) genericIssues(query string) ([]issue.IssueInstance, error) { + parseTree, err := queryparser.Parse(query) + if err != nil { + return nil, fmt.Errorf("error parsing query: %w", err) + } var result []issue.IssueInstance var unsupportedConstructs []string visited := make(map[protoreflect.Message]bool) From c127704a201cac3f016522747a8f2ff3dd03f715 Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Mon, 9 Dec 2024 22:38:42 +0530 Subject: [PATCH 02/10] added reporting in assess-migration --- yb-voyager/cmd/assessMigrationCommand.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yb-voyager/cmd/assessMigrationCommand.go b/yb-voyager/cmd/assessMigrationCommand.go index f15c43a0f..efd8c5630 100644 --- a/yb-voyager/cmd/assessMigrationCommand.go +++ b/yb-voyager/cmd/assessMigrationCommand.go @@ -945,6 +945,9 @@ func getUnsupportedFeaturesFromSchemaAnalysisReport(featureName string, issueRea var minVersionsFixedInSet bool for _, issue := range schemaAnalysisReport.Issues { + if !slices.Contains([]string{UNSUPPORTED_FEATURES, MIGRATION_CAVEATS}, issue.IssueType) { + continue + } if strings.Contains(issue.Reason, issueReason) { objectInfo := ObjectInfo{ ObjectName: issue.ObjectName, @@ -994,6 +997,9 @@ func fetchUnsupportedPGFeaturesFromSchemaReport(schemaAnalysisReport utils.Schem unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport(UNLOGGED_TABLE_FEATURE, ISSUE_UNLOGGED_TABLE, schemaAnalysisReport, false, "")) unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport(REFERENCING_TRIGGER_FEATURE, REFERENCING_CLAUSE_FOR_TRIGGERS, schemaAnalysisReport, false, "")) unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport(BEFORE_FOR_EACH_ROW_TRIGGERS_ON_PARTITIONED_TABLE_FEATURE, BEFORE_FOR_EACH_ROW_TRIGGERS_ON_PARTITIONED_TABLE, schemaAnalysisReport, false, "")) + unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport("Advisory Locks", "Advisory Locks", schemaAnalysisReport, false, "")) + unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport("XML Functions", "XML Functions", schemaAnalysisReport, false, "")) + unsupportedFeatures = append(unsupportedFeatures, getUnsupportedFeaturesFromSchemaAnalysisReport("System Columns", "System Columns", schemaAnalysisReport, false, "")) return unsupportedFeatures, nil } From 8afaaeaf4e06a01518234549a13a11c713f20f75 Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Tue, 10 Dec 2024 18:10:09 +0530 Subject: [PATCH 03/10] Moved MVIEW/View select generic issues to the unsupported features --- yb-voyager/src/queryissue/queryissue.go | 91 ++++++++----------- yb-voyager/src/queryissue/unsupported_ddls.go | 68 +++++++------- yb-voyager/src/queryparser/ddl_processor.go | 30 ++++++ yb-voyager/src/queryparser/helpers_struct.go | 35 ------- 4 files changed, 101 insertions(+), 123 deletions(-) diff --git a/yb-voyager/src/queryissue/queryissue.go b/yb-voyager/src/queryissue/queryissue.go index b9451db27..259ab874e 100644 --- a/yb-voyager/src/queryissue/queryissue.go +++ b/yb-voyager/src/queryissue/queryissue.go @@ -94,11 +94,15 @@ func (p *ParserIssueDetector) getAllIssues(query string) ([]issue.IssueInstance, if err != nil { return nil, fmt.Errorf("error getting plpgsql issues: %v", err) } + dmlIssues, err := p.genericIssues(query) + if err != nil { + return nil, fmt.Errorf("error getting generic issues: %v", err) + } ddlIssues, err := p.getDDLIssues(query) if err != nil { return nil, fmt.Errorf("error getting ddl issues: %v", err) } - issues := lo.Flatten([][]issue.IssueInstance{plpgsqlIssues, ddlIssues}) + issues := lo.Flatten([][]issue.IssueInstance{plpgsqlIssues, dmlIssues, ddlIssues}) return issues, nil } @@ -130,59 +134,40 @@ func (p *ParserIssueDetector) getPLPGSQLIssues(query string) ([]issue.IssueInsta if err != nil { return nil, fmt.Errorf("error parsing query: %w", err) } - //TODO handle this in DDLPARSER, DDLIssueDetector - if queryparser.IsPLPGSQLObject(parseTree) { - objType, objName := queryparser.GetObjectTypeAndObjectName(parseTree) - plpgsqlQueries, err := queryparser.GetAllPLPGSQLStatements(query) - if err != nil { - return nil, fmt.Errorf("error getting all the queries from query: %w", err) - } - var issues []issue.IssueInstance - for _, plpgsqlQuery := range plpgsqlQueries { - issuesInQuery, err := p.getAllIssues(plpgsqlQuery) - if err != nil { - //there can be plpgsql expr queries no parseable via parser e.g. "withdrawal > balance" - log.Errorf("error getting issues in query-%s: %v", query, err) - continue - } - issues = append(issues, issuesInQuery...) - } - percentTypeSyntaxIssues, err := p.GetPercentTypeSyntaxIssues(query) - if err != nil { - return nil, fmt.Errorf("error getting reference TYPE syntax issues: %v", err) - } - issues = append(issues, percentTypeSyntaxIssues...) - - return lo.Map(issues, func(i issue.IssueInstance, _ int) issue.IssueInstance { - //Replacing the objectType and objectName to the original ObjectType and ObjectName of the PLPGSQL object - //e.g. replacing the DML_QUERY and "" to FUNCTION and - i.ObjectType = objType - i.ObjectName = objName - return i - }), nil - } - //Handle the Mview/View DDL's Select stmt issues - if queryparser.IsViewObject(parseTree) || queryparser.IsMviewObject(parseTree) { - objType, objName := queryparser.GetObjectTypeAndObjectName(parseTree) - selectStmtQuery, err := queryparser.GetSelectStmtQueryFromViewOrMView(parseTree) - if err != nil { - return nil, fmt.Errorf("error deparsing a select stmt: %v", err) - } - issues, err := p.genericIssues(selectStmtQuery) + if !queryparser.IsPLPGSQLObject(parseTree) { + return nil, nil + } + //TODO handle this in DDLPARSER, DDLIssueDetector + objType, objName := queryparser.GetObjectTypeAndObjectName(parseTree) + plpgsqlQueries, err := queryparser.GetAllPLPGSQLStatements(query) + if err != nil { + return nil, fmt.Errorf("error getting all the queries from query: %w", err) + } + var issues []issue.IssueInstance + for _, plpgsqlQuery := range plpgsqlQueries { + issuesInQuery, err := p.getAllIssues(plpgsqlQuery) if err != nil { - return nil, err + //there can be plpgsql expr queries no parseable via parser e.g. "withdrawal > balance" + log.Errorf("error getting issues in query-%s: %v", query, err) + continue } + issues = append(issues, issuesInQuery...) + } - return lo.Map(issues, func(i issue.IssueInstance, _ int) issue.IssueInstance { - //Replacing the objectType and objectName to the original ObjectType and ObjectName of the PLPGSQL object - //e.g. replacing the DML_QUERY and "" to FUNCTION and - i.ObjectType = objType - i.ObjectName = objName - return i - }), nil + percentTypeSyntaxIssues, err := p.GetPercentTypeSyntaxIssues(query) + if err != nil { + return nil, fmt.Errorf("error getting reference TYPE syntax issues: %v", err) } - return nil, nil + issues = append(issues, percentTypeSyntaxIssues...) + + return lo.Map(issues, func(i issue.IssueInstance, _ int) issue.IssueInstance { + //Replacing the objectType and objectName to the original ObjectType and ObjectName of the PLPGSQL object + //e.g. replacing the DML_QUERY and "" to FUNCTION and + i.ObjectType = objType + i.ObjectName = objName + return i + }), nil } func (p *ParserIssueDetector) ParseRequiredDDLs(query string) error { @@ -280,6 +265,9 @@ func (p *ParserIssueDetector) getDDLIssues(query string) ([]issue.IssueInstance, return nil, fmt.Errorf("error detecting issues: %w", err) } + if _, ok := ddlObj.(*queryparser.Object); ok { // In case the DDL doesn't have any processor skip checking generic issues + return issues, nil + } // Add the original query to each issue for i := range issues { if issues[i].SqlStatement == "" { @@ -287,11 +275,6 @@ func (p *ParserIssueDetector) getDDLIssues(query string) ([]issue.IssueInstance, } } - if ddlObj.GetObjectType() == queryparser.MVIEW_OBJECT_TYPE || ddlObj.GetObjectType() == queryparser.VIEW_OBJECT_TYPE { - //Already reporting these generic issues in plpgsql section on MVIEW/VIEW - return issues, nil - } - genericIssues, err := p.genericIssues(query) if err != nil { return nil, fmt.Errorf("error getting generic issues: %w", err) diff --git a/yb-voyager/src/queryissue/unsupported_ddls.go b/yb-voyager/src/queryissue/unsupported_ddls.go index fe4121e60..0a79d1af7 100644 --- a/yb-voyager/src/queryissue/unsupported_ddls.go +++ b/yb-voyager/src/queryissue/unsupported_ddls.go @@ -51,7 +51,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is // Check for generated columns if len(table.GeneratedColumns) > 0 { issues = append(issues, issue.NewGeneratedColumnsIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), "", // query string table.GeneratedColumns, @@ -61,7 +61,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is // Check for unlogged table if table.IsUnlogged { issues = append(issues, issue.NewUnloggedTableIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), "", // query string )) @@ -69,7 +69,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is if table.IsInherited { issues = append(issues, issue.NewInheritanceIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), "", )) @@ -80,7 +80,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is for _, c := range table.Constraints { if c.ConstraintType == queryparser.EXCLUSION_CONSTR_TYPE { issues = append(issues, issue.NewExclusionConstraintIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), fmt.Sprintf("%s, constraint: (%s)", table.GetObjectName(), c.ConstraintName), "", )) @@ -88,7 +88,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is if c.ConstraintType != queryparser.FOREIGN_CONSTR_TYPE && c.IsDeferrable { issues = append(issues, issue.NewDeferrableConstraintIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), fmt.Sprintf("%s, constraint: (%s)", table.GetObjectName(), c.ConstraintName), "", )) @@ -106,7 +106,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is continue } issues = append(issues, issue.NewPrimaryOrUniqueConsOnUnsupportedIndexTypesIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), fmt.Sprintf("%s, constraint: %s", table.GetObjectName(), c.ConstraintName), "", typeName, @@ -130,10 +130,10 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is isUnsupportedDatatypeInLiveWithFFOrFB := isUnsupportedDatatypeInLiveWithFFOrFBList || isUDTDatatype || isArrayOfEnumsDatatype if isUnsupportedDatatype { - reportUnsupportedDatatypes(col, issue.TABLE_OBJECT_TYPE, table.GetObjectName(), &issues) + reportUnsupportedDatatypes(col, obj.GetObjectType(), table.GetObjectName(), &issues) } else if isUnsupportedDatatypeInLive { issues = append(issues, issue.NewUnsupportedDatatypesForLMIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), "", col.TypeName, @@ -146,7 +146,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is reportTypeName = fmt.Sprintf("%s[]", reportTypeName) } issues = append(issues, issue.NewUnsupportedDatatypesForLMWithFFOrFBIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), "", reportTypeName, @@ -166,7 +166,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is alterAddPk := d.primaryConsInAlter[table.GetObjectName()] if alterAddPk != nil { issues = append(issues, issue.NewAlterTableAddPKOnPartiionIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), alterAddPk.Query, )) @@ -176,7 +176,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is if table.IsExpressionPartition && (len(primaryKeyColumns) > 0 || len(uniqueKeyColumns) > 0) { issues = append(issues, issue.NewExpressionPartitionIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), "", )) @@ -185,7 +185,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is if table.PartitionStrategy == queryparser.LIST_PARTITION && len(table.PartitionColumns) > 1 { issues = append(issues, issue.NewMultiColumnListPartition( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), "", )) @@ -193,7 +193,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is partitionColumnsNotInPK, _ := lo.Difference(table.PartitionColumns, primaryKeyColumns) if len(primaryKeyColumns) > 0 && len(partitionColumnsNotInPK) > 0 { issues = append(issues, issue.NewInsufficientColumnInPKForPartition( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), table.GetObjectName(), "", partitionColumnsNotInPK, @@ -253,7 +253,7 @@ func (f *ForeignTableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]i issues := make([]issue.IssueInstance, 0) issues = append(issues, issue.NewForeignTableIssue( - issue.FOREIGN_TABLE_OBJECT_TYPE, + obj.GetObjectType(), foreignTable.GetObjectName(), "", foreignTable.ServerName, @@ -262,7 +262,7 @@ func (f *ForeignTableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]i for _, col := range foreignTable.Columns { isUnsupportedDatatype := utils.ContainsAnyStringFromSlice(srcdb.PostgresUnsupportedDataTypes, col.TypeName) if isUnsupportedDatatype { - reportUnsupportedDatatypes(col, issue.FOREIGN_TABLE_OBJECT_TYPE, foreignTable.GetObjectName(), &issues) + reportUnsupportedDatatypes(col, obj.GetObjectType(), foreignTable.GetObjectName(), &issues) } } @@ -288,7 +288,7 @@ func (d *IndexIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is // Check for unsupported index methods if slices.Contains(UnsupportedIndexMethods, index.AccessMethod) { issues = append(issues, issue.NewUnsupportedIndexMethodIssue( - issue.INDEX_OBJECT_TYPE, + obj.GetObjectType(), index.GetObjectName(), "", // query string index.AccessMethod, @@ -298,7 +298,7 @@ func (d *IndexIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is // Check for storage parameters if index.NumStorageOptions > 0 { issues = append(issues, issue.NewStorageParameterIssue( - issue.INDEX_OBJECT_TYPE, + obj.GetObjectType(), index.GetObjectName(), "", // query string )) @@ -308,7 +308,7 @@ func (d *IndexIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is if index.AccessMethod == GIN_ACCESS_METHOD { if len(index.Params) > 1 { issues = append(issues, issue.NewMultiColumnGinIndexIssue( - issue.INDEX_OBJECT_TYPE, + obj.GetObjectType(), index.GetObjectName(), "", )) @@ -317,7 +317,7 @@ func (d *IndexIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is param := index.Params[0] if param.SortByOrder != queryparser.DEFAULT_SORTING_ORDER { issues = append(issues, issue.NewOrderedGinIndexIssue( - issue.INDEX_OBJECT_TYPE, + obj.GetObjectType(), index.GetObjectName(), "", )) @@ -342,7 +342,7 @@ func (d *IndexIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is isUDTType := slices.Contains(d.compositeTypes, param.GetFullExprCastTypeName()) if param.IsExprCastArrayType { issues = append(issues, issue.NewIndexOnComplexDatatypesIssue( - issue.INDEX_OBJECT_TYPE, + obj.GetObjectType(), index.GetObjectName(), "", "array", @@ -353,7 +353,7 @@ func (d *IndexIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is reportTypeName = "user_defined_type" } issues = append(issues, issue.NewIndexOnComplexDatatypesIssue( - issue.INDEX_OBJECT_TYPE, + obj.GetObjectType(), index.GetObjectName(), "", reportTypeName, @@ -367,7 +367,7 @@ func (d *IndexIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.Is continue } issues = append(issues, issue.NewIndexOnComplexDatatypesIssue( - issue.INDEX_OBJECT_TYPE, + obj.GetObjectType(), index.GetObjectName(), "", typeName, @@ -398,7 +398,7 @@ func (aid *AlterTableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]i case queryparser.SET_OPTIONS: if alter.NumSetAttributes > 0 { issues = append(issues, issue.NewSetAttributeIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), alter.GetObjectName(), "", // query string )) @@ -406,21 +406,21 @@ func (aid *AlterTableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]i case queryparser.ADD_CONSTRAINT: if alter.NumStorageOptions > 0 { issues = append(issues, issue.NewStorageParameterIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), alter.GetObjectName(), "", // query string )) } if alter.ConstraintType == queryparser.EXCLUSION_CONSTR_TYPE { issues = append(issues, issue.NewExclusionConstraintIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), fmt.Sprintf("%s, constraint: (%s)", alter.GetObjectName(), alter.ConstraintName), "", )) } if alter.ConstraintType != queryparser.FOREIGN_CONSTR_TYPE && alter.IsDeferrable { issues = append(issues, issue.NewDeferrableConstraintIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), fmt.Sprintf("%s, constraint: (%s)", alter.GetObjectName(), alter.ConstraintName), "", )) @@ -429,7 +429,7 @@ func (aid *AlterTableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]i if alter.ConstraintType == queryparser.PRIMARY_CONSTR_TYPE && aid.partitionTablesMap[alter.GetObjectName()] { issues = append(issues, issue.NewAlterTableAddPKOnPartiionIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), alter.GetObjectName(), "", )) @@ -447,7 +447,7 @@ func (aid *AlterTableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]i continue } issues = append(issues, issue.NewPrimaryOrUniqueConsOnUnsupportedIndexTypesIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), fmt.Sprintf("%s, constraint: %s", alter.GetObjectName(), alter.ConstraintName), "", typeName, @@ -458,14 +458,14 @@ func (aid *AlterTableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]i } case queryparser.DISABLE_RULE: issues = append(issues, issue.NewDisableRuleIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), alter.GetObjectName(), "", // query string alter.RuleName, )) case queryparser.CLUSTER_ON: issues = append(issues, issue.NewClusterONIssue( - issue.TABLE_OBJECT_TYPE, + obj.GetObjectType(), alter.GetObjectName(), "", // query string )) @@ -487,7 +487,7 @@ func (p *PolicyIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issue.I issues := make([]issue.IssueInstance, 0) if len(policy.RoleNames) > 0 { issues = append(issues, issue.NewPolicyRoleIssue( - issue.POLICY_OBJECT_TYPE, + obj.GetObjectType(), policy.GetObjectName(), "", policy.RoleNames, @@ -512,7 +512,7 @@ func (tid *TriggerIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issu if trigger.IsConstraint { issues = append(issues, issue.NewConstraintTriggerIssue( - issue.TRIGGER_OBJECT_TYPE, + obj.GetObjectType(), trigger.GetObjectName(), "", )) @@ -520,7 +520,7 @@ func (tid *TriggerIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issu if trigger.NumTransitionRelations > 0 { issues = append(issues, issue.NewReferencingClauseTrigIssue( - issue.TRIGGER_OBJECT_TYPE, + obj.GetObjectType(), trigger.GetObjectName(), "", )) @@ -528,7 +528,7 @@ func (tid *TriggerIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]issu if trigger.IsBeforeRowTrigger() && tid.partitionTablesMap[trigger.GetTableName()] { issues = append(issues, issue.NewBeforeRowOnPartitionTableIssue( - issue.TRIGGER_OBJECT_TYPE, + obj.GetObjectType(), trigger.GetObjectName(), "", )) diff --git a/yb-voyager/src/queryparser/ddl_processor.go b/yb-voyager/src/queryparser/ddl_processor.go index f7249d889..7644ee4b4 100644 --- a/yb-voyager/src/queryparser/ddl_processor.go +++ b/yb-voyager/src/queryparser/ddl_processor.go @@ -41,6 +41,7 @@ with the required for storing the information which should have these required f */ type DDLObject interface { GetObjectName() string + GetObjectType() string GetSchemaName() string } @@ -322,6 +323,8 @@ func (t *Table) GetObjectName() string { } func (t *Table) GetSchemaName() string { return t.SchemaName } +func (t *Table) GetObjectType() string { return TABLE_OBJECT_TYPE } + func (t *Table) PrimaryKeyColumns() []string { for _, c := range t.Constraints { if c.ConstraintType == PRIMARY_CONSTR_TYPE { @@ -404,6 +407,8 @@ func (f *ForeignTable) GetObjectName() string { } func (f *ForeignTable) GetSchemaName() string { return f.SchemaName } +func (t *ForeignTable) GetObjectType() string { return FOREIGN_TABLE_OBJECT_TYPE } + //===========INDEX PROCESSOR ================================ // IndexProcessor handles parsing CREATE INDEX statements @@ -501,6 +506,8 @@ func (i *Index) GetTableName() string { return lo.Ternary(i.SchemaName != "", fmt.Sprintf("%s.%s", i.SchemaName, i.TableName), i.TableName) } +func (i *Index) GetObjectType() string { return INDEX_OBJECT_TYPE } + //===========ALTER TABLE PROCESSOR ================================ // AlterTableProcessor handles parsing ALTER TABLE statements @@ -609,6 +616,8 @@ func (a *AlterTable) GetObjectName() string { } func (a *AlterTable) GetSchemaName() string { return a.SchemaName } +func (a *AlterTable) GetObjectType() string { return TABLE_OBJECT_TYPE } + func (a *AlterTable) AddPrimaryKeyOrUniqueCons() bool { return a.ConstraintType == PRIMARY_CONSTR_TYPE || a.ConstraintType == UNIQUE_CONSTR_TYPE } @@ -673,6 +682,8 @@ func (p *Policy) GetObjectName() string { } func (p *Policy) GetSchemaName() string { return p.SchemaName } +func (p *Policy) GetObjectType() string { return POLICY_OBJECT_TYPE } + //=====================TRIGGER PROCESSOR ================== // TriggerProcessor handles parsing CREATE Trigger statements @@ -745,6 +756,8 @@ func (t *Trigger) GetTableName() string { func (t *Trigger) GetSchemaName() string { return t.SchemaName } +func (t *Trigger) GetObjectType() string { return TRIGGER_OBJECT_TYPE } + /* e.g.CREATE TRIGGER after_insert_or_delete_trigger @@ -819,6 +832,8 @@ func (c *CreateType) GetObjectName() string { } func (c *CreateType) GetSchemaName() string { return c.SchemaName } +func (c *CreateType) GetObjectType() string { return TYPE_OBJECT_TYPE } + //===========================VIEW PROCESSOR=================== type ViewProcessor struct{} @@ -849,6 +864,8 @@ func (v *View) GetObjectName() string { } func (v *View) GetSchemaName() string { return v.SchemaName } +func (v *View) GetObjectType() string { return VIEW_OBJECT_TYPE } + //===========================MVIEW PROCESSOR=================== type MViewProcessor struct{} @@ -879,6 +896,8 @@ func (mv *MView) GetObjectName() string { } func (mv *MView) GetSchemaName() string { return mv.SchemaName } +func (mv *MView) GetObjectType() string { return MVIEW_OBJECT_TYPE } + //=============================No-Op PROCESSOR ================== //No op Processor for objects we don't have Processor yet @@ -896,6 +915,7 @@ type Object struct { func (o *Object) GetObjectName() string { return o.ObjectName } func (o *Object) GetSchemaName() string { return o.SchemaName } +func (o *Object) GetObjectType() string { return "OBJECT" } func (n *NoOpProcessor) Process(parseTree *pg_query.ParseResult) (DDLObject, error) { return &Object{}, nil @@ -932,6 +952,16 @@ func GetDDLProcessor(parseTree *pg_query.ParseResult) (DDLProcessor, error) { } const ( + TABLE_OBJECT_TYPE = "TABLE" + TYPE_OBJECT_TYPE = "TYPE" + VIEW_OBJECT_TYPE = "VIEW" + MVIEW_OBJECT_TYPE = "MVIEW" + FOREIGN_TABLE_OBJECT_TYPE = "FOREIGN TABLE" + FUNCTION_OBJECT_TYPE = "FUNCTION" + PROCEDURE_OBJECT_TYPE = "PROCEDURE" + INDEX_OBJECT_TYPE = "INDEX" + POLICY_OBJECT_TYPE = "POLICY" + TRIGGER_OBJECT_TYPE = "TRIGGER" ADD_CONSTRAINT = pg_query.AlterTableType_AT_AddConstraint SET_OPTIONS = pg_query.AlterTableType_AT_SetOptions DISABLE_RULE = pg_query.AlterTableType_AT_DisableRule diff --git a/yb-voyager/src/queryparser/helpers_struct.go b/yb-voyager/src/queryparser/helpers_struct.go index e332547cd..0f00de256 100644 --- a/yb-voyager/src/queryparser/helpers_struct.go +++ b/yb-voyager/src/queryparser/helpers_struct.go @@ -24,25 +24,6 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -func DeparseSelectStmt(selectStmt *pg_query.SelectStmt) (string, error) { - if selectStmt != nil { - parseResult := &pg_query.ParseResult{ - Stmts: []*pg_query.RawStmt{ - { - Stmt: &pg_query.Node{ - Node: &pg_query.Node_SelectStmt{SelectStmt: selectStmt}, - }, - }, - }, - } - - // Deparse the SelectStmt to get the string representation - selectSQL, err := pg_query.Deparse(parseResult) - return selectSQL, err - } - return "", nil -} - func GetProtoMessageFromParseTree(parseTree *pg_query.ParseResult) protoreflect.Message { return parseTree.Stmts[0].Stmt.ProtoReflect() } @@ -63,22 +44,6 @@ func IsMviewObject(parseTree *pg_query.ParseResult) bool { return isCreateAsStmt && createAsNode.CreateTableAsStmt.Objtype == pg_query.ObjectType_OBJECT_MATVIEW } -func GetSelectStmtQueryFromViewOrMView(parseTree *pg_query.ParseResult) (string, error) { - viewNode, isViewStmt := getCreateViewNode(parseTree) - createAsNode, _ := getCreateTableAsStmtNode(parseTree) //For MVIEW case - var selectStmt *pg_query.SelectStmt - if isViewStmt { - selectStmt = viewNode.ViewStmt.GetQuery().GetSelectStmt() - } else { - selectStmt = createAsNode.CreateTableAsStmt.GetQuery().GetSelectStmt() - } - selectStmtQuery, err := DeparseSelectStmt(selectStmt) - if err != nil { - return "", fmt.Errorf("deparsing the select stmt: %v", err) - } - return selectStmtQuery, nil -} - func GetObjectTypeAndObjectName(parseTree *pg_query.ParseResult) (string, string) { createFuncNode, isCreateFunc := getCreateFuncStmtNode(parseTree) viewNode, isViewStmt := getCreateViewNode(parseTree) From 0baf78c2f2523348e5402100e32794fcd5861607 Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Tue, 10 Dec 2024 18:11:47 +0530 Subject: [PATCH 04/10] fix tests and add case for TABLE in analyze-schema --- .../dummy-export-dir/schema/tables/table.sql | 9 ++- .../tests/analyze-schema/expected_issues.json | 46 +++++++++---- migtests/tests/analyze-schema/summary.json | 4 +- .../expectedAssessmentReport.json | 66 ++++++++++--------- 4 files changed, 79 insertions(+), 46 deletions(-) diff --git a/migtests/tests/analyze-schema/dummy-export-dir/schema/tables/table.sql b/migtests/tests/analyze-schema/dummy-export-dir/schema/tables/table.sql index 3af667c48..5452b47f2 100755 --- a/migtests/tests/analyze-schema/dummy-export-dir/schema/tables/table.sql +++ b/migtests/tests/analyze-schema/dummy-export-dir/schema/tables/table.sql @@ -375,4 +375,11 @@ CREATE TABLE public.locations ( id integer NOT NULL, name character varying(100), geom geometry(Point,4326) - ); \ No newline at end of file + ); + + CREATE TABLE public.xml_data_example ( + id SERIAL PRIMARY KEY, + name VARCHAR(255), + description XML DEFAULT xmlparse(document 'Default Product100.00Electronics'), + created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/migtests/tests/analyze-schema/expected_issues.json b/migtests/tests/analyze-schema/expected_issues.json index b83666353..dcdf4e602 100644 --- a/migtests/tests/analyze-schema/expected_issues.json +++ b/migtests/tests/analyze-schema/expected_issues.json @@ -20,6 +20,28 @@ "GH": "https://github.com/yugabyte/yb-voyager/issues/1542", "MinimumVersionsFixedIn": null }, + { + "IssueType": "unsupported_features", + "ObjectType": "TABLE", + "ObjectName": "public.xml_data_example", + "Reason": "XML Functions", + "SqlStatement": " CREATE TABLE public.xml_data_example (\n id SERIAL PRIMARY KEY,\n name VARCHAR(255),\n description XML DEFAULT xmlparse(document '\u003cproduct\u003e\u003cname\u003eDefault Product\u003c/name\u003e\u003cprice\u003e100.00\u003c/price\u003e\u003ccategory\u003eElectronics\u003c/category\u003e\u003c/product\u003e'),\n created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP\n);", + "Suggestion": "", + "GH": "", + "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", + "MinimumVersionsFixedIn": null + }, + { + "IssueType": "unsupported_datatypes", + "ObjectType": "TABLE", + "ObjectName": "public.xml_data_example", + "Reason": "Unsupported datatype - xml on column - description", + "SqlStatement": " CREATE TABLE public.xml_data_example (\n id SERIAL PRIMARY KEY,\n name VARCHAR(255),\n description XML DEFAULT xmlparse(document '\u003cproduct\u003e\u003cname\u003eDefault Product\u003c/name\u003e\u003cprice\u003e100.00\u003c/price\u003e\u003ccategory\u003eElectronics\u003c/category\u003e\u003c/product\u003e'),\n created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP\n);", + "Suggestion": "Data ingestion is not supported for this type in YugabyteDB so handle this type in different way. Refer link for more details.", + "GH": "https://github.com/yugabyte/yugabyte-db/issues/1043", + "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#data-ingestion-on-xml-data-type-is-not-supported", + "MinimumVersionsFixedIn": null + }, { "IssueType": "unsupported_features", "ObjectType": "INDEX", @@ -1682,66 +1704,66 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "MVIEW", "ObjectName": "public.sample_data_view", "Reason": "XML Functions", - "SqlStatement": "SELECT sample_data.id, sample_data.name, sample_data.description, xmlforest(sample_data.name AS name, sample_data.description AS description) AS xml_data, pg_try_advisory_lock(sample_data.id::bigint) AS lock_acquired, sample_data.ctid AS row_ctid, sample_data.xmin AS xmin_value FROM public.sample_data", + "SqlStatement": "CREATE MATERIALIZED VIEW public.sample_data_view AS\n SELECT sample_data.id,\n sample_data.name,\n sample_data.description,\n XMLFOREST(sample_data.name AS name, sample_data.description AS description) AS xml_data,\n pg_try_advisory_lock((sample_data.id)::bigint) AS lock_acquired,\n sample_data.ctid AS row_ctid,\n sample_data.xmin AS xmin_value\n FROM public.sample_data\n WITH NO DATA;", "Suggestion": "", "GH": "", "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "MVIEW", "ObjectName": "public.sample_data_view", "Reason": "Advisory Locks", - "SqlStatement": "SELECT sample_data.id, sample_data.name, sample_data.description, xmlforest(sample_data.name AS name, sample_data.description AS description) AS xml_data, pg_try_advisory_lock(sample_data.id::bigint) AS lock_acquired, sample_data.ctid AS row_ctid, sample_data.xmin AS xmin_value FROM public.sample_data", + "SqlStatement": "CREATE MATERIALIZED VIEW public.sample_data_view AS\n SELECT sample_data.id,\n sample_data.name,\n sample_data.description,\n XMLFOREST(sample_data.name AS name, sample_data.description AS description) AS xml_data,\n pg_try_advisory_lock((sample_data.id)::bigint) AS lock_acquired,\n sample_data.ctid AS row_ctid,\n sample_data.xmin AS xmin_value\n FROM public.sample_data\n WITH NO DATA;", "Suggestion": "", "GH": "", "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#advisory-locks-is-not-yet-implemented", "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "MVIEW", "ObjectName": "public.sample_data_view", "Reason": "System Columns", - "SqlStatement": "SELECT sample_data.id, sample_data.name, sample_data.description, xmlforest(sample_data.name AS name, sample_data.description AS description) AS xml_data, pg_try_advisory_lock(sample_data.id::bigint) AS lock_acquired, sample_data.ctid AS row_ctid, sample_data.xmin AS xmin_value FROM public.sample_data", + "SqlStatement": "CREATE MATERIALIZED VIEW public.sample_data_view AS\n SELECT sample_data.id,\n sample_data.name,\n sample_data.description,\n XMLFOREST(sample_data.name AS name, sample_data.description AS description) AS xml_data,\n pg_try_advisory_lock((sample_data.id)::bigint) AS lock_acquired,\n sample_data.ctid AS row_ctid,\n sample_data.xmin AS xmin_value\n FROM public.sample_data\n WITH NO DATA;", "Suggestion": "", "GH": "", "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#system-columns-is-not-yet-supported", "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "public.orders_view", "Reason": "XML Functions", - "SqlStatement": "SELECT orders.order_id, orders.customer_name, orders.product_name, orders.quantity, orders.price, xmlelement(name \"OrderDetails\", xmlelement(name \"Customer\", orders.customer_name), xmlelement(name \"Product\", orders.product_name), xmlelement(name \"Quantity\", orders.quantity), xmlelement(name \"TotalPrice\", orders.price * orders.quantity::numeric)) AS order_xml, xmlconcat(xmlelement(name \"Customer\", orders.customer_name), xmlelement(name \"Product\", orders.product_name)) AS summary_xml, pg_try_advisory_lock(hashtext(orders.customer_name || orders.product_name)::bigint) AS lock_acquired, orders.ctid AS row_ctid, orders.xmin AS transaction_id FROM public.orders", + "SqlStatement": "CREATE VIEW public.orders_view AS\n SELECT orders.order_id,\n orders.customer_name,\n orders.product_name,\n orders.quantity,\n orders.price,\n XMLELEMENT(NAME \"OrderDetails\", XMLELEMENT(NAME \"Customer\", orders.customer_name), XMLELEMENT(NAME \"Product\", orders.product_name), XMLELEMENT(NAME \"Quantity\", orders.quantity), XMLELEMENT(NAME \"TotalPrice\", (orders.price * (orders.quantity)::numeric))) AS order_xml,\n XMLCONCAT(XMLELEMENT(NAME \"Customer\", orders.customer_name), XMLELEMENT(NAME \"Product\", orders.product_name)) AS summary_xml,\n pg_try_advisory_lock((hashtext((orders.customer_name || orders.product_name)))::bigint) AS lock_acquired,\n orders.ctid AS row_ctid,\n orders.xmin AS transaction_id\n FROM public.orders;", "Suggestion": "", "GH": "", "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "public.orders_view", "Reason": "Advisory Locks", - "SqlStatement": "SELECT orders.order_id, orders.customer_name, orders.product_name, orders.quantity, orders.price, xmlelement(name \"OrderDetails\", xmlelement(name \"Customer\", orders.customer_name), xmlelement(name \"Product\", orders.product_name), xmlelement(name \"Quantity\", orders.quantity), xmlelement(name \"TotalPrice\", orders.price * orders.quantity::numeric)) AS order_xml, xmlconcat(xmlelement(name \"Customer\", orders.customer_name), xmlelement(name \"Product\", orders.product_name)) AS summary_xml, pg_try_advisory_lock(hashtext(orders.customer_name || orders.product_name)::bigint) AS lock_acquired, orders.ctid AS row_ctid, orders.xmin AS transaction_id FROM public.orders", + "SqlStatement": "CREATE VIEW public.orders_view AS\n SELECT orders.order_id,\n orders.customer_name,\n orders.product_name,\n orders.quantity,\n orders.price,\n XMLELEMENT(NAME \"OrderDetails\", XMLELEMENT(NAME \"Customer\", orders.customer_name), XMLELEMENT(NAME \"Product\", orders.product_name), XMLELEMENT(NAME \"Quantity\", orders.quantity), XMLELEMENT(NAME \"TotalPrice\", (orders.price * (orders.quantity)::numeric))) AS order_xml,\n XMLCONCAT(XMLELEMENT(NAME \"Customer\", orders.customer_name), XMLELEMENT(NAME \"Product\", orders.product_name)) AS summary_xml,\n pg_try_advisory_lock((hashtext((orders.customer_name || orders.product_name)))::bigint) AS lock_acquired,\n orders.ctid AS row_ctid,\n orders.xmin AS transaction_id\n FROM public.orders;", "Suggestion": "", "GH": "", "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#advisory-locks-is-not-yet-implemented", "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "public.orders_view", "Reason": "System Columns", - "SqlStatement": "SELECT orders.order_id, orders.customer_name, orders.product_name, orders.quantity, orders.price, xmlelement(name \"OrderDetails\", xmlelement(name \"Customer\", orders.customer_name), xmlelement(name \"Product\", orders.product_name), xmlelement(name \"Quantity\", orders.quantity), xmlelement(name \"TotalPrice\", orders.price * orders.quantity::numeric)) AS order_xml, xmlconcat(xmlelement(name \"Customer\", orders.customer_name), xmlelement(name \"Product\", orders.product_name)) AS summary_xml, pg_try_advisory_lock(hashtext(orders.customer_name || orders.product_name)::bigint) AS lock_acquired, orders.ctid AS row_ctid, orders.xmin AS transaction_id FROM public.orders", + "SqlStatement": "CREATE VIEW public.orders_view AS\n SELECT orders.order_id,\n orders.customer_name,\n orders.product_name,\n orders.quantity,\n orders.price,\n XMLELEMENT(NAME \"OrderDetails\", XMLELEMENT(NAME \"Customer\", orders.customer_name), XMLELEMENT(NAME \"Product\", orders.product_name), XMLELEMENT(NAME \"Quantity\", orders.quantity), XMLELEMENT(NAME \"TotalPrice\", (orders.price * (orders.quantity)::numeric))) AS order_xml,\n XMLCONCAT(XMLELEMENT(NAME \"Customer\", orders.customer_name), XMLELEMENT(NAME \"Product\", orders.product_name)) AS summary_xml,\n pg_try_advisory_lock((hashtext((orders.customer_name || orders.product_name)))::bigint) AS lock_acquired,\n orders.ctid AS row_ctid,\n orders.xmin AS transaction_id\n FROM public.orders;", "Suggestion": "", "GH": "", "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#system-columns-is-not-yet-supported", diff --git a/migtests/tests/analyze-schema/summary.json b/migtests/tests/analyze-schema/summary.json index 09b4ec3f2..e047b08fd 100644 --- a/migtests/tests/analyze-schema/summary.json +++ b/migtests/tests/analyze-schema/summary.json @@ -24,9 +24,9 @@ }, { "ObjectType": "TABLE", - "TotalCount": 49, + "TotalCount": 50, "InvalidCount": 33, - "ObjectNames": "combined_tbl1, test_arr_enum, public.locations, test_udt, combined_tbl, public.ts_query_table, public.documents, public.citext_type, public.inet_type, public.test_jsonb, test_xml_type, test_xid_type, public.range_columns_partition_test_copy, anydata_test, uritype_test, public.foreign_def_test, test_4, enum_example.bugs, table_abc, anydataset_test, unique_def_test1, test_2, table_1, public.range_columns_partition_test, table_xyz, public.users, test_3, test_5, test_7, foreign_def_test2, unique_def_test, sales_data, table_test, test_interval, test_non_pk_multi_column_list, test_9, test_8, order_details, public.employees4, anytype_test, public.meeting, test_table_in_type_file, sales, test_1, \"Test\", foreign_def_test1, salaries2, test_6, public.pr" }, + "ObjectNames": "public.xml_data_example, combined_tbl1, test_arr_enum, public.locations, test_udt, combined_tbl, public.ts_query_table, public.documents, public.citext_type, public.inet_type, public.test_jsonb, test_xml_type, test_xid_type, public.range_columns_partition_test_copy, anydata_test, uritype_test, public.foreign_def_test, test_4, enum_example.bugs, table_abc, anydataset_test, unique_def_test1, test_2, table_1, public.range_columns_partition_test, table_xyz, public.users, test_3, test_5, test_7, foreign_def_test2, unique_def_test, sales_data, table_test, test_interval, test_non_pk_multi_column_list, test_9, test_8, order_details, public.employees4, anytype_test, public.meeting, test_table_in_type_file, sales, test_1, \"Test\", foreign_def_test1, salaries2, test_6, public.pr" }, { "ObjectType": "INDEX", "TotalCount": 43, diff --git a/migtests/tests/pg/assessment-report-test/expectedAssessmentReport.json b/migtests/tests/pg/assessment-report-test/expectedAssessmentReport.json index 262923e0d..324ae5cc7 100644 --- a/migtests/tests/pg/assessment-report-test/expectedAssessmentReport.json +++ b/migtests/tests/pg/assessment-report-test/expectedAssessmentReport.json @@ -551,7 +551,40 @@ ], "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unlogged-table-is-not-supported", "MinimumVersionsFixedIn": null - } + }, + { + "FeatureName": "System Columns", + "Objects": [ + { + "ObjectName": "public.ordersentry_view", + "SqlStatement": "CREATE VIEW public.ordersentry_view AS\n SELECT ordersentry.order_id,\n ordersentry.customer_name,\n ordersentry.product_name,\n ordersentry.quantity,\n ordersentry.price,\n XMLELEMENT(NAME \"OrderDetails\", XMLELEMENT(NAME \"Customer\", ordersentry.customer_name), XMLELEMENT(NAME \"Product\", ordersentry.product_name), XMLELEMENT(NAME \"Quantity\", ordersentry.quantity), XMLELEMENT(NAME \"TotalPrice\", (ordersentry.price * (ordersentry.quantity)::numeric))) AS order_xml,\n XMLCONCAT(XMLELEMENT(NAME \"Customer\", ordersentry.customer_name), XMLELEMENT(NAME \"Product\", ordersentry.product_name)) AS summary_xml,\n pg_try_advisory_lock((hashtext((ordersentry.customer_name || ordersentry.product_name)))::bigint) AS lock_acquired,\n ordersentry.ctid AS row_ctid,\n ordersentry.xmin AS transaction_id\n FROM public.ordersentry;" + } + ], + "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#system-columns-is-not-yet-supported", + "MinimumVersionsFixedIn": null + }, + { + "FeatureName": "XML Functions", + "Objects": [ + { + "ObjectName": "public.ordersentry_view", + "SqlStatement": "CREATE VIEW public.ordersentry_view AS\n SELECT ordersentry.order_id,\n ordersentry.customer_name,\n ordersentry.product_name,\n ordersentry.quantity,\n ordersentry.price,\n XMLELEMENT(NAME \"OrderDetails\", XMLELEMENT(NAME \"Customer\", ordersentry.customer_name), XMLELEMENT(NAME \"Product\", ordersentry.product_name), XMLELEMENT(NAME \"Quantity\", ordersentry.quantity), XMLELEMENT(NAME \"TotalPrice\", (ordersentry.price * (ordersentry.quantity)::numeric))) AS order_xml,\n XMLCONCAT(XMLELEMENT(NAME \"Customer\", ordersentry.customer_name), XMLELEMENT(NAME \"Product\", ordersentry.product_name)) AS summary_xml,\n pg_try_advisory_lock((hashtext((ordersentry.customer_name || ordersentry.product_name)))::bigint) AS lock_acquired,\n ordersentry.ctid AS row_ctid,\n ordersentry.xmin AS transaction_id\n FROM public.ordersentry;" + } + ], + "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", + "MinimumVersionsFixedIn": null + }, + { + "FeatureName": "Advisory Locks", + "Objects": [ + { + "ObjectName": "public.ordersentry_view", + "SqlStatement": "CREATE VIEW public.ordersentry_view AS\n SELECT ordersentry.order_id,\n ordersentry.customer_name,\n ordersentry.product_name,\n ordersentry.quantity,\n ordersentry.price,\n XMLELEMENT(NAME \"OrderDetails\", XMLELEMENT(NAME \"Customer\", ordersentry.customer_name), XMLELEMENT(NAME \"Product\", ordersentry.product_name), XMLELEMENT(NAME \"Quantity\", ordersentry.quantity), XMLELEMENT(NAME \"TotalPrice\", (ordersentry.price * (ordersentry.quantity)::numeric))) AS order_xml,\n XMLCONCAT(XMLELEMENT(NAME \"Customer\", ordersentry.customer_name), XMLELEMENT(NAME \"Product\", ordersentry.product_name)) AS summary_xml,\n pg_try_advisory_lock((hashtext((ordersentry.customer_name || ordersentry.product_name)))::bigint) AS lock_acquired,\n ordersentry.ctid AS row_ctid,\n ordersentry.xmin AS transaction_id\n FROM public.ordersentry;" + } + ], + "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#advisory-locks-is-not-yet-implemented", + "MinimumVersionsFixedIn": null + } ], "UnsupportedFeaturesDesc": "Features of the source database that are not supported on the target YugabyteDB.", "TableIndexStats": [ @@ -2199,39 +2232,10 @@ "ObjectType": "FUNCTION", "ObjectName": "schema2.process_order", "SqlStatement": "SELECT pg_advisory_unlock(orderid);" - }, - { - "ObjectType": "VIEW", - "ObjectName": "public.ordersentry_view", - "SqlStatement": "SELECT ordersentry.order_id, ordersentry.customer_name, ordersentry.product_name, ordersentry.quantity, ordersentry.price, xmlelement(name \"OrderDetails\", xmlelement(name \"Customer\", ordersentry.customer_name), xmlelement(name \"Product\", ordersentry.product_name), xmlelement(name \"Quantity\", ordersentry.quantity), xmlelement(name \"TotalPrice\", ordersentry.price * ordersentry.quantity::numeric)) AS order_xml, xmlconcat(xmlelement(name \"Customer\", ordersentry.customer_name), xmlelement(name \"Product\", ordersentry.product_name)) AS summary_xml, pg_try_advisory_lock(hashtext(ordersentry.customer_name || ordersentry.product_name)::bigint) AS lock_acquired, ordersentry.ctid AS row_ctid, ordersentry.xmin AS transaction_id FROM public.ordersentry" } ], "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#advisory-locks-is-not-yet-implemented", "MinimumVersionsFixedIn": null - }, - { - "FeatureName": "XML Functions", - "Objects": [ - { - "ObjectType": "VIEW", - "ObjectName": "public.ordersentry_view", - "SqlStatement": "SELECT ordersentry.order_id, ordersentry.customer_name, ordersentry.product_name, ordersentry.quantity, ordersentry.price, xmlelement(name \"OrderDetails\", xmlelement(name \"Customer\", ordersentry.customer_name), xmlelement(name \"Product\", ordersentry.product_name), xmlelement(name \"Quantity\", ordersentry.quantity), xmlelement(name \"TotalPrice\", ordersentry.price * ordersentry.quantity::numeric)) AS order_xml, xmlconcat(xmlelement(name \"Customer\", ordersentry.customer_name), xmlelement(name \"Product\", ordersentry.product_name)) AS summary_xml, pg_try_advisory_lock(hashtext(ordersentry.customer_name || ordersentry.product_name)::bigint) AS lock_acquired, ordersentry.ctid AS row_ctid, ordersentry.xmin AS transaction_id FROM public.ordersentry" - } - ], - "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", - "MinimumVersionsFixedIn": null - }, - { - "FeatureName": "System Columns", - "Objects": [ - { - "ObjectType": "VIEW", - "ObjectName": "public.ordersentry_view", - "SqlStatement": "SELECT ordersentry.order_id, ordersentry.customer_name, ordersentry.product_name, ordersentry.quantity, ordersentry.price, xmlelement(name \"OrderDetails\", xmlelement(name \"Customer\", ordersentry.customer_name), xmlelement(name \"Product\", ordersentry.product_name), xmlelement(name \"Quantity\", ordersentry.quantity), xmlelement(name \"TotalPrice\", ordersentry.price * ordersentry.quantity::numeric)) AS order_xml, xmlconcat(xmlelement(name \"Customer\", ordersentry.customer_name), xmlelement(name \"Product\", ordersentry.product_name)) AS summary_xml, pg_try_advisory_lock(hashtext(ordersentry.customer_name || ordersentry.product_name)::bigint) AS lock_acquired, ordersentry.ctid AS row_ctid, ordersentry.xmin AS transaction_id FROM public.ordersentry" - } - ], - "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#system-columns-is-not-yet-supported", - "MinimumVersionsFixedIn": null - } + } ] } \ No newline at end of file From c52834663da642cd3fad50457052f9b623b4a913 Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Tue, 10 Dec 2024 18:21:11 +0530 Subject: [PATCH 05/10] minor change --- yb-voyager/src/queryissue/queryissue.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/yb-voyager/src/queryissue/queryissue.go b/yb-voyager/src/queryissue/queryissue.go index 259ab874e..190f2c136 100644 --- a/yb-voyager/src/queryissue/queryissue.go +++ b/yb-voyager/src/queryissue/queryissue.go @@ -265,9 +265,6 @@ func (p *ParserIssueDetector) getDDLIssues(query string) ([]issue.IssueInstance, return nil, fmt.Errorf("error detecting issues: %w", err) } - if _, ok := ddlObj.(*queryparser.Object); ok { // In case the DDL doesn't have any processor skip checking generic issues - return issues, nil - } // Add the original query to each issue for i := range issues { if issues[i].SqlStatement == "" { @@ -275,6 +272,10 @@ func (p *ParserIssueDetector) getDDLIssues(query string) ([]issue.IssueInstance, } } + if _, ok := ddlObj.(*queryparser.Object); ok { // In case the DDL doesn't have any processor skip checking generic issues + return issues, nil + } + genericIssues, err := p.genericIssues(query) if err != nil { return nil, fmt.Errorf("error getting generic issues: %w", err) From 9e0c2659d98c0f4217a18521cbe90bd890db684f Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Wed, 11 Dec 2024 16:48:00 +0530 Subject: [PATCH 06/10] update expected assessment report for pg complex schemas --- .../expectedAssessmentReport.json | 99 ++++++++++--------- .../expected_schema_analysis_report.json | 32 +++--- .../expectedAssessmentReport.json | 15 +++ .../expectedAssessmentReport.json | 15 +++ .../expectedAssessmentReport.json | 15 +++ .../expectedAssessmentReport.json | 15 +++ .../expectedAssessmentReport.json | 15 +++ .../expectedAssessmentReport.json | 15 +++ .../expectedAssessmentReport.json | 15 +++ .../expectedAssessmentReport.json | 15 +++ 10 files changed, 186 insertions(+), 65 deletions(-) diff --git a/migtests/tests/pg/adventureworks/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/adventureworks/expected_files/expectedAssessmentReport.json index 842f993a5..ceecd2595 100755 --- a/migtests/tests/pg/adventureworks/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/adventureworks/expected_files/expectedAssessmentReport.json @@ -648,6 +648,55 @@ "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unsupported-alter-table-ddl-variants-in-source-schema", "MinimumVersionsFixedIn": null }, + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [ + { + "ObjectName": "humanresources.vjobcandidate", + "SqlStatement": "CREATE VIEW humanresources.vjobcandidate AS\n SELECT jobcandidate.jobcandidateid,\n jobcandidate.businessentityid,\n ((xpath('/n:Resume/n:Name/n:Name.Prefix/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.Prefix\",\n ((xpath('/n:Resume/n:Name/n:Name.First/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.First\",\n ((xpath('/n:Resume/n:Name/n:Name.Middle/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.Middle\",\n ((xpath('/n:Resume/n:Name/n:Name.Last/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.Last\",\n ((xpath('/n:Resume/n:Name/n:Name.Suffix/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.Suffix\",\n ((xpath('/n:Resume/n:Skills/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying AS \"Skills\",\n ((xpath('n:Address/n:Addr.Type/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Addr.Type\",\n ((xpath('n:Address/n:Addr.Location/n:Location/n:Loc.CountryRegion/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(100) AS \"Addr.Loc.CountryRegion\",\n ((xpath('n:Address/n:Addr.Location/n:Location/n:Loc.State/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(100) AS \"Addr.Loc.State\",\n ((xpath('n:Address/n:Addr.Location/n:Location/n:Loc.City/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(100) AS \"Addr.Loc.City\",\n ((xpath('n:Address/n:Addr.PostalCode/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(20) AS \"Addr.PostalCode\",\n ((xpath('/n:Resume/n:EMail/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying AS \"EMail\",\n ((xpath('/n:Resume/n:WebSite/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying AS \"WebSite\",\n jobcandidate.modifieddate\n FROM humanresources.jobcandidate;" + }, + { + "ObjectName": "humanresources.vjobcandidateeducation", + "SqlStatement": "CREATE VIEW humanresources.vjobcandidateeducation AS\n SELECT jc.jobcandidateid,\n ((xpath('/root/ns:Education/ns:Edu.Level/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(50) AS \"Edu.Level\",\n (((xpath('/root/ns:Education/ns:Edu.StartDate/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(20))::date AS \"Edu.StartDate\",\n (((xpath('/root/ns:Education/ns:Edu.EndDate/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(20))::date AS \"Edu.EndDate\",\n ((xpath('/root/ns:Education/ns:Edu.Degree/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(50) AS \"Edu.Degree\",\n ((xpath('/root/ns:Education/ns:Edu.Major/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(50) AS \"Edu.Major\",\n ((xpath('/root/ns:Education/ns:Edu.Minor/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(50) AS \"Edu.Minor\",\n ((xpath('/root/ns:Education/ns:Edu.GPA/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(5) AS \"Edu.GPA\",\n ((xpath('/root/ns:Education/ns:Edu.GPAScale/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(5) AS \"Edu.GPAScale\",\n ((xpath('/root/ns:Education/ns:Edu.School/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(100) AS \"Edu.School\",\n ((xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.CountryRegion/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(100) AS \"Edu.Loc.CountryRegion\",\n ((xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.State/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(100) AS \"Edu.Loc.State\",\n ((xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.City/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(100) AS \"Edu.Loc.City\"\n FROM ( SELECT unnesting.jobcandidateid,\n ((('\u003croot xmlns:ns=\"http://adventureworks.com\"\u003e'::text || ((unnesting.education)::character varying)::text) || '\u003c/root\u003e'::text))::xml AS doc\n FROM ( SELECT jobcandidate.jobcandidateid,\n unnest(xpath('/ns:Resume/ns:Education'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])) AS education\n FROM humanresources.jobcandidate) unnesting) jc;" + }, + { + "ObjectName": "humanresources.vjobcandidateemployment", + "SqlStatement": "CREATE VIEW humanresources.vjobcandidateemployment AS\n SELECT jobcandidate.jobcandidateid,\n ((unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.StartDate/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying(20))::date AS \"Emp.StartDate\",\n ((unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.EndDate/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying(20))::date AS \"Emp.EndDate\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.OrgName/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying(100) AS \"Emp.OrgName\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.JobTitle/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying(100) AS \"Emp.JobTitle\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Responsibility/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.Responsibility\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.FunctionCategory/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.FunctionCategory\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.IndustryCategory/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.IndustryCategory\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.CountryRegion/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.Loc.CountryRegion\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.State/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.Loc.State\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.City/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.Loc.City\"\n FROM humanresources.jobcandidate;" + }, + { + "ObjectName": "person.vadditionalcontactinfo", + "SqlStatement": "CREATE VIEW person.vadditionalcontactinfo AS\n SELECT p.businessentityid,\n p.firstname,\n p.middlename,\n p.lastname,\n (xpath('(act:telephoneNumber)[1]/act:number/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS telephonenumber,\n btrim((((xpath('(act:telephoneNumber)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1])::character varying)::text) AS telephonespecialinstructions,\n (xpath('(act:homePostalAddress)[1]/act:Street/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS street,\n (xpath('(act:homePostalAddress)[1]/act:City/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS city,\n (xpath('(act:homePostalAddress)[1]/act:StateProvince/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS stateprovince,\n (xpath('(act:homePostalAddress)[1]/act:PostalCode/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS postalcode,\n (xpath('(act:homePostalAddress)[1]/act:CountryRegion/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS countryregion,\n (xpath('(act:homePostalAddress)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS homeaddressspecialinstructions,\n (xpath('(act:eMail)[1]/act:eMailAddress/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS emailaddress,\n btrim((((xpath('(act:eMail)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1])::character varying)::text) AS emailspecialinstructions,\n (xpath('((act:eMail)[1]/act:SpecialInstructions/act:telephoneNumber)[1]/act:number/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS emailtelephonenumber,\n p.rowguid,\n p.modifieddate\n FROM (person.person p\n LEFT JOIN ( SELECT person.businessentityid,\n unnest(xpath('/ci:AdditionalContactInfo'::text, person.additionalcontactinfo, '{{ci,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo}}'::text[])) AS node\n FROM person.person\n WHERE (person.additionalcontactinfo IS NOT NULL)) additional ON ((p.businessentityid = additional.businessentityid)));" + }, + { + "ObjectName": "production.vproductmodelcatalogdescription", + "SqlStatement": "CREATE VIEW production.vproductmodelcatalogdescription AS\n SELECT productmodel.productmodelid,\n productmodel.name,\n ((xpath('/p1:ProductDescription/p1:Summary/html:p/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{html,http://www.w3.org/1999/xhtml}}'::text[]))[1])::character varying AS \"Summary\",\n ((xpath('/p1:ProductDescription/p1:Manufacturer/p1:Name/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying AS manufacturer,\n ((xpath('/p1:ProductDescription/p1:Manufacturer/p1:Copyright/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(30) AS copyright,\n ((xpath('/p1:ProductDescription/p1:Manufacturer/p1:ProductURL/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS producturl,\n ((xpath('/p1:ProductDescription/p1:Features/wm:Warranty/wm:WarrantyPeriod/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1])::character varying(256) AS warrantyperiod,\n ((xpath('/p1:ProductDescription/p1:Features/wm:Warranty/wm:Description/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1])::character varying(256) AS warrantydescription,\n ((xpath('/p1:ProductDescription/p1:Features/wm:Maintenance/wm:NoOfYears/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1])::character varying(256) AS noofyears,\n ((xpath('/p1:ProductDescription/p1:Features/wm:Maintenance/wm:Description/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1])::character varying(256) AS maintenancedescription,\n ((xpath('/p1:ProductDescription/p1:Features/wf:wheel/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying(256) AS wheel,\n ((xpath('/p1:ProductDescription/p1:Features/wf:saddle/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying(256) AS saddle,\n ((xpath('/p1:ProductDescription/p1:Features/wf:pedal/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying(256) AS pedal,\n ((xpath('/p1:ProductDescription/p1:Features/wf:BikeFrame/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying AS bikeframe,\n ((xpath('/p1:ProductDescription/p1:Features/wf:crankset/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying(256) AS crankset,\n ((xpath('/p1:ProductDescription/p1:Picture/p1:Angle/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS pictureangle,\n ((xpath('/p1:ProductDescription/p1:Picture/p1:Size/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS picturesize,\n ((xpath('/p1:ProductDescription/p1:Picture/p1:ProductPhotoID/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS productphotoid,\n ((xpath('/p1:ProductDescription/p1:Specifications/Material/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS material,\n ((xpath('/p1:ProductDescription/p1:Specifications/Color/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS color,\n ((xpath('/p1:ProductDescription/p1:Specifications/ProductLine/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS productline,\n ((xpath('/p1:ProductDescription/p1:Specifications/Style/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS style,\n ((xpath('/p1:ProductDescription/p1:Specifications/RiderExperience/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(1024) AS riderexperience,\n productmodel.rowguid,\n productmodel.modifieddate\n FROM production.productmodel\n WHERE (productmodel.catalogdescription IS NOT NULL);" + }, + { + "ObjectName": "production.vproductmodelinstructions", + "SqlStatement": "CREATE VIEW production.vproductmodelinstructions AS\n SELECT pm.productmodelid,\n pm.name,\n ((xpath('/ns:root/text()'::text, pm.instructions, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions}}'::text[]))[1])::character varying AS instructions,\n (((xpath('@LocationID'::text, pm.mfginstructions))[1])::character varying)::integer AS \"LocationID\",\n (((xpath('@SetupHours'::text, pm.mfginstructions))[1])::character varying)::numeric(9,4) AS \"SetupHours\",\n (((xpath('@MachineHours'::text, pm.mfginstructions))[1])::character varying)::numeric(9,4) AS \"MachineHours\",\n (((xpath('@LaborHours'::text, pm.mfginstructions))[1])::character varying)::numeric(9,4) AS \"LaborHours\",\n (((xpath('@LotSize'::text, pm.mfginstructions))[1])::character varying)::integer AS \"LotSize\",\n ((xpath('/step/text()'::text, pm.step))[1])::character varying(1024) AS \"Step\",\n pm.rowguid,\n pm.modifieddate\n FROM ( SELECT locations.productmodelid,\n locations.name,\n locations.rowguid,\n locations.modifieddate,\n locations.instructions,\n locations.mfginstructions,\n unnest(xpath('step'::text, locations.mfginstructions)) AS step\n FROM ( SELECT productmodel.productmodelid,\n productmodel.name,\n productmodel.rowguid,\n productmodel.modifieddate,\n productmodel.instructions,\n unnest(xpath('/ns:root/ns:Location'::text, productmodel.instructions, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions}}'::text[])) AS mfginstructions\n FROM production.productmodel) locations) pm;" + }, + { + "ObjectName": "sales.vpersondemographics", + "SqlStatement": "CREATE VIEW sales.vpersondemographics AS\n SELECT person.businessentityid,\n (((xpath('n:TotalPurchaseYTD/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::money AS totalpurchaseytd,\n (((xpath('n:DateFirstPurchase/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::date AS datefirstpurchase,\n (((xpath('n:BirthDate/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::date AS birthdate,\n ((xpath('n:MaritalStatus/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(1) AS maritalstatus,\n ((xpath('n:YearlyIncome/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(30) AS yearlyincome,\n ((xpath('n:Gender/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(1) AS gender,\n (((xpath('n:TotalChildren/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::integer AS totalchildren,\n (((xpath('n:NumberChildrenAtHome/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::integer AS numberchildrenathome,\n ((xpath('n:Education/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(30) AS education,\n ((xpath('n:Occupation/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(30) AS occupation,\n (((xpath('n:HomeOwnerFlag/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::boolean AS homeownerflag,\n (((xpath('n:NumberCarsOwned/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::integer AS numbercarsowned\n FROM person.person\n WHERE (person.demographics IS NOT NULL);" + }, + { + "ObjectName": "sales.vstorewithdemographics", + "SqlStatement": "CREATE VIEW sales.vstorewithdemographics AS\n SELECT store.businessentityid,\n store.name,\n ((unnest(xpath('/ns:StoreSurvey/ns:AnnualSales/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::money AS \"AnnualSales\",\n ((unnest(xpath('/ns:StoreSurvey/ns:AnnualRevenue/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::money AS \"AnnualRevenue\",\n (unnest(xpath('/ns:StoreSurvey/ns:BankName/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(50) AS \"BankName\",\n (unnest(xpath('/ns:StoreSurvey/ns:BusinessType/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(5) AS \"BusinessType\",\n ((unnest(xpath('/ns:StoreSurvey/ns:YearOpened/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::integer AS \"YearOpened\",\n (unnest(xpath('/ns:StoreSurvey/ns:Specialty/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(50) AS \"Specialty\",\n ((unnest(xpath('/ns:StoreSurvey/ns:SquareFeet/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::integer AS \"SquareFeet\",\n (unnest(xpath('/ns:StoreSurvey/ns:Brands/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(30) AS \"Brands\",\n (unnest(xpath('/ns:StoreSurvey/ns:Internet/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(30) AS \"Internet\",\n ((unnest(xpath('/ns:StoreSurvey/ns:NumberEmployees/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::integer AS \"NumberEmployees\"\n FROM sales.store;" + } + ], + "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", + "MinimumVersionsFixedIn": null + }, { "FeatureName": "Storage parameters in DDLs", "Objects": [], @@ -1736,53 +1785,5 @@ } ], "UnsupportedQueryConstructs": null, - "UnsupportedPlPgSqlObjects": [ - { - "FeatureName": "XML Functions", - "Objects": [ - { - "ObjectType": "VIEW", - "ObjectName": "humanresources.vjobcandidate", - "SqlStatement": "SELECT jobcandidate.jobcandidateid, jobcandidate.businessentityid, (xpath('/n:Resume/n:Name/n:Name.Prefix/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.Prefix\", (xpath('/n:Resume/n:Name/n:Name.First/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.First\", (xpath('/n:Resume/n:Name/n:Name.Middle/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.Middle\", (xpath('/n:Resume/n:Name/n:Name.Last/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.Last\", (xpath('/n:Resume/n:Name/n:Name.Suffix/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.Suffix\", (xpath('/n:Resume/n:Skills/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar AS \"Skills\", (xpath('n:Address/n:Addr.Type/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Addr.Type\", (xpath('n:Address/n:Addr.Location/n:Location/n:Loc.CountryRegion/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(100) AS \"Addr.Loc.CountryRegion\", (xpath('n:Address/n:Addr.Location/n:Location/n:Loc.State/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(100) AS \"Addr.Loc.State\", (xpath('n:Address/n:Addr.Location/n:Location/n:Loc.City/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(100) AS \"Addr.Loc.City\", (xpath('n:Address/n:Addr.PostalCode/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(20) AS \"Addr.PostalCode\", (xpath('/n:Resume/n:EMail/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar AS \"EMail\", (xpath('/n:Resume/n:WebSite/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar AS \"WebSite\", jobcandidate.modifieddate FROM humanresources.jobcandidate" - }, - { - "ObjectType": "VIEW", - "ObjectName": "humanresources.vjobcandidateeducation", - "SqlStatement": "SELECT jc.jobcandidateid, (xpath('/root/ns:Education/ns:Edu.Level/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(50) AS \"Edu.Level\", (xpath('/root/ns:Education/ns:Edu.StartDate/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(20)::date AS \"Edu.StartDate\", (xpath('/root/ns:Education/ns:Edu.EndDate/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(20)::date AS \"Edu.EndDate\", (xpath('/root/ns:Education/ns:Edu.Degree/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(50) AS \"Edu.Degree\", (xpath('/root/ns:Education/ns:Edu.Major/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(50) AS \"Edu.Major\", (xpath('/root/ns:Education/ns:Edu.Minor/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(50) AS \"Edu.Minor\", (xpath('/root/ns:Education/ns:Edu.GPA/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(5) AS \"Edu.GPA\", (xpath('/root/ns:Education/ns:Edu.GPAScale/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(5) AS \"Edu.GPAScale\", (xpath('/root/ns:Education/ns:Edu.School/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(100) AS \"Edu.School\", (xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.CountryRegion/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(100) AS \"Edu.Loc.CountryRegion\", (xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.State/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(100) AS \"Edu.Loc.State\", (xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.City/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(100) AS \"Edu.Loc.City\" FROM (SELECT unnesting.jobcandidateid, CAST(('\u003croot xmlns:ns=\"http://adventureworks.com\"\u003e'::text || unnesting.education::varchar::text) || '\u003c/root\u003e'::text AS xml) AS doc FROM (SELECT jobcandidate.jobcandidateid, unnest(xpath('/ns:Resume/ns:Education'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])) AS education FROM humanresources.jobcandidate) unnesting) jc" - }, - { - "ObjectType": "VIEW", - "ObjectName": "humanresources.vjobcandidateemployment", - "SqlStatement": "SELECT jobcandidate.jobcandidateid, unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.StartDate/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar(20)::date AS \"Emp.StartDate\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.EndDate/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar(20)::date AS \"Emp.EndDate\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.OrgName/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar(100) AS \"Emp.OrgName\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.JobTitle/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar(100) AS \"Emp.JobTitle\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Responsibility/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.Responsibility\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.FunctionCategory/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.FunctionCategory\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.IndustryCategory/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.IndustryCategory\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.CountryRegion/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.Loc.CountryRegion\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.State/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.Loc.State\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.City/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.Loc.City\" FROM humanresources.jobcandidate" - }, - { - "ObjectType": "VIEW", - "ObjectName": "person.vadditionalcontactinfo", - "SqlStatement": "SELECT p.businessentityid, p.firstname, p.middlename, p.lastname, (xpath('(act:telephoneNumber)[1]/act:number/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS telephonenumber, btrim((xpath('(act:telephoneNumber)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1]::varchar::text) AS telephonespecialinstructions, (xpath('(act:homePostalAddress)[1]/act:Street/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS street, (xpath('(act:homePostalAddress)[1]/act:City/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS city, (xpath('(act:homePostalAddress)[1]/act:StateProvince/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS stateprovince, (xpath('(act:homePostalAddress)[1]/act:PostalCode/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS postalcode, (xpath('(act:homePostalAddress)[1]/act:CountryRegion/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS countryregion, (xpath('(act:homePostalAddress)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS homeaddressspecialinstructions, (xpath('(act:eMail)[1]/act:eMailAddress/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS emailaddress, btrim((xpath('(act:eMail)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1]::varchar::text) AS emailspecialinstructions, (xpath('((act:eMail)[1]/act:SpecialInstructions/act:telephoneNumber)[1]/act:number/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS emailtelephonenumber, p.rowguid, p.modifieddate FROM person.person p LEFT JOIN (SELECT person.businessentityid, unnest(xpath('/ci:AdditionalContactInfo'::text, person.additionalcontactinfo, '{{ci,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo}}'::text[])) AS node FROM person.person WHERE person.additionalcontactinfo IS NOT NULL) additional ON p.businessentityid = additional.businessentityid" - }, - { - "ObjectType": "VIEW", - "ObjectName": "production.vproductmodelcatalogdescription", - "SqlStatement": "SELECT productmodel.productmodelid, productmodel.name, (xpath('/p1:ProductDescription/p1:Summary/html:p/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{html,http://www.w3.org/1999/xhtml}}'::text[]))[1]::varchar AS \"Summary\", (xpath('/p1:ProductDescription/p1:Manufacturer/p1:Name/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar AS manufacturer, (xpath('/p1:ProductDescription/p1:Manufacturer/p1:Copyright/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(30) AS copyright, (xpath('/p1:ProductDescription/p1:Manufacturer/p1:ProductURL/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS producturl, (xpath('/p1:ProductDescription/p1:Features/wm:Warranty/wm:WarrantyPeriod/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1]::varchar(256) AS warrantyperiod, (xpath('/p1:ProductDescription/p1:Features/wm:Warranty/wm:Description/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1]::varchar(256) AS warrantydescription, (xpath('/p1:ProductDescription/p1:Features/wm:Maintenance/wm:NoOfYears/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1]::varchar(256) AS noofyears, (xpath('/p1:ProductDescription/p1:Features/wm:Maintenance/wm:Description/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1]::varchar(256) AS maintenancedescription, (xpath('/p1:ProductDescription/p1:Features/wf:wheel/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar(256) AS wheel, (xpath('/p1:ProductDescription/p1:Features/wf:saddle/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar(256) AS saddle, (xpath('/p1:ProductDescription/p1:Features/wf:pedal/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar(256) AS pedal, (xpath('/p1:ProductDescription/p1:Features/wf:BikeFrame/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar AS bikeframe, (xpath('/p1:ProductDescription/p1:Features/wf:crankset/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar(256) AS crankset, (xpath('/p1:ProductDescription/p1:Picture/p1:Angle/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS pictureangle, (xpath('/p1:ProductDescription/p1:Picture/p1:Size/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS picturesize, (xpath('/p1:ProductDescription/p1:Picture/p1:ProductPhotoID/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS productphotoid, (xpath('/p1:ProductDescription/p1:Specifications/Material/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS material, (xpath('/p1:ProductDescription/p1:Specifications/Color/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS color, (xpath('/p1:ProductDescription/p1:Specifications/ProductLine/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS productline, (xpath('/p1:ProductDescription/p1:Specifications/Style/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS style, (xpath('/p1:ProductDescription/p1:Specifications/RiderExperience/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(1024) AS riderexperience, productmodel.rowguid, productmodel.modifieddate FROM production.productmodel WHERE productmodel.catalogdescription IS NOT NULL" - }, - { - "ObjectType": "VIEW", - "ObjectName": "production.vproductmodelinstructions", - "SqlStatement": "SELECT pm.productmodelid, pm.name, (xpath('/ns:root/text()'::text, pm.instructions, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions}}'::text[]))[1]::varchar AS instructions, (xpath('@LocationID'::text, pm.mfginstructions))[1]::varchar::int AS \"LocationID\", (xpath('@SetupHours'::text, pm.mfginstructions))[1]::varchar::numeric(9, 4) AS \"SetupHours\", (xpath('@MachineHours'::text, pm.mfginstructions))[1]::varchar::numeric(9, 4) AS \"MachineHours\", (xpath('@LaborHours'::text, pm.mfginstructions))[1]::varchar::numeric(9, 4) AS \"LaborHours\", (xpath('@LotSize'::text, pm.mfginstructions))[1]::varchar::int AS \"LotSize\", (xpath('/step/text()'::text, pm.step))[1]::varchar(1024) AS \"Step\", pm.rowguid, pm.modifieddate FROM (SELECT locations.productmodelid, locations.name, locations.rowguid, locations.modifieddate, locations.instructions, locations.mfginstructions, unnest(xpath('step'::text, locations.mfginstructions)) AS step FROM (SELECT productmodel.productmodelid, productmodel.name, productmodel.rowguid, productmodel.modifieddate, productmodel.instructions, unnest(xpath('/ns:root/ns:Location'::text, productmodel.instructions, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions}}'::text[])) AS mfginstructions FROM production.productmodel) locations) pm" - }, - { - "ObjectType": "VIEW", - "ObjectName": "sales.vpersondemographics", - "SqlStatement": "SELECT person.businessentityid, (xpath('n:TotalPurchaseYTD/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::money AS totalpurchaseytd, (xpath('n:DateFirstPurchase/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::date AS datefirstpurchase, (xpath('n:BirthDate/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::date AS birthdate, (xpath('n:MaritalStatus/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(1) AS maritalstatus, (xpath('n:YearlyIncome/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(30) AS yearlyincome, (xpath('n:Gender/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(1) AS gender, (xpath('n:TotalChildren/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::int AS totalchildren, (xpath('n:NumberChildrenAtHome/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::int AS numberchildrenathome, (xpath('n:Education/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(30) AS education, (xpath('n:Occupation/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(30) AS occupation, (xpath('n:HomeOwnerFlag/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::boolean AS homeownerflag, (xpath('n:NumberCarsOwned/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::int AS numbercarsowned FROM person.person WHERE person.demographics IS NOT NULL" - }, - { - "ObjectType": "VIEW", - "ObjectName": "sales.vstorewithdemographics", - "SqlStatement": "SELECT store.businessentityid, store.name, unnest(xpath('/ns:StoreSurvey/ns:AnnualSales/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::money AS \"AnnualSales\", unnest(xpath('/ns:StoreSurvey/ns:AnnualRevenue/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::money AS \"AnnualRevenue\", unnest(xpath('/ns:StoreSurvey/ns:BankName/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(50) AS \"BankName\", unnest(xpath('/ns:StoreSurvey/ns:BusinessType/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(5) AS \"BusinessType\", unnest(xpath('/ns:StoreSurvey/ns:YearOpened/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::int AS \"YearOpened\", unnest(xpath('/ns:StoreSurvey/ns:Specialty/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(50) AS \"Specialty\", unnest(xpath('/ns:StoreSurvey/ns:SquareFeet/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::int AS \"SquareFeet\", unnest(xpath('/ns:StoreSurvey/ns:Brands/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(30) AS \"Brands\", unnest(xpath('/ns:StoreSurvey/ns:Internet/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(30) AS \"Internet\", unnest(xpath('/ns:StoreSurvey/ns:NumberEmployees/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::int AS \"NumberEmployees\" FROM sales.store" - } - ], - "DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", - "MinimumVersionsFixedIn": null - } - ] + "UnsupportedPlPgSqlObjects": null } diff --git a/migtests/tests/pg/adventureworks/expected_files/expected_schema_analysis_report.json b/migtests/tests/pg/adventureworks/expected_files/expected_schema_analysis_report.json index 5e8900e50..728396eb1 100755 --- a/migtests/tests/pg/adventureworks/expected_files/expected_schema_analysis_report.json +++ b/migtests/tests/pg/adventureworks/expected_files/expected_schema_analysis_report.json @@ -972,11 +972,11 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "humanresources.vjobcandidate", "Reason": "XML Functions", - "SqlStatement": "SELECT jobcandidate.jobcandidateid, jobcandidate.businessentityid, (xpath('/n:Resume/n:Name/n:Name.Prefix/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.Prefix\", (xpath('/n:Resume/n:Name/n:Name.First/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.First\", (xpath('/n:Resume/n:Name/n:Name.Middle/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.Middle\", (xpath('/n:Resume/n:Name/n:Name.Last/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.Last\", (xpath('/n:Resume/n:Name/n:Name.Suffix/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Name.Suffix\", (xpath('/n:Resume/n:Skills/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar AS \"Skills\", (xpath('n:Address/n:Addr.Type/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(30) AS \"Addr.Type\", (xpath('n:Address/n:Addr.Location/n:Location/n:Loc.CountryRegion/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(100) AS \"Addr.Loc.CountryRegion\", (xpath('n:Address/n:Addr.Location/n:Location/n:Loc.State/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(100) AS \"Addr.Loc.State\", (xpath('n:Address/n:Addr.Location/n:Location/n:Loc.City/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(100) AS \"Addr.Loc.City\", (xpath('n:Address/n:Addr.PostalCode/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar(20) AS \"Addr.PostalCode\", (xpath('/n:Resume/n:EMail/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar AS \"EMail\", (xpath('/n:Resume/n:WebSite/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1]::varchar AS \"WebSite\", jobcandidate.modifieddate FROM humanresources.jobcandidate", + "SqlStatement": "CREATE VIEW humanresources.vjobcandidate AS\n SELECT jobcandidate.jobcandidateid,\n jobcandidate.businessentityid,\n ((xpath('/n:Resume/n:Name/n:Name.Prefix/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.Prefix\",\n ((xpath('/n:Resume/n:Name/n:Name.First/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.First\",\n ((xpath('/n:Resume/n:Name/n:Name.Middle/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.Middle\",\n ((xpath('/n:Resume/n:Name/n:Name.Last/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.Last\",\n ((xpath('/n:Resume/n:Name/n:Name.Suffix/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Name.Suffix\",\n ((xpath('/n:Resume/n:Skills/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying AS \"Skills\",\n ((xpath('n:Address/n:Addr.Type/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(30) AS \"Addr.Type\",\n ((xpath('n:Address/n:Addr.Location/n:Location/n:Loc.CountryRegion/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(100) AS \"Addr.Loc.CountryRegion\",\n ((xpath('n:Address/n:Addr.Location/n:Location/n:Loc.State/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(100) AS \"Addr.Loc.State\",\n ((xpath('n:Address/n:Addr.Location/n:Location/n:Loc.City/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(100) AS \"Addr.Loc.City\",\n ((xpath('n:Address/n:Addr.PostalCode/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying(20) AS \"Addr.PostalCode\",\n ((xpath('/n:Resume/n:EMail/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying AS \"EMail\",\n ((xpath('/n:Resume/n:WebSite/text()'::text, jobcandidate.resume, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))[1])::character varying AS \"WebSite\",\n jobcandidate.modifieddate\n FROM humanresources.jobcandidate;", "FilePath": "/Users/priyanshigupta/Documents/voyager/yb-voyager/migtests/tests/pg/adventureworks/export-dir/schema/views/view.sql", "Suggestion": "", "GH": "", @@ -984,11 +984,11 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "humanresources.vjobcandidateeducation", "Reason": "XML Functions", - "SqlStatement": "SELECT jc.jobcandidateid, (xpath('/root/ns:Education/ns:Edu.Level/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(50) AS \"Edu.Level\", (xpath('/root/ns:Education/ns:Edu.StartDate/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(20)::date AS \"Edu.StartDate\", (xpath('/root/ns:Education/ns:Edu.EndDate/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(20)::date AS \"Edu.EndDate\", (xpath('/root/ns:Education/ns:Edu.Degree/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(50) AS \"Edu.Degree\", (xpath('/root/ns:Education/ns:Edu.Major/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(50) AS \"Edu.Major\", (xpath('/root/ns:Education/ns:Edu.Minor/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(50) AS \"Edu.Minor\", (xpath('/root/ns:Education/ns:Edu.GPA/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(5) AS \"Edu.GPA\", (xpath('/root/ns:Education/ns:Edu.GPAScale/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(5) AS \"Edu.GPAScale\", (xpath('/root/ns:Education/ns:Edu.School/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(100) AS \"Edu.School\", (xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.CountryRegion/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(100) AS \"Edu.Loc.CountryRegion\", (xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.State/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(100) AS \"Edu.Loc.State\", (xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.City/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1]::varchar(100) AS \"Edu.Loc.City\" FROM (SELECT unnesting.jobcandidateid, CAST(('\u003croot xmlns:ns=\"http://adventureworks.com\"\u003e'::text || unnesting.education::varchar::text) || '\u003c/root\u003e'::text AS xml) AS doc FROM (SELECT jobcandidate.jobcandidateid, unnest(xpath('/ns:Resume/ns:Education'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])) AS education FROM humanresources.jobcandidate) unnesting) jc", + "SqlStatement": "CREATE VIEW humanresources.vjobcandidateeducation AS\n SELECT jc.jobcandidateid,\n ((xpath('/root/ns:Education/ns:Edu.Level/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(50) AS \"Edu.Level\",\n (((xpath('/root/ns:Education/ns:Edu.StartDate/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(20))::date AS \"Edu.StartDate\",\n (((xpath('/root/ns:Education/ns:Edu.EndDate/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(20))::date AS \"Edu.EndDate\",\n ((xpath('/root/ns:Education/ns:Edu.Degree/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(50) AS \"Edu.Degree\",\n ((xpath('/root/ns:Education/ns:Edu.Major/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(50) AS \"Edu.Major\",\n ((xpath('/root/ns:Education/ns:Edu.Minor/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(50) AS \"Edu.Minor\",\n ((xpath('/root/ns:Education/ns:Edu.GPA/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(5) AS \"Edu.GPA\",\n ((xpath('/root/ns:Education/ns:Edu.GPAScale/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(5) AS \"Edu.GPAScale\",\n ((xpath('/root/ns:Education/ns:Edu.School/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(100) AS \"Edu.School\",\n ((xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.CountryRegion/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(100) AS \"Edu.Loc.CountryRegion\",\n ((xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.State/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(100) AS \"Edu.Loc.State\",\n ((xpath('/root/ns:Education/ns:Edu.Location/ns:Location/ns:Loc.City/text()'::text, jc.doc, '{{ns,http://adventureworks.com}}'::text[]))[1])::character varying(100) AS \"Edu.Loc.City\"\n FROM ( SELECT unnesting.jobcandidateid,\n ((('\u003croot xmlns:ns=\"http://adventureworks.com\"\u003e'::text || ((unnesting.education)::character varying)::text) || '\u003c/root\u003e'::text))::xml AS doc\n FROM ( SELECT jobcandidate.jobcandidateid,\n unnest(xpath('/ns:Resume/ns:Education'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])) AS education\n FROM humanresources.jobcandidate) unnesting) jc;", "FilePath": "/Users/priyanshigupta/Documents/voyager/yb-voyager/migtests/tests/pg/adventureworks/export-dir/schema/views/view.sql", "Suggestion": "", "GH": "", @@ -996,11 +996,11 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "humanresources.vjobcandidateemployment", "Reason": "XML Functions", - "SqlStatement": "SELECT jobcandidate.jobcandidateid, unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.StartDate/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar(20)::date AS \"Emp.StartDate\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.EndDate/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar(20)::date AS \"Emp.EndDate\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.OrgName/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar(100) AS \"Emp.OrgName\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.JobTitle/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar(100) AS \"Emp.JobTitle\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Responsibility/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.Responsibility\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.FunctionCategory/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.FunctionCategory\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.IndustryCategory/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.IndustryCategory\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.CountryRegion/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.Loc.CountryRegion\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.State/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.Loc.State\", unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.City/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[]))::varchar AS \"Emp.Loc.City\" FROM humanresources.jobcandidate", + "SqlStatement": "CREATE VIEW humanresources.vjobcandidateemployment AS\n SELECT jobcandidate.jobcandidateid,\n ((unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.StartDate/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying(20))::date AS \"Emp.StartDate\",\n ((unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.EndDate/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying(20))::date AS \"Emp.EndDate\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.OrgName/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying(100) AS \"Emp.OrgName\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.JobTitle/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying(100) AS \"Emp.JobTitle\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Responsibility/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.Responsibility\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.FunctionCategory/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.FunctionCategory\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.IndustryCategory/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.IndustryCategory\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.CountryRegion/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.Loc.CountryRegion\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.State/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.Loc.State\",\n (unnest(xpath('/ns:Resume/ns:Employment/ns:Emp.Location/ns:Location/ns:Loc.City/text()'::text, jobcandidate.resume, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume}}'::text[])))::character varying AS \"Emp.Loc.City\"\n FROM humanresources.jobcandidate;", "FilePath": "/Users/priyanshigupta/Documents/voyager/yb-voyager/migtests/tests/pg/adventureworks/export-dir/schema/views/view.sql", "Suggestion": "", "GH": "", @@ -1008,11 +1008,11 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "person.vadditionalcontactinfo", "Reason": "XML Functions", - "SqlStatement": "SELECT p.businessentityid, p.firstname, p.middlename, p.lastname, (xpath('(act:telephoneNumber)[1]/act:number/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS telephonenumber, btrim((xpath('(act:telephoneNumber)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1]::varchar::text) AS telephonespecialinstructions, (xpath('(act:homePostalAddress)[1]/act:Street/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS street, (xpath('(act:homePostalAddress)[1]/act:City/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS city, (xpath('(act:homePostalAddress)[1]/act:StateProvince/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS stateprovince, (xpath('(act:homePostalAddress)[1]/act:PostalCode/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS postalcode, (xpath('(act:homePostalAddress)[1]/act:CountryRegion/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS countryregion, (xpath('(act:homePostalAddress)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS homeaddressspecialinstructions, (xpath('(act:eMail)[1]/act:eMailAddress/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS emailaddress, btrim((xpath('(act:eMail)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1]::varchar::text) AS emailspecialinstructions, (xpath('((act:eMail)[1]/act:SpecialInstructions/act:telephoneNumber)[1]/act:number/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS emailtelephonenumber, p.rowguid, p.modifieddate FROM person.person p LEFT JOIN (SELECT person.businessentityid, unnest(xpath('/ci:AdditionalContactInfo'::text, person.additionalcontactinfo, '{{ci,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo}}'::text[])) AS node FROM person.person WHERE person.additionalcontactinfo IS NOT NULL) additional ON p.businessentityid = additional.businessentityid", + "SqlStatement": "CREATE VIEW person.vadditionalcontactinfo AS\n SELECT p.businessentityid,\n p.firstname,\n p.middlename,\n p.lastname,\n (xpath('(act:telephoneNumber)[1]/act:number/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS telephonenumber,\n btrim((((xpath('(act:telephoneNumber)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1])::character varying)::text) AS telephonespecialinstructions,\n (xpath('(act:homePostalAddress)[1]/act:Street/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS street,\n (xpath('(act:homePostalAddress)[1]/act:City/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS city,\n (xpath('(act:homePostalAddress)[1]/act:StateProvince/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS stateprovince,\n (xpath('(act:homePostalAddress)[1]/act:PostalCode/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS postalcode,\n (xpath('(act:homePostalAddress)[1]/act:CountryRegion/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS countryregion,\n (xpath('(act:homePostalAddress)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS homeaddressspecialinstructions,\n (xpath('(act:eMail)[1]/act:eMailAddress/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS emailaddress,\n btrim((((xpath('(act:eMail)[1]/act:SpecialInstructions/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1])::character varying)::text) AS emailspecialinstructions,\n (xpath('((act:eMail)[1]/act:SpecialInstructions/act:telephoneNumber)[1]/act:number/text()'::text, additional.node, '{{act,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes}}'::text[]))[1] AS emailtelephonenumber,\n p.rowguid,\n p.modifieddate\n FROM (person.person p\n LEFT JOIN ( SELECT person.businessentityid,\n unnest(xpath('/ci:AdditionalContactInfo'::text, person.additionalcontactinfo, '{{ci,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo}}'::text[])) AS node\n FROM person.person\n WHERE (person.additionalcontactinfo IS NOT NULL)) additional ON ((p.businessentityid = additional.businessentityid)));", "FilePath": "/Users/priyanshigupta/Documents/voyager/yb-voyager/migtests/tests/pg/adventureworks/export-dir/schema/views/view.sql", "Suggestion": "", "GH": "", @@ -1020,11 +1020,11 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "production.vproductmodelcatalogdescription", "Reason": "XML Functions", - "SqlStatement": "SELECT productmodel.productmodelid, productmodel.name, (xpath('/p1:ProductDescription/p1:Summary/html:p/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{html,http://www.w3.org/1999/xhtml}}'::text[]))[1]::varchar AS \"Summary\", (xpath('/p1:ProductDescription/p1:Manufacturer/p1:Name/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar AS manufacturer, (xpath('/p1:ProductDescription/p1:Manufacturer/p1:Copyright/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(30) AS copyright, (xpath('/p1:ProductDescription/p1:Manufacturer/p1:ProductURL/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS producturl, (xpath('/p1:ProductDescription/p1:Features/wm:Warranty/wm:WarrantyPeriod/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1]::varchar(256) AS warrantyperiod, (xpath('/p1:ProductDescription/p1:Features/wm:Warranty/wm:Description/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1]::varchar(256) AS warrantydescription, (xpath('/p1:ProductDescription/p1:Features/wm:Maintenance/wm:NoOfYears/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1]::varchar(256) AS noofyears, (xpath('/p1:ProductDescription/p1:Features/wm:Maintenance/wm:Description/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1]::varchar(256) AS maintenancedescription, (xpath('/p1:ProductDescription/p1:Features/wf:wheel/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar(256) AS wheel, (xpath('/p1:ProductDescription/p1:Features/wf:saddle/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar(256) AS saddle, (xpath('/p1:ProductDescription/p1:Features/wf:pedal/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar(256) AS pedal, (xpath('/p1:ProductDescription/p1:Features/wf:BikeFrame/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar AS bikeframe, (xpath('/p1:ProductDescription/p1:Features/wf:crankset/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1]::varchar(256) AS crankset, (xpath('/p1:ProductDescription/p1:Picture/p1:Angle/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS pictureangle, (xpath('/p1:ProductDescription/p1:Picture/p1:Size/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS picturesize, (xpath('/p1:ProductDescription/p1:Picture/p1:ProductPhotoID/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS productphotoid, (xpath('/p1:ProductDescription/p1:Specifications/Material/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS material, (xpath('/p1:ProductDescription/p1:Specifications/Color/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS color, (xpath('/p1:ProductDescription/p1:Specifications/ProductLine/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS productline, (xpath('/p1:ProductDescription/p1:Specifications/Style/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(256) AS style, (xpath('/p1:ProductDescription/p1:Specifications/RiderExperience/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1]::varchar(1024) AS riderexperience, productmodel.rowguid, productmodel.modifieddate FROM production.productmodel WHERE productmodel.catalogdescription IS NOT NULL", + "SqlStatement": "CREATE VIEW production.vproductmodelcatalogdescription AS\n SELECT productmodel.productmodelid,\n productmodel.name,\n ((xpath('/p1:ProductDescription/p1:Summary/html:p/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{html,http://www.w3.org/1999/xhtml}}'::text[]))[1])::character varying AS \"Summary\",\n ((xpath('/p1:ProductDescription/p1:Manufacturer/p1:Name/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying AS manufacturer,\n ((xpath('/p1:ProductDescription/p1:Manufacturer/p1:Copyright/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(30) AS copyright,\n ((xpath('/p1:ProductDescription/p1:Manufacturer/p1:ProductURL/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS producturl,\n ((xpath('/p1:ProductDescription/p1:Features/wm:Warranty/wm:WarrantyPeriod/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1])::character varying(256) AS warrantyperiod,\n ((xpath('/p1:ProductDescription/p1:Features/wm:Warranty/wm:Description/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1])::character varying(256) AS warrantydescription,\n ((xpath('/p1:ProductDescription/p1:Features/wm:Maintenance/wm:NoOfYears/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1])::character varying(256) AS noofyears,\n ((xpath('/p1:ProductDescription/p1:Features/wm:Maintenance/wm:Description/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wm,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain}}'::text[]))[1])::character varying(256) AS maintenancedescription,\n ((xpath('/p1:ProductDescription/p1:Features/wf:wheel/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying(256) AS wheel,\n ((xpath('/p1:ProductDescription/p1:Features/wf:saddle/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying(256) AS saddle,\n ((xpath('/p1:ProductDescription/p1:Features/wf:pedal/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying(256) AS pedal,\n ((xpath('/p1:ProductDescription/p1:Features/wf:BikeFrame/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying AS bikeframe,\n ((xpath('/p1:ProductDescription/p1:Features/wf:crankset/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription},{wf,http://www.adventure-works.com/schemas/OtherFeatures}}'::text[]))[1])::character varying(256) AS crankset,\n ((xpath('/p1:ProductDescription/p1:Picture/p1:Angle/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS pictureangle,\n ((xpath('/p1:ProductDescription/p1:Picture/p1:Size/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS picturesize,\n ((xpath('/p1:ProductDescription/p1:Picture/p1:ProductPhotoID/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS productphotoid,\n ((xpath('/p1:ProductDescription/p1:Specifications/Material/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS material,\n ((xpath('/p1:ProductDescription/p1:Specifications/Color/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS color,\n ((xpath('/p1:ProductDescription/p1:Specifications/ProductLine/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS productline,\n ((xpath('/p1:ProductDescription/p1:Specifications/Style/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(256) AS style,\n ((xpath('/p1:ProductDescription/p1:Specifications/RiderExperience/text()'::text, productmodel.catalogdescription, '{{p1,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription}}'::text[]))[1])::character varying(1024) AS riderexperience,\n productmodel.rowguid,\n productmodel.modifieddate\n FROM production.productmodel\n WHERE (productmodel.catalogdescription IS NOT NULL);", "FilePath": "/Users/priyanshigupta/Documents/voyager/yb-voyager/migtests/tests/pg/adventureworks/export-dir/schema/views/view.sql", "Suggestion": "", "GH": "", @@ -1032,11 +1032,11 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "production.vproductmodelinstructions", "Reason": "XML Functions", - "SqlStatement": "SELECT pm.productmodelid, pm.name, (xpath('/ns:root/text()'::text, pm.instructions, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions}}'::text[]))[1]::varchar AS instructions, (xpath('@LocationID'::text, pm.mfginstructions))[1]::varchar::int AS \"LocationID\", (xpath('@SetupHours'::text, pm.mfginstructions))[1]::varchar::numeric(9, 4) AS \"SetupHours\", (xpath('@MachineHours'::text, pm.mfginstructions))[1]::varchar::numeric(9, 4) AS \"MachineHours\", (xpath('@LaborHours'::text, pm.mfginstructions))[1]::varchar::numeric(9, 4) AS \"LaborHours\", (xpath('@LotSize'::text, pm.mfginstructions))[1]::varchar::int AS \"LotSize\", (xpath('/step/text()'::text, pm.step))[1]::varchar(1024) AS \"Step\", pm.rowguid, pm.modifieddate FROM (SELECT locations.productmodelid, locations.name, locations.rowguid, locations.modifieddate, locations.instructions, locations.mfginstructions, unnest(xpath('step'::text, locations.mfginstructions)) AS step FROM (SELECT productmodel.productmodelid, productmodel.name, productmodel.rowguid, productmodel.modifieddate, productmodel.instructions, unnest(xpath('/ns:root/ns:Location'::text, productmodel.instructions, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions}}'::text[])) AS mfginstructions FROM production.productmodel) locations) pm", + "SqlStatement": "CREATE VIEW production.vproductmodelinstructions AS\n SELECT pm.productmodelid,\n pm.name,\n ((xpath('/ns:root/text()'::text, pm.instructions, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions}}'::text[]))[1])::character varying AS instructions,\n (((xpath('@LocationID'::text, pm.mfginstructions))[1])::character varying)::integer AS \"LocationID\",\n (((xpath('@SetupHours'::text, pm.mfginstructions))[1])::character varying)::numeric(9,4) AS \"SetupHours\",\n (((xpath('@MachineHours'::text, pm.mfginstructions))[1])::character varying)::numeric(9,4) AS \"MachineHours\",\n (((xpath('@LaborHours'::text, pm.mfginstructions))[1])::character varying)::numeric(9,4) AS \"LaborHours\",\n (((xpath('@LotSize'::text, pm.mfginstructions))[1])::character varying)::integer AS \"LotSize\",\n ((xpath('/step/text()'::text, pm.step))[1])::character varying(1024) AS \"Step\",\n pm.rowguid,\n pm.modifieddate\n FROM ( SELECT locations.productmodelid,\n locations.name,\n locations.rowguid,\n locations.modifieddate,\n locations.instructions,\n locations.mfginstructions,\n unnest(xpath('step'::text, locations.mfginstructions)) AS step\n FROM ( SELECT productmodel.productmodelid,\n productmodel.name,\n productmodel.rowguid,\n productmodel.modifieddate,\n productmodel.instructions,\n unnest(xpath('/ns:root/ns:Location'::text, productmodel.instructions, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions}}'::text[])) AS mfginstructions\n FROM production.productmodel) locations) pm;", "FilePath": "/Users/priyanshigupta/Documents/voyager/yb-voyager/migtests/tests/pg/adventureworks/export-dir/schema/views/view.sql", "Suggestion": "", "GH": "", @@ -1044,11 +1044,11 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "sales.vpersondemographics", "Reason": "XML Functions", - "SqlStatement": "SELECT person.businessentityid, (xpath('n:TotalPurchaseYTD/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::money AS totalpurchaseytd, (xpath('n:DateFirstPurchase/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::date AS datefirstpurchase, (xpath('n:BirthDate/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::date AS birthdate, (xpath('n:MaritalStatus/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(1) AS maritalstatus, (xpath('n:YearlyIncome/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(30) AS yearlyincome, (xpath('n:Gender/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(1) AS gender, (xpath('n:TotalChildren/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::int AS totalchildren, (xpath('n:NumberChildrenAtHome/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::int AS numberchildrenathome, (xpath('n:Education/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(30) AS education, (xpath('n:Occupation/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar(30) AS occupation, (xpath('n:HomeOwnerFlag/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::boolean AS homeownerflag, (xpath('n:NumberCarsOwned/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1]::varchar::int AS numbercarsowned FROM person.person WHERE person.demographics IS NOT NULL", + "SqlStatement": "CREATE VIEW sales.vpersondemographics AS\n SELECT person.businessentityid,\n (((xpath('n:TotalPurchaseYTD/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::money AS totalpurchaseytd,\n (((xpath('n:DateFirstPurchase/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::date AS datefirstpurchase,\n (((xpath('n:BirthDate/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::date AS birthdate,\n ((xpath('n:MaritalStatus/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(1) AS maritalstatus,\n ((xpath('n:YearlyIncome/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(30) AS yearlyincome,\n ((xpath('n:Gender/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(1) AS gender,\n (((xpath('n:TotalChildren/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::integer AS totalchildren,\n (((xpath('n:NumberChildrenAtHome/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::integer AS numberchildrenathome,\n ((xpath('n:Education/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(30) AS education,\n ((xpath('n:Occupation/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying(30) AS occupation,\n (((xpath('n:HomeOwnerFlag/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::boolean AS homeownerflag,\n (((xpath('n:NumberCarsOwned/text()'::text, person.demographics, '{{n,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey}}'::text[]))[1])::character varying)::integer AS numbercarsowned\n FROM person.person\n WHERE (person.demographics IS NOT NULL);", "FilePath": "/Users/priyanshigupta/Documents/voyager/yb-voyager/migtests/tests/pg/adventureworks/export-dir/schema/views/view.sql", "Suggestion": "", "GH": "", @@ -1056,11 +1056,11 @@ "MinimumVersionsFixedIn": null }, { - "IssueType": "unsupported_plpgsql_objects", + "IssueType": "unsupported_features", "ObjectType": "VIEW", "ObjectName": "sales.vstorewithdemographics", "Reason": "XML Functions", - "SqlStatement": "SELECT store.businessentityid, store.name, unnest(xpath('/ns:StoreSurvey/ns:AnnualSales/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::money AS \"AnnualSales\", unnest(xpath('/ns:StoreSurvey/ns:AnnualRevenue/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::money AS \"AnnualRevenue\", unnest(xpath('/ns:StoreSurvey/ns:BankName/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(50) AS \"BankName\", unnest(xpath('/ns:StoreSurvey/ns:BusinessType/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(5) AS \"BusinessType\", unnest(xpath('/ns:StoreSurvey/ns:YearOpened/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::int AS \"YearOpened\", unnest(xpath('/ns:StoreSurvey/ns:Specialty/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(50) AS \"Specialty\", unnest(xpath('/ns:StoreSurvey/ns:SquareFeet/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::int AS \"SquareFeet\", unnest(xpath('/ns:StoreSurvey/ns:Brands/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(30) AS \"Brands\", unnest(xpath('/ns:StoreSurvey/ns:Internet/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar(30) AS \"Internet\", unnest(xpath('/ns:StoreSurvey/ns:NumberEmployees/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[]))::varchar::int AS \"NumberEmployees\" FROM sales.store", + "SqlStatement": "CREATE VIEW sales.vstorewithdemographics AS\n SELECT store.businessentityid,\n store.name,\n ((unnest(xpath('/ns:StoreSurvey/ns:AnnualSales/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::money AS \"AnnualSales\",\n ((unnest(xpath('/ns:StoreSurvey/ns:AnnualRevenue/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::money AS \"AnnualRevenue\",\n (unnest(xpath('/ns:StoreSurvey/ns:BankName/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(50) AS \"BankName\",\n (unnest(xpath('/ns:StoreSurvey/ns:BusinessType/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(5) AS \"BusinessType\",\n ((unnest(xpath('/ns:StoreSurvey/ns:YearOpened/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::integer AS \"YearOpened\",\n (unnest(xpath('/ns:StoreSurvey/ns:Specialty/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(50) AS \"Specialty\",\n ((unnest(xpath('/ns:StoreSurvey/ns:SquareFeet/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::integer AS \"SquareFeet\",\n (unnest(xpath('/ns:StoreSurvey/ns:Brands/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(30) AS \"Brands\",\n (unnest(xpath('/ns:StoreSurvey/ns:Internet/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying(30) AS \"Internet\",\n ((unnest(xpath('/ns:StoreSurvey/ns:NumberEmployees/text()'::text, store.demographics, '{{ns,http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey}}'::text[])))::character varying)::integer AS \"NumberEmployees\"\n FROM sales.store;", "FilePath": "/Users/priyanshigupta/Documents/voyager/yb-voyager/migtests/tests/pg/adventureworks/export-dir/schema/views/view.sql", "Suggestion": "", "GH": "", diff --git a/migtests/tests/pg/mgi/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/mgi/expected_files/expectedAssessmentReport.json index 8e10a3d80..77a3e8bdf 100644 --- a/migtests/tests/pg/mgi/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/mgi/expected_files/expectedAssessmentReport.json @@ -248,6 +248,21 @@ "UnsupportedDataTypes": null, "UnsupportedDataTypesDesc": "Data types of the source database that are not supported on the target YugabyteDB.", "UnsupportedFeatures": [ + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [], +"MinimumVersionsFixedIn":null + }, { "FeatureName": "GIST indexes", "Objects": [], diff --git a/migtests/tests/pg/omnibus/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/omnibus/expected_files/expectedAssessmentReport.json index 6c6a0be1e..f14e1b0e5 100755 --- a/migtests/tests/pg/omnibus/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/omnibus/expected_files/expectedAssessmentReport.json @@ -493,6 +493,21 @@ "UnsupportedDataTypes": null, "UnsupportedDataTypesDesc": "Data types of the source database that are not supported on the target YugabyteDB.", "UnsupportedFeatures": [ + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [], +"MinimumVersionsFixedIn":null + }, { "FeatureName": "GIST indexes", "Objects": [ diff --git a/migtests/tests/pg/osm/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/osm/expected_files/expectedAssessmentReport.json index 5fdd45235..b3d67ae3c 100755 --- a/migtests/tests/pg/osm/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/osm/expected_files/expectedAssessmentReport.json @@ -73,6 +73,21 @@ ], "UnsupportedDataTypesDesc": "Data types of the source database that are not supported on the target YugabyteDB.", "UnsupportedFeatures": [ + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [], +"MinimumVersionsFixedIn":null + }, { "FeatureName": "GIST indexes", "Objects": [ diff --git a/migtests/tests/pg/pgtbrus/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/pgtbrus/expected_files/expectedAssessmentReport.json index 8c511ac3c..a8222d3a4 100755 --- a/migtests/tests/pg/pgtbrus/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/pgtbrus/expected_files/expectedAssessmentReport.json @@ -80,6 +80,21 @@ "UnsupportedDataTypes": null, "UnsupportedDataTypesDesc": "Data types of the source database that are not supported on the target YugabyteDB.", "UnsupportedFeatures": [ + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [], +"MinimumVersionsFixedIn":null + }, { "FeatureName": "GIST indexes", "Objects": [], diff --git a/migtests/tests/pg/rna/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/rna/expected_files/expectedAssessmentReport.json index 560cd9403..d7fd60bcc 100644 --- a/migtests/tests/pg/rna/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/rna/expected_files/expectedAssessmentReport.json @@ -377,6 +377,21 @@ "UnsupportedDataTypes": null, "UnsupportedDataTypesDesc": "Data types of the source database that are not supported on the target YugabyteDB.", "UnsupportedFeatures": [ + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [], +"MinimumVersionsFixedIn":null + }, { "FeatureName": "GIST indexes", "Objects": [], diff --git a/migtests/tests/pg/sakila/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/sakila/expected_files/expectedAssessmentReport.json index 184099368..0c474ddcf 100755 --- a/migtests/tests/pg/sakila/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/sakila/expected_files/expectedAssessmentReport.json @@ -118,6 +118,21 @@ "UnsupportedDataTypes": null, "UnsupportedDataTypesDesc": "Data types of the source database that are not supported on the target YugabyteDB.", "UnsupportedFeatures": [ + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [], +"MinimumVersionsFixedIn":null + }, { "FeatureName": "GIST indexes", "Objects": [ diff --git a/migtests/tests/pg/sample-is/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/sample-is/expected_files/expectedAssessmentReport.json index cb0333a96..59c7edd00 100755 --- a/migtests/tests/pg/sample-is/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/sample-is/expected_files/expectedAssessmentReport.json @@ -76,6 +76,21 @@ "UnsupportedDataTypes": null, "UnsupportedDataTypesDesc": "Data types of the source database that are not supported on the target YugabyteDB.", "UnsupportedFeatures": [ + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [], +"MinimumVersionsFixedIn":null + }, { "FeatureName": "GIST indexes", "Objects": [], diff --git a/migtests/tests/pg/stackexchange/expected_files/expectedAssessmentReport.json b/migtests/tests/pg/stackexchange/expected_files/expectedAssessmentReport.json index f6be2c83e..682f4b098 100644 --- a/migtests/tests/pg/stackexchange/expected_files/expectedAssessmentReport.json +++ b/migtests/tests/pg/stackexchange/expected_files/expectedAssessmentReport.json @@ -82,6 +82,21 @@ "UnsupportedDataTypes": null, "UnsupportedDataTypesDesc": "Data types of the source database that are not supported on the target YugabyteDB.", "UnsupportedFeatures": [ + { + "FeatureName": "Advisory Locks", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName":"System Columns", + "Objects":[], + "MinimumVersionsFixedIn":null + }, + { + "FeatureName": "XML Functions", + "Objects": [], +"MinimumVersionsFixedIn":null + }, { "FeatureName": "GIST indexes", "Objects": [], From 1d73003dc8f3ab218a845215709b7d402efb564e Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Wed, 11 Dec 2024 17:45:45 +0530 Subject: [PATCH 07/10] minor fix in the format of reporting constraint for a couple of cases --- .../tests/analyze-schema/expected_issues.json | 16 ++++++++-------- .../expectedAssessmentReport.json | 6 +++--- yb-voyager/src/query/queryissue/detectors_ddl.go | 4 ++-- .../src/query/queryparser/ddl_processor.go | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/migtests/tests/analyze-schema/expected_issues.json b/migtests/tests/analyze-schema/expected_issues.json index dcdf4e602..8b8afcbe4 100644 --- a/migtests/tests/analyze-schema/expected_issues.json +++ b/migtests/tests/analyze-schema/expected_issues.json @@ -802,7 +802,7 @@ { "IssueType": "unsupported_features", "ObjectType": "TABLE", - "ObjectName": "combined_tbl, constraint: combined_tbl_j_key", + "ObjectName": "combined_tbl, constraint: (combined_tbl_j_key)", "Reason": "Primary key and Unique constraint on column 'json' not yet supported", "SqlStatement": "create table combined_tbl (\n\tid int,\n\tc cidr,\n\tci circle,\n\tb box,\n\tj json UNIQUE,\n\tl line,\n\tls lseg,\n\tmaddr macaddr,\n\tmaddr8 macaddr8,\n\tp point,\n\tlsn pg_lsn,\n\tp1 path,\n\tp2 polygon,\n\tid1 txid_snapshot,\n\tbitt bit (13),\n\tbittv bit varying(15),\n\tCONSTRAINT pk PRIMARY KEY (id, maddr8)\n);", "Suggestion": "Refer to the docs link for the workaround", @@ -813,7 +813,7 @@ { "IssueType": "unsupported_features", "ObjectType": "TABLE", - "ObjectName": "combined_tbl, constraint: pk", + "ObjectName": "combined_tbl, constraint: (pk)", "Reason": "Primary key and Unique constraint on column 'macaddr8' not yet supported", "SqlStatement": "create table combined_tbl (\n\tid int,\n\tc cidr,\n\tci circle,\n\tb box,\n\tj json UNIQUE,\n\tl line,\n\tls lseg,\n\tmaddr macaddr,\n\tmaddr8 macaddr8,\n\tp point,\n\tlsn pg_lsn,\n\tp1 path,\n\tp2 polygon,\n\tid1 txid_snapshot,\n\tbitt bit (13),\n\tbittv bit varying(15),\n\tCONSTRAINT pk PRIMARY KEY (id, maddr8)\n);", "Suggestion": "Refer to the docs link for the workaround", @@ -824,7 +824,7 @@ { "IssueType": "unsupported_features", "ObjectType": "TABLE", - "ObjectName": "combined_tbl, constraint: combined_tbl_unique", + "ObjectName": "combined_tbl, constraint: (combined_tbl_unique)", "Reason": "Primary key and Unique constraint on column 'bit' not yet supported", "SqlStatement": "ALTER TABLE combined_tbl\n\t\tADD CONSTRAINT combined_tbl_unique UNIQUE(id, bitt);", "Suggestion": "Refer to the docs link for the workaround", @@ -835,7 +835,7 @@ { "IssueType": "unsupported_features", "ObjectType": "TABLE", - "ObjectName": "combined_tbl1, constraint: combined_tbl1_i4_key", + "ObjectName": "combined_tbl1, constraint: (combined_tbl1_i4_key)", "Reason": "Primary key and Unique constraint on column 'int4range' not yet supported", "SqlStatement": "CREATE TABLE combined_tbl1(\n\tid int,\n\tt tsrange,\n\td daterange,\n\ttz tstzrange,\n\tn numrange,\n\ti4 int4range UNIQUE,\n\ti8 int8range,\n\tinym INTERVAL YEAR TO MONTH,\n\tinds INTERVAL DAY TO SECOND(9),\n\tPRIMARY KEY(id, t, n)\n);", "Suggestion": "Refer to the docs link for the workaround", @@ -846,7 +846,7 @@ { "IssueType": "unsupported_features", "ObjectType": "TABLE", - "ObjectName": "combined_tbl1, constraint: combined_tbl1_id_t_n_pkey", + "ObjectName": "combined_tbl1, constraint: (combined_tbl1_id_t_n_pkey)", "Reason": "Primary key and Unique constraint on column 'tsrange' not yet supported", "SqlStatement": "CREATE TABLE combined_tbl1(\n\tid int,\n\tt tsrange,\n\td daterange,\n\ttz tstzrange,\n\tn numrange,\n\ti4 int4range UNIQUE,\n\ti8 int8range,\n\tinym INTERVAL YEAR TO MONTH,\n\tinds INTERVAL DAY TO SECOND(9),\n\tPRIMARY KEY(id, t, n)\n);", "Suggestion": "Refer to the docs link for the workaround", @@ -857,7 +857,7 @@ { "IssueType": "unsupported_features", "ObjectType": "TABLE", - "ObjectName": "combined_tbl1, constraint: combined_tbl1_id_t_n_pkey", + "ObjectName": "combined_tbl1, constraint: (combined_tbl1_id_t_n_pkey)", "Reason": "Primary key and Unique constraint on column 'numrange' not yet supported", "SqlStatement": "CREATE TABLE combined_tbl1(\n\tid int,\n\tt tsrange,\n\td daterange,\n\ttz tstzrange,\n\tn numrange,\n\ti4 int4range UNIQUE,\n\ti8 int8range,\n\tinym INTERVAL YEAR TO MONTH,\n\tinds INTERVAL DAY TO SECOND(9),\n\tPRIMARY KEY(id, t, n)\n);", "Suggestion": "Refer to the docs link for the workaround", @@ -868,7 +868,7 @@ { "IssueType": "unsupported_features", "ObjectType": "TABLE", - "ObjectName": "combined_tbl1, constraint: combined_tbl1_unique", + "ObjectName": "combined_tbl1, constraint: (combined_tbl1_unique)", "Reason": "Primary key and Unique constraint on column 'daterange' not yet supported", "SqlStatement": "ALTER TABLE combined_tbl1\n\t\tADD CONSTRAINT combined_tbl1_unique UNIQUE(id, d);", "Suggestion": "Refer to the docs link for the workaround", @@ -901,7 +901,7 @@ { "IssueType": "unsupported_features", "ObjectType": "TABLE", - "ObjectName": "test_interval, constraint: test_interval_frequency_pkey", + "ObjectName": "test_interval, constraint: (test_interval_frequency_pkey)", "Reason": "Primary key and Unique constraint on column 'interval' not yet supported", "SqlStatement": "create table test_interval(\n frequency interval primary key,\n\tcol1 int\n);", "Suggestion": "Refer to the docs link for the workaround", diff --git a/migtests/tests/pg/assessment-report-test/expectedAssessmentReport.json b/migtests/tests/pg/assessment-report-test/expectedAssessmentReport.json index 324ae5cc7..9536a7bf6 100644 --- a/migtests/tests/pg/assessment-report-test/expectedAssessmentReport.json +++ b/migtests/tests/pg/assessment-report-test/expectedAssessmentReport.json @@ -522,15 +522,15 @@ "FeatureName": "Primary / Unique key constraints on complex datatypes", "Objects": [ { - "ObjectName": "public.combined_tbl, constraint: combined_tbl_bittv_key", + "ObjectName": "public.combined_tbl, constraint: (combined_tbl_bittv_key)", "SqlStatement": "ALTER TABLE ONLY public.combined_tbl\n ADD CONSTRAINT combined_tbl_bittv_key UNIQUE (bittv);" }, { - "ObjectName": "public.combined_tbl, constraint: uk", + "ObjectName": "public.combined_tbl, constraint: (uk)", "SqlStatement": "ALTER TABLE ONLY public.combined_tbl\n ADD CONSTRAINT uk UNIQUE (lsn);" }, { - "ObjectName": "public.combined_tbl, constraint: combined_tbl_pkey", + "ObjectName": "public.combined_tbl, constraint: (combined_tbl_pkey)", "SqlStatement": "ALTER TABLE ONLY public.combined_tbl\n ADD CONSTRAINT combined_tbl_pkey PRIMARY KEY (id, arr_enum);" } ], diff --git a/yb-voyager/src/query/queryissue/detectors_ddl.go b/yb-voyager/src/query/queryissue/detectors_ddl.go index daac8e4cb..33714d00c 100644 --- a/yb-voyager/src/query/queryissue/detectors_ddl.go +++ b/yb-voyager/src/query/queryissue/detectors_ddl.go @@ -106,7 +106,7 @@ func (d *TableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]QueryIss } issues = append(issues, NewPrimaryOrUniqueConsOnUnsupportedIndexTypesIssue( obj.GetObjectType(), - fmt.Sprintf("%s, constraint: %s", table.GetObjectName(), c.ConstraintName), + fmt.Sprintf("%s, constraint: (%s)", table.GetObjectName(), c.ConstraintName), "", typeName, true, @@ -447,7 +447,7 @@ func (aid *AlterTableIssueDetector) DetectIssues(obj queryparser.DDLObject) ([]Q } issues = append(issues, NewPrimaryOrUniqueConsOnUnsupportedIndexTypesIssue( obj.GetObjectType(), - fmt.Sprintf("%s, constraint: %s", alter.GetObjectName(), alter.ConstraintName), + fmt.Sprintf("%s, constraint: (%s)", alter.GetObjectName(), alter.ConstraintName), "", typeName, false, diff --git a/yb-voyager/src/query/queryparser/ddl_processor.go b/yb-voyager/src/query/queryparser/ddl_processor.go index 7644ee4b4..43b82db89 100644 --- a/yb-voyager/src/query/queryparser/ddl_processor.go +++ b/yb-voyager/src/query/queryparser/ddl_processor.go @@ -350,7 +350,7 @@ func (t *Table) addConstraint(conType pg_query.ConstrType, columns []string, spe Columns: columns, IsDeferrable: deferrable, } - generatedConName := tc.generateConstraintName(t.GetObjectName()) + generatedConName := tc.generateConstraintName(t.TableName) conName := lo.Ternary(specifiedConName == "", generatedConName, specifiedConName) tc.ConstraintName = conName t.Constraints = append(t.Constraints, tc) From 43f1853dba061b795a881bb7be7729ba8445ec8a Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Wed, 11 Dec 2024 17:48:51 +0530 Subject: [PATCH 08/10] added unit tests for GetDDLIssues() --- ..._test.go => parser_issue_detector_test.go} | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) rename yb-voyager/src/query/queryissue/{unsupported_ddls_test.go => parser_issue_detector_test.go} (66%) diff --git a/yb-voyager/src/query/queryissue/unsupported_ddls_test.go b/yb-voyager/src/query/queryissue/parser_issue_detector_test.go similarity index 66% rename from yb-voyager/src/query/queryissue/unsupported_ddls_test.go rename to yb-voyager/src/query/queryissue/parser_issue_detector_test.go index a04f20984..243576675 100644 --- a/yb-voyager/src/query/queryissue/unsupported_ddls_test.go +++ b/yb-voyager/src/query/queryissue/parser_issue_detector_test.go @@ -118,9 +118,43 @@ $$ LANGUAGE plpgsql;` );` stmt12 = `CREATE TABLE test_dt (id int, d daterange);` stmt13 = `CREATE INDEX idx_on_daterange on test_dt (d);` + stmt14 = `CREATE MATERIALIZED VIEW public.sample_data_view AS + SELECT sample_data.id, + sample_data.name, + sample_data.description, + XMLFOREST(sample_data.name AS name, sample_data.description AS description) AS xml_data, + pg_try_advisory_lock((sample_data.id)::bigint) AS lock_acquired, + sample_data.ctid AS row_ctid, + sample_data.xmin AS xmin_value + FROM public.sample_data + WITH NO DATA;` + stmt15 = `CREATE VIEW public.orders_view AS + SELECT orders.order_id, + orders.customer_name, + orders.product_name, + orders.quantity, + orders.price, + XMLELEMENT(NAME "OrderDetails", XMLELEMENT(NAME "Customer", orders.customer_name), XMLELEMENT(NAME "Product", orders.product_name), XMLELEMENT(NAME "Quantity", orders.quantity), XMLELEMENT(NAME "TotalPrice", (orders.price * (orders.quantity)::numeric))) AS order_xml, + XMLCONCAT(XMLELEMENT(NAME "Customer", orders.customer_name), XMLELEMENT(NAME "Product", orders.product_name)) AS summary_xml, + pg_try_advisory_lock((hashtext((orders.customer_name || orders.product_name)))::bigint) AS lock_acquired, + orders.ctid AS row_ctid, + orders.xmin AS transaction_id + FROM public.orders + WITH LOCAL CHECK OPTION;` + stmt16 = `CREATE TABLE public.xml_data_example ( + id SERIAL PRIMARY KEY, + name VARCHAR(255), + d daterange Unique, + description XML DEFAULT xmlparse(document 'Default Product100.00Electronics'), + created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP +) PARTITION BY LIST(id, name);` + stmt17 = `ALTER TABLE invoices +ADD CONSTRAINT valid_invoice_structure +CHECK (xpath_exists('/invoice/customer', data));` + stmt18 = `CREATE INDEX idx_invoices on invoices (xpath('/invoice/customer/text()', data));` ) -func TestAllDDLIssues(t *testing.T) { +func TestAllIssues(t *testing.T) { requiredDDLs := []string{stmt12} parserIssueDetector := NewParserIssueDetector() stmtsWithExpectedIssues := map[string][]QueryIssue{ @@ -198,3 +232,54 @@ func TestAllDDLIssues(t *testing.T) { } } + +func TestDDLIssues(t *testing.T) { + requiredDDLs := []string{stmt16} + parserIssueDetector := NewParserIssueDetector() + stmtsWithExpectedIssues := map[string][]QueryIssue{ + stmt14: []QueryIssue{ + NewAdvisoryLocksIssue("MVIEW", "public.sample_data_view", stmt14), + NewSystemColumnsIssue("MVIEW", "public.sample_data_view", stmt14), + NewXmlFunctionsIssue("MVIEW", "public.sample_data_view", stmt14), + }, + stmt15: []QueryIssue{ + NewAdvisoryLocksIssue("VIEW", "public.orders_view", stmt15), + NewSystemColumnsIssue("VIEW", "public.orders_view", stmt15), + NewXmlFunctionsIssue("VIEW", "public.orders_view", stmt15), + //TODO: Add CHECK OPTION issue when we move it from regex to parser logic + }, + stmt16: []QueryIssue{ + NewXmlFunctionsIssue("TABLE", "public.xml_data_example", stmt16), + NewPrimaryOrUniqueConsOnUnsupportedIndexTypesIssue("TABLE", "public.xml_data_example, constraint: (xml_data_example_d_key)", stmt16, "daterange", true), + NewMultiColumnListPartition("TABLE", "public.xml_data_example", stmt16), + NewInsufficientColumnInPKForPartition("TABLE", "public.xml_data_example", stmt16, []string{"name"}), + NewXMLDatatypeIssue("TABLE", "public.xml_data_example", stmt16, "description"), + }, + stmt17: []QueryIssue{ + NewXmlFunctionsIssue("TABLE", "invoices", stmt17), + }, + stmt18: []QueryIssue{ + NewXmlFunctionsIssue("INDEX", "idx_invoices ON invoices", stmt18), + }, + } + for _, stmt := range requiredDDLs { + err := parserIssueDetector.ParseRequiredDDLs(stmt) + assert.NoError(t, err, "Error parsing required ddl: %s", stmt) + } + for stmt, expectedIssues := range stmtsWithExpectedIssues { + issues, err := parserIssueDetector.GetDDLIssues(stmt, ybversion.LatestStable) + assert.NoError(t, err, "Error detecting issues for statement: %s", stmt) + + assert.Equal(t, len(expectedIssues), len(issues), "Mismatch in issue count for statement: %s", stmt) + for _, expectedIssue := range expectedIssues { + found := slices.ContainsFunc(issues, func(QueryIssue QueryIssue) bool { + typeNameMatches := QueryIssue.TypeName == expectedIssue.TypeName + queryMatches := QueryIssue.SqlStatement == expectedIssue.SqlStatement + objectNameMatches := QueryIssue.ObjectName == expectedIssue.ObjectName + objectTypeMatches := QueryIssue.ObjectType == expectedIssue.ObjectType + return typeNameMatches && queryMatches && objectNameMatches && objectTypeMatches + }) + assert.True(t, found, "Expected issue not found: %v in statement: %s", expectedIssue, stmt) + } + } +} From cea64105ccfd663f35fc600e8edce806bf86bcee Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Fri, 13 Dec 2024 13:44:24 +0530 Subject: [PATCH 09/10] review comments --- .../query/queryissue/parser_issue_detector.go | 19 +++++-- .../queryissue/parser_issue_detector_test.go | 50 +++++++++++-------- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/yb-voyager/src/query/queryissue/parser_issue_detector.go b/yb-voyager/src/query/queryissue/parser_issue_detector.go index 342a354d1..7da82d4b4 100644 --- a/yb-voyager/src/query/queryissue/parser_issue_detector.go +++ b/yb-voyager/src/query/queryissue/parser_issue_detector.go @@ -274,6 +274,11 @@ func (p *ParserIssueDetector) getDDLIssues(query string) ([]QueryIssue, error) { return issues, nil } + /* + For detecting these generic issues (Advisory locks, XML functions and System columns as of now) on DDL example - + CREATE INDEX idx_invoices on invoices (xpath('/invoice/customer/text()', data)); + We need to call it on DDLs as well + */ genericIssues, err := p.genericIssues(query) if err != nil { return nil, fmt.Errorf("error getting generic issues: %w", err) @@ -319,6 +324,15 @@ func (p *ParserIssueDetector) GetPercentTypeSyntaxIssues(query string) ([]QueryI } func (p *ParserIssueDetector) GetDMLIssues(query string, targetDbVersion *ybversion.YBVersion) ([]QueryIssue, error) { + issues, err := p.getDMLIssues(query) + if err != nil { + return issues, err + } + + return p.getIssuesNotFixedInTargetDbVersion(issues, targetDbVersion) +} + +func (p *ParserIssueDetector) getDMLIssues(query string) ([]QueryIssue, error) { parseTree, err := queryparser.Parse(query) if err != nil { return nil, fmt.Errorf("error parsing query: %w", err) @@ -335,10 +349,9 @@ func (p *ParserIssueDetector) GetDMLIssues(query string, targetDbVersion *ybvers if err != nil { return issues, err } - - return p.getIssuesNotFixedInTargetDbVersion(issues, targetDbVersion) + return issues, err } - + func (p *ParserIssueDetector) genericIssues(query string) ([]QueryIssue, error) { parseTree, err := queryparser.Parse(query) if err != nil { diff --git a/yb-voyager/src/query/queryissue/parser_issue_detector_test.go b/yb-voyager/src/query/queryissue/parser_issue_detector_test.go index 243576675..e9330a09e 100644 --- a/yb-voyager/src/query/queryissue/parser_issue_detector_test.go +++ b/yb-voyager/src/query/queryissue/parser_issue_detector_test.go @@ -19,6 +19,8 @@ import ( "slices" "testing" + "github.com/google/go-cmp/cmp" + "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/yugabyte/yb-voyager/yb-voyager/src/ybversion" @@ -154,6 +156,13 @@ CHECK (xpath_exists('/invoice/customer', data));` stmt18 = `CREATE INDEX idx_invoices on invoices (xpath('/invoice/customer/text()', data));` ) +func modifyiedIssuesforPLPGSQL(issues []QueryIssue, objType string, objName string) []QueryIssue { + return lo.Map(issues, func(i QueryIssue, _ int) QueryIssue { + i.ObjectType = objType + i.ObjectName = objName + return i + }) +} func TestAllIssues(t *testing.T) { requiredDDLs := []string{stmt12} parserIssueDetector := NewParserIssueDetector() @@ -162,19 +171,19 @@ func TestAllIssues(t *testing.T) { NewPercentTypeSyntaxIssue("FUNCTION", "list_high_earners", "public.emp1.salary%TYPE"), NewPercentTypeSyntaxIssue("FUNCTION", "list_high_earners", "employees.name%TYPE"), NewPercentTypeSyntaxIssue("FUNCTION", "list_high_earners", "employees.salary%TYPE"), - NewClusterONIssue("FUNCTION", "list_high_earners", "ALTER TABLE employees CLUSTER ON idx;"), - NewAdvisoryLocksIssue("FUNCTION", "list_high_earners", "SELECT pg_advisory_unlock(sender_id);"), - NewAdvisoryLocksIssue("FUNCTION", "list_high_earners", "SELECT pg_advisory_unlock(receiver_id);"), - NewXmlFunctionsIssue("FUNCTION", "list_high_earners", "SELECT id, xpath('/person/name/text()', data) AS name FROM test_xml_type;"), - NewSystemColumnsIssue("FUNCTION", "list_high_earners", "SELECT * FROM employees e WHERE e.xmax = (SELECT MAX(xmax) FROM employees WHERE department = e.department);"), + NewClusterONIssue("TABLE", "employees", "ALTER TABLE employees CLUSTER ON idx;"), + NewAdvisoryLocksIssue("DML_QUERY", "", "SELECT pg_advisory_unlock(sender_id);"), + NewAdvisoryLocksIssue("DML_QUERY", "", "SELECT pg_advisory_unlock(receiver_id);"), + NewXmlFunctionsIssue("DML_QUERY", "", "SELECT id, xpath('/person/name/text()', data) AS name FROM test_xml_type;"), + NewSystemColumnsIssue("DML_QUERY", "", "SELECT * FROM employees e WHERE e.xmax = (SELECT MAX(xmax) FROM employees WHERE department = e.department);"), }, stmt2: []QueryIssue{ NewPercentTypeSyntaxIssue("FUNCTION", "process_order", "orders.id%TYPE"), - NewStorageParameterIssue("FUNCTION", "process_order", "ALTER TABLE ONLY public.example ADD CONSTRAINT example_email_key UNIQUE (email) WITH (fillfactor=70);"), - NewUnloggedTableIssue("FUNCTION", "process_order", "CREATE UNLOGGED TABLE tbl_unlog (id int, val text);"), - NewMultiColumnGinIndexIssue("FUNCTION", "process_order", "CREATE INDEX idx_example ON example_table USING gin(name, name1);"), - NewUnsupportedIndexMethodIssue("FUNCTION", "process_order", "CREATE INDEX idx_example ON schema1.example_table USING gist(name);", "gist"), - NewAdvisoryLocksIssue("FUNCTION", "process_order", "SELECT pg_advisory_unlock(orderid);"), + NewStorageParameterIssue("TABLE", "public.example", "ALTER TABLE ONLY public.example ADD CONSTRAINT example_email_key UNIQUE (email) WITH (fillfactor=70);"), + NewUnloggedTableIssue("TABLE", "tbl_unlog", "CREATE UNLOGGED TABLE tbl_unlog (id int, val text);"), + NewMultiColumnGinIndexIssue("INDEX", "idx_example ON example_table", "CREATE INDEX idx_example ON example_table USING gin(name, name1);"), + NewUnsupportedIndexMethodIssue("INDEX", "idx_example ON schema1.example_table", "CREATE INDEX idx_example ON schema1.example_table USING gist(name);", "gist"), + NewAdvisoryLocksIssue("DML_QUERY", "", "SELECT pg_advisory_unlock(orderid);"), }, stmt3: []QueryIssue{ NewStorageParameterIssue("INDEX", "abc ON public.example", stmt3), @@ -210,6 +219,11 @@ func TestAllIssues(t *testing.T) { }, } + //Should modify it in similar way we do it actual code as the particular DDL issue in plpgsql can have different Details map on the basis of objectType + stmtsWithExpectedIssues[stmt1] = modifyiedIssuesforPLPGSQL(stmtsWithExpectedIssues[stmt1], "FUNCTION", "list_high_earners") + + stmtsWithExpectedIssues[stmt2] = modifyiedIssuesforPLPGSQL(stmtsWithExpectedIssues[stmt2], "FUNCTION", "process_order") + for _, stmt := range requiredDDLs { err := parserIssueDetector.ParseRequiredDDLs(stmt) assert.NoError(t, err, "Error parsing required ddl: %s", stmt) @@ -220,12 +234,8 @@ func TestAllIssues(t *testing.T) { assert.Equal(t, len(expectedIssues), len(issues), "Mismatch in issue count for statement: %s", stmt) for _, expectedIssue := range expectedIssues { - found := slices.ContainsFunc(issues, func(QueryIssue QueryIssue) bool { - typeNameMatches := QueryIssue.TypeName == expectedIssue.TypeName - queryMatches := QueryIssue.SqlStatement == expectedIssue.SqlStatement - objectNameMatches := QueryIssue.ObjectName == expectedIssue.ObjectName - objectTypeMatches := QueryIssue.ObjectType == expectedIssue.ObjectType - return typeNameMatches && queryMatches && objectNameMatches && objectTypeMatches + found := slices.ContainsFunc(issues, func(queryIssue QueryIssue) bool { + return cmp.Equal(expectedIssue, queryIssue) }) assert.True(t, found, "Expected issue not found: %v in statement: %s", expectedIssue, stmt) } @@ -272,12 +282,8 @@ func TestDDLIssues(t *testing.T) { assert.Equal(t, len(expectedIssues), len(issues), "Mismatch in issue count for statement: %s", stmt) for _, expectedIssue := range expectedIssues { - found := slices.ContainsFunc(issues, func(QueryIssue QueryIssue) bool { - typeNameMatches := QueryIssue.TypeName == expectedIssue.TypeName - queryMatches := QueryIssue.SqlStatement == expectedIssue.SqlStatement - objectNameMatches := QueryIssue.ObjectName == expectedIssue.ObjectName - objectTypeMatches := QueryIssue.ObjectType == expectedIssue.ObjectType - return typeNameMatches && queryMatches && objectNameMatches && objectTypeMatches + found := slices.ContainsFunc(issues, func(queryIssue QueryIssue) bool { + return cmp.Equal(expectedIssue, queryIssue) }) assert.True(t, found, "Expected issue not found: %v in statement: %s", expectedIssue, stmt) } From 1cd099d088743a543e6c20963e93721a408e8ae6 Mon Sep 17 00:00:00 2001 From: priyanshi-yb Date: Fri, 13 Dec 2024 14:31:41 +0530 Subject: [PATCH 10/10] review comment --- .../query/queryissue/parser_issue_detector.go | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/yb-voyager/src/query/queryissue/parser_issue_detector.go b/yb-voyager/src/query/queryissue/parser_issue_detector.go index 7da82d4b4..2fc872014 100644 --- a/yb-voyager/src/query/queryissue/parser_issue_detector.go +++ b/yb-voyager/src/query/queryissue/parser_issue_detector.go @@ -93,7 +93,7 @@ func (p *ParserIssueDetector) getAllIssues(query string) ([]QueryIssue, error) { if err != nil { return nil, fmt.Errorf("error getting plpgsql issues: %v", err) } - dmlIssues, err := p.genericIssues(query) + dmlIssues, err := p.getDMLIssues(query) if err != nil { return nil, fmt.Errorf("error getting generic issues: %v", err) } @@ -246,6 +246,13 @@ func (p *ParserIssueDetector) getDDLIssues(query string) ([]QueryIssue, error) { if err != nil { return nil, fmt.Errorf("error parsing a query: %v", err) } + isDDL, err := queryparser.IsDDL(parseTree) + if err != nil { + return nil, fmt.Errorf("error checking if query is ddl: %w", err) + } + if !isDDL { + return nil, nil + } // Parse the query into a DDL object ddlObj, err := queryparser.ProcessDDL(parseTree) if err != nil { @@ -270,14 +277,10 @@ func (p *ParserIssueDetector) getDDLIssues(query string) ([]QueryIssue, error) { } } - if _, ok := ddlObj.(*queryparser.Object); ok { // In case the DDL doesn't have any processor skip checking generic issues - return issues, nil - } - /* - For detecting these generic issues (Advisory locks, XML functions and System columns as of now) on DDL example - - CREATE INDEX idx_invoices on invoices (xpath('/invoice/customer/text()', data)); - We need to call it on DDLs as well + For detecting these generic issues (Advisory locks, XML functions and System columns as of now) on DDL example - + CREATE INDEX idx_invoices on invoices (xpath('/invoice/customer/text()', data)); + We need to call it on DDLs as well */ genericIssues, err := p.genericIssues(query) if err != nil { @@ -351,7 +354,7 @@ func (p *ParserIssueDetector) getDMLIssues(query string) ([]QueryIssue, error) { } return issues, err } - + func (p *ParserIssueDetector) genericIssues(query string) ([]QueryIssue, error) { parseTree, err := queryparser.Parse(query) if err != nil {