Documentation ¶
Overview ¶
Implements structured report generation for Spanner migration tool.
Index ¶
- Variables
- func AnalyzeCols(conv *internal.Conv, tableId string) (map[string][]internal.SchemaIssue, int64, int64)
- func AnalyzeTables(conv *internal.Conv, badWrites map[string]int64) (r []tableReport)
- func Contains(l []Issue, str string) bool
- func GenerateSummary(conv *internal.Conv, r []tableReport, badWrites map[string]int64) (string, string)
- func GenerateTextReport(structuredReport StructuredReport, w *bufio.Writer)
- func RateSchema(cols, warnings, errors int64, missingPKey, summary bool) (string, string)
- type ConversionMetadata
- type DataReport
- type IgnoredStatement
- type Issue
- type Issues
- type NameChange
- type SchemaReport
- type StatementStat
- type StatementStats
- type StructuredReport
- type Summary
- type TableReport
- type UnexpectedCondition
- type UnexpectedConditions
Constants ¶
This section is empty.
Variables ¶
var IssueDB = map[internal.SchemaIssue]struct { Brief string // Short description of issue. severity severity batch bool // Whether multiple instances of this issue are combined. Category string // Standarized issue type CategoryDescription string }{ internal.DefaultValue: {Brief: "Some columns have default values which Spanner migration tool does not migrate. Please add the default constraints manually after the migration is complete", Category: "MISSING_DEFAULT_VALUE_CONSTRAINTS", /* contains filtered or unexported fields */}, internal.ForeignKey: {Brief: "Spanner does not support foreign keys", Category: "FOREIGN_KEY_USES", /* contains filtered or unexported fields */}, internal.MultiDimensionalArray: {Brief: "Spanner doesn't support multi-dimensional arrays", Category: "MULTI_DIMENSIONAL_ARRAY_USES", /* contains filtered or unexported fields */}, internal.NoGoodType: {Brief: "No appropriate Spanner type. The column will be made nullable in Spanner", Category: "INAPPROPRIATE_TYPE", CategoryDescription: "No appropriate Spanner type", // contains filtered or unexported fields }, internal.Numeric: {Brief: "Spanner does not support numeric. This type mapping could lose precision and is not recommended for production use", Category: "NUMERIC_USES", /* contains filtered or unexported fields */}, internal.NumericThatFits: {Brief: "Spanner does not support numeric, but this type mapping preserves the numeric's specified precision", Category: "NUMERIC_THAT_FITS", /* contains filtered or unexported fields */}, internal.Decimal: {Brief: "Spanner does not support decimal. This type mapping could lose precision and is not recommended for production use", Category: "DECIMAL_USES", /* contains filtered or unexported fields */}, internal.DecimalThatFits: {Brief: "Spanner does not support decimal, but this type mapping preserves the decimal's specified precision", Category: "DECIMAL_THAT_FITS", /* contains filtered or unexported fields */}, internal.Serial: {Brief: "Spanner does not support autoincrementing types", Category: "AUTOINCREMENTING_TYPE_USES", /* contains filtered or unexported fields */}, internal.AutoIncrement: {Brief: "Spanner does not support auto_increment attribute", Category: "AUTO_INCREMENT_ATTRIBUTE_USES", /* contains filtered or unexported fields */}, internal.Timestamp: {Brief: "Spanner timestamp is closer to PostgreSQL timestamptz", Category: "TIMESTAMP_SUGGESTION", /* contains filtered or unexported fields */}, internal.Datetime: {Brief: "Spanner timestamp is closer to MySQL timestamp", Category: "TIMESTAMP_WARNING", /* contains filtered or unexported fields */}, internal.Time: {Brief: "Spanner does not support time/year types", Category: "TIME_YEAR_TYPE_USES", /* contains filtered or unexported fields */}, internal.Widened: {Brief: "Some columns will consume more storage in Spanner", Category: "STORAGE_WARNING", /* contains filtered or unexported fields */}, internal.StringOverflow: {Brief: "String overflow issue might occur as maximum supported length in Spanner is 2621440", Category: "STRING_OVERFLOW_WARNING", /* contains filtered or unexported fields */}, internal.HotspotTimestamp: {Brief: "Timestamp Hotspot Occured", Category: "TIMESTAMP_HOTSPOT", /* contains filtered or unexported fields */}, internal.HotspotAutoIncrement: {Brief: "Autoincrement Hotspot Occured", Category: "AUTOINCREMENT_HOTSPOT", /* contains filtered or unexported fields */}, internal.InterleavedOrder: {Brief: "can be converted as Interleaved with Table", Category: "INTERLEAVE_TABLE_SUGGESTION", CategoryDescription: "Some tables can be interleaved", // contains filtered or unexported fields }, internal.RedundantIndex: {Brief: "Redundant Index", Category: "REDUNDANT_INDEX", /* contains filtered or unexported fields */}, internal.AutoIncrementIndex: {Brief: "Auto increment column in Index can create a Hotspot", Category: "AUTO-INCREMENT_INDEX", /* contains filtered or unexported fields */}, internal.InterleaveIndex: {Brief: "can be converted to an Interleave Index", Category: "INTERLEAVE_INDEX_SUGGESTION", CategoryDescription: "Some columns can be converted to interleave index", // contains filtered or unexported fields }, internal.InterleavedNotInOrder: {Brief: "if primary key order parameter is changed for the table", Category: "INTERLEAVED_NOT_IN_ORDER", CategoryDescription: "Some tables can be interleaved with parent table if primary key order parameter is changed to 1", // contains filtered or unexported fields }, internal.InterleavedAddColumn: {Brief: "Candidate for Interleaved Table", Category: "ADD_INTERLEAVED_COLUMN", CategoryDescription: "If there is some primary key added in table, it can be interleaved", // contains filtered or unexported fields }, internal.IllegalName: {Brief: "Names must adhere to the spanner regular expression {a-z|A-Z}[{a-z|A-Z|0-9|_}+]", Category: "ILLEGAL_NAME", /* contains filtered or unexported fields */}, internal.InterleavedRenameColumn: {Brief: "Candidate for Interleaved Table", Category: "RENAME_INTERLEAVED_COLUMN_PRIMARY_KEY", CategoryDescription: "If primary key is renamed in table to match the foreign key, the table can be interleaved", // contains filtered or unexported fields }, internal.InterleavedChangeColumnSize: {Brief: "Candidate for Interleaved Table", Category: "CHANGE_INTERLEAVED_COLUMN_SIZE", CategoryDescription: "If column size of this table's primary key is changed to match the foreign key, the table can be interleaved", // contains filtered or unexported fields }, internal.RowLimitExceeded: {Brief: "Non key columns exceed the spanner limit of 1600 MB. Please modify the column sizes", Category: "ROW_LIMIT_EXCEEDED", /* contains filtered or unexported fields */}, internal.ShardIdColumnAdded: {Brief: "column was added because this is a sharded migration and this column cannot be dropped", Category: "SHARD_ID_COLUMN_ADDED", CategoryDescription: "Shard id column was added because this is a sharded migration and that column couldn't be dropped", // contains filtered or unexported fields }, internal.ShardIdColumnPrimaryKey: {Brief: "column is not a part of primary key. You may go to the Primary Key tab and add this column as a part of Primary Key", Category: "SHARD_ID_ADD_COLUMN_PRIMARY_KEY", CategoryDescription: "Shard id column is not a part of primary key. Please add it to primary key", // contains filtered or unexported fields }, internal.MissingPrimaryKey: {Category: "MISSING_PRIMARY_KEY", CategoryDescription: "Primary Key is missing, synthetic column created as a primary key"}, internal.UniqueIndexPrimaryKey: {Category: "UNIQUE_INDEX_PRIMARY_KEY", CategoryDescription: "Primary Key is missing, unique column(s) used as primary key"}, internal.ArrayTypeNotSupported: {Brief: "Array datatype migration is not fully supported. Please validate data after data migration", Category: "ARRAY_TYPE_NOT_SUPPORTED", /* contains filtered or unexported fields */}, }
IssueDB provides a description and severity for each schema issue. Note on batch: for some issues, we'd like to report just the first instance in a table and suppress other instances i.e. adding more instances of the issue in the same table has little value and could be very noisy. This is controlled via 'batch': if true, we count only the first instance for assessing warnings, and we give only the first instance in the report. TODO: add links in these descriptions to further documentation e.g. for timestamp description.
Functions ¶
func AnalyzeCols ¶
func AnalyzeCols(conv *internal.Conv, tableId string) (map[string][]internal.SchemaIssue, int64, int64)
AnalyzeCols returns information about the quality of schema mappings for table 'srcTable'. It assumes 'srcTable' is in the conv.SrcSchema map.
func AnalyzeTables ¶
AnalyzeTables generates table reports for all processed tables.
func GenerateSummary ¶
func GenerateSummary(conv *internal.Conv, r []tableReport, badWrites map[string]int64) (string, string)
GenerateSummary creates a summarized version of a tableReport.
func GenerateTextReport ¶
func GenerateTextReport(structuredReport StructuredReport, w *bufio.Writer)
report_text.go contains the logic to convert a structured spanner migration tool report to a human readable text report. The structure of the report created is present in (internal/reports/REPORT.md) A sample report can be found in (test_data/mysql_text_report.txt)
Types ¶
type ConversionMetadata ¶
type DataReport ¶
type IgnoredStatement ¶
type NameChange ¶
type SchemaReport ¶
type StatementStat ¶
type StatementStats ¶
type StatementStats struct { DriverName string `json:"driverName"` StatementStats []StatementStat `json:"statementStats"` }
type StructuredReport ¶
type StructuredReport struct { Summary Summary `json:"summary"` IsSharded bool `json:"isSharded"` IgnoredStatements []IgnoredStatement `json:"ignoredStatements"` ConversionMetadata []ConversionMetadata `json:"conversionMetadata"` MigrationType string `json:"migrationType"` StatementStats StatementStats `json:"statementStats"` NameChanges []NameChange `json:"nameChanges"` TableReports []TableReport `json:"tableReports"` UnexpectedConditions UnexpectedConditions `json:"unexpectedConditions"` SchemaOnly bool `json:"-"` }
func GenerateStructuredReport ¶
func GenerateStructuredReport(driverName string, dbName string, conv *internal.Conv, badWrites map[string]int64, printTableReports bool, printUnexpecteds bool) StructuredReport
A report consists of the following parts: 1. Summary (overall quality of conversion) 2. Sharding information 2. Ignored statements 3. Conversion duration 4. Migration Type 5. Statement stats (in case of dumps) 6. Name changes 7. Individual table reports (Detailed + Quality of conversion for each) 8. Unexpected conditions
This method the RAW structured report in JSON format. Several utilities can be built on top of this raw, nested JSON data to output the reports in different user and machine friendly formats such as CSV, TXT etc.
type TableReport ¶
type TableReport struct { SrcTableName string `json:"srcTableName"` SpTableName string `json:"spTableName"` SchemaReport SchemaReport `json:"schemaReport"` DataReport DataReport `json:"dataReport"` Issues []Issues `json:"issues"` }
type UnexpectedCondition ¶
type UnexpectedConditions ¶
type UnexpectedConditions struct { Reparsed int64 UnexpectedConditions []UnexpectedCondition `json:"unexpectedConditions"` }