diff --git a/.github/workflows/misc-migtests.yml b/.github/workflows/misc-migtests.yml index 3385743b8..336202848 100644 --- a/.github/workflows/misc-migtests.yml +++ b/.github/workflows/misc-migtests.yml @@ -114,9 +114,6 @@ jobs: echo "127.0.0.1 yb-master-n1" | sudo tee -a /etc/hosts psql "postgresql://yugabyte@yb-tserver-n1:5433/yugabyte" -c "SELECT version();" - echo "TEST: PG sample schemas (omnibus)" - migtests/scripts/run-schema-migration.sh pg/omnibus - echo "Setup the gcp credentials" migtests/scripts/gcs/create_gcs_credentials_file diff --git a/.github/workflows/pg-17-migtests.yml b/.github/workflows/pg-17-migtests.yml index fc2aba70b..27aacc0c6 100644 --- a/.github/workflows/pg-17-migtests.yml +++ b/.github/workflows/pg-17-migtests.yml @@ -117,6 +117,10 @@ jobs: if: ${{ !cancelled() && matrix.test_group == 'offline' }} run: migtests/scripts/run-schema-migration.sh pg/osm + - name: "TEST: PG sample schemas (omnibus)" + if: ${{ !cancelled() && matrix.test_group == 'offline' }} + run: migtests/scripts/run-schema-migration.sh pg/omnibus + - name: "TEST: PG sample schemas (adventureworks)" if: ${{ !cancelled() && matrix.test_group == 'offline' }} run: migtests/scripts/run-schema-migration.sh pg/adventureworks diff --git a/migtests/scripts/functions.sh b/migtests/scripts/functions.sh index 18f3ff9a2..4d8e1d6f4 100644 --- a/migtests/scripts/functions.sh +++ b/migtests/scripts/functions.sh @@ -877,7 +877,13 @@ normalize_json() { # Normalize JSON with jq; use --sort-keys to avoid the need to keep the same sequence of keys in expected vs actual json jq --sort-keys 'walk( if type == "object" then - .ObjectNames? |= (if type == "string" then split(", ") | sort | join(", ") else . end) | + .ObjectNames? |= ( + if type == "string" then + split(", ") | sort | join(", ") + else + . + end + ) | .VoyagerVersion? = "IGNORED" | .TargetDBVersion? = "IGNORED" | .DbVersion? = "IGNORED" | @@ -885,10 +891,17 @@ normalize_json() { .OptimalSelectConnectionsPerNode? = "IGNORED" | .OptimalInsertConnectionsPerNode? = "IGNORED" | .RowCount? = "IGNORED" | - .SqlStatement? |= (if type == "string" then gsub("\\n"; " ") else . end) + # Replace newline characters in SqlStatement with spaces + .SqlStatement? |= ( + if type == "string" then + gsub("\\n"; " ") + else + . + end + ) elif type == "array" then - sort_by(tostring) - else + sort_by(tostring) + else . end )' "$input_file" > "$temp_file" diff --git a/yb-voyager/cmd/analyzeSchema.go b/yb-voyager/cmd/analyzeSchema.go index f23c13d0b..3eb78dc3b 100644 --- a/yb-voyager/cmd/analyzeSchema.go +++ b/yb-voyager/cmd/analyzeSchema.go @@ -34,6 +34,7 @@ import ( "golang.org/x/exp/slices" "github.com/yugabyte/yb-voyager/yb-voyager/src/callhome" + "github.com/yugabyte/yb-voyager/yb-voyager/src/constants" "github.com/yugabyte/yb-voyager/yb-voyager/src/cp" "github.com/yugabyte/yb-voyager/yb-voyager/src/metadb" "github.com/yugabyte/yb-voyager/yb-voyager/src/query/queryissue" @@ -220,7 +221,7 @@ const ( ) // Reports one case in JSON -func reportCase(filePath string, reason string, ghIssue string, suggestion string, objType string, objName string, sqlStmt string, issueType string, docsLink string) { +func reportCase(filePath string, reason string, ghIssue string, suggestion string, objType string, objName string, sqlStmt string, category string, docsLink string, impact string) { var issue utils.AnalyzeSchemaIssue issue.FilePath = filePath issue.Reason = reason @@ -229,7 +230,8 @@ func reportCase(filePath string, reason string, ghIssue string, suggestion strin issue.ObjectType = objType issue.ObjectName = objName issue.SqlStatement = sqlStmt - issue.IssueType = issueType + issue.IssueType = category // IssueType field of analyze schema should be renamed to Category + issue.Impact = lo.Ternary(impact != "", impact, constants.IMPACT_LEVEL_1) if sourceDBType == POSTGRESQL { issue.DocsLink = docsLink } @@ -239,13 +241,13 @@ func reportCase(filePath string, reason string, ghIssue string, suggestion strin func reportBasedOnComment(comment int, fpath string, issue string, suggestion string, objName string, objType string, line string) { if comment == 1 { - reportCase(fpath, "Unsupported, please edit to match PostgreSQL syntax", "https://github.com/yugabyte/yb-voyager/issues/1625", suggestion, objType, objName, line, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "Unsupported, please edit to match PostgreSQL syntax", "https://github.com/yugabyte/yb-voyager/issues/1625", suggestion, objType, objName, line, UNSUPPORTED_FEATURES_CATEGORY, "", "") summaryMap[objType].invalidCount[objName] = true } else if comment == 2 { - // reportCase(fpath, "PACKAGE in oracle are exported as Schema, please review and edit to match PostgreSQL syntax if required, Package is "+objName, issue, suggestion, objType) + // reportCase(fpath, "PACKAGE in oracle are exported as Schema, please review and edit to match PostgreSQL syntax if required, Package is "+objName, issue, suggestion, objType, "") summaryMap["PACKAGE"].objSet = append(summaryMap["PACKAGE"].objSet, objName) } else if comment == 3 { - reportCase(fpath, "SQLs in file might be unsupported please review and edit to match PostgreSQL syntax if required. ", "https://github.com/yugabyte/yb-voyager/issues/1625", suggestion, objType, objName, line, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "SQLs in file might be unsupported please review and edit to match PostgreSQL syntax if required. ", "https://github.com/yugabyte/yb-voyager/issues/1625", suggestion, objType, objName, line, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if comment == 4 { summaryMap[objType].details["Inherited Types are present which are not supported in PostgreSQL syntax, so exported as Inherited Tables"] = true } @@ -321,7 +323,7 @@ func checkStmtsUsingParser(sqlInfoArr []sqlInfo, fpath string, objType string) { if !summaryMap[objType].invalidCount[sqlStmtInfo.objName] { reason := fmt.Sprintf("%s - '%s'", UNSUPPORTED_PG_SYNTAX, err.Error()) reportCase(fpath, reason, "https://github.com/yugabyte/yb-voyager/issues/1625", - "Fix the schema as per PG syntax", objType, sqlStmtInfo.objName, sqlStmtInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "Fix the schema as per PG syntax", objType, sqlStmtInfo.objName, sqlStmtInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } continue } @@ -348,7 +350,7 @@ func checkViews(sqlInfoArr []sqlInfo, fpath string) { if view := viewWithCheckRegex.FindStringSubmatch(sqlInfo.stmt); view != nil { summaryMap["VIEW"].invalidCount[sqlInfo.objName] = true reportCase(fpath, VIEW_CHECK_OPTION_ISSUE, "https://github.com/yugabyte/yugabyte-db/issues/22716", - "Use Trigger with INSTEAD OF clause on INSERT/UPDATE on view to get this functionality", "VIEW", view[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, VIEW_CHECK_OPTION_DOC_LINK) + "Use Trigger with INSTEAD OF clause on INSERT/UPDATE on view to get this functionality", "VIEW", view[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, VIEW_CHECK_OPTION_DOC_LINK, "") } } } @@ -372,47 +374,47 @@ func checkSql(sqlInfoArr []sqlInfo, fpath string) { if rangeRegex.MatchString(sqlInfo.stmt) { reportCase(fpath, "RANGE with offset PRECEDING/FOLLOWING is not supported for column type numeric and offset type double precision", - "https://github.com/yugabyte/yugabyte-db/issues/10692", "", "TABLE", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yugabyte-db/issues/10692", "", "TABLE", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true } else if stmt := fetchRegex.FindStringSubmatch(sqlInfo.stmt); stmt != nil { location := strings.ToUpper(stmt[1]) if slices.Contains(notSupportedFetchLocation, location) { summaryMap["PROCEDURE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "This FETCH clause might not be supported yet", "https://github.com/YugaByte/yugabyte-db/issues/6514", - "Please verify the DDL on your YugabyteDB version before proceeding", "CURSOR", sqlInfo.objName, sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "Please verify the DDL on your YugabyteDB version before proceeding", "CURSOR", sqlInfo.objName, sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } } else if stmt := alterAggRegex.FindStringSubmatch(sqlInfo.stmt); stmt != nil { summaryMap["AGGREGATE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER AGGREGATE not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/2717", "", "AGGREGATE", stmt[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/2717", "", "AGGREGATE", stmt[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if dropCollRegex.MatchString(sqlInfo.stmt) { summaryMap["COLLATION"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "DROP multiple objects not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP COLLATION", sqlInfo.formattedStmt), "COLLATION", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP COLLATION", sqlInfo.formattedStmt), "COLLATION", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if dropIdxRegex.MatchString(sqlInfo.stmt) { summaryMap["INDEX"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "DROP multiple objects not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP INDEX", sqlInfo.formattedStmt), "INDEX", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP INDEX", sqlInfo.formattedStmt), "INDEX", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if dropViewRegex.MatchString(sqlInfo.stmt) { summaryMap["VIEW"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "DROP multiple objects not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP VIEW", sqlInfo.formattedStmt), "VIEW", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP VIEW", sqlInfo.formattedStmt), "VIEW", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if dropSeqRegex.MatchString(sqlInfo.stmt) { summaryMap["SEQUENCE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "DROP multiple objects not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP SEQUENCE", sqlInfo.formattedStmt), "SEQUENCE", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP SEQUENCE", sqlInfo.formattedStmt), "SEQUENCE", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if dropForeignRegex.MatchString(sqlInfo.stmt) { summaryMap["FOREIGN TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "DROP multiple objects not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP FOREIGN TABLE", sqlInfo.formattedStmt), "FOREIGN TABLE", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/880", separateMultiObj("DROP FOREIGN TABLE", sqlInfo.formattedStmt), "FOREIGN TABLE", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if idx := dropIdxConcurRegex.FindStringSubmatch(sqlInfo.stmt); idx != nil { summaryMap["INDEX"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "DROP INDEX CONCURRENTLY not supported yet", - "https://github.com/yugabyte/yugabyte-db/issues/22717", "", "INDEX", idx[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yugabyte-db/issues/22717", "", "INDEX", idx[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if currentOfRegex.MatchString(sqlInfo.stmt) { - reportCase(fpath, "WHERE CURRENT OF not supported yet", "https://github.com/YugaByte/yugabyte-db/issues/737", "", "CURSOR", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "WHERE CURRENT OF not supported yet", "https://github.com/YugaByte/yugabyte-db/issues/737", "", "CURSOR", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if bulkCollectRegex.MatchString(sqlInfo.stmt) { - reportCase(fpath, "BULK COLLECT keyword of oracle is not converted into PostgreSQL compatible syntax", "https://github.com/yugabyte/yb-voyager/issues/1539", "", "", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "BULK COLLECT keyword of oracle is not converted into PostgreSQL compatible syntax", "https://github.com/yugabyte/yb-voyager/issues/1539", "", "", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } } } @@ -424,106 +426,106 @@ func checkDDL(sqlInfoArr []sqlInfo, fpath string, objType string) { if am := amRegex.FindStringSubmatch(sqlInfo.stmt); am != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "CREATE ACCESS METHOD is not supported.", - "https://github.com/yugabyte/yugabyte-db/issues/10693", "", "ACCESS METHOD", am[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yugabyte-db/issues/10693", "", "ACCESS METHOD", am[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := idxConcRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "REINDEX is not supported.", - "https://github.com/yugabyte/yugabyte-db/issues/10267", "", "TABLE", tbl[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yugabyte-db/issues/10267", "", "TABLE", tbl[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := likeAllRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "LIKE ALL is not supported yet.", - "https://github.com/yugabyte/yugabyte-db/issues/10697", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yugabyte-db/issues/10697", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := likeRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "LIKE clause not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1129", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1129", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := withOidsRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "OIDs are not supported for user tables.", - "https://github.com/yugabyte/yugabyte-db/issues/10273", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yugabyte-db/issues/10273", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterOfRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE OF not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterSchemaRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE SET SCHEMA not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/3947", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/3947", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if createSchemaRegex.MatchString(sqlInfo.stmt) { summaryMap["SCHEMA"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "CREATE SCHEMA with elements not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/10865", "", "SCHEMA", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/10865", "", "SCHEMA", "", sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterNotOfRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE NOT OF not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterColumnStatsRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE ALTER column SET STATISTICS not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterColumnStorageRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE ALTER column SET STORAGE not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterColumnResetAttributesRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE ALTER column RESET (attribute) not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterConstrRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE ALTER CONSTRAINT not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := setOidsRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE SET WITH OIDS not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[4], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[4], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := withoutClusterRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE SET WITHOUT CLUSTER not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterSetRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE SET not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterIdxRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER INDEX SET not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "INDEX", tbl[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "INDEX", tbl[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterResetRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE RESET not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterOptionsRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if typ := dropAttrRegex.FindStringSubmatch(sqlInfo.stmt); typ != nil { summaryMap["TYPE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TYPE DROP ATTRIBUTE not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1893", "", "TYPE", typ[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1893", "", "TYPE", typ[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if typ := alterTypeRegex.FindStringSubmatch(sqlInfo.stmt); typ != nil { summaryMap["TYPE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TYPE not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1893", "", "TYPE", typ[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1893", "", "TYPE", typ[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := alterInhRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE INHERIT not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := valConstrRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLE VALIDATE CONSTRAINT not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1124", "", "TABLE", tbl[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if spc := alterTblSpcRegex.FindStringSubmatch(sqlInfo.stmt); spc != nil { summaryMap["TABLESPACE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER TABLESPACE not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1153", "", "TABLESPACE", spc[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1153", "", "TABLESPACE", spc[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if spc := alterViewRegex.FindStringSubmatch(sqlInfo.stmt); spc != nil { summaryMap["VIEW"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "ALTER VIEW not supported yet.", - "https://github.com/YugaByte/yugabyte-db/issues/1131", "", "VIEW", spc[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/YugaByte/yugabyte-db/issues/1131", "", "VIEW", spc[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := cLangRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { reportCase(fpath, "LANGUAGE C not supported yet.", - "https://github.com/yugabyte/yb-voyager/issues/1540", "", "FUNCTION", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yb-voyager/issues/1540", "", "FUNCTION", tbl[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") summaryMap["FUNCTION"].invalidCount[sqlInfo.objName] = true } else if strings.Contains(strings.ToLower(sqlInfo.stmt), "drop temporary table") { filePath := strings.Split(fpath, "/") @@ -531,22 +533,22 @@ func checkDDL(sqlInfoArr []sqlInfo, fpath string, objType string) { objType := strings.ToUpper(strings.Split(fileName, ".")[0]) summaryMap[objType].invalidCount[sqlInfo.objName] = true reportCase(fpath, `temporary table is not a supported clause for drop`, - "https://github.com/yugabyte/yb-voyager/issues/705", `remove "temporary" and change it to "drop table"`, objType, sqlInfo.objName, sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, DROP_TEMP_TABLE_DOC_LINK) + "https://github.com/yugabyte/yb-voyager/issues/705", `remove "temporary" and change it to "drop table"`, objType, sqlInfo.objName, sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, DROP_TEMP_TABLE_DOC_LINK, "") } else if regMatch := anydataRegex.FindStringSubmatch(sqlInfo.stmt); regMatch != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true - reportCase(fpath, "AnyData datatype doesn't have a mapping in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1541", `Remove the column with AnyData datatype or change it to a relevant supported datatype`, "TABLE", regMatch[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "AnyData datatype doesn't have a mapping in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1541", `Remove the column with AnyData datatype or change it to a relevant supported datatype`, "TABLE", regMatch[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if regMatch := anydatasetRegex.FindStringSubmatch(sqlInfo.stmt); regMatch != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true - reportCase(fpath, "AnyDataSet datatype doesn't have a mapping in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1541", `Remove the column with AnyDataSet datatype or change it to a relevant supported datatype`, "TABLE", regMatch[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "AnyDataSet datatype doesn't have a mapping in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1541", `Remove the column with AnyDataSet datatype or change it to a relevant supported datatype`, "TABLE", regMatch[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if regMatch := anyTypeRegex.FindStringSubmatch(sqlInfo.stmt); regMatch != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true - reportCase(fpath, "AnyType datatype doesn't have a mapping in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1541", `Remove the column with AnyType datatype or change it to a relevant supported datatype`, "TABLE", regMatch[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "AnyType datatype doesn't have a mapping in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1541", `Remove the column with AnyType datatype or change it to a relevant supported datatype`, "TABLE", regMatch[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if regMatch := uriTypeRegex.FindStringSubmatch(sqlInfo.stmt); regMatch != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true - reportCase(fpath, "URIType datatype doesn't have a mapping in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1541", `Remove the column with URIType datatype or change it to a relevant supported datatype`, "TABLE", regMatch[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "URIType datatype doesn't have a mapping in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1541", `Remove the column with URIType datatype or change it to a relevant supported datatype`, "TABLE", regMatch[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if regMatch := jsonFuncRegex.FindStringSubmatch(sqlInfo.stmt); regMatch != nil { summaryMap[objType].invalidCount[sqlInfo.objName] = true - reportCase(fpath, "JSON_ARRAYAGG() function is not available in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1542", `Rename the function to YugabyteDB's equivalent JSON_AGG()`, objType, regMatch[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + reportCase(fpath, "JSON_ARRAYAGG() function is not available in YugabyteDB", "https://github.com/yugabyte/yb-voyager/issues/1542", `Rename the function to YugabyteDB's equivalent JSON_AGG()`, objType, regMatch[3], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } } @@ -559,11 +561,11 @@ func checkForeign(sqlInfoArr []sqlInfo, fpath string) { if tbl := primRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "Primary key constraints are not supported on foreign tables.", - "https://github.com/yugabyte/yugabyte-db/issues/10698", "", "TABLE", tbl[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yugabyte-db/issues/10698", "", "TABLE", tbl[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } else if tbl := foreignKeyRegex.FindStringSubmatch(sqlInfo.stmt); tbl != nil { summaryMap["TABLE"].invalidCount[sqlInfo.objName] = true reportCase(fpath, "Foreign key constraints are not supported on foreign tables.", - "https://github.com/yugabyte/yugabyte-db/issues/10699", "", "TABLE", tbl[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yugabyte-db/issues/10699", "", "TABLE", tbl[1], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") } } } @@ -573,7 +575,7 @@ func checkRemaining(sqlInfoArr []sqlInfo, fpath string) { for _, sqlInfo := range sqlInfoArr { if trig := compoundTrigRegex.FindStringSubmatch(sqlInfo.stmt); trig != nil { reportCase(fpath, COMPOUND_TRIGGER_ISSUE_REASON, - "https://github.com/yugabyte/yb-voyager/issues/1543", "", "TRIGGER", trig[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, "") + "https://github.com/yugabyte/yb-voyager/issues/1543", "", "TRIGGER", trig[2], sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, "", "") summaryMap["TRIGGER"].invalidCount[sqlInfo.objName] = true } } @@ -620,18 +622,18 @@ var MigrationCaveatsIssues = []string{ } func convertIssueInstanceToAnalyzeIssue(issueInstance queryissue.QueryIssue, fileName string, isPlPgSQLIssue bool) utils.AnalyzeSchemaIssue { - issueType := UNSUPPORTED_FEATURES + issueType := UNSUPPORTED_FEATURES_CATEGORY switch true { case isPlPgSQLIssue: - issueType = UNSUPPORTED_PLPGSQL_OBEJCTS + issueType = UNSUPPORTED_PLPGSQL_OBJECTS_CATEGORY case slices.ContainsFunc(MigrationCaveatsIssues, func(i string) bool { //Adding the MIGRATION_CAVEATS issueType of the utils.Issue for these issueInstances in MigrationCaveatsIssues - return strings.Contains(issueInstance.TypeName, i) + return strings.Contains(issueInstance.Name, i) }): - issueType = MIGRATION_CAVEATS - case strings.HasPrefix(issueInstance.TypeName, UNSUPPORTED_DATATYPE): + issueType = MIGRATION_CAVEATS_CATEGORY + case strings.HasPrefix(issueInstance.Name, UNSUPPORTED_DATATYPE): //Adding the UNSUPPORTED_DATATYPES issueType of the utils.Issue for these issues whose TypeName starts with "Unsupported datatype ..." - issueType = UNSUPPORTED_DATATYPES + issueType = UNSUPPORTED_DATATYPES_CATEGORY } var constraintIssues = []string{ @@ -674,8 +676,9 @@ func convertIssueInstanceToAnalyzeIssue(issueInstance queryissue.QueryIssue, fil IssueType: issueType, ObjectType: issueInstance.ObjectType, ObjectName: displayObjectName, - Reason: issueInstance.TypeName, + Reason: issueInstance.Name, Type: issueInstance.Type, + Impact: issueInstance.Impact, SqlStatement: issueInstance.SqlStatement, DocsLink: issueInstance.DocsLink, FilePath: fileName, @@ -690,7 +693,7 @@ func checkExtensions(sqlInfoArr []sqlInfo, fpath string) { if sqlInfo.objName != "" && !slices.Contains(supportedExtensionsOnYB, sqlInfo.objName) { summaryMap["EXTENSION"].invalidCount[sqlInfo.objName] = true reportCase(fpath, UNSUPPORTED_EXTENSION_ISSUE+" Refer to the docs link for the more information on supported extensions.", "https://github.com/yugabyte/yb-voyager/issues/1538", "", "EXTENSION", - sqlInfo.objName, sqlInfo.formattedStmt, UNSUPPORTED_FEATURES, EXTENSION_DOC_LINK) + sqlInfo.objName, sqlInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, EXTENSION_DOC_LINK, constants.IMPACT_LEVEL_3) } if strings.ToLower(sqlInfo.objName) == "hll" { summaryMap["EXTENSION"].details[`'hll' extension is supported in YugabyteDB v2.18 onwards. Please verify this extension as per the target YugabyteDB version.`] = true @@ -1110,12 +1113,12 @@ func checkConversions(sqlInfoArr []sqlInfo, filePath string) { convName = fmt.Sprintf("%s.%s", convName, nameList[1].GetString_().Sval) } reportCase(filePath, CONVERSION_ISSUE_REASON, "https://github.com/yugabyte/yugabyte-db/issues/10866", - "Remove it from the exported schema", "CONVERSION", convName, sqlStmtInfo.formattedStmt, UNSUPPORTED_FEATURES, CREATE_CONVERSION_DOC_LINK) + "Remove it from the exported schema", "CONVERSION", convName, sqlStmtInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, CREATE_CONVERSION_DOC_LINK, constants.IMPACT_LEVEL_3) } else { //pg_query doesn't seem to have a Node type of AlterConversionStmt so using regex for now if stmt := alterConvRegex.FindStringSubmatch(sqlStmtInfo.stmt); stmt != nil { reportCase(filePath, "ALTER CONVERSION is not supported yet", "https://github.com/YugaByte/yugabyte-db/issues/10866", - "Remove it from the exported schema", "CONVERSION", stmt[1], sqlStmtInfo.formattedStmt, UNSUPPORTED_FEATURES, CREATE_CONVERSION_DOC_LINK) + "Remove it from the exported schema", "CONVERSION", stmt[1], sqlStmtInfo.formattedStmt, UNSUPPORTED_FEATURES_CATEGORY, CREATE_CONVERSION_DOC_LINK, "") } } diff --git a/yb-voyager/cmd/assessMigrationCommand.go b/yb-voyager/cmd/assessMigrationCommand.go index f22eba98e..a80de6b4e 100644 --- a/yb-voyager/cmd/assessMigrationCommand.go +++ b/yb-voyager/cmd/assessMigrationCommand.go @@ -38,6 +38,7 @@ import ( "golang.org/x/exp/slices" "github.com/yugabyte/yb-voyager/yb-voyager/src/callhome" + "github.com/yugabyte/yb-voyager/yb-voyager/src/constants" "github.com/yugabyte/yb-voyager/yb-voyager/src/cp" "github.com/yugabyte/yb-voyager/yb-voyager/src/metadb" "github.com/yugabyte/yb-voyager/yb-voyager/src/migassessment" @@ -423,6 +424,7 @@ func assessMigration() (err error) { return fmt.Errorf("failed to generate assessment report: %w", err) } + log.Infof("number of assessment issues detected: %d\n", len(assessmentReport.Issues)) utils.PrintAndLog("Migration assessment completed successfully.") completedEvent := createMigrationAssessmentCompletedEvent() controlPlane.MigrationAssessmentCompleted(completedEvent) @@ -538,8 +540,8 @@ func flattenAssessmentReportToAssessmentIssues(ar AssessmentReport) []Assessment } for _, unsupportedDataType := range ar.UnsupportedDataTypes { issues = append(issues, AssessmentIssueYugabyteD{ - Type: DATATYPE, - TypeDescription: DATATYPE_ISSUE_TYPE_DESCRIPTION, + Type: constants.DATATYPE, + TypeDescription: GetCategoryDescription(constants.DATATYPE), Subtype: unsupportedDataType.DataType, ObjectName: fmt.Sprintf("%s.%s.%s", unsupportedDataType.SchemaName, unsupportedDataType.TableName, unsupportedDataType.ColumnName), SqlStatement: "", @@ -550,8 +552,8 @@ func flattenAssessmentReportToAssessmentIssues(ar AssessmentReport) []Assessment for _, unsupportedFeature := range ar.UnsupportedFeatures { for _, object := range unsupportedFeature.Objects { issues = append(issues, AssessmentIssueYugabyteD{ - Type: FEATURE, - TypeDescription: FEATURE_ISSUE_TYPE_DESCRIPTION, + Type: constants.FEATURE, + TypeDescription: GetCategoryDescription(constants.FEATURE), Subtype: unsupportedFeature.FeatureName, SubtypeDescription: unsupportedFeature.FeatureDescription, // TODO: test payload once we add desc for unsupported features ObjectName: object.ObjectName, @@ -565,8 +567,8 @@ func flattenAssessmentReportToAssessmentIssues(ar AssessmentReport) []Assessment for _, migrationCaveat := range ar.MigrationCaveats { for _, object := range migrationCaveat.Objects { issues = append(issues, AssessmentIssueYugabyteD{ - Type: MIGRATION_CAVEATS, - TypeDescription: MIGRATION_CAVEATS_TYPE_DESCRIPTION, + Type: constants.MIGRATION_CAVEATS, + TypeDescription: GetCategoryDescription(constants.MIGRATION_CAVEATS), Subtype: migrationCaveat.FeatureName, SubtypeDescription: migrationCaveat.FeatureDescription, ObjectName: object.ObjectName, @@ -579,8 +581,8 @@ func flattenAssessmentReportToAssessmentIssues(ar AssessmentReport) []Assessment for _, uqc := range ar.UnsupportedQueryConstructs { issues = append(issues, AssessmentIssueYugabyteD{ - Type: QUERY_CONSTRUCT, - TypeDescription: UNSUPPORTED_QUERY_CONSTRUTS_DESCRIPTION, + Type: constants.QUERY_CONSTRUCT, + TypeDescription: GetCategoryDescription(constants.QUERY_CONSTRUCT), Subtype: uqc.ConstructTypeName, SqlStatement: uqc.Query, DocsLink: uqc.DocsLink, @@ -591,8 +593,8 @@ func flattenAssessmentReportToAssessmentIssues(ar AssessmentReport) []Assessment for _, plpgsqlObjects := range ar.UnsupportedPlPgSqlObjects { for _, object := range plpgsqlObjects.Objects { issues = append(issues, AssessmentIssueYugabyteD{ - Type: PLPGSQL_OBJECT, - TypeDescription: UNSUPPPORTED_PLPGSQL_OBJECT_DESCRIPTION, + Type: constants.PLPGSQL_OBJECT, + TypeDescription: GetCategoryDescription(constants.PLPGSQL_OBJECT), Subtype: plpgsqlObjects.FeatureName, SubtypeDescription: plpgsqlObjects.FeatureDescription, ObjectName: object.ObjectName, @@ -888,7 +890,11 @@ func generateAssessmentReport() (err error) { return fmt.Errorf("failed to fetch columns with unsupported data types: %w", err) } assessmentReport.UnsupportedDataTypes = unsupportedDataTypes - assessmentReport.UnsupportedDataTypesDesc = DATATYPE_ISSUE_TYPE_DESCRIPTION + assessmentReport.UnsupportedDataTypesDesc = DATATYPE_CATEGORY_DESCRIPTION + + assessmentReport.AppendIssues(getAssessmentIssuesForUnsupportedDatatypes(unsupportedDataTypes)...) + + addMigrationCaveatsToAssessmentReport(unsupportedDataTypesForLiveMigration, unsupportedDataTypesForLiveMigrationWithFForFB) assessmentReport.Sizing = migassessment.SizingReport assessmentReport.TableIndexStats, err = assessmentDB.FetchAllStats() @@ -897,7 +903,6 @@ func generateAssessmentReport() (err error) { } addNotesToAssessmentReport() - addMigrationCaveatsToAssessmentReport(unsupportedDataTypesForLiveMigration, unsupportedDataTypesForLiveMigrationWithFForFB) postProcessingOfAssessmentReport() assessmentReportDir := filepath.Join(exportDir, "assessment", "reports") @@ -915,20 +920,16 @@ func generateAssessmentReport() (err error) { func getAssessmentReportContentFromAnalyzeSchema() error { /* - Here we are generating analyze schema report which converts issue instance to analyze schema issue - Then in assessment codepath we extract the required information from analyze schema issue which could have been done directly from issue instance(TODO) + Here we are generating analyze schema report which converts issue instance to analyze schema issue + Then in assessment codepath we extract the required information from analyze schema issue which could have been done directly from issue instance(TODO) - But current Limitation is analyze schema currently uses regexp etc to detect some issues(not using parser). + But current Limitation is analyze schema currently uses regexp etc to detect some issues(not using parser). */ schemaAnalysisReport := analyzeSchemaInternal(&source, true) assessmentReport.MigrationComplexity = schemaAnalysisReport.MigrationComplexity assessmentReport.SchemaSummary = schemaAnalysisReport.SchemaSummary - assessmentReport.SchemaSummary.Description = SCHEMA_SUMMARY_DESCRIPTION - if source.DBType == ORACLE { - assessmentReport.SchemaSummary.Description = SCHEMA_SUMMARY_DESCRIPTION_ORACLE - } + assessmentReport.SchemaSummary.Description = lo.Ternary(source.DBType == ORACLE, SCHEMA_SUMMARY_DESCRIPTION_ORACLE, SCHEMA_SUMMARY_DESCRIPTION) - // fetching unsupportedFeaturing with the help of Issues report in SchemaReport var unsupportedFeatures []UnsupportedFeature var err error switch source.DBType { @@ -940,13 +941,14 @@ func getAssessmentReportContentFromAnalyzeSchema() error { panic(fmt.Sprintf("unsupported source db type %q", source.DBType)) } if err != nil { - return fmt.Errorf("failed to fetch %s unsupported features: %w", source.DBType, err) + return fmt.Errorf("failed to fetch '%s' unsupported features: %w", source.DBType, err) } assessmentReport.UnsupportedFeatures = append(assessmentReport.UnsupportedFeatures, unsupportedFeatures...) - assessmentReport.UnsupportedFeaturesDesc = FEATURE_ISSUE_TYPE_DESCRIPTION + assessmentReport.UnsupportedFeaturesDesc = FEATURE_CATEGORY_DESCRIPTION + + // Ques: Do we still need this and REPORT_UNSUPPORTED_QUERY_CONSTRUCTS env var if utils.GetEnvAsBool("REPORT_UNSUPPORTED_PLPGSQL_OBJECTS", true) { - unsupportedPlpgSqlObjects := fetchUnsupportedPlPgSQLObjects(schemaAnalysisReport) - assessmentReport.UnsupportedPlPgSqlObjects = unsupportedPlpgSqlObjects + assessmentReport.UnsupportedPlPgSqlObjects = fetchUnsupportedPlPgSQLObjects(schemaAnalysisReport) } return nil } @@ -980,31 +982,52 @@ func getUnsupportedFeaturesFromSchemaAnalysisReport(featureName string, issueRea var minVersionsFixedIn map[string]*ybversion.YBVersion var minVersionsFixedInSet bool - for _, issue := range schemaAnalysisReport.Issues { - if !slices.Contains([]string{UNSUPPORTED_FEATURES, MIGRATION_CAVEATS}, issue.IssueType) { + for _, analyzeIssue := range schemaAnalysisReport.Issues { + if !slices.Contains([]string{UNSUPPORTED_FEATURES_CATEGORY, MIGRATION_CAVEATS_CATEGORY}, analyzeIssue.IssueType) { continue } - issueMatched := lo.Ternary[bool](issueType != "", issueType == issue.Type, strings.Contains(issue.Reason, issueReason)) + issueMatched := lo.Ternary[bool](issueType != "", issueType == analyzeIssue.Type, strings.Contains(analyzeIssue.Reason, issueReason)) if issueMatched { - objectInfo := ObjectInfo{ - ObjectName: issue.ObjectName, - SqlStatement: issue.SqlStatement, - } - link = issue.DocsLink - objects = append(objects, objectInfo) if !minVersionsFixedInSet { - minVersionsFixedIn = issue.MinimumVersionsFixedIn + minVersionsFixedIn = analyzeIssue.MinimumVersionsFixedIn minVersionsFixedInSet = true } - if !areMinVersionsFixedInEqual(minVersionsFixedIn, issue.MinimumVersionsFixedIn) { - utils.ErrExit("Issues belonging to UnsupportedFeature %s have different minimum versions fixed in: %v, %v", featureName, minVersionsFixedIn, issue.MinimumVersionsFixedIn) + if !areMinVersionsFixedInEqual(minVersionsFixedIn, analyzeIssue.MinimumVersionsFixedIn) { + utils.ErrExit("Issues belonging to UnsupportedFeature %s have different minimum versions fixed in: %v, %v", featureName, minVersionsFixedIn, analyzeIssue.MinimumVersionsFixedIn) } + + objectInfo := ObjectInfo{ + ObjectName: analyzeIssue.ObjectName, + SqlStatement: analyzeIssue.SqlStatement, + } + link = analyzeIssue.DocsLink + objects = append(objects, objectInfo) + + assessmentReport.AppendIssues(convertAnalyzeSchemaIssueToAssessmentIssue(analyzeIssue, description, minVersionsFixedIn)) } } + return UnsupportedFeature{featureName, objects, displayDDLInHTML, link, description, minVersionsFixedIn} } +// Q: do we no need of displayDDLInHTML in this approach? DDL can always be there for issues in the table if present. +func convertAnalyzeSchemaIssueToAssessmentIssue(analyzeSchemaIssue utils.AnalyzeSchemaIssue, issueDescription string, minVersionsFixedIn map[string]*ybversion.YBVersion) AssessmentIssue { + return AssessmentIssue{ + Category: analyzeSchemaIssue.IssueType, + CategoryDescription: GetCategoryDescription(analyzeSchemaIssue.IssueType), + Type: analyzeSchemaIssue.Type, + Name: analyzeSchemaIssue.Reason, // in convertIssueInstanceToAnalyzeIssue() we assign IssueType to Reason field + Description: issueDescription, // TODO: verify + Impact: analyzeSchemaIssue.Impact, + ObjectType: analyzeSchemaIssue.ObjectType, + ObjectName: analyzeSchemaIssue.ObjectName, + SqlStatement: analyzeSchemaIssue.SqlStatement, + DocsLink: analyzeSchemaIssue.DocsLink, + MinimumVersionFixedIn: minVersionsFixedIn, + } +} + func fetchUnsupportedPGFeaturesFromSchemaReport(schemaAnalysisReport utils.SchemaReport) ([]UnsupportedFeature, error) { log.Infof("fetching unsupported features for PG...") unsupportedFeatures := make([]UnsupportedFeature, 0) @@ -1115,13 +1138,42 @@ func fetchUnsupportedObjectTypes() ([]UnsupportedFeature, error) { unsupportedIndexes = append(unsupportedIndexes, ObjectInfo{ ObjectName: fmt.Sprintf("Index Name: %s, Index Type=%s", objectName, objectType), }) + + assessmentReport.AppendIssues(AssessmentIssue{ + Category: UNSUPPORTED_FEATURES_CATEGORY, + Type: "", // TODO + Name: UNSUPPORTED_INDEXES_FEATURE, + ObjectType: "INDEX", + ObjectName: fmt.Sprintf("Index Name: %s, Index Type=%s", objectName, objectType), + }) } else if objectType == VIRTUAL_COLUMN { virtualColumns = append(virtualColumns, ObjectInfo{ObjectName: objectName}) + assessmentReport.AppendIssues(AssessmentIssue{ + Category: UNSUPPORTED_FEATURES_CATEGORY, + Type: "", // TODO + Name: VIRTUAL_COLUMNS_FEATURE, + ObjectName: objectName, + }) } else if objectType == INHERITED_TYPE { inheritedTypes = append(inheritedTypes, ObjectInfo{ObjectName: objectName}) + assessmentReport.AppendIssues(AssessmentIssue{ + Category: UNSUPPORTED_FEATURES_CATEGORY, + Type: "", // TODO + Name: INHERITED_TYPES_FEATURE, + ObjectName: objectName, + }) } else if objectType == REFERENCE_PARTITION || objectType == SYSTEM_PARTITION { referenceOrTablePartitionPresent = true unsupportedPartitionTypes = append(unsupportedPartitionTypes, ObjectInfo{ObjectName: fmt.Sprintf("Table Name: %s, Partition Method: %s", objectName, objectType)}) + + // For oracle migration complexity comes from ora2pg, so defining Impact not required right now + assessmentReport.AppendIssues(AssessmentIssue{ + Category: UNSUPPORTED_FEATURES_CATEGORY, + Type: "", // TODO + Name: UNSUPPORTED_PARTITIONING_METHODS_FEATURE, + ObjectType: "TABLE", + ObjectName: fmt.Sprintf("Table Name: %s, Partition Method: %s", objectName, objectType), + }) } } @@ -1139,9 +1191,9 @@ func fetchUnsupportedPlPgSQLObjects(schemaAnalysisReport utils.SchemaReport) []U if source.DBType != POSTGRESQL { return nil } - analyzeIssues := schemaAnalysisReport.Issues - plpgsqlIssues := lo.Filter(analyzeIssues, func(issue utils.AnalyzeSchemaIssue, _ int) bool { - return issue.IssueType == UNSUPPORTED_PLPGSQL_OBEJCTS + + plpgsqlIssues := lo.Filter(schemaAnalysisReport.Issues, func(issue utils.AnalyzeSchemaIssue, _ int) bool { + return issue.IssueType == UNSUPPORTED_PLPGSQL_OBJECTS_CATEGORY }) groupPlpgsqlIssuesByReason := lo.GroupBy(plpgsqlIssues, func(issue utils.AnalyzeSchemaIssue) string { return issue.Reason @@ -1154,11 +1206,6 @@ func fetchUnsupportedPlPgSQLObjects(schemaAnalysisReport utils.SchemaReport) []U var minVersionsFixedInSet bool for _, issue := range issues { - objects = append(objects, ObjectInfo{ - ObjectType: issue.ObjectType, - ObjectName: issue.ObjectName, - SqlStatement: issue.SqlStatement, - }) if !minVersionsFixedInSet { minVersionsFixedIn = issue.MinimumVersionsFixedIn minVersionsFixedInSet = true @@ -1166,7 +1213,25 @@ func fetchUnsupportedPlPgSQLObjects(schemaAnalysisReport utils.SchemaReport) []U if !areMinVersionsFixedInEqual(minVersionsFixedIn, issue.MinimumVersionsFixedIn) { utils.ErrExit("Issues belonging to UnsupportedFeature %s have different minimum versions fixed in: %v, %v", reason, minVersionsFixedIn, issue.MinimumVersionsFixedIn) } + + objects = append(objects, ObjectInfo{ + ObjectType: issue.ObjectType, + ObjectName: issue.ObjectName, + SqlStatement: issue.SqlStatement, + }) docsLink = issue.DocsLink + + assessmentReport.AppendIssues(AssessmentIssue{ + Category: UNSUPPORTED_PLPGSQL_OBJECTS_CATEGORY, + Type: issue.Type, + Name: reason, + Impact: issue.Impact, // TODO: verify(expected already there since underlying issues are assigned) + ObjectType: issue.ObjectType, + ObjectName: issue.ObjectName, + SqlStatement: issue.SqlStatement, + DocsLink: issue.DocsLink, + MinimumVersionFixedIn: issue.MinimumVersionsFixedIn, + }) } feature := UnsupportedFeature{ FeatureName: reason, @@ -1237,11 +1302,21 @@ func fetchUnsupportedQueryConstructs() ([]utils.UnsupportedQueryConstruct, error for _, issue := range issues { uqc := utils.UnsupportedQueryConstruct{ Query: issue.SqlStatement, - ConstructTypeName: issue.TypeName, + ConstructTypeName: issue.Name, DocsLink: issue.DocsLink, MinimumVersionsFixedIn: issue.MinimumVersionsFixedIn, } result = append(result, uqc) + + assessmentReport.AppendIssues(AssessmentIssue{ + Category: UNSUPPORTED_QUERY_CONSTRUCTS_CATEGORY, + Type: issue.Type, + Name: issue.Name, + Impact: issue.Impact, + SqlStatement: issue.SqlStatement, + DocsLink: issue.DocsLink, + MinimumVersionFixedIn: issue.MinimumVersionsFixedIn, + }) } } @@ -1334,6 +1409,27 @@ func fetchColumnsWithUnsupportedDataTypes() ([]utils.TableColumnsDataTypes, []ut return unsupportedDataTypes, unsupportedDataTypesForLiveMigration, unsupportedDataTypesForLiveMigrationWithFForFB, nil } +func getAssessmentIssuesForUnsupportedDatatypes(unsupportedDatatypes []utils.TableColumnsDataTypes) []AssessmentIssue { + var assessmentIssues []AssessmentIssue + for _, colInfo := range unsupportedDatatypes { + qualifiedColName := fmt.Sprintf("%s.%s.%s", colInfo.SchemaName, colInfo.TableName, colInfo.ColumnName) + issue := AssessmentIssue{ + Category: UNSUPPORTED_DATATYPES_CATEGORY, + CategoryDescription: GetCategoryDescription(UNSUPPORTED_DATATYPES_CATEGORY), + Type: colInfo.DataType, // TODO: maybe name it like "unsupported datatype - geometry" + Name: colInfo.DataType, // TODO: maybe name it like "unsupported datatype - geometry" + Impact: constants.IMPACT_LEVEL_3, + ObjectType: constants.COLUMN, + ObjectName: qualifiedColName, + DocsLink: "", // TODO + MinimumVersionFixedIn: nil, // TODO + } + assessmentIssues = append(assessmentIssues, issue) + } + + return assessmentIssues +} + /* Queries to ignore: - Collected schemas is totally different than source schema list, not containing "" @@ -1427,24 +1523,48 @@ func addMigrationCaveatsToAssessmentReport(unsupportedDataTypesForLiveMigration migrationCaveats = append(migrationCaveats, getUnsupportedFeaturesFromSchemaAnalysisReport(FOREIGN_TABLE_CAVEAT_FEATURE, "", queryissue.FOREIGN_TABLE, schemaAnalysisReport, false, DESCRIPTION_FOREIGN_TABLES)) migrationCaveats = append(migrationCaveats, getUnsupportedFeaturesFromSchemaAnalysisReport(POLICIES_CAVEAT_FEATURE, "", queryissue.POLICY_WITH_ROLES, - schemaAnalysisReport, false, DESCRIPTION_POLICY_ROLE_ISSUE)) + schemaAnalysisReport, false, DESCRIPTION_POLICY_ROLE_DESCRIPTION)) if len(unsupportedDataTypesForLiveMigration) > 0 { columns := make([]ObjectInfo, 0) - for _, col := range unsupportedDataTypesForLiveMigration { - columns = append(columns, ObjectInfo{ObjectName: fmt.Sprintf("%s.%s.%s (%s)", col.SchemaName, col.TableName, col.ColumnName, col.DataType)}) + for _, colInfo := range unsupportedDataTypesForLiveMigration { + columns = append(columns, ObjectInfo{ObjectName: fmt.Sprintf("%s.%s.%s (%s)", colInfo.SchemaName, colInfo.TableName, colInfo.ColumnName, colInfo.DataType)}) + + assessmentReport.AppendIssues(AssessmentIssue{ + Category: MIGRATION_CAVEATS_CATEGORY, + CategoryDescription: "", // TODO + Type: UNSUPPORTED_DATATYPES_LIVE_CAVEAT_FEATURE, // TODO add object type in type name + Name: "", // TODO + Impact: constants.IMPACT_LEVEL_1, // Caveat - we don't know the migration is offline/online; + Description: UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_DESCRIPTION, + ObjectType: constants.COLUMN, + ObjectName: fmt.Sprintf("%s.%s.%s", colInfo.SchemaName, colInfo.TableName, colInfo.ColumnName), + DocsLink: UNSUPPORTED_DATATYPE_LIVE_MIGRATION_DOC_LINK, + }) } if len(columns) > 0 { - migrationCaveats = append(migrationCaveats, UnsupportedFeature{UNSUPPORTED_DATATYPES_LIVE_CAVEAT_FEATURE, columns, false, UNSUPPORTED_DATATYPE_LIVE_MIGRATION_DOC_LINK, UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_ISSUE, nil}) + migrationCaveats = append(migrationCaveats, UnsupportedFeature{UNSUPPORTED_DATATYPES_LIVE_CAVEAT_FEATURE, columns, false, UNSUPPORTED_DATATYPE_LIVE_MIGRATION_DOC_LINK, UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_DESCRIPTION, nil}) } } if len(unsupportedDataTypesForLiveMigrationWithFForFB) > 0 { columns := make([]ObjectInfo, 0) - for _, col := range unsupportedDataTypesForLiveMigrationWithFForFB { - columns = append(columns, ObjectInfo{ObjectName: fmt.Sprintf("%s.%s.%s (%s)", col.SchemaName, col.TableName, col.ColumnName, col.DataType)}) + for _, colInfo := range unsupportedDataTypesForLiveMigrationWithFForFB { + columns = append(columns, ObjectInfo{ObjectName: fmt.Sprintf("%s.%s.%s (%s)", colInfo.SchemaName, colInfo.TableName, colInfo.ColumnName, colInfo.DataType)}) + + assessmentReport.AppendIssues(AssessmentIssue{ + Category: MIGRATION_CAVEATS_CATEGORY, + CategoryDescription: "", // TODO + Type: UNSUPPORTED_DATATYPES_LIVE_WITH_FF_FB_CAVEAT_FEATURE, // TODO add object type in type name + Name: "", // TODO + Impact: constants.IMPACT_LEVEL_1, + Description: UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_WITH_FF_FB_DESCRIPTION, + ObjectType: constants.COLUMN, + ObjectName: fmt.Sprintf("%s.%s.%s", colInfo.SchemaName, colInfo.TableName, colInfo.ColumnName), + DocsLink: UNSUPPORTED_DATATYPE_LIVE_MIGRATION_DOC_LINK, + }) } if len(columns) > 0 { - migrationCaveats = append(migrationCaveats, UnsupportedFeature{UNSUPPORTED_DATATYPES_LIVE_WITH_FF_FB_CAVEAT_FEATURE, columns, false, UNSUPPORTED_DATATYPE_LIVE_MIGRATION_DOC_LINK, UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_WITH_FF_FB_ISSUE, nil}) + migrationCaveats = append(migrationCaveats, UnsupportedFeature{UNSUPPORTED_DATATYPES_LIVE_WITH_FF_FB_CAVEAT_FEATURE, columns, false, UNSUPPORTED_DATATYPE_LIVE_MIGRATION_DOC_LINK, UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_WITH_FF_FB_DESCRIPTION, nil}) } } migrationCaveats = lo.Filter(migrationCaveats, func(m UnsupportedFeature, _ int) bool { diff --git a/yb-voyager/cmd/common.go b/yb-voyager/cmd/common.go index 47c5a7c49..2542c14d1 100644 --- a/yb-voyager/cmd/common.go +++ b/yb-voyager/cmd/common.go @@ -1195,13 +1195,15 @@ type AssessmentReport struct { MigrationCaveats []UnsupportedFeature `json:"MigrationCaveats"` } +// Fields apart from Category, CategoryDescription, TypeName and Impact will be populated only if/when available type AssessmentIssue struct { - Category string + Category string // expected values: feature, query_constrcuts, migration_caveats, plpgsql_objects, datatytpe CategoryDescription string - TypeName string - TypeDescription string - Impact string - ObjectType string + Type string // Ex: GIN_INDEXES, SECURITY_INVOKER_VIEWS, STORED_GENERATED_COLUMNS + Name string // Ex: "Stored generated columns are not supported." + Description string + Impact string // Level-1, Level-2, Level-3 (default: Level-1 ??) + ObjectType string // For datatype category, ObjectType will be datatype (for eg "geometry") ObjectName string SqlStatement string DocsLink string @@ -1313,6 +1315,10 @@ func ParseJSONToAssessmentReport(reportPath string) (*AssessmentReport, error) { return &report, nil } +func (ar *AssessmentReport) AppendIssues(issues ...AssessmentIssue) { + ar.Issues = append(ar.Issues, issues...) +} + func (ar *AssessmentReport) GetShardedTablesRecommendation() ([]string, error) { if ar.Sizing == nil { return nil, fmt.Errorf("sizing report is null, can't fetch sharded tables") diff --git a/yb-voyager/cmd/constants.go b/yb-voyager/cmd/constants.go index f4d9cc4fc..5a2d496be 100644 --- a/yb-voyager/cmd/constants.go +++ b/yb-voyager/cmd/constants.go @@ -15,6 +15,11 @@ limitations under the License. */ package cmd +import ( + "github.com/yugabyte/yb-voyager/yb-voyager/src/constants" + "github.com/yugabyte/yb-voyager/yb-voyager/src/utils" +) + const ( KB = 1024 MB = 1024 * 1024 @@ -102,10 +107,12 @@ const ( REFERENCE_PARTITION = "REFERENCE PARTITION" SYSTEM_PARTITION = "SYSTEM PARTITION" - UNSUPPORTED_FEATURES = "unsupported_features" - UNSUPPORTED_DATATYPES = "unsupported_datatypes" - UNSUPPORTED_PLPGSQL_OBEJCTS = "unsupported_plpgsql_objects" - REPORT_UNSUPPORTED_QUERY_CONSTRUCTS = "REPORT_UNSUPPORTED_QUERY_CONSTRUCTS" + UNSUPPORTED_FEATURES_CATEGORY = "unsupported_features" + UNSUPPORTED_DATATYPES_CATEGORY = "unsupported_datatypes" + UNSUPPORTED_QUERY_CONSTRUCTS_CATEGORY = "unsupported_query_constructs" + UNSUPPORTED_PLPGSQL_OBJECTS_CATEGORY = "unsupported_plpgsql_objects" + MIGRATION_CAVEATS_CATEGORY = "migration_caveats" + REPORT_UNSUPPORTED_QUERY_CONSTRUCTS = "REPORT_UNSUPPORTED_QUERY_CONSTRUCTS" HTML = "html" JSON = "json" @@ -173,21 +180,14 @@ const ( List of all the features we are reporting as part of Unsupported features and Migration caveats */ const ( - // AssessmentIssue types used in YugabyteD payload - FEATURE = "feature" - DATATYPE = "datatype" - QUERY_CONSTRUCT = "query_construct" // confused: in json for some values we are using space separated and for some snake_case - MIGRATION_CAVEATS = "migration_caveats" - PLPGSQL_OBJECT = "plpgsql_object" - // Description - FEATURE_ISSUE_TYPE_DESCRIPTION = "Features of the source database that are not supported on the target YugabyteDB." - DATATYPE_ISSUE_TYPE_DESCRIPTION = "Data types of the source database that are not supported on the target YugabyteDB." - MIGRATION_CAVEATS_TYPE_DESCRIPTION = "Migration Caveats highlights the current limitations with the migration workflow." - UNSUPPORTED_QUERY_CONSTRUTS_DESCRIPTION = "Source database queries not supported in YugabyteDB, identified by scanning system tables." - UNSUPPPORTED_PLPGSQL_OBJECT_DESCRIPTION = "Source schema objects having unsupported statements on the target YugabyteDB in PL/pgSQL code block" - SCHEMA_SUMMARY_DESCRIPTION = "Objects that will be created on the target YugabyteDB." - SCHEMA_SUMMARY_DESCRIPTION_ORACLE = SCHEMA_SUMMARY_DESCRIPTION + " Some of the index and sequence names might be different from those in the source database." + FEATURE_CATEGORY_DESCRIPTION = "Features of the source database that are not supported on the target YugabyteDB." + DATATYPE_CATEGORY_DESCRIPTION = "Data types of the source database that are not supported on the target YugabyteDB." + MIGRATION_CAVEATS_CATEGORY_DESCRIPTION = "Migration Caveats highlights the current limitations with the migration workflow." + UNSUPPORTED_QUERY_CONSTRUCTS_CATEGORY_DESCRIPTION = "Source database queries not supported in YugabyteDB, identified by scanning system tables." + UNSUPPPORTED_PLPGSQL_OBJECT_CATEGORY_DESCRIPTION = "Source schema objects having unsupported statements on the target YugabyteDB in PL/pgSQL code block" + SCHEMA_SUMMARY_DESCRIPTION = "Objects that will be created on the target YugabyteDB." + SCHEMA_SUMMARY_DESCRIPTION_ORACLE = SCHEMA_SUMMARY_DESCRIPTION + " Some of the index and sequence names might be different from those in the source database." //Unsupported Features @@ -222,16 +222,16 @@ const ( // Migration caveats //POSTGRESQL - ALTER_PARTITION_ADD_PK_CAVEAT_FEATURE = "Alter partitioned tables to add Primary Key" - FOREIGN_TABLE_CAVEAT_FEATURE = "Foreign tables" - POLICIES_CAVEAT_FEATURE = "Policies" - UNSUPPORTED_DATATYPES_LIVE_CAVEAT_FEATURE = "Unsupported Data Types for Live Migration" - UNSUPPORTED_DATATYPES_LIVE_WITH_FF_FB_CAVEAT_FEATURE = "Unsupported Data Types for Live Migration with Fall-forward/Fallback" - UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_ISSUE = "There are some data types in the schema that are not supported by live migration of data. These columns will be excluded when exporting and importing data in live migration workflows." - UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_WITH_FF_FB_ISSUE = "There are some data types in the schema that are not supported by live migration with fall-forward/fall-back. These columns will be excluded when exporting and importing data in live migration workflows." - DESCRIPTION_ADD_PK_TO_PARTITION_TABLE = `After export schema, the ALTER table should be merged with CREATE table for partitioned tables as alter of partitioned tables to add primary key is not supported.` - DESCRIPTION_FOREIGN_TABLES = `During the export schema phase, SERVER and USER MAPPING objects are not exported. These should be manually created to make the foreign tables work.` - DESCRIPTION_POLICY_ROLE_ISSUE = `There are some policies that are created for certain users/roles. During the export schema phase, USERs and GRANTs are not exported. Therefore, they will have to be manually created before running import schema.` + ALTER_PARTITION_ADD_PK_CAVEAT_FEATURE = "Alter partitioned tables to add Primary Key" + FOREIGN_TABLE_CAVEAT_FEATURE = "Foreign tables" + POLICIES_CAVEAT_FEATURE = "Policies" + UNSUPPORTED_DATATYPES_LIVE_CAVEAT_FEATURE = "Unsupported Data Types for Live Migration" + UNSUPPORTED_DATATYPES_LIVE_WITH_FF_FB_CAVEAT_FEATURE = "Unsupported Data Types for Live Migration with Fall-forward/Fallback" + UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_DESCRIPTION = "There are some data types in the schema that are not supported by live migration of data. These columns will be excluded when exporting and importing data in live migration workflows." + UNSUPPORTED_DATATYPES_FOR_LIVE_MIGRATION_WITH_FF_FB_DESCRIPTION = "There are some data types in the schema that are not supported by live migration with fall-forward/fall-back. These columns will be excluded when exporting and importing data in live migration workflows." + DESCRIPTION_ADD_PK_TO_PARTITION_TABLE = `After export schema, the ALTER table should be merged with CREATE table for partitioned tables as alter of partitioned tables to add primary key is not supported.` + DESCRIPTION_FOREIGN_TABLES = `During the export schema phase, SERVER and USER MAPPING objects are not exported. These should be manually created to make the foreign tables work.` + DESCRIPTION_POLICY_ROLE_DESCRIPTION = `There are some policies that are created for certain users/roles. During the export schema phase, USERs and GRANTs are not exported. Therefore, they will have to be manually created before running import schema.` ) var supportedSourceDBTypes = []string{ORACLE, MYSQL, POSTGRESQL, YUGABYTEDB} @@ -244,3 +244,22 @@ var validSSLModes = map[string][]string{ } var EVENT_BATCH_MAX_RETRY_COUNT = 50 + +// returns the description for a given assessment issue category +func GetCategoryDescription(category string) string { + switch category { + case UNSUPPORTED_FEATURES_CATEGORY, constants.FEATURE: + return FEATURE_CATEGORY_DESCRIPTION + case UNSUPPORTED_DATATYPES_CATEGORY, constants.DATATYPE: + return DATATYPE_CATEGORY_DESCRIPTION + case UNSUPPORTED_QUERY_CONSTRUCTS_CATEGORY, constants.QUERY_CONSTRUCT: + return UNSUPPORTED_QUERY_CONSTRUCTS_CATEGORY_DESCRIPTION + case UNSUPPORTED_PLPGSQL_OBJECTS_CATEGORY, constants.PLPGSQL_OBJECT: + return UNSUPPPORTED_PLPGSQL_OBJECT_CATEGORY_DESCRIPTION + case MIGRATION_CAVEATS_CATEGORY: // or constants.MIGRATION_CAVEATS (identical) + return MIGRATION_CAVEATS_CATEGORY_DESCRIPTION + default: + utils.ErrExit("ERROR: unsupported assessment issue category %q", category) + } + return "" +} diff --git a/yb-voyager/src/constants/constants.go b/yb-voyager/src/constants/constants.go index 7912fb1d5..9e194afe6 100644 --- a/yb-voyager/src/constants/constants.go +++ b/yb-voyager/src/constants/constants.go @@ -19,10 +19,24 @@ const ( // Database Object types TABLE = "table" FUNCTION = "function" + COLUMN = "column" // Source DB Types YUGABYTEDB = "yugabytedb" POSTGRESQL = "postgresql" ORACLE = "oracle" MYSQL = "mysql" -) + + // AssessmentIssue Categoes - used by YugabyteD payload and Migration Complexity Explainability + // TODO: soon to be renamed as SCHEMA, SCHEMA_PLPGSQL, DML_QUERY, MIGRATION_CAVEAT, "DATATYPE" + FEATURE = "feature" + DATATYPE = "datatype" + QUERY_CONSTRUCT = "query_construct" + MIGRATION_CAVEATS = "migration_caveats" + PLPGSQL_OBJECT = "plpgsql_object" + + // constants for the Impact Buckets + IMPACT_LEVEL_1 = "LEVEL_1" // Represents minimal impact like only the schema ddl + IMPACT_LEVEL_2 = "LEVEL_2" // Represents moderate impact like dml queries which might impact a lot of implementation/assumption in app layer + IMPACT_LEVEL_3 = "LEVEL_3" // Represent significant impact like TABLE INHERITANCE, which doesn't have any simple workaround but can impact multiple objects/apps +) \ No newline at end of file diff --git a/yb-voyager/src/issue/issue.go b/yb-voyager/src/issue/issue.go index c30d4f837..47bf663fb 100644 --- a/yb-voyager/src/issue/issue.go +++ b/yb-voyager/src/issue/issue.go @@ -22,8 +22,9 @@ import ( type Issue struct { Type string // (advisory_locks, index_not_supported, etc) - TypeName string // for display - TypeDescription string + Name string // for display + Description string + Impact string Suggestion string GH string DocsLink string @@ -40,3 +41,36 @@ func (i Issue) IsFixedIn(v *ybversion.YBVersion) (bool, error) { } return v.GreaterThanOrEqual(minVersionFixedInSeries), nil } + +/* + Dynamic Impact Determination (TODO) + - We can define the impact calculator function based on issue type wherever/whenever needed + - Map will have functions only for issue type with dynamic impact determination + + For example: + + type ImpactCalcFunc func(issue QueryIssue, stats *PgStats) string + + var impactCalculators = map[string]ImpactCalcFunc{ + INHERITED_TABLE: inheritedTableImpactCalc, + // etc... + } + + // Example dynamic function + func inheritedTableImpactCalc(i QueryIssue, stats *PgStats) string { + usage := stats.GetUsage(i.ObjectName) // e.g. how many reads/writes + if usage.WritesPerDay > 1000 { + return "LEVEL_2" + } + return "LEVEL_3" + } + + func (i Issue) GetImpact(stats *PgStats) string { + if calc, ok := impactCalculators[i.Type]; ok { + return calc(i, stats) + } + + return lo.Ternary(i.Impact != "", i.Impact, constants.IMPACT_LEVEL_1) + } + +*/ diff --git a/yb-voyager/src/query/queryissue/issues_ddl.go b/yb-voyager/src/query/queryissue/issues_ddl.go index 2930b5df4..7a06bcaa0 100644 --- a/yb-voyager/src/query/queryissue/issues_ddl.go +++ b/yb-voyager/src/query/queryissue/issues_ddl.go @@ -20,13 +20,15 @@ import ( "fmt" "strings" + "github.com/yugabyte/yb-voyager/yb-voyager/src/constants" "github.com/yugabyte/yb-voyager/yb-voyager/src/issue" "github.com/yugabyte/yb-voyager/yb-voyager/src/ybversion" ) var generatedColumnsIssue = issue.Issue{ Type: STORED_GENERATED_COLUMNS, - TypeName: "Stored generated columns are not supported.", + Name: "Stored generated columns are not supported.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/10695", Suggestion: "Using Triggers to update the generated columns is one way to work around this issue, refer docs link for more details.", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#generated-always-as-stored-type-column-is-not-supported", @@ -34,13 +36,14 @@ var generatedColumnsIssue = issue.Issue{ func NewGeneratedColumnsIssue(objectType string, objectName string, sqlStatement string, generatedColumns []string) QueryIssue { issue := generatedColumnsIssue - issue.TypeName = issue.TypeName + fmt.Sprintf(" Generated Columns: (%s)", strings.Join(generatedColumns, ",")) + issue.Name = issue.Name + fmt.Sprintf(" Generated Columns: (%s)", strings.Join(generatedColumns, ",")) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var unloggedTableIssue = issue.Issue{ Type: UNLOGGED_TABLE, - TypeName: "UNLOGGED tables are not supported yet.", + Name: "UNLOGGED tables are not supported yet.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/1129/", Suggestion: "Remove UNLOGGED keyword to make it work", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unlogged-table-is-not-supported", @@ -56,20 +59,22 @@ func NewUnloggedTableIssue(objectType string, objectName string, sqlStatement st var unsupportedIndexMethodIssue = issue.Issue{ Type: UNSUPPORTED_INDEX_METHOD, - TypeName: "Schema contains %s index which is not supported.", + Name: "Schema contains %s index which is not supported.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/YugaByte/yugabyte-db/issues/1337", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#gist-brin-and-spgist-index-types-are-not-supported", } func NewUnsupportedIndexMethodIssue(objectType string, objectName string, sqlStatement string, indexAccessMethod string) QueryIssue { issue := unsupportedIndexMethodIssue - issue.TypeName = fmt.Sprintf(unsupportedIndexMethodIssue.TypeName, strings.ToUpper(indexAccessMethod)) + issue.Name = fmt.Sprintf(unsupportedIndexMethodIssue.Name, strings.ToUpper(indexAccessMethod)) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var storageParameterIssue = issue.Issue{ Type: STORAGE_PARAMETER, - TypeName: "Storage parameters are not supported yet.", + Name: "Storage parameters are not supported yet.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/23467", Suggestion: "Remove the storage parameters from the DDL", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#storage-parameters-on-indexes-or-constraints-in-the-source-postgresql", @@ -82,7 +87,8 @@ func NewStorageParameterIssue(objectType string, objectName string, sqlStatement var setColumnAttributeIssue = issue.Issue{ Type: ALTER_TABLE_SET_COLUMN_ATTRIBUTE, - TypeName: "ALTER TABLE .. ALTER COLUMN .. SET ( attribute = value ) not supported yet", + Name: "ALTER TABLE .. ALTER COLUMN .. SET ( attribute = value ) not supported yet", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/1124", Suggestion: "Remove it from the exported schema", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unsupported-alter-table-ddl-variants-in-source-schema", @@ -95,7 +101,8 @@ func NewSetColumnAttributeIssue(objectType string, objectName string, sqlStateme var alterTableClusterOnIssue = issue.Issue{ Type: ALTER_TABLE_CLUSTER_ON, - TypeName: "ALTER TABLE CLUSTER not supported yet.", + Name: "ALTER TABLE CLUSTER not supported yet.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/YugaByte/yugabyte-db/issues/1124", Suggestion: "Remove it from the exported schema.", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unsupported-alter-table-ddl-variants-in-source-schema", @@ -108,7 +115,8 @@ func NewClusterONIssue(objectType string, objectName string, sqlStatement string var alterTableDisableRuleIssue = issue.Issue{ Type: ALTER_TABLE_DISABLE_RULE, - TypeName: "ALTER TABLE name DISABLE RULE not supported yet", + Name: "ALTER TABLE name DISABLE RULE not supported yet", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/1124", Suggestion: "Remove this and the rule '%s' from the exported schema to be not enabled on the table.", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unsupported-alter-table-ddl-variants-in-source-schema", @@ -123,7 +131,8 @@ func NewAlterTableDisableRuleIssue(objectType string, objectName string, sqlStat var exclusionConstraintIssue = issue.Issue{ Type: EXCLUSION_CONSTRAINTS, - TypeName: "Exclusion constraint is not supported yet", + Name: "Exclusion constraint is not supported yet", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/3944", Suggestion: "Refer docs link for details on possible workaround", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#exclusion-constraints-is-not-supported", @@ -138,7 +147,8 @@ func NewExclusionConstraintIssue(objectType string, objectName string, sqlStatem var deferrableConstraintIssue = issue.Issue{ Type: DEFERRABLE_CONSTRAINTS, - TypeName: "DEFERRABLE constraints not supported yet", + Name: "DEFERRABLE constraints not supported yet", + Impact: constants.IMPACT_LEVEL_3, GH: "https://github.com/yugabyte/yugabyte-db/issues/1709", Suggestion: "Remove these constraints from the exported schema and make the neccessary changes to the application to work on target seamlessly", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#deferrable-constraint-on-constraints-other-than-foreign-keys-is-not-supported", @@ -153,7 +163,8 @@ func NewDeferrableConstraintIssue(objectType string, objectName string, sqlState var multiColumnGinIndexIssue = issue.Issue{ Type: MULTI_COLUMN_GIN_INDEX, - TypeName: "Schema contains gin index on multi column which is not supported.", + Name: "Schema contains gin index on multi column which is not supported.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/10652", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#gin-indexes-on-multiple-columns-are-not-supported", } @@ -164,7 +175,8 @@ func NewMultiColumnGinIndexIssue(objectType string, objectName string, sqlStatem var orderedGinIndexIssue = issue.Issue{ Type: ORDERED_GIN_INDEX, - TypeName: "Schema contains gin index on column with ASC/DESC/HASH Clause which is not supported.", + Name: "Schema contains gin index on column with ASC/DESC/HASH Clause which is not supported.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/10653", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#issue-in-some-unsupported-cases-of-gin-indexes", } @@ -175,7 +187,8 @@ func NewOrderedGinIndexIssue(objectType string, objectName string, sqlStatement var policyRoleIssue = issue.Issue{ Type: POLICY_WITH_ROLES, - TypeName: "Policy require roles to be created.", + Name: "Policy require roles to be created.", + Impact: constants.IMPACT_LEVEL_1, Suggestion: "Users/Grants are not migrated during the schema migration. Create the Users manually to make the policies work", GH: "https://github.com/yugabyte/yb-voyager/issues/1655", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#policies-on-users-in-source-require-manual-user-creation", @@ -183,13 +196,14 @@ var policyRoleIssue = issue.Issue{ func NewPolicyRoleIssue(objectType string, objectName string, sqlStatement string, roles []string) QueryIssue { issue := policyRoleIssue - issue.TypeName = fmt.Sprintf("%s Users - (%s)", issue.TypeName, strings.Join(roles, ",")) + issue.Name = fmt.Sprintf("%s Users - (%s)", issue.Name, strings.Join(roles, ",")) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var constraintTriggerIssue = issue.Issue{ Type: CONSTRAINT_TRIGGER, - TypeName: "CONSTRAINT TRIGGER not supported yet.", + Name: "CONSTRAINT TRIGGER not supported yet.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/YugaByte/yugabyte-db/issues/1709", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#constraint-trigger-is-not-supported", } @@ -201,7 +215,8 @@ func NewConstraintTriggerIssue(objectType string, objectName string, sqlStatemen var referencingClauseInTriggerIssue = issue.Issue{ Type: REFERENCING_CLAUSE_IN_TRIGGER, - TypeName: "REFERENCING clause (transition tables) not supported yet.", + Name: "REFERENCING clause (transition tables) not supported yet.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/YugaByte/yugabyte-db/issues/1668", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#referencing-clause-for-triggers", } @@ -212,7 +227,8 @@ func NewReferencingClauseTrigIssue(objectType string, objectName string, sqlStat var beforeRowTriggerOnPartitionTableIssue = issue.Issue{ Type: BEFORE_ROW_TRIGGER_ON_PARTITIONED_TABLE, - TypeName: "Partitioned tables cannot have BEFORE / FOR EACH ROW triggers.", + Name: "Partitioned tables cannot have BEFORE / FOR EACH ROW triggers.", + Impact: constants.IMPACT_LEVEL_1, DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#before-row-triggers-on-partitioned-tables", GH: "https://github.com/yugabyte/yugabyte-db/issues/24830", Suggestion: "Create the triggers on individual partitions.", @@ -224,7 +240,8 @@ func NewBeforeRowOnPartitionTableIssue(objectType string, objectName string, sql var alterTableAddPKOnPartitionIssue = issue.Issue{ Type: ALTER_TABLE_ADD_PK_ON_PARTITIONED_TABLE, - TypeName: "Adding primary key to a partitioned table is not supported yet.", + Name: "Adding primary key to a partitioned table is not supported yet.", + Impact: constants.IMPACT_LEVEL_1, DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#adding-primary-key-to-a-partitioned-table-results-in-an-error", GH: "https://github.com/yugabyte/yugabyte-db/issues/10074", MinimumVersionsFixedIn: map[string]*ybversion.YBVersion{ @@ -241,7 +258,8 @@ func NewAlterTableAddPKOnPartiionIssue(objectType string, objectName string, sql var expressionPartitionIssue = issue.Issue{ Type: EXPRESSION_PARTITION_WITH_PK_UK, - TypeName: "Issue with Partition using Expression on a table which cannot contain Primary Key / Unique Key on any column", + Name: "Issue with Partition using Expression on a table which cannot contain Primary Key / Unique Key on any column", + Impact: constants.IMPACT_LEVEL_1, Suggestion: "Remove the Constriant from the table definition", GH: "https://github.com/yugabyte/yb-voyager/issues/698", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/mysql/#tables-partitioned-with-expressions-cannot-contain-primary-unique-keys", @@ -253,7 +271,8 @@ func NewExpressionPartitionIssue(objectType string, objectName string, sqlStatem var multiColumnListPartition = issue.Issue{ Type: MULTI_COLUMN_LIST_PARTITION, - TypeName: `cannot use "list" partition strategy with more than one column`, + Name: `cannot use "list" partition strategy with more than one column`, + Impact: constants.IMPACT_LEVEL_1, Suggestion: "Make it a single column partition by list or choose other supported Partitioning methods", GH: "https://github.com/yugabyte/yb-voyager/issues/699", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/mysql/#multi-column-partition-by-list-is-not-supported", @@ -265,7 +284,8 @@ func NewMultiColumnListPartition(objectType string, objectName string, sqlStatem var insufficientColumnsInPKForPartition = issue.Issue{ Type: INSUFFICIENT_COLUMNS_IN_PK_FOR_PARTITION, - TypeName: "insufficient columns in the PRIMARY KEY constraint definition in CREATE TABLE", + Name: "insufficient columns in the PRIMARY KEY constraint definition in CREATE TABLE", + Impact: constants.IMPACT_LEVEL_1, Suggestion: "Add all Partition columns to Primary Key", GH: "https://github.com/yugabyte/yb-voyager/issues/578", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/oracle/#partition-key-column-not-part-of-primary-key-columns", @@ -273,13 +293,14 @@ var insufficientColumnsInPKForPartition = issue.Issue{ func NewInsufficientColumnInPKForPartition(objectType string, objectName string, sqlStatement string, partitionColumnsNotInPK []string) QueryIssue { issue := insufficientColumnsInPKForPartition - issue.TypeName = fmt.Sprintf("%s - (%s)", issue.TypeName, strings.Join(partitionColumnsNotInPK, ", ")) + issue.Name = fmt.Sprintf("%s - (%s)", issue.Name, strings.Join(partitionColumnsNotInPK, ", ")) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var xmlDatatypeIssue = issue.Issue{ Type: XML_DATATYPE, - TypeName: "Unsupported datatype - xml", + Name: "Unsupported datatype - xml", + Impact: constants.IMPACT_LEVEL_3, 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", @@ -287,13 +308,14 @@ var xmlDatatypeIssue = issue.Issue{ func NewXMLDatatypeIssue(objectType string, objectName string, sqlStatement string, colName string) QueryIssue { issue := xmlDatatypeIssue - issue.TypeName = fmt.Sprintf("%s on column - %s", issue.TypeName, colName) + issue.Name = fmt.Sprintf("%s on column - %s", issue.Name, colName) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var xidDatatypeIssue = issue.Issue{ Type: XID_DATATYPE, - TypeName: "Unsupported datatype - xid", + Name: "Unsupported datatype - xid", + Impact: constants.IMPACT_LEVEL_3, Suggestion: "Functions for this type e.g. txid_current are not supported in YugabyteDB yet", GH: "https://github.com/yugabyte/yugabyte-db/issues/15638", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xid-functions-is-not-supported", @@ -301,65 +323,70 @@ var xidDatatypeIssue = issue.Issue{ func NewXIDDatatypeIssue(objectType string, objectName string, sqlStatement string, colName string) QueryIssue { issue := xidDatatypeIssue - issue.TypeName = fmt.Sprintf("%s on column - %s", issue.TypeName, colName) + issue.Name = fmt.Sprintf("%s on column - %s", issue.Name, colName) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var postgisDatatypeIssue = issue.Issue{ Type: POSTGIS_DATATYPES, - TypeName: "Unsupported datatype", + Name: "Unsupported datatype", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/11323", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unsupported-datatypes-by-yugabytedb", } func NewPostGisDatatypeIssue(objectType string, objectName string, sqlStatement string, typeName string, colName string) QueryIssue { issue := postgisDatatypeIssue - issue.TypeName = fmt.Sprintf("%s - %s on column - %s", issue.TypeName, typeName, colName) + issue.Name = fmt.Sprintf("%s - %s on column - %s", issue.Name, typeName, colName) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var unsupportedDatatypesIssue = issue.Issue{ Type: UNSUPPORTED_DATATYPES, - TypeName: "Unsupported datatype", + Name: "Unsupported datatype", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yb-voyager/issues/1731", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unsupported-datatypes-by-yugabytedb", } func NewUnsupportedDatatypesIssue(objectType string, objectName string, sqlStatement string, typeName string, colName string) QueryIssue { issue := unsupportedDatatypesIssue - issue.TypeName = fmt.Sprintf("%s - %s on column - %s", issue.TypeName, typeName, colName) + issue.Name = fmt.Sprintf("%s - %s on column - %s", issue.Name, typeName, colName) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var unsupportedDatatypesForLiveMigrationIssue = issue.Issue{ Type: UNSUPPORTED_DATATYPES_LIVE_MIGRATION, - TypeName: "Unsupported datatype for Live migration", + Name: "Unsupported datatype for Live migration", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yb-voyager/issues/1731", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unsupported-datatypes-by-voyager-during-live-migration", } func NewUnsupportedDatatypesForLMIssue(objectType string, objectName string, sqlStatement string, typeName string, colName string) QueryIssue { issue := unsupportedDatatypesForLiveMigrationIssue - issue.TypeName = fmt.Sprintf("%s - %s on column - %s", issue.TypeName, typeName, colName) + issue.Name = fmt.Sprintf("%s - %s on column - %s", issue.Name, typeName, colName) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var unsupportedDatatypesForLiveMigrationWithFFOrFBIssue = issue.Issue{ Type: UNSUPPORTED_DATATYPES_LIVE_MIGRATION_WITH_FF_FB, - TypeName: "Unsupported datatype for Live migration with fall-forward/fallback", + Name: "Unsupported datatype for Live migration with fall-forward/fallback", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yb-voyager/issues/1731", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#unsupported-datatypes-by-voyager-during-live-migration", } func NewUnsupportedDatatypesForLMWithFFOrFBIssue(objectType string, objectName string, sqlStatement string, typeName string, colName string) QueryIssue { issue := unsupportedDatatypesForLiveMigrationWithFFOrFBIssue - issue.TypeName = fmt.Sprintf("%s - %s on column - %s", issue.TypeName, typeName, colName) + issue.Name = fmt.Sprintf("%s - %s on column - %s", issue.Name, typeName, colName) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var primaryOrUniqueOnUnsupportedIndexTypesIssue = issue.Issue{ Type: PK_UK_ON_COMPLEX_DATATYPE, - TypeName: "Primary key and Unique constraint on column '%s' not yet supported", + Name: "Primary key and Unique constraint on column '%s' not yet supported", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/25003", Suggestion: "Refer to the docs link for the workaround", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#indexes-on-some-complex-data-types-are-not-supported", //Keeping it similar for now, will see if we need to a separate issue on docs, @@ -370,13 +397,14 @@ func NewPrimaryOrUniqueConsOnUnsupportedIndexTypesIssue(objectType string, objec CONSTRAINT_NAME: constraintName, } issue := primaryOrUniqueOnUnsupportedIndexTypesIssue - issue.TypeName = fmt.Sprintf(issue.TypeName, typeName) + issue.Name = fmt.Sprintf(issue.Name, typeName) return newQueryIssue(issue, objectType, objectName, sqlStatement, details) } var indexOnComplexDatatypesIssue = issue.Issue{ Type: INDEX_ON_COMPLEX_DATATYPE, - TypeName: "INDEX on column '%s' not yet supported", + Name: "INDEX on column '%s' not yet supported", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yugabyte-db/issues/25003", Suggestion: "Refer to the docs link for the workaround", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#indexes-on-some-complex-data-types-are-not-supported", @@ -384,13 +412,14 @@ var indexOnComplexDatatypesIssue = issue.Issue{ func NewIndexOnComplexDatatypesIssue(objectType string, objectName string, sqlStatement string, typeName string) QueryIssue { issue := indexOnComplexDatatypesIssue - issue.TypeName = fmt.Sprintf(issue.TypeName, typeName) + issue.Name = fmt.Sprintf(issue.Name, typeName) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var foreignTableIssue = issue.Issue{ Type: FOREIGN_TABLE, - TypeName: "Foreign tables require manual intervention.", + Name: "Foreign tables require manual intervention.", + Impact: constants.IMPACT_LEVEL_1, GH: "https://github.com/yugabyte/yb-voyager/issues/1627", Suggestion: "SERVER '%s', and USER MAPPING should be created manually on the target to create and use the foreign table", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#foreign-table-in-the-source-database-requires-server-and-user-mapping", @@ -404,7 +433,8 @@ func NewForeignTableIssue(objectType string, objectName string, sqlStatement str var inheritanceIssue = issue.Issue{ Type: INHERITANCE, - TypeName: "TABLE INHERITANCE not supported in YugabyteDB", + Name: "TABLE INHERITANCE not supported in YugabyteDB", + Impact: constants.IMPACT_LEVEL_3, GH: "https://github.com/YugaByte/yugabyte-db/issues/1129", DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#table-inheritance-is-not-supported", } @@ -414,12 +444,13 @@ func NewInheritanceIssue(objectType string, objectName string, sqlStatement stri } var percentTypeSyntax = issue.Issue{ - Type: REFERENCED_TYPE_DECLARATION, - TypeName: "Referenced type declaration of variables", - TypeDescription: "", - Suggestion: "Fix the syntax to include the actual type name instead of referencing the type of a column", - GH: "https://github.com/yugabyte/yugabyte-db/issues/23619", - DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported", + Type: REFERENCED_TYPE_DECLARATION, + Name: "Referenced type declaration of variables", + Impact: constants.IMPACT_LEVEL_1, + Description: "", + Suggestion: "Fix the syntax to include the actual type name instead of referencing the type of a column", + GH: "https://github.com/yugabyte/yugabyte-db/issues/23619", + DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported", } func NewPercentTypeSyntaxIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -428,7 +459,8 @@ func NewPercentTypeSyntaxIssue(objectType string, objectName string, sqlStatemen var loDatatypeIssue = issue.Issue{ Type: LARGE_OBJECT_DATATYPE, - TypeName: "Unsupported datatype - lo", + Name: "Unsupported datatype - lo", + Impact: constants.IMPACT_LEVEL_1, Suggestion: "Large objects are not yet supported in YugabyteDB, no workaround available currently", GH: "https://github.com/yugabyte/yugabyte-db/issues/25318", DocsLink: "", // TODO @@ -436,13 +468,14 @@ var loDatatypeIssue = issue.Issue{ func NewLODatatypeIssue(objectType string, objectName string, SqlStatement string, colName string) QueryIssue { issue := loDatatypeIssue - issue.TypeName = fmt.Sprintf("%s on column - %s", issue.TypeName, colName) + issue.Name = fmt.Sprintf("%s on column - %s", issue.Name, colName) return newQueryIssue(issue, objectType, objectName, SqlStatement, map[string]interface{}{}) } var multiRangeDatatypeIssue = issue.Issue{ Type: MULTI_RANGE_DATATYPE, - TypeName: "Unsupported datatype", + Name: "Unsupported datatype", + Impact: constants.IMPACT_LEVEL_1, Suggestion: "Multirange data type is not yet supported in YugabyteDB, no workaround available currently", GH: "", //TODO DocsLink: "", //TODO @@ -450,13 +483,14 @@ var multiRangeDatatypeIssue = issue.Issue{ func NewMultiRangeDatatypeIssue(objectType string, objectName string, sqlStatement string, typeName string, colName string) QueryIssue { issue := multiRangeDatatypeIssue - issue.TypeName = fmt.Sprintf("%s - %s on column - %s", issue.TypeName, typeName, colName) + issue.Name = fmt.Sprintf("%s - %s on column - %s", issue.Name, typeName, colName) return newQueryIssue(issue, objectType, objectName, sqlStatement, map[string]interface{}{}) } var securityInvokerViewIssue = issue.Issue{ Type: SECURITY_INVOKER_VIEWS, - TypeName: "Security Invoker Views not supported yet", + Name: "Security Invoker Views not supported yet", + Impact: constants.IMPACT_LEVEL_1, Suggestion: "Security Invoker Views are not yet supported in YugabyteDB, no workaround available currently", GH: "", // TODO DocsLink: "", // TODO @@ -468,7 +502,8 @@ func NewSecurityInvokerViewIssue(objectType string, objectName string, SqlStatem var foreignKeyReferencesPartitionedTableIssue = issue.Issue{ Type: FOREIGN_KEY_REFERENCES_PARTITIONED_TABLE, - TypeName: FOREIGN_KEY_REFERENCES_PARTITIONED_TABLE_NAME, + Name: FOREIGN_KEY_REFERENCES_PARTITIONED_TABLE_NAME, + Impact: constants.IMPACT_LEVEL_1, Suggestion: "No workaround available ", GH: "", // TODO DocsLink: "", // TODO diff --git a/yb-voyager/src/query/queryissue/issues_dml.go b/yb-voyager/src/query/queryissue/issues_dml.go index e9b8f2592..393841a79 100644 --- a/yb-voyager/src/query/queryissue/issues_dml.go +++ b/yb-voyager/src/query/queryissue/issues_dml.go @@ -19,16 +19,18 @@ package queryissue import ( "sort" + "github.com/yugabyte/yb-voyager/yb-voyager/src/constants" "github.com/yugabyte/yb-voyager/yb-voyager/src/issue" ) var advisoryLocksIssue = issue.Issue{ - Type: ADVISORY_LOCKS, - TypeName: "Advisory Locks", - TypeDescription: "", - Suggestion: "", - GH: "", - DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#advisory-locks-is-not-yet-implemented", + Type: ADVISORY_LOCKS, + Name: "Advisory Locks", + Impact: constants.IMPACT_LEVEL_2, + Description: "", + Suggestion: "", + GH: "", + DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#advisory-locks-is-not-yet-implemented", } func NewAdvisoryLocksIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -36,12 +38,13 @@ func NewAdvisoryLocksIssue(objectType string, objectName string, sqlStatement st } var systemColumnsIssue = issue.Issue{ - Type: SYSTEM_COLUMNS, - TypeName: "System Columns", - TypeDescription: "", - Suggestion: "", - GH: "", - DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#system-columns-is-not-yet-supported", + Type: SYSTEM_COLUMNS, + Name: "System Columns", + Impact: constants.IMPACT_LEVEL_2, + Description: "", + Suggestion: "", + GH: "", + DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#system-columns-is-not-yet-supported", } func NewSystemColumnsIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -49,12 +52,13 @@ func NewSystemColumnsIssue(objectType string, objectName string, sqlStatement st } var xmlFunctionsIssue = issue.Issue{ - Type: XML_FUNCTIONS, - TypeName: "XML Functions", - TypeDescription: "", - Suggestion: "", - GH: "", - DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", + Type: XML_FUNCTIONS, + Name: "XML Functions", + Impact: constants.IMPACT_LEVEL_2, + Description: "", + Suggestion: "", + GH: "", + DocsLink: "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#xml-functions-is-not-yet-supported", } func NewXmlFunctionsIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -62,12 +66,13 @@ func NewXmlFunctionsIssue(objectType string, objectName string, sqlStatement str } var regexFunctionsIssue = issue.Issue{ - Type: REGEX_FUNCTIONS, - TypeName: "Regex Functions", - TypeDescription: "", - Suggestion: "", - GH: "", - DocsLink: "", + Type: REGEX_FUNCTIONS, + Name: "Regex Functions", + Impact: constants.IMPACT_LEVEL_2, + Description: "", + Suggestion: "", + GH: "", + DocsLink: "", } func NewRegexFunctionsIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -75,12 +80,13 @@ func NewRegexFunctionsIssue(objectType string, objectName string, sqlStatement s } var aggregateFunctionIssue = issue.Issue{ - Type: AGGREGATE_FUNCTION, - TypeName: AGGREGATION_FUNCTIONS_NAME, - TypeDescription: "any_value, range_agg and range_intersect_agg functions not supported yet in YugabyteDB", - Suggestion: "", - GH: "", - DocsLink: "", + Type: AGGREGATE_FUNCTION, + Name: AGGREGATION_FUNCTIONS_NAME, + Impact: constants.IMPACT_LEVEL_2, + Description: "any_value, range_agg and range_intersect_agg functions not supported yet in YugabyteDB", + Suggestion: "", + GH: "", + DocsLink: "", } func NewAggregationFunctionIssue(objectType string, objectName string, sqlStatement string, funcNames []string) QueryIssue { @@ -92,12 +98,13 @@ func NewAggregationFunctionIssue(objectType string, objectName string, sqlStatem } var jsonConstructorFunctionsIssue = issue.Issue{ - Type: JSON_CONSTRUCTOR_FUNCTION, - TypeName: JSON_CONSTRUCTOR_FUNCTION_NAME, - TypeDescription: "Postgresql 17 features not supported yet in YugabyteDB", - Suggestion: "", - GH: "", - DocsLink: "", + Type: JSON_CONSTRUCTOR_FUNCTION, + Name: JSON_CONSTRUCTOR_FUNCTION_NAME, + Impact: constants.IMPACT_LEVEL_2, + Description: "Postgresql 17 features not supported yet in YugabyteDB", + Suggestion: "", + GH: "", + DocsLink: "", } func NewJsonConstructorFunctionIssue(objectType string, objectName string, sqlStatement string, funcNames []string) QueryIssue { @@ -109,12 +116,13 @@ func NewJsonConstructorFunctionIssue(objectType string, objectName string, sqlSt } var jsonQueryFunctionIssue = issue.Issue{ - Type: JSON_QUERY_FUNCTION, - TypeName: JSON_QUERY_FUNCTIONS_NAME, - TypeDescription: "Postgresql 17 features not supported yet in YugabyteDB", - Suggestion: "", - GH: "", - DocsLink: "", + Type: JSON_QUERY_FUNCTION, + Name: JSON_QUERY_FUNCTIONS_NAME, + Impact: constants.IMPACT_LEVEL_2, + Description: "Postgresql 17 features not supported yet in YugabyteDB", + Suggestion: "", + GH: "", + DocsLink: "", } func NewJsonQueryFunctionIssue(objectType string, objectName string, sqlStatement string, funcNames []string) QueryIssue { @@ -126,12 +134,13 @@ func NewJsonQueryFunctionIssue(objectType string, objectName string, sqlStatemen } var loFunctionsIssue = issue.Issue{ - Type: LARGE_OBJECT_FUNCTIONS, - TypeName: LARGE_OBJECT_FUNCTIONS_NAME, - TypeDescription: "Large Objects functions are not supported in YugabyteDB", - Suggestion: "Large objects functions are not yet supported in YugabyteDB, no workaround available right now", - GH: "https://github.com/yugabyte/yugabyte-db/issues/25318", - DocsLink: "", //TODO + Type: LARGE_OBJECT_FUNCTIONS, + Name: LARGE_OBJECT_FUNCTIONS_NAME, + Impact: constants.IMPACT_LEVEL_2, + Description: "Large Objects functions are not supported in YugabyteDB", + Suggestion: "Large objects functions are not yet supported in YugabyteDB, no workaround available right now", + GH: "https://github.com/yugabyte/yugabyte-db/issues/25318", + DocsLink: "", //TODO } func NewLOFuntionsIssue(objectType string, objectName string, sqlStatement string, funcNames []string) QueryIssue { @@ -143,12 +152,13 @@ func NewLOFuntionsIssue(objectType string, objectName string, sqlStatement strin } var jsonbSubscriptingIssue = issue.Issue{ - Type: JSONB_SUBSCRIPTING, - TypeName: JSONB_SUBSCRIPTING_NAME, - TypeDescription: "Jsonb subscripting is not supported in YugabyteDB yet", - Suggestion: "Use Arrow operators (-> / ->>) to access the jsonb fields.", - GH: "", - DocsLink: "", //TODO + Type: JSONB_SUBSCRIPTING, + Name: JSONB_SUBSCRIPTING_NAME, + Impact: constants.IMPACT_LEVEL_2, + Description: "Jsonb subscripting is not supported in YugabyteDB yet", + Suggestion: "Use Arrow operators (-> / ->>) to access the jsonb fields.", + GH: "", + DocsLink: "", //TODO } func NewJsonbSubscriptingIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -156,12 +166,13 @@ func NewJsonbSubscriptingIssue(objectType string, objectName string, sqlStatemen } var jsonPredicateIssue = issue.Issue{ - Type: JSON_TYPE_PREDICATE, - TypeName: JSON_TYPE_PREDICATE_NAME, - TypeDescription: "IS JSON predicate expressions not supported yet in YugabyteDB", - Suggestion: "", - GH: "", - DocsLink: "", //TODO + Type: JSON_TYPE_PREDICATE, + Name: JSON_TYPE_PREDICATE_NAME, + Impact: constants.IMPACT_LEVEL_2, + Description: "IS JSON predicate expressions not supported yet in YugabyteDB", + Suggestion: "", + GH: "", + DocsLink: "", //TODO } func NewJsonPredicateIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -169,12 +180,13 @@ func NewJsonPredicateIssue(objectType string, objectName string, sqlStatement st } var copyFromWhereIssue = issue.Issue{ - Type: COPY_FROM_WHERE, - TypeName: "COPY FROM ... WHERE", - TypeDescription: "", - Suggestion: "", - GH: "", - DocsLink: "", + Type: COPY_FROM_WHERE, + Name: "COPY FROM ... WHERE", + Impact: constants.IMPACT_LEVEL_2, + Description: "", + Suggestion: "", + GH: "", + DocsLink: "", } func NewCopyFromWhereIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -182,12 +194,13 @@ func NewCopyFromWhereIssue(objectType string, objectName string, sqlStatement st } var copyOnErrorIssue = issue.Issue{ - Type: COPY_ON_ERROR, - TypeName: "COPY ... ON_ERROR", - TypeDescription: "", - Suggestion: "", - GH: "", - DocsLink: "", + Type: COPY_ON_ERROR, + Name: "COPY ... ON_ERROR", + Impact: constants.IMPACT_LEVEL_2, + Description: "", + Suggestion: "", + GH: "", + DocsLink: "", } func NewCopyOnErrorIssue(objectType string, objectName string, sqlStatement string) QueryIssue { @@ -195,12 +208,13 @@ func NewCopyOnErrorIssue(objectType string, objectName string, sqlStatement stri } var fetchWithTiesIssue = issue.Issue{ - Type: FETCH_WITH_TIES, - TypeName: "FETCH .. WITH TIES", - TypeDescription: "FETCH .. WITH TIES is not supported in YugabyteDB", - Suggestion: "No workaround available right now", - GH: "", - DocsLink: "", //TODO + Type: FETCH_WITH_TIES, + Name: "FETCH .. WITH TIES", + Impact: constants.IMPACT_LEVEL_2, + Description: "FETCH .. WITH TIES is not supported in YugabyteDB", + Suggestion: "No workaround available right now", + GH: "", + DocsLink: "", //TODO } func NewFetchWithTiesIssue(objectType string, objectName string, sqlStatement string) QueryIssue { diff --git a/yb-voyager/src/query/queryparser/object_collector.go b/yb-voyager/src/query/queryparser/object_collector.go index ba7561a1b..9a6020699 100644 --- a/yb-voyager/src/query/queryparser/object_collector.go +++ b/yb-voyager/src/query/queryparser/object_collector.go @@ -93,7 +93,7 @@ func (c *ObjectCollector) Collect(msg protoreflect.Message) { relName := GetStringField(relationMsg, "relname") objectName := utils.BuildObjectName(schemaName, relName) log.Debugf("[IUD] fetched schemaname=%s relname=%s objectname=%s field\n", schemaName, relName, objectName) - if c.predicate(schemaName, relName, "table") { + if c.predicate(schemaName, relName, constants.TABLE) { c.addObject(objectName) } } diff --git a/yb-voyager/src/utils/commonVariables.go b/yb-voyager/src/utils/commonVariables.go index b42c547d9..16a8725ad 100644 --- a/yb-voyager/src/utils/commonVariables.go +++ b/yb-voyager/src/utils/commonVariables.go @@ -107,6 +107,7 @@ type AnalyzeSchemaIssue struct { ObjectName string `json:"ObjectName"` Reason string `json:"Reason"` Type string `json:"-" xml:"-"` // identifier for issue type ADVISORY_LOCKS, SYSTEM_COLUMNS, etc + Impact string `json:"-" xml:"-"` // temporary field; since currently we generate assessment issue from analyze issue SqlStatement string `json:"SqlStatement,omitempty"` FilePath string `json:"FilePath"` Suggestion string `json:"Suggestion"`