From ea3facb31bd986f953af42255f1cc48cf22a7e35 Mon Sep 17 00:00:00 2001 From: Sanyam Singhal Date: Fri, 4 Oct 2024 14:24:48 +0000 Subject: [PATCH 1/3] [DB-13024] Implement Detailed Reporting for Unsupported Query Constructs - Added functionality to detect and report Unsupported Query Constructs, starting with advisory locks, within migration assessments. - Enhanced HTML and JSON report formats to display unsupported query details effectively. - Designed with extensibility in mind, allowing for easy addition of future query construct types. - Initial advisory lock detection covers common cases, with plans for more comprehensive coverage. --- yb-voyager/cmd/analyzeSchema.go | 30 +++-- yb-voyager/cmd/assessMigrationCommand.go | 71 +++++++++- yb-voyager/cmd/common.go | 1 + .../cmd/templates/assessmentReport.template | 38 +++++- yb-voyager/src/migassessment/assessmentDB.go | 11 ++ yb-voyager/src/queryparser/queryParser.go | 33 +++++ .../src/queryparser/unsupportedConstructs.go | 126 ++++++++++++++++++ .../postgresql/db_queries_summary.psql | 20 +++ yb-voyager/src/utils/commonVariables.go | 5 + 9 files changed, 317 insertions(+), 18 deletions(-) create mode 100644 yb-voyager/src/queryparser/queryParser.go create mode 100644 yb-voyager/src/queryparser/unsupportedConstructs.go create mode 100644 yb-voyager/src/srcdb/data/gather-assessment-metadata/postgresql/db_queries_summary.psql diff --git a/yb-voyager/cmd/analyzeSchema.go b/yb-voyager/cmd/analyzeSchema.go index fc69e7894..05f4514d0 100644 --- a/yb-voyager/cmd/analyzeSchema.go +++ b/yb-voyager/cmd/analyzeSchema.go @@ -581,7 +581,7 @@ func reportUnsupportedIndexesOnComplexDatatypes(createIndexNode *pg_query.Node_I 1. normal index on column with these types 2. expression index with casting of unsupported column to supported types [No handling as such just to test as colName will not be there] 3. expression index with casting to unsupported types - 4. normal index on column with UDTs + 4. normal index on column with UDTs 5. these type of indexes on different access method like gin etc.. [TODO to explore more, for now not reporting the indexes on anyother access method than btree] */ colName := param.GetIndexElem().GetName() @@ -615,7 +615,7 @@ func reportUnsupportedIndexesOnComplexDatatypes(createIndexNode *pg_query.Node_I summaryMap["INDEX"].invalidCount[displayObjName] = true reason := fmt.Sprintf(ISSUE_INDEX_WITH_COMPLEX_DATATYPES, castTypeName) if slices.Contains(compositeTypes, fullCastTypeName) { - reason = fmt.Sprintf(ISSUE_INDEX_WITH_COMPLEX_DATATYPES, "user_defined_type") + reason = fmt.Sprintf(ISSUE_INDEX_WITH_COMPLEX_DATATYPES, "user_defined_type") } reportCase(fpath, reason, "https://github.com/yugabyte/yugabyte-db/issues/9698", "Refer to the docs link for the workaround", "INDEX", displayObjName, sqlStmtInfo.formattedStmt, @@ -1001,7 +1001,9 @@ func reportGeneratedStoredColumnTables(createTableNode *pg_query.Node_CreateStmt if len(generatedColumns) > 0 { summaryMap["TABLE"].invalidCount[sqlStmtInfo.objName] = true reportCase(fpath, STORED_GENERATED_COLUMN_ISSUE_REASON+fmt.Sprintf(" Generated Columns: (%s)", strings.Join(generatedColumns, ",")), - "https://github.com/yugabyte/yugabyte-db/issues/10695", "Using Triggers to update the generated columns is one way to work around this issue, refer docs link for more details.", "TABLE", fullyQualifiedName, sqlStmtInfo.formattedStmt, UNSUPPORTED_FEATURES, GENERATED_STORED_COLUMN_DOC_LINK) + "https://github.com/yugabyte/yugabyte-db/issues/10695", + "Using Triggers to update the generated columns is one way to work around this issue, refer docs link for more details.", + TABLE, fullyQualifiedName, sqlStmtInfo.formattedStmt, UNSUPPORTED_FEATURES, GENERATED_STORED_COLUMN_DOC_LINK) } } @@ -1799,17 +1801,17 @@ func packAndSendAnalyzeSchemaPayload(status string) { issue.SqlStatement = "" // Obfuscate sensitive information before sending to callhome cluster issue.ObjectName = "XXX" // Redacting object name before sending /* - Removing Reason and Suggestion completely for now as there can be sensitive information in some of the cases - so will enable it later with proper understanding - some of the examples - - Reason: - Stored generated columns are not supported. [columns] - Unsupported datatype - xml on [column] - Unsupported datatype - xid on [column] - Unsupported PG syntax - [error msg from parser] - Policy require roles to be created. [role names] - Suggestion: - Foreign Table issue mentions Server name to be created. + Removing Reason and Suggestion completely for now as there can be sensitive information in some of the cases + so will enable it later with proper understanding + some of the examples - + Reason: + Stored generated columns are not supported. [columns] + Unsupported datatype - xml on [column] + Unsupported datatype - xid on [column] + Unsupported PG syntax - [error msg from parser] + Policy require roles to be created. [role names] + Suggestion: + Foreign Table issue mentions Server name to be created. */ issue.Reason = "XXX" issue.Suggestion = "XXX" diff --git a/yb-voyager/cmd/assessMigrationCommand.go b/yb-voyager/cmd/assessMigrationCommand.go index 2aaf1447e..ddfde30fb 100644 --- a/yb-voyager/cmd/assessMigrationCommand.go +++ b/yb-voyager/cmd/assessMigrationCommand.go @@ -38,6 +38,7 @@ import ( "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" + "github.com/yugabyte/yb-voyager/yb-voyager/src/queryparser" "github.com/yugabyte/yb-voyager/yb-voyager/src/srcdb" "github.com/yugabyte/yb-voyager/yb-voyager/src/utils" ) @@ -723,6 +724,12 @@ func generateAssessmentReport() (err error) { } assessmentReport.UnsupportedFeatures = append(assessmentReport.UnsupportedFeatures, unsupportedFeatures...) + unsupportedQueries, err := fetchUnsupportedQueryConstructs() + if err != nil { + return fmt.Errorf("failed to fetch unsupported queries on YugabyteDB: %w", err) + } + assessmentReport.UnsupportedQueryConstructs = unsupportedQueries + unsupportedDataTypes, unsupportedDataTypesForLiveMigration, err := fetchColumnsWithUnsupportedDataTypes() if err != nil { return fmt.Errorf("failed to fetch columns with unsupported data types: %w", err) @@ -833,7 +840,7 @@ func getIndexesOnComplexTypeUnsupportedFeature(schemaAnalysisiReport utils.Schem DisplayDDL: false, Objects: []ObjectInfo{}, } - unsupportedIndexDatatypes = append(unsupportedIndexDatatypes, "array") // adding it here only as we know issue form analyze will come with type + unsupportedIndexDatatypes = append(unsupportedIndexDatatypes, "array") // adding it here only as we know issue form analyze will come with type unsupportedIndexDatatypes = append(unsupportedIndexDatatypes, "user_defined_type") // adding it here as we UDTs will come with this type. for _, unsupportedType := range unsupportedIndexDatatypes { indexes := getUnsupportedFeaturesFromSchemaAnalysisReport(fmt.Sprintf("%s indexes", unsupportedType), fmt.Sprintf(ISSUE_INDEX_WITH_COMPLEX_DATATYPES, unsupportedType), schemaAnalysisReport, false, "") @@ -906,6 +913,66 @@ func fetchUnsupportedObjectTypes() ([]UnsupportedFeature, error) { return unsupportedFeatures, nil } +func fetchUnsupportedQueryConstructs() ([]utils.UnsupportedQueryConstruct, error) { + query := fmt.Sprintf("SELECT DISTINCT query from %s", migassessment.DB_QUERIES_SUMMARY) + rows, err := assessmentDB.Query(query) + if err != nil { + return nil, fmt.Errorf("error querying=%s on assessmentDB: %w", query, err) + } + defer func() { + closeErr := rows.Close() + if closeErr != nil { + log.Warnf("error closing rows while fetching database queries summary metadata: %v", err) + } + }() + + var executedQueries []string + for rows.Next() { + var executedQuery string + err := rows.Scan(&executedQuery) + if err != nil { + return nil, fmt.Errorf("error scanning rows: %w", err) + } + executedQueries = append(executedQueries, executedQuery) + } + + var result []utils.UnsupportedQueryConstruct + for i := 0; i < len(executedQueries); i++ { + query := executedQueries[i] + + // Check if the query starts with CREATE, INSERT, UPDATE, or DELETE + upperQuery := strings.ToUpper(strings.TrimSpace(query)) + if strings.HasPrefix(upperQuery, "CREATE") || strings.HasPrefix(upperQuery, "INSERT") || + strings.HasPrefix(upperQuery, "UPDATE") || strings.HasPrefix(upperQuery, "DELETE") { + continue + } + + queryParser := queryparser.New(query) + err := queryParser.Parse() + if err != nil { + return nil, fmt.Errorf("failed to parse query-%s: %w", query, err) + } + + // Check for unsupported constructs in the parsed query + unsupportedConstructType, err := queryParser.CheckUnsupportedQueryConstruct() + if err != nil { + log.Warnf("failed while trying to parse the query: %s", err.Error()) + } + if unsupportedConstructType != "" { + fmt.Printf("Unsupported query: %s, Type: %s\n", query, unsupportedConstructType) + result = append(result, utils.UnsupportedQueryConstruct{ + ConstructType: unsupportedConstructType, + Query: query, + }) + } + } + if len(result) != 0 { + utils.PrintAndLog("Found YB unsupported queries in source DB, for more details please refer migration assessment report") + } + // TODO: sort the slice for better readability + return result, nil +} + func fetchColumnsWithUnsupportedDataTypes() ([]utils.TableColumnsDataTypes, []utils.TableColumnsDataTypes, error) { var unsupportedDataTypes []utils.TableColumnsDataTypes var unsupportedDataTypesForLiveMigration []utils.TableColumnsDataTypes @@ -914,7 +981,7 @@ func fetchColumnsWithUnsupportedDataTypes() ([]utils.TableColumnsDataTypes, []ut migassessment.TABLE_COLUMNS_DATA_TYPES) rows, err := assessmentDB.Query(query) if err != nil { - return nil, nil, fmt.Errorf("error querying-%s: %w", query, err) + return nil, nil, fmt.Errorf("error querying-%s on assessmentDB: %w", query, err) } defer func() { closeErr := rows.Close() diff --git a/yb-voyager/cmd/common.go b/yb-voyager/cmd/common.go index 11ce70643..e890efbc5 100644 --- a/yb-voyager/cmd/common.go +++ b/yb-voyager/cmd/common.go @@ -1117,6 +1117,7 @@ type AssessmentReport struct { TableIndexStats *[]migassessment.TableIndexStats `json:"TableIndexStats"` Notes []string `json:"Notes"` MigrationCaveats []UnsupportedFeature `json:"MigrationCaveats"` + UnsupportedQueryConstructs []utils.UnsupportedQueryConstruct `json:"UnsupportedQueryConstructs"` } type AssessmentDetail struct { diff --git a/yb-voyager/cmd/templates/assessmentReport.template b/yb-voyager/cmd/templates/assessmentReport.template index 364e7fe63..28911d15b 100644 --- a/yb-voyager/cmd/templates/assessmentReport.template +++ b/yb-voyager/cmd/templates/assessmentReport.template @@ -67,7 +67,7 @@

Migration Assessment Report

Database Name: {{.SchemaSummary.DBName}}

{{ if .SchemaSummary.SchemaNames}} -

Schema Name: +

Schema Name: {{range $i, $a := .SchemaSummary.SchemaNames}} {{$a}}  {{end}} @@ -213,7 +213,6 @@

No unsupported features were present among the ones assessed.

{{end}} - {{if .Notes}}

@@ -227,6 +226,41 @@ {{end}} +

Unsupported Query Constructs

+

Below are source database queries not supported in YugabyteDB, identified by scanning system tables.:

+ + + + + + {{ $currentType := "" }} + {{ range $i, $construct := .UnsupportedQueryConstructs }} + {{ if ne $construct.ConstructType $currentType }} + {{ if ne $currentType "" }} + + + + + {{ end }} + + + + + {{ end }} +
Construct TypeQueries
{{ $construct.ConstructType }} +
+
    + {{ $currentType = $construct.ConstructType }} + {{ end }} +
  • {{ $construct.Query }}
  • + {{ end }} + + {{ if ne $currentType "" }} +
+
+
+ + {{ if .MigrationCaveats}}

Migration caveats

diff --git a/yb-voyager/src/migassessment/assessmentDB.go b/yb-voyager/src/migassessment/assessmentDB.go index de7b58b88..e31421a63 100644 --- a/yb-voyager/src/migassessment/assessmentDB.go +++ b/yb-voyager/src/migassessment/assessmentDB.go @@ -38,6 +38,7 @@ const ( OBJECT_TYPE_MAPPING = "object_type_mapping" TABLE_COLUMNS_DATA_TYPES = "table_columns_data_types" TABLE_INDEX_STATS = "table_index_stats" + DB_QUERIES_SUMMARY = "db_queries_summary" PARTITIONED_TABLE_OBJECT_TYPE = "partitioned table" PARTITIONED_INDEX_OBJECT_TYPE = "partitioned index" @@ -132,6 +133,16 @@ func InitAssessmentDB() error { parent_table_name TEXT, size_in_bytes INTEGER, PRIMARY KEY(schema_name, object_name));`, TABLE_INDEX_STATS), + fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s ( + queryid BIGINT, + query TEXT, + calls BIGINT, + total_exec_time REAL, + mean_exec_time REAL, + min_exec_time REAL, + max_exec_time REAL, + rows BIGINT, + PRIMARY KEY(queryid));`, DB_QUERIES_SUMMARY), } for _, cmd := range cmds { diff --git a/yb-voyager/src/queryparser/queryParser.go b/yb-voyager/src/queryparser/queryParser.go new file mode 100644 index 000000000..409918da2 --- /dev/null +++ b/yb-voyager/src/queryparser/queryParser.go @@ -0,0 +1,33 @@ +package queryparser + +import ( + pg_query "github.com/pganalyze/pg_query_go/v5" +) + +type QueryParser struct { + QueryString string + ParseTree *pg_query.ParseResult +} + +func New(query string) *QueryParser { + return &QueryParser{ + QueryString: query, + } +} + +func (qp *QueryParser) Parse() error { + tree, err := pg_query.Parse(qp.QueryString) + if err != nil { + return err + } + qp.ParseTree = tree + return nil +} + +func (qp *QueryParser) CheckUnsupportedQueryConstruct() (string, error) { + if qp.containsAdvisoryLocks() { + return ADVISORY_LOCKS, nil + } + // TODO: Add checks for unsupported constructs - system columns, XML functions + return "", nil +} diff --git a/yb-voyager/src/queryparser/unsupportedConstructs.go b/yb-voyager/src/queryparser/unsupportedConstructs.go new file mode 100644 index 000000000..4379028dd --- /dev/null +++ b/yb-voyager/src/queryparser/unsupportedConstructs.go @@ -0,0 +1,126 @@ +package queryparser + +import ( + "slices" + + pg_query "github.com/pganalyze/pg_query_go/v5" +) + +const ( + ADVISORY_LOCKS = "Advisory Locks" + SYSTEM_COLUMNS = "System Columns" + XML_FUNCTIONS = "XML Functions" +) + +// NOTE: pg parser converts the func names in parse tree to lower case by default +var advisoryLockFunctions = []string{ + "pg_advisory_lock", "pg_try_advisory_lock", "pg_advisory_xact_lock", + "pg_advisory_unlock", "pg_advisory_unlock_all", "pg_try_advisory_xact_lock", +} + +func (qp *QueryParser) containsAdvisoryLocks() bool { + if qp.ParseTree == nil { + return false + } + + selectStmtNode, isSelectStmt := qp.ParseTree.Stmts[0].Stmt.Node.(*pg_query.Node_SelectStmt) + if !isSelectStmt { + return false + } + + // Check advisory locks in the target list + if containsAdvisoryLocksInTargetList(selectStmtNode.SelectStmt.TargetList) { + return true + } + + // Check advisory locks in FROM clause + if containsAdvisoryLocksInFromClause(selectStmtNode.SelectStmt.FromClause) { + return true + } + + // Check advisory locks in WHERE clause + if containsAdvisoryLocksInWhereClause(selectStmtNode.SelectStmt.WhereClause) { + return true + } + return false +} + +// Checks for advisory lock functions in the main query's target list. +// This includes direct function calls like: +// Example: SELECT pg_advisory_lock(1); +// Example: SELECT col1, pg_try_advisory_lock(2) FROM my_table; +func containsAdvisoryLocksInTargetList(targetList []*pg_query.Node) bool { + for _, target := range targetList { + if resTarget := target.GetResTarget(); resTarget != nil { + if funcCallNode, isFuncCall := resTarget.Val.Node.(*pg_query.Node_FuncCall); isFuncCall { + funcList := funcCallNode.FuncCall.Funcname + functionName := funcList[0].GetString_().Sval + if slices.Contains(advisoryLockFunctions, functionName) { + return true + } + } + } + } + return false +} + +// Recursively checks the FROM clause for subqueries containing advisory locks. +// This covers advisory locks embedded in subqueries such as: +// Example: SELECT * FROM (SELECT pg_advisory_lock(1)) AS lock_query; +// Example: SELECT * FROM my_table JOIN LATERAL (SELECT pg_try_advisory_xact_lock(3)) AS lock_check ON true; +func containsAdvisoryLocksInFromClause(fromClause []*pg_query.Node) bool { + for _, fromItem := range fromClause { + if subselectNode, isSubselect := fromItem.Node.(*pg_query.Node_RangeSubselect); isSubselect { + subSelectStmt := subselectNode.RangeSubselect.Subquery.GetSelectStmt() + if subSelectStmt != nil { + // Recursively check for advisory locks in the subquery's target list + if containsAdvisoryLocksInTargetList(subSelectStmt.TargetList) { + return true + } + // Recursively check for advisory locks in the subquery's FROM clause + if containsAdvisoryLocksInFromClause(subSelectStmt.FromClause) { + return true + } + } + } + } + return false +} + +// Recursively checks the WHERE clause for advisory lock functions. +// This allows for advisory locks embedded within conditions like: +// Example: SELECT * FROM my_table WHERE pg_advisory_lock(1) = true; +func containsAdvisoryLocksInWhereClause(whereClause *pg_query.Node) bool { + if whereClause == nil { + return false + } + + if funcCallNode := whereClause.GetFuncCall(); funcCallNode != nil { + funcList := funcCallNode.Funcname + functionName := funcList[0].GetString_().Sval + if slices.Contains(advisoryLockFunctions, functionName) { + return true + } + } + + // Recursively check for advisory locks in nested expressions + switch n := whereClause.Node.(type) { + case *pg_query.Node_BoolExpr: + return containsAdvisoryLocksInNodeList(n.BoolExpr.Args) + case *pg_query.Node_SubLink: + return containsAdvisoryLocksInWhereClause(n.SubLink.Subselect) + // Add more cases for other types of expressions as needed + } + + return false +} + +// Helper function to check advisory locks within a node list (for WHERE clause and nested conditions). +func containsAdvisoryLocksInNodeList(nodes []*pg_query.Node) bool { + for _, node := range nodes { + if containsAdvisoryLocksInWhereClause(node) { + return true + } + } + return false +} diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata/postgresql/db_queries_summary.psql b/yb-voyager/src/srcdb/data/gather-assessment-metadata/postgresql/db_queries_summary.psql new file mode 100644 index 000000000..26de12265 --- /dev/null +++ b/yb-voyager/src/srcdb/data/gather-assessment-metadata/postgresql/db_queries_summary.psql @@ -0,0 +1,20 @@ +CREATE EXTENSION IF NOT EXISTS pg_stat_statements; + +CREATE TEMP TABLE temp_table AS +SELECT + queryid, + query, + calls, + total_exec_time, + mean_exec_time, + min_exec_time, + max_exec_time, + rows +FROM + pg_stat_statements +WHERE + dbid = (SELECT oid FROM pg_database WHERE datname = current_database()); + +\copy temp_table to 'db_queries_summary.csv' WITH CSV HEADER; + +DROP TABLE temp_table; \ No newline at end of file diff --git a/yb-voyager/src/utils/commonVariables.go b/yb-voyager/src/utils/commonVariables.go index a024c5952..c8f36d8f9 100644 --- a/yb-voyager/src/utils/commonVariables.go +++ b/yb-voyager/src/utils/commonVariables.go @@ -121,6 +121,11 @@ type TableColumnsDataTypes struct { DataType string `json:"DataType"` } +type UnsupportedQueryConstruct struct { + ConstructType string + Query string +} + // ================== Segment ============================== type Segment struct { Num int From 935a495ed8b4e2a016dbee223bae6db22a9f6fe4 Mon Sep 17 00:00:00 2001 From: Sanyam Singhal Date: Fri, 4 Oct 2024 14:28:34 +0000 Subject: [PATCH 2/3] Updated gather assessment metadata tarball --- .../data/gather-assessment-metadata.tar.gz | Bin 9278 -> 9489 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index 7be29d652e629334f8a5cd5e4cfc672c264ef73c..9153c2ffed84e8398df6276f48502f02981415c3 100644 GIT binary patch literal 9489 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 jWXX~xOO`BIvSi7UB}5ioYhOr0Pp|+@D+vJ literal 9278 zcmV-EB*EJsiwFQqoAPD=1MNNiciKpj`|I&n^b#_Hj0FZ8=RLB_g@BxJgOLYtGTBUq zl|jb30ZEaB9dDBR+pnrWq?V8XCyuk3LGL9->h9|5>gxLFu99X(aA|s~;rpiVFHAd7 z7iM5gjlihc@k^GyHU{0muO%lU_^R;yJH z$$qVRv|r!N|9xC*=HKy*$=tjHF|hUg*AJ_Y>jyCZ`$zT1yZOJ5YxDdE#`)Y-C(eAi zuzeLv)ZoT7{W1s!cfRyD_W|@cIy}sr|0+y2&VT)=`uOPJaSi7GarFS?|Nhq>{$GCn zhuVl}?H4-HkB@VBbF68dXRY?n;e!`itJCd2CwiaWp0ox(pPiES@FhGU9j(_r>5jAk z*(1N4=_4&{cG`Nb4ZHu;$UeOt4Z0`8Q(f-~IMC)qKO2ShUuuKy@oRdUQ&pn9w*unW zWcW*un4af&K5;yv5BW{*)eEh!K^v@~4F>vvXuozxcvpshZM~yKRrH}$jHa*fB#(+xY68P|`+)el} z>JIO)%c$raN{sU{9~B8`$^YoxezMBk^l?DQ0RpuqJ`ia3J28}aVf28)>uJZMRp_qa z1)>W#i1*+I*&Vn+5(Bkox+F^twN5MCl9)54Wn=`XyPht+#sG zu&osVD;$s&SdI;xLDm zfw;C(#IBVsb_L2P6C+XB?wx@w9H1=h=qIgiAAcR6_1mMa-dCTshFXV21zl*Sl97Ij zH+_9@(&|+P+RKzSQei0-jZml~8exrSElZ196o1* z!`B9#meenOY!yLAH8W~G>uCxZ#R^wc%9^$?je}7a)o2xsim~6L~1rQ1(!$AWb2y-Ks%X25qv9Jze789!gEWO4N zMo%122uJM0_;JZOp+yDsh#7Q%Q+$w86=uxQ8u4+lN^(cH_t2em4?T&@CKuhwwiV;d zL+u^L+k2~wx|hmYaZBfJ9CU#rp3P&z zl1ZU+=0?bt+aT*VLB4<@IGXhYQM!E?3uv4U8NEK$wj%}InY#@k{H1Gp5i;E&9ccfI zkLgQB7|{+Vv`l4M_3y3vdYr}XI z8Q)YlAxhs*&u6-yAT{SlQcX_R$0ZG*-HOeQ7Mb!VC& zz`;lBohhg2fh2Oa2gd~ohsEyF0L2wd_6)~`amqZqYc@Vpk)-l28uea?^Zjf{?yh^i zwmtvzoNIOBEbZVH=YHbawEuflJ)-Bo_4-l0RzCv&uU@ZJcmCgfTz_5vPd>+!xI1#< zsHn_PIcx(IHA%D;O67i6Xdo9^^*GOo|<| z)!{9xWSc(jEI09#Kp|AXOyAK9Ej;q>JG<^OHt ze<=6g@&518(P47`w^rSq|K7{>*VX@b8UMpp#clV0!$6=&rF?n#Pxb}^-wcj>m6BVm zpY=z@MxY507g!y4j>A+8*f*sa}bx)ozYR^6(KU&}M{A;5idk8C(4 z?52%ole^=hFx)WJhW{FTbz7HZ6W_(phVGU1Qcdc0CogL)QTz)auswKa+Q_NRbeR1^gT{V_8n-sCt>6-5 zl;2|hAinkXMBKG9qd-$8SGZqQ&6=xo8H zvSY6gbIP*1qXoi@?vUfNjqMZx_NUEh`12dtVzxG#)!*6@`!?5R`~T)#y>f1h8PsA= z)a*88|1zbI_4)s`qsNEUc>e!E_3`8Vo&A3w*Mq-T&MmtF*6C&L0W6!g@pz5 zNr}8(&J2|Noo9Ps*G|g02eeYpnwYk4VoK2z1OS@1E!O~@Bue(kOVjf~%#&JqpA@k| zo)_g|FSlOToE-jzg+~)g<>0%}hh>(Rlw+svxq>3eodML+$IOmuu zL=0%*-q2j0s3tK2jy7JGLEttjmFw&4vO!TUJKn4^XI1@5uiMu8Lrn#=d80EMj1!-D z=DVfkv1BB}1*|4$eUQ0vjedzS^GrNMb`a}p&qCz|R=9H!TpONA;Y=-%h88Hq7}*4l zFm|~D5DpY<9`tW_m?t3YyTd&SWoVkQb{7tVy09jIkUd+%VkI-@%JgiS17>;) z%lE0$1!sf8nOh4hFqk4}G z00_Pq5B0M_TWhF={ZDyP%99^{B9*CmRk4@zIr-rS;$BZd+H-*Y)`-|2M9OF)F)WYWAl)r@4#-WuOmQ?VdJ1 zZ4HO7^g*Zj4;Rq9hSmL3T=FO^QS~kuty-^DGa0S*tc{FDlotc|uYx431WqNQT}9AN z$>mPxCJHW-Gmry1%AFe%Mg{uo(wT#t;$E3C!LWXEWz2zBKrmRGuWp>B2SBbY&#|$K zaxR|(9nrotCx3+cMOA_CT;jOMZ#f|B8<6|eJZUybo|Wav+b3Anrn6{HE*+>5O7uK? ziko`-xeF`m06-Zqm7#i#geh_$EQ2d+YEDIu5AsBv2jn27FQG8@??6pR*j97qTJ&zjQ7vr>>CS0`bizfYWVKe3D~)glOx-Xcqi6X@0 zBA4)^qcIlS#xzI!=KP$X1UzI@MxROYf?^tKN@EV}H4POd+kk?yIa+DJl1ntxX(8Le zz;*D36aWAUuiunMzbWMHTin%^ALk$a2CG3{4ic@Q5~uwf*!ux9x~?sBdyMH+^v?PO z!Z}Oi^$_U z$&NB4dWy;_W{9EXLrtSx#8=(^u?}2?9q=tWZpNlyN6$Yva)4DnZ7Nq=0W0}r)E^RR zKyhnUo;-m)PSvBQk8u9L!HAXo9ZK@Dx^Ctltxo6zqP-6Qd3Hn-b{WMp2rCYJ6+ZbN zL>CVpJ^e)2yGMnpl8?5sqIqcMr{`9K&0eDrf{WNkLgfs7Rlz;R^&eslAr(ytO{T#k zHp1l=q9?FJ%n*ipth_0f-hwp|v#vg@*jl(uixwIvPl!eS(Iow2`0?Y9rIfmSDvAY* z{2!@MOXpFul2sEgA3Wv&>ca}zBl#w70%TQ1CTtpSYHzcv%>3nfvGV&H@>}rs$B*n! zp#p&Od$f55^iOQTMwrK3kh>d!yn?=9Br%U@+Yx~od4~hBreA_TcuiZPO>N`5!y6^m z7a&f3!3@k-p2nZV@9;QqbwD`m*xY6enwkk0Bu^K_LqE<|a8F11(C0iK=NC4JRb(0A zx9ksQKdl>Ungu;h3Z;~jq+6RF2Q0Y^lQfm6!chQ|DWaR0!6!dnF&aE` z;aq|H#JyQ^;W>*;EuCYv$D($MsSx)&LPMHY05c!V!q6*`RZ*-V>Lj!hRSz8MkCivS zKYjb?>Bq_=yqrT=EkqCcqMOyirfHt#t3K;p^rGL40DDnXU_-9CJCN;$_tB^H? z%zgBaWagPJQJqtw{Ql zQmC;s+@}@Jn^*!360r~Zu0-{d8<8}^wgy%kib!8?2P}zouIIxs# zC*a#F*b-~jPM@=yon~@0Y_OSIP9UKKT|QL`9}m?1b|Kpi4|goqBVQ=W+YK<2SvB+0@<|9fj(00%H=A#iGsF#g=z>laIQY>fox(TW zxxWv^d_x;VS|K`Yt2`1xwok~^fuZ*t$Ayu5&T@81Oam6)@R!~xl#BMbg3b5l1jUOL znP#k%8#|F)1XGF@-w@1aer zUWt10k@|M_7;iXnmh&kcB0Y>=+S71%p7$-fNZXgEq>b4*^sl!7Oa4NfB7)tq_ycVT z)#Z=Yh)-$lrW~~6`jzSZLO;Bag(b|nE+$@Ya{_dW%deOap zMx%2F@O%gqU2Wa%j~aLaJ~KW1tv%NU;r&1ZP+(Qf_l5wphgE%m3c?2l*X_3kug4iU z@lw|PYVoLhf?mjrWVWXr9F9v^QLN7J?$Lx}z5aZ^=LPzBFq*+zD>U zzd`yWTlDmHtG7iv#!Ns4{gq&#(3tAb!yI;2jP3}}e83ZRJkVi&m%&diz`1n6zYMj) zNIN<00iRK42$+BLqM5Il!9+Th!;mslWm2UKvhad0#?S@Q_VjEeYWmWH3K3dFe&@pJlVzX39x1oLb;=UM! zgfz^80fU6mUQ8HWlcF-SXJC-gjccB;x9+lz)8*wVh{}f#pj*o=44s0Om1%k(qWoil zEuOaCKkhzH1!vmRB%H$P@&I49kYs(a5^*p-54K@Gn#uNV=xZyR#XJrS*nOz|a)!AA z@RKSH_!| z5M;XrObLT`K)d!ZGJ3=S(;RY3p|T%_T*lol1QrH z6&gEI!^k9O@@PC+fXBgQ6I4~-5j7CVI5EIPJ(nR7b+XDZL{)8Pd0^foyop+MyO zaWP6XsO!TK%yK}IH6k;Zmw@;LUX7120FT_c=0*7CPtZ%C)dMt#!3W3~)pWUV$A&)! zZyw`LRdDX%FD#i2{1HPW@)@_L2x}NoBN`C{lu8h}QmA8aH(IDr$FpV@eqKO|cDcZP zAPni_F}F0FLgci#jysLThZ_qXr#eIdEtvv79{88p^Liw9B^disZ7D475qv zGv}G9XDKiJqYeH5p27qoPrMPAcC4(c>WZpiE}3|Jo3f^rC0bD?URSf527hC#g=mGs z&a;fU^>1i~Nx;%Oeenf@%F_PBcCKyqc=a{EThNPUQhAt3wNOf|Ti0I(W#4=^4wmj1 zHgYXPl*LTr7urYBk zp&3R{k8yV)%xZ z{SMs(fV*Rq&E)59zq3b7izb7a?_Cea0Ek*hPE54 zE!R|i6AXHKz)9;k;^fM|MFQN05s54Z#a*6*jQHpqAU!@>_7%*LL(=9hdZVGE=@GtEURL03N=k`3dC#*a+wEIrTUa395n?1Af(D&(hQ>zW`pKn&XadtiD;<=!2UHH5 z`g7BCqqT=qgs}h~GLf`o(Jr4ohD1(2G#E+R}%Nw z!{Z112kU^Il!*Gf$?DszK}B1mh&wt5W%*rSG!C z4Rm(z^LN+rt!zc^L3zSsAh_w1=sk~F#d-X@VQIW-4KUW?l|gq+8nIEJ*rjUUM!hi= z-gn$Xr@j)~Daa>8UKb;GL%TX@Rnc>s3Of+N-5PF5QOB0P0Eit+RQMr6nRKY90OjZp zUgKT^^VR^`()@2yd|m06RyaVEkNN4k6H#KdD3%bGD9f)88UZGPHekmFJei!9z<~L7 z6uk2r@nrVo=ylg8K8N{?_(KbXfC7UM_2<>2#B_|?KkiTuB< zlN!=(;ABEWS}o4fF=IK|PAbfoz99S{HSd8Q1&Pg;&4~}Vz+<6Cn{ybj$?Xyts1(V} zUigxP1Ex_WoT)RNJW0ynEXm?)<|&TqyDVXMA$q|8@!0IjTVYV9_s3LMkB1}uv$DLuN~?2w=^ zKr1;fV(SE#4R=7v6+7G$iitX<{25wkyq2o+XZ%$p$_M7m6b?Qq;oC{d(c|i;l+;W! zOwCMm-k?;LyOunf{7M(nGVL!*rz1O}Ie4Pe6Unx#AQj49ow6;+`VAl0Qc z1HX2C0?l3K%g9p^@gpBa20y9{mg?B^oA55dj4DikY15fyem%yZsuLDA?z21g8ff|x z(7ysVaAxu%W^Q843_h4U##Fts3^fd`Qa#7PUT8coj~(IBofy`utOj&O9M4B5F+z-+ z6WpGx68fIsZRqBmT-(KeNbzao1&h1CMF{AI_|Iy6|1pdIJgU`duzdDwNA-h)UHr#= zT)X(s|FHPauN9d%fh7&nsJuaeg5A z6-Is)$*&6WcB@doJN+cryaY)vVq%0=|Z50hzNMJ#z?Dm`t^mCulU`2aDq<8>!lKfu~hK&NX3^pIfUlit=d#6;v1~#sz!y{kZ5MX7EtJJeH z>XX#*K9R=jnG<~X&p>PIgU*xOGwnH73HY(dfV~_UBdpnbox=Sc`4bJ;A#HN31MS-{ zV*P>fOtnC4WIbI!4IPivj@WeZe#BX}v=hal80bOg-1U z;TU3V`N6WJp_4C@!7Da1Vs>mmD2T=otv30?q~RiqHP?RC+GnsF*?wSgg@{VGKhy^J z2{>3E@j)v*qAFYOnF?XIJm9Zl! zJFFqFZ!>s4Z%iU`h4hs+Zf}#M{T=VYrm2|kOO<|?*XQVeETx;}TkZpF(Et07YxTtb z@8g5oPXFJ_1=cWQfhe{h#UtQyj@{7UV|rATVLb5K7^09cA!Oem)rv@Z1aikLFeU6f z6t_|+1P5K_oGMAiSkIp&wQl=r3HCmMU{^8MX{olv6_5R;;LE?a7tq)}o;tRE g&ujCGk(fT%nd-Z1ckQm-^?hCc4__#zNdU?K0LR!X)Bpeg From e7a86775cf52f047dee4638ef2fbb84cc8a2b9b6 Mon Sep 17 00:00:00 2001 From: Sanyam Singhal Date: Fri, 4 Oct 2024 15:06:17 +0000 Subject: [PATCH 3/3] Updated gather assessment metadata tarball --- .../data/gather-assessment-metadata.tar.gz | Bin 9489 -> 9482 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz b/yb-voyager/src/srcdb/data/gather-assessment-metadata.tar.gz index 9153c2ffed84e8398df6276f48502f02981415c3..b69b3d7f72ca09e0e2d1d7e069a46aa531154541 100644 GIT binary patch delta 9464 zcmV2a_OLE=~Ws?!og7=RgMU@9(bV|NhQSj{my{`=I~LKXv8u`VZ%S zXK1v?1~Yzt9UJ{ochG0u6V@M$;X!va9x-n*0s4gWACBS?JSmlApRw`cl#Sa@dj^9x zZxWhQo3r+)G%|WdXIx@%q10Sk^R4to{G6G#9f+Ty8=Cfnf8eu8Xf3&Txa6j@^2}O& zWPZp$^4+VTbTS;gpu1K4ORt_ALxURUQ)|wSSXJPE%Urm_j@StmU}^@O5j2Ba$6Rs% zo<+V7!z2LJS`8@j+syT@RVsuo(+ZSk7F=rVRd@WHbw)4QbEAE1459n+aIi|rC-=ht z&GerT(k*AsKj?w=FCN@Q{cqF%?H1@f>HqFQYiGNK`oD9q`=I~#ap^ki_#BjjnIwCz z4|2+X5+M#k*M}b$TqrLCafobCqC1!Xr|twEX-|8^g4qRMniIU0hM?|qJ8pHS|Ho&c z(%NZ{3`W230$uEj4(~t|K^Zk)V`F@%(Zt$Kpk55>nSN-6mh14jSf_SFFDvdvvVRj~ zw`lxZdoAN$OJIR-nKmfboLyS{D(z+TfCyTDv#`5o)#(;G%VBW1HmtLnXUJffr+iHqb%CV<4~SQP zK}NQa`&-y|3!%4=?6n#Vj;=1>L4pYYftM9{zJ(UNMpIxzD%MAE|GL^94%@Ha1fg#^ zi%IBCOy4)JtB0DDc-sm>9QUJEdy5_e^lm&j9vrd@)0ustcdIkkj+PE1 zO4itw6<$c?p+{ApzmF`RL=2oMI4bvloGn2$tr%))EqvmB4d)s}p%;ZT`pk7gbcEOg z?+divB=>Y~*}TBDjR#WQGXCJN=h+^vO|HB6e<6|q`~_EdhX~*{|G(4P&ins^o$Uwz ze;?O_BmYY}a-`R~*>YYDd>KuhfRhuHIZbD9)*n~DuO*3%8G?tJMq!-U;Qfk!%Y}zd zv}8ZBX5u8_krm8+*Yo(ib|YpP_o<|k)eM3XzgB{n2nGaFYa#*F5hsIvoyAMO35z%( zgP2J=)!-?9mJ67&ffArV5!7nHbZeBPWVC;e*rzaCE^;vsLB*ebZRY>4r~0LPZ7u-P zTj=Zi)PswHIc~21whs1pcB%e06775KKdjy^a?IMYO?)!5`VO#a?nh0N2U3 z>rGZgfU;~Vg9X4buHA?&&1>ekA&Ua6F<1em9E^XMaWACA#$9^0WjbJg9w`9|(;4bC z$ZI)>I}J^MHyK$Lnb=53u-=IFf1&ZZ2t)6%(YU(0s+)vx-Srm@TL1=)UbkcPM}`ha z%axuvHpnlg|b1Mx1AmIClk7fyZaoxiy2;Ig1E%o-N!kGR_sJ zlPjUy-(j`SC!@jHuwxwRmFA~1tCiVzKeEQ0UpAb`w%K>zG4E;)em@?u-+p1hkXVhS zfhx^fsr20FoleHauj8X~=`4U%9I}c6&wfBB?K%#GT~r|<-}NK=L2+4dmzuaqY~m(> z?~kQY$F*(f8?aMT?rwe$BKMoP$#(avuwVOv`h7&}-)cY8JlYn^;WpUrWX73|66iQ`Y zVrUjzaA3aWKy(fAECdcZ1Q8E_5{xN~Tbb(A^0*#w2a2Rq&&|jVS!=t0S-WwxQYq#dfSo=&ZI4E;2E*f{ zA3UJ<73k)VS-Y{S06*F8%(PJh4)=C`lF4e;Y=i}L!As~6^*M)0?$q0l`G-qK1lmu#mCa@r~q}G6c1>5gjTE6SxJoQq! z1oparbHQit5?in9pj94oJ=CTWu=@?z;8vL(9kH@#E3>yx5Y!Dtz zN}8o}E1dv_GC{x+znR)K)GJW(OKZ;O@r;kkOb2G|6wDRd?&cq~*z8TA%)V7t&?-Sz zl_InV+3wdyNRV^{9&|1R8apNWQz{(d2!tMgdJVv7`#|NSYhZKkrMibK0zrs;6e2}s zitO^SW3eTXnp`FVl#1wlRB4qILLXJOOKT{7 zRM`P)%o4F&V}HrG1zQLrZ5=XzXz(r5=Rk-xJ&QEtI5DB?dgZMulWJdRhtd6q_;&$+ zQEq)jLVAN|lap=_f}k~%srg$9Qn%ej3I0`U>~|WH3>mZeCAW{z4A8^i!a5I?<|Xuo zfdJsAva;egmFgT3*CX~1?eS~<@lt<0XOEvBK7Midcm#<*dsCs2-?EAvqRc)*{tjJC zAa1;dGE-u`(kEa(a66m;1twn#)ntBu3A%tsG*Ve@`-GZz5;-DNiv1WxB_d45cw};E z`WB`FfppZfhh`kyh)~eR>Yx~ntT#t#hcss?qG?nT9!C*aV4uh~>Wt?S zqNNu7e322Ug)9$G;8n?%1qc_dBaa4b9`4Dl&Z1W>0W?_zN@@Xp3 zj~I!+5FK|R2?5UEZ@?cn3ga2#v57RBEiGXvtNfn9`V-R~&YCRGz>FrcvN0SEhM+R> zMCT?X@AJcC=5op_VX9IlEy0W>OMk?MJaFwx8RbslH&$pV`gPaZYwEgx*5X%ZHyUh_ zLW;mp;xGc)hXerAjWq@v*XZ*lUruF;D~|%Db~?2u-Tuh{NE6&P=#jP#Nh#D`6kOc6 z6g4vjHAGUEQqJoCg1%`~o46{L)g#>jcB1c96U8_HK4d8;(ONJ)Py*%5KrxF2N%;rN z21###P*_$7E#NZ90_qfhmIXjZ!2?QnhQR8;;&7O6&fbaodN6Sv;4E52Rw+z&^|1YZ z#>%q#A4sK*i~sUIkhOnVzSh(kv?t|SO1yFDB$CN2RJLZE|SZfg38jKe4|7O+Kjec!K0^)W$dlyme5Vx;30neoAUu~lhz-QW< z!^i_{58rC|8_OH`y9Po8eISmdwE<$(BF;OIt26@(@7*P&_Ew;vAsJXSBl7T?2f#$M z12;mgGP;1-QrC@t4^;Q7*A#&0`$B((#>HlZbHM3FF6lsb~oBH2?~je)Cb2mmW7 zf|4Sg36}HyltutAtzTukpa>!BBch^Y`k@p{O&wK>i!IVuL%S?Qfc#g|(qQ9zI#=)n zVvmGm0+6=P)G{ApjSXc+U21uFb0(#4T@R2wjKj2`p*L86W1-d7sk2x4B7_$3Hj>DXgoMQ0xrQb zQFNgbv9#-aWH}(drk$1DtbCJhP`!{qMX4rbK6ri=|LjOg%!6XO7H)aT@}$CDz?Fx( zL;@Q#1FXe=e}w5MqK~q7bJ|HJP_&6fqL^p#d?d1IX_jIOEUR0XqNAOp)+-kRg!6Mw zp#mOLPEuk>HZy(6c2B?zPNdOBVhK~OJk6jXa_lv$Sx=X*C})rrZ6;*|_;qEBP{>Fa z<}6=mIeb$INdW=Y9VCZOz6Z0^N>j){^|`3xg838m}u85mmg>K)U5 z7s*Uz=aVKM=_mE{aqE*b!Ri9}2MnIjr{pF-Br2;@D;Z6BrHu-Vt=&zNn%raFt5-(DGN8aUB&ejY$nC-Cs!Xh zN>;IdMjmxBmhL+Cb#j*zMjaTy9pbFW>vi36b)12!xpe1VIS_@>PeA_?(!d3mO(NXH z11|W$cFnndX_)Z4Q=q=|zTdm!l-1*PFo#x)d`H%a!?r{Fontzx$fv27VCApXgecg(I z)PtY`AUy{fPVM{{G*xB{08+;g0C<-q$~juXMrjLB5z!>-$SGV1H$?asQY|*|U9l^56aFU2=X8PyS`k_N_aW zw?^?F4(9#4T$|Z{<$Utwj>i9++wK2e^B`~k0sg`M-^cZE{{Js_{{PQ9M*i^L-TJfV zg8Vv?|MOg2>1(U;XJ4Q5{uj0qu{L~v4g9w6KOAh+``_Em{Z?~-XCLkV{@%m)AMWMS zbtXh0tt|+%t%TiM@p~@fhBhC`RIPCy5*kYsITxbF`h{LZnN)ZcWnxj7N+wV2q*4lz zL)WFGD$#Rh=Ffd&x9?ujZrRLq0LhmaO?Y@dpr63e|Njpe9-^wTiE*XJ|WpR=LS84Qn~l%5*Tqy>gWc0=4(T)sw+IOCRXXXRLNX9s`vff~Dnz+`&i3GdkJn>mpWhYurmt92sDX930 z&srAm*KB2A<>lPG`IEakgLcmtb&P8Ntk>(FR0D_{Z0nL^FtEk+7I2|SAGP8^XkqL% zpCkg6880~on)lE_28_OTwd((4)=LMNtRd4^9xPQHrNX8JGQ*jFm^%(26sBuPwT-+J z9vN~KCChX-el-I;+a15*i{ZJKkZML5fu*P1tduPUoRUh}Z82t-s z+A5z^5vkwI(gM(8Nyz}-#$2g|L=FfHki<_)**pAIsR+|zWYcnX?z_tkzJ+x|jG(y2 zzgLWKgZ~FY%xwOD1wI44>GyvV|KB>;ZasYe_g=2s`M)CI5c+v`6l^}nZSmiJYd;_V zHTNFkzk9hbkTN>Y2W)V1LQ&O;VH`hgcYaPDpatvppMe*o+ZXNO&u6D(+rTd#8@=v} z?${WzE%wXV0NhaA?X>;O7GU`@Im54$f$r-MN+9tZk=yufc+#PBbTVfW-U-3k+J zh4^|mz7RogbI}JZ1|xZciD}<}J_taE_V6=PW4x=wzs}&;NI?c81>&UL?VUj=SQ6M2 zneR-+x-L$)OnM3N=Gt68&NWgABZtt(YS_ z@=+>h%2X=^J1P*n0;GZ)kctt*QIaZHm|eD)sMYF!*j`4ElpUO;xAt92OG-+a-pK4; z_h*A?$HU5F707`Ql2ak9KhPK%n3)~TA-oq2Vfv~Kc1Y3=z$PIFC5Tv})gbd7zt(Cr zAJwHsuSbv$V{vL|oB+oCj-k~`kne%{dHPz#Uk$aNNF#(s4~^4T2nRRy{{zS!)Z4s z$ixlB+qI>*Dsso|bShDZ1YU_iZiqsZ_M%jJW%Ha&b21&?C2mZ0CvsIx3XYv!-Am-i z8i`RyG>SGkW{_NkzKO4Pt(5+WC`gMGD7&v9_67=Rk$4x?omqKrra~&15b=m`M1nK$ zDj?YOp&EKePHc_SVYJAx-bb9hpx!jws_XJO2wfU)LfQz5I$Ee8vNCc&RJBzK12Qv77ZUe<({NR5FEcm_;8< z{<_IIH~{0-7xZP?4`Ska&XjBlAy;ESY@Xw{A9(*yXjA`>Ud+AO6mY`${~W_q|L^d5 z(VqX?3EA;~8~&fTu3qc<$-5zyt$tDbfQP$(f7nA>r$1K$vv7?euQMQ726ZA4|PG@B0=j9^wjI>j3+Gw?0<2IPkE-Aa!*Fv}^T0wk1_ippdGWUaEvEq})y*mgmUz1fsW6TqSpWIk`oTNFQ?`wr0K?FMf1XZBQPUzv5n>c;gIvRX;VtnBD!iu_@4ep4 zuhby?Y8^{I!Om08elg`rHbYOQ;wTj=S>{>})KJ|9X=7^H$|AtzdjPO)Sb5ViIX$3?b|NUJU)CtD#4$R*Eu$5sV7{v<5rG*=c zb8tRK+#!NEy&%U(sBudX1dsv3#m5y<;=u)|k_?VlWPd&3C+G{u_sFGq^g3%O?3!w2 ze&L?Z@|G5#A`%vSAk^p<5^pxPe>Dp1hh5Y9@r`WWTZv}%V_Ra6L&^5PgdIcQY#INv z_~N(219kuZvtOST?f#FQ(4*mhp6(d`lj)A{90Bxu2km?qW+&A@aiD9M*?PF0Y>U9- zVs@G;gp$e_jKS-~JlT!*z@nd-dlXHHy+C&S)dKmUKvW(=oBf$hfcSI{fA*cUK=#bk z>a+{cHY+=sO0Cwb_xt$R?R5s7Dh#1zXHe~CGbf$?0G>G(Xg1UB^za2Tkj-YQopu{c zj!~^Ls9}Y&M&O9$MTHlZ_hkHXE>n4h-DVia;uP* z&L+HmFPN5W>4?BE%+D=^r5?gkbP@E<;(Q5(7>z;ffazpTFLzsUjaY43M1NjSjKur{nXx$ot8M(!Z%*GGlAH1eD*(SE}_V`AP^#I0+ zFKFOA@>YGL{=((JXoaxaO5YkPP0WN#$0Z-cFTN^P@SD`~7oW+zDlfDWQD$kwuUQ`S zzOII6NyDsMzSP8F^PQ-4I|pioO6{S&|dH6^0czjzS(zky@Mt)xj4Up_e!FK z6c*e3e-W_F`7A5fH7Vmf`kgafP8Lqy>pJNVXCDej@1JTwChG!ZlIIMP%OBk^o_c7~ zFd0;xId5@*>Y+T9oVak&&NQH^hcbwPScjO!?lFy7D~D@CD{Gu`0u9C6<-U-*4JE!m zO5K{05_c)m^1>>>QO__wxf?=do9D~Iu-B%Tf3EcTY!3$;8;#>&C&OT~nG!_8hN?F` zZvi!5daLOtdVOpE_huKud3uUAfzX&>R|lq9GIlmAXEXS0mdK2t4VrsI)F`UDvhf=S z5t2Ckh39*Zn<-t>ShEovw>;rQ#$V2Qz8|ADjyO=S+;>5yDnPA3;8ly#4}PIY@*t=J zf0l+L;=n04sw*4UU9dazi=}q~jZ9d%0i_q%fq|hywx*JGk+kpN;>j1joH!NMr?~Hw z=TBANWrPE*1unM@D?TVXLyF9b(Vb)lUx<=#T171;7URrGAKVr`qzdEvbhIUewhSBV zGBd{FLi5%!Sjd6RJt7z5BG_?go-J9cf5=NK5Vg3#6A!+)jWQ0NHCe_gGI5<-GXvsrJB$i~w?4?Ser zRtA;P;IvyGwJP0iqkYW7-&A_llS;2xf+6qX)A=&jj=X`i^%4TjL%&`xa?MWrxP(_5 zkSC{Cd0WCAJ?FVt>@`1`V+Lhkv$iNc|rNu{se+P{gdPS|S z)V6=Ln%GIDzpk%%@-RQ$WHG(@PdG)hQ>`@DNJoVU znxXTS3y?6TYGg5ot`(y@!cIQmiaIXnP`~S(tz3X}xd8uCj0$-5e-q@4I71-(gOjpb znA}`Qt8%!dY?7y1Wgm3me!2K!Rlz#P*|n4lIBdTxF>n-V_xT0;*l zY<`ryHrFe-A!HRolunFbTC-R$;8+ZpK1sS zN=_CiFH^cc)uWh3R%oW^wV96=bCm+QlVn;=myo{8_j4;bgtVb4e-Ef6)b{d%wrf~b z8cPNN8GKnxTJ*{#TCiSUMzbi~-on_rU%{B^Km$z zRP^%zUp5sMef}k4Wqh{ThWcm|I(I`Z6f9?4tQd%UzyA9W&kDdJ88qO(XlU|W{b%JE z-@a+o-(sX*;~3Nqe?0MR;~1;gsn%=59>#02i2c)cr+wOD_6gbYfg84GXw2LaCeDuD z-@E9F1ST-P7ydViPnN>cXQkC*FLbArk~C=u6(F=%o? z!Z89fn1z7)1X)$%jzaw=EJe?>YH>*2Z2uPH!tCf8I(+>zYa z^2yEqkzCtvn#D{wUCxvt1V~m)+(BQZqU3Gl&?1chB2C_Ic52s)JGHA;Qg>)KT(4~$ z+V%8@cEijho!Rxw=PFg8R`NfPR&8LXuYN&KFlT!;jh3{3z(5$L>^p2_1>&~qHCm!+RYVz z)94L`l_rR8bJ&Vphh?ZZz3ghEx__Q6@t^>^&In_i*86G{nP2TGUA2MmvR1H3>3nZ* zLXLu8&?%Tcy#Q8BBTUB5AXv!@wd^A4TC&AjI2R%6$4;Fhz{&^TI|FzYFC>+-es)Ze zu)OFmT}Dx0XnhZ>%2?CSioz1BIYk#=@>cD`qJr7rd0-0)Q0_YL1) z8Frwqj6h%LfnIy?wXQl``}@22x3Rxlm;XlBgGPI=)okv6@73$g2ldA8ezWy}?S3^3 zuDL=#&^^W;gtO2N!fW7eX#bmD%gy|E9Y0ulhX29(lcKOC{{duox7ltzs5k3yd(Z#7 zxVGc}VmAE{8lGwRQ$Jj-bnmL_!t*WXKnCyawKwvAuhok9zt^mToHX0}?fnO={!Ldd zuK#fUcSl-(XQDCfw~00w_l5)3J7$C71RnIplQDCbQ=m^k|1nTJ{3nHi=rhq?p0G*h zSzlw&=1v2BW*MwAE{wIl)}0g>TqreH=3*zg;XmiPW%>MP-~_rgH9i{iX<)7l{%~dJ z_S!RZ{gM7L`^a-H{lf8R_>%6{@h`l7p^Y?ZT+GaW1v_MAjxTfI4m)BeRDhZ88;qbC z+}ire0N{D(c`!^2P_9&fBEQca_e!Qh;4mdeY3BZg!d~|#FIac{ioMV}N7@LwAB~3V zlzeh0{NGOh2_e^UCDDT{^J4;&AEoEuzu8Hht@ffC)q1lU#EcS(CXW9HA#jg>ydTVV*Qo?%6; z&g}n;c_6iRJ7bN}FT6k(2fV|35JgZ%#Z%Y>A1XAlavi7}fx5aEn1Sio#)7X?xu%yH z^&;874ziaw{*Ap>QLh!Sz%z9Vlxx8*Oye?t>81672uf(bx1CFyKh_3E61{>eSI`SA z*Bn&Wa+X#23G?WP$P`t!Jg9t~u~P--jmwc`oHA#z3_>M+;D?ygy-Tj(r?!Qncv&T^I^!%>#<6>ijj zIhGPUAYKL;*+K5_VBZ~t-a)cgDl|B{x@-pl#sN59rtf+tTJQ=@fendRAHw~ca%VK^ zym{*fo@p^b(+_amPfFz-dJNFJ$?#}+z|M7h0Xl<<20cmDO#93! z&mAjV*^DSzVV7obE|iBJl|AD_XnG`nV&F`{Q8{O91*&OAP%Crk5%()N*Dws+Frd-r zjvb&Q#2$E`qxCwur!&(sa$MVFDAX7>DSDO(n9_j~pgB(&3&r=dCnZy*MA#-`+Kc6)&KXJ7$$)KZ`IrN`}*IVTn~S!%}l#C)BW?p zLv%c#nx45l55P23*qd;vW0rXIY=`yidA0D6fcoa#uzm1vAs8c%vWN~CG58}|cGxS! z^TBnpX0^`B2v8JFMX&%k#+4JYm43x+Ct#tEH3rkCl!F-`=Y|_lV&klTT+7sLFprb~ z1<4Fm8sv=_#F+&;!0U`Gi%4t)Bv@}m`@hh5odDURHHNxaxSzn#BSATEExT z24hVHq{T{4Z3|?a#o5;Eis>%kG$*@d>6gs$m=0QkF^GdWUwRNT*vlQ}J7>YA?in-= zSW)46WTHhF!pda;Ae(M~vm*GH-nht~b;iB%4vm7QaCkaluhHNRCOvJ8$#8c#IO~YXC$|B&V_9v>O{n3W+m^Bjvls+&nYqusVAgg3hz0 zb76QkW~Z*jR1l8pkqMWoEvY#ZE1$T*w zn?@#X3iv)P6uORoWkFw`op38T{EX9(80F6h%Z5k_ikGFd(!z zHAn6s6-ljKO5zkik3esUcR!!QQ~Ys&2-g-f{HTyV30fR`Z(ut`T2bp)#jG@0@0(arcxh}3h>1nWvYA+Ck^DZq8kc@a2BVPKvy zGhhqH@X1UYAAvSRY}0Z5>0EaM;NX;aa-mz%43P{YJ42uI5Tx$RT!vyPaSx>Y%Fsa& zqS{w)crs=;tRq=J3b7M<;2+8$#l8X4Ec{B9m5+>nGd;8d)@ar%*N#>wL|g-~ljkR$ z@%Z&{baeQW3-rDO-F%w18|w=2v*pZn3pL9KxEpTcHGi%Xe zpn0zjB64CGXhRI49u7Dk*TM_|$wR-+9Scl`&wZjk4?>_MP!lwP`JpMa2K+17e*41o z92@6MnG6Tnb92w3bl6T60b1xkKlE{sJq;IKh1?+yLFl2^5S+FLRF1p)mSMPw?jegn z5JC@yNK)B6<`^F`w8)>h)RqX9nGQt`^kg35o&?%@7y-zbZ%KqE7l{CcJUSni8U=~a zhoxp=1Emj3Euh9c7RwFxmyDaggCN4zAp?j8KQMIxgxJtCPeYDk6S}Ea)~Yh0_PKU{ z7~Ow>f0q#DR@Wq?KYTtt?)4!E+Ax`%za=15%UKrSU%A5mpdrbSG0V6xtV1*d^w2*y z&jP7=1-)S)0Qk8mt@v%Jyg^hSNOQXehYqZbE{ULHIeL*mcgmT2U6tR#jg zvQLn|Ll+&08?B+pq*$-;8JG{;4yHhVf$7&mHJ)F9F5wZ4RFvC3qvjolHV>5|KSogr z50fz-nO^9giK&1u9QAy);3f`~&cwo@9tAf%6tu89$VVgVZJ@M6nzQ23G%AS^MG;tF zpNcl>jOP-0=GaZum#X&rCG2s0I^1x8wFb3I&1OU^G4F((6=ou?xH4`bWI0}^5>BOG&2FF7njepaihsq`- zg;2Ype}3&!htU;>vx7Eq_KEC4zR9#FV51eOQphr>L5{+`#@{i$OEXVEIM zQf{)V2AvOcRut8LUnp%<{1^AWsQrubwIa`;JSkQZ;uTAo*^BH4h>P*>4XW|FGa3N< zU+YvgIY_Mn%`Ulp8~w&2%D&SXI^{~dQc%p8yk4M4^{8xAg$(k4YgmH<>j{aph@>d7 zk?MZcs>HF__%-84LOU>Q<64qL6fskIsUr?8;ytDH z7`QBl0I-rgC?V3RU^&}QY6S4Y=2dobiV&hc!YfL;7YMOb56oc7vq7??i0`mSII15u8N0J+7N%aLxht2#plvvqlCPeQ zC&QCN;1WFJMHe~|OS{g8rVZk&TWQ%%%Qxu;)e8xfmueE`gXfp=Pmd(UJSe6c;Z_$c zODfz2Tzja03M8;GHNZyv$C!>H`Y3zXr=4U1c^h9Oig_B(hdi4WW+}43qPm4CI@(EU zy>uWzI6E^aRKR1(aY_uyW~wjQ?kSkTsW93|EN;rBrztdej=ffq!dR4U@6=$GoF5NkoHbi0c6VSha zG;nE%CLV6$0T+B=Ir>7qFm*LPTBUl9gR|hq@1Zy^QsaNBAfHNcO&}797ps#5AtlWj zY0rYhxhK{LkbeQ~#hFX8J5ufK4D%w~loES?oK)RG^&pZv?jlvO`tsO`HoFaw^kS4E z-^Kp_cIQ91Q49n>)s^m|>)ZAS=ndyT8;y1=bN+L;Ro}fo|8W=BEzW+gK=K$I0Pj*q?D)AjGj+s{AG-q_@UUFwtQ=y0 zhNtD$;bFcQK7vLZve3z4JwXcUl`J?q$QKc6bALew>@O`g>K_p)eYP)4{@WkDi_h=j z$-ng3zD=j{HYoo6!MuN$YdiZdoll8p`1+E6_rI`}h_&Tw;5U8$VZTZ5e>dxUjrv||5AFZn zZtLFu-^Hb>jEg{0Ti|9}3cGir_gwf5Z9bBz+Tc6{G?pkbE<}#?bG?W(DfcSU#Jn&S zPafMzsT3lHt_n$&qUY4iU;4)Gz`3N|vbk=HGwZpp&z>2$>x*>r;L+4{&t zN?xhWQL!xzku=_IBJSIN|AFeIxB2|TjqiW%wzBzuyV;GL`_wnCfEdJYqUP*Wr zz5B^rKMbnA@nIT-?i4qYwjhP;LyWb+@{MlG$lx%v7j>IgQPY^%gokPS>>u)j&|Rb- zEDY-wh^E#ikoBC)Dc>XG*d8c<*)1mp!Lkp(Rg_I18^TlJT!VaCEXCQl==C5wO-dHi za>K~FWlhD=4WtSmcw+>gA?BZZwe-)#-Er{#ZF7V#aMF36IsY>k(Kg|~S>5Y4{vULW zznJ^A{r^6%|J3*Q+O54k^8fqy{{K#{t-t>S%x9eW*MIz}ET1+adx0;1ie#gE=^5Vmi>T)~;+IL^1<^#h>#yGXI{&08_yVl%^IJ?9=(OFh$Ct6IG zUPSaMsOXB$TITQ9?4)4DWnaJflexOXPG1{$wesM!-|roleTW<^^TNPjV27y<;6j}~ zYGwF=iLuvW8Vgivy!aSs)wJ<$qHZQwKnvCzJO?jGw=X-RUrtZR zwt-(f()zuZy@@trJM7ofA-JKa+ezoSHtzke#_DuC8TDR&j!%Zeel!mBd5Pb$h~Qso zqu%iwy5%O?4Dj`Cd?A9~=AsW+49DUI6VrhPeGq^S?crypCU{qcf8F7cmVgY$62x(* z*FS|&u)wj&GvBF-b(NoP%apv>rYeo^R{d}mmySe)Hl}12LzwliRY4CaF8=h1DN_ai z!1K&7skXI$S<-j}YrU^UBG`b$+AyhNR(c3&1i3O=F}0grE5lLUowXT}T;BBhyiaAiCyH zAQKM)T0Td5=36NfK5yeN)WL` zt3c*Ed81TlKB`NN-;5z0#^TgSI|hsgT}`PJAm0P?^X!d`zZ_~m5k?4&9vY|b5DsqZ z|8q8frnZg)ZaV+7w@dY(cD>!+ZS(U#?e_iopF6q!bNxS+nDFp*k_YlM8}6c%kA*&e zj<^Oxl`hKgm*QE2G`}f~}zLV?T{(qVM-+VAWvi_-eBjgt$ z(nas=>kau1z)T##`a2gKAekZW#S0FTN&q%h-%Z)drQg4ZTn0;->}W^Y%rU#>X0scA zp^P>$F@@d!DcHgh+QOsZ%T8~Azm87_UHrnO`V5lCBbGGupd0?56i)DFFdV(?^lKyS zRZbtNv672MY}65ryiJZdBv*l_ ze~w|Q|9AMjXwU!cgzWgg4gXJESFe9{{p8({%2vN9e!#=sKkfEQq%>K4Ol!9rA_=sF zFs=a~-~RS~;&!|`%fp3US3`(WuqO<73Hli|Cn#~6bMlh=%o#Ks^8Tgia19HRo zZly<_I1kO6Cr+C$tQ3jqChZ!|w~(t%m#mWHu0MSBSfZz0QrVANONm<{`I~r* z<`v9Xx#Vs~ymW?rVZDeo+O_&0+mb3MP)OBGFIB=7Qf?;@%X8#<0@2$_6=-1aLhEL$ zxka6Ak;C`mZinj2X&at)tpEINePfIi`D~Ql%PARr>q+2s{XZG&anlVz3I5;VA;tfb z{l5c?|GgWs{@+9VzYqc{$+UkFM8>J8DciTh_QKN;%G_wq=MZlilI(lTM4`H1okvF)CP=d>6ak#x#G~vwoaC8)}%4 zMa!b-b`R;zx^=BzUvK?JxJj~qL#<6lcq*m2sKDj40-}!p{w@sa1mkxHW^aGk$}ka( zVuj<$=a8GA>ON)O`5eW-E5NdP_i8mYD8U^;lu4(=FMmF!QM6>#_EwRU;Wcy#j zj-hY1jQ?4D@!R2ny8r*#ug{8h|Hn?~(eOV{cZ~nZbjNp&0Q$Xyc0LTVlj@&1&^63# zJ={*VMc{EUJ53crNo5Si;B{i2>_&TF(a+31il)R~AUpnQf&70^ASw@`&Hl_LKzup} z`%YRQduD2N+68Evm7PqbR_oRKeSGZpI)hFXhS0JzsCKiNlTLpC&m0Rho9T9X_yQTo zW;4}JyA3ACs8$(NFgZBoZ{TaAT?_xunT)RwfBNKyfG?E*KRdljwOJn}qkhtjO4|^$gXhHq zqo7q@RZ-BK^hqxXEz|;q8gV%vJWRxbg6_0%Y${WZ5(Fk@nE-+Ll}MIk=CtGlfR<*& zG7D+BRY*%`6JEa;OiQ+OL|_=^=N7_J4`C^~2zqC6zJz~5jK&~#z;rUFm%Fgxtk!Qo zA<0Heb&UOa1Zi?k)ClU3;4KbTiXn!U4>66N1aigDEU*9$+U=RRBkLcGIpE6Gb!9Xa zh?4IN+I@!@P|TW@JCAdZUA1?#hy908ZgR*^5aPQxi1^rNV#~)`U+Iyvx$Sx2ciIpMxs$6;y9fzZrKr2op zHt7f+h!KJNlrZ)PcdkI#NuOo1h^wbqSGN&c3qRA$3=Nc*&dm8o*=fIqho?`onz*bh zGO3yKU#CDUoxO6w6cfn@kNF1T!xxfs+_EcO*b;vx6vFcPS@FF&%G6(d%oIMHIqz=X zKfR;>QU%D^&5`7W-0$fJ8*r|;Als{f`~^LrCW=S2ZjHc<++sy$zzm6CU z%gMF(c_JWu=>=D&QThpuJ>s!7rh@8s2t$9GMF2A&%)$VaR2qs@BvOXBnO}lKeOEa9 zaP)rf=&rDbbaclSg?M5mQ}@S%_NK3K!W%CgB;Otc-WE%Fuqrt2H;6u|FSDDzLoo16 zNVtexPzbiHE2#%swV;EE#3CvqSrVX_#J-1y5$$Epxyle|uXl5KT3Kn|?7O+%K@)$O zT%6y)dnHjq3X5(22-xO)mX+(8lyM&Y&Y3PJ3n%Y&o%DyZ4~3)mPcU464qYw>UucP@YOoT)1dw8c@|k8N@)WL(F3Ln8vJ?!?mH6HBLE!hT`pV zUr61C65k)CZcRyvyA)}8VHM!0XBdB<+zp|!>hp*lSZvSNeRmhl7oc#&NKdVX)au z2_j)b)tjETfSND8)$|j+zP0~*vkT!oJw=;9XiTuH1Jf)SJDZiW8GJTNWJb^i%{?M& z6jfc>_>F@INgV#d^S#H-l&)#4*$9qXo^T@LFK0d9k5L;(9H>|ByC72)pjLk%@Tx`W z2ft7xc@R_qOT!Uy;FKHHm5u8z*q!;s(z}30Cam0m(hKasz)&GuQ^~qW+IMjAgHV!hzNTm)nLF9~7M-MP|k5PBMcpM9DX;q81a2apt5CZVMk$h4Fnl z+7d!rhK+TZ8DnvwdFvP~*I>zC@>N8zJGO~u zEVuVbr&VVS?us!7UzYOe!pdJ3u4W(kZl&Tu;o@ordgjGpnvFLs!LWZ{@9}QqV;BkV zS5NA#3J(fj*<5S%ack(P+G(}w?E&Y5S@Aqn>|f;JztV6hbOhzUuGT{dAwi|ttT#tw z<7uCV91?&x*kh z7H8P&ylvD<9=;S$ubZ99pu}e37hp@ya34ypRMGZVOq&?hhg?DVK;?fL?Mm--WZ;Q~(&D4R zgGLLzqE=UG+do=O?4;6P*H=7wn4fO5A9*LTqSr*@Pv>8qw$y8EyA%9${sY=4oTAyO zR+?+1qrwEu(0R)RNElN!vY12HiqRcmCm(P{9T#+{-*wJbF2K25fPX1Q1-$yd335i9 zArSt-N!cw-ZZ3bMRXN;JHpx@1vJblOl6{QBL3cQi(iu&IeJO2Vj%g-LP>TpXH@}=s z37>qep@$Z>zGi&ATwW`GB8D6=c>KHDTW6ozr6(RV>izv)Dx#F`rmpi&D9Ug;7%b#u zV(f@dH3S7ECkvF9DP5oHQA{H%G*k52%twp4N`c%-GOd56OGw}4`?-}ILfX)j2UHSj zdwD_IHLNO)C4+zrzAPp!dgT%=Sg$XmSrl$>VQk&6;MOTfSs3ff;Nf>E`tejd?bnTC zZFZCSIGj%^`gwpan+l6Q{}Qn>KHF?VeY6RkyCD|}mNPC^48*-(|9yyO1>lhk8t`8< zG$PDIDwM%I za;lF;7uVo%Fx>=E^Z$18H=G$y$=Jz%lyh?O7g2$6^7*+p`UDDXvP^PDghFKVaY{>+ zi0i``G&vyQ7=angLO^|jtg3aq0gv4KlLaBP1xIdxjKK#m)M~uCUX0HD5qR^s?=%n2 zJ^X)%PbNV=6h;D{aqSkN34_)MYD6>AHi#Taj4?PH&4*BLIh)S#dMRnQ%O%bO;g&wO z=ay`z;AdJE-eRom5&8Ow2eM;&0t&?CbCC)Azmxa>>%eihd;ik`#ea~`{~rE!VE6y; zg6#R5j_f8J*iAmJE1f1qS$DLjcl9#HZ?b>X zw6pOd>@}~!j=u!^0WE^HNj$#{b%7D5=Ac`&UQ-YsW|M~SS753I%t$aI53ZqlZ`MB1 zHPS`x=8C^*^ajI96GXQ;Y(=iaGE|&icC}I6KhKtUP=H-$gfUL*eKm^AulAI#+CX?& zE7+uTzPC3aN5L=X6ilC904t^uCSyfs5Uk{dT6U3iE!kqNixBl=r%n-I<%92?0X&Nr zlFC^>JElljUi6nPqbM-6zK2z1tm)@P%uQfgCW*caYMm22@8&{!liMUClk6l23{oQf M51iFY%mDBJ08bZqr2qf`