| 84 | } |
| 85 | |
| 86 | func (t *TableSchema) RowMd5Query() string { |
| 87 | if t.rowMd5Query != "" { |
| 88 | return t.rowMd5Query |
| 89 | } |
| 90 | |
| 91 | columns := make([]schema.TableColumn, 0, len(t.Columns)) |
| 92 | for _, column := range t.Columns { |
| 93 | _, isCompressed := t.CompressedColumnsForVerification[column.Name] |
| 94 | _, isIgnored := t.IgnoredColumnsForVerification[column.Name] |
| 95 | |
| 96 | if isCompressed || isIgnored { |
| 97 | continue |
| 98 | } |
| 99 | |
| 100 | columns = append(columns, column) |
| 101 | } |
| 102 | |
| 103 | hashStrs := make([]string, len(columns)) |
| 104 | for i, column := range columns { |
| 105 | // Magic string that's unlikely to be a real record. For a history of this |
| 106 | // issue, refer to https://github.com/Shopify/ghostferry/pull/137 |
| 107 | hashStrs[i] = fmt.Sprintf("MD5(COALESCE(%s, 'NULL_PBj}b]74P@JTo$5G_null'))", normalizeAndQuoteColumn(column)) |
| 108 | } |
| 109 | |
| 110 | t.rowMd5Query = fmt.Sprintf("MD5(CONCAT(%s)) AS __ghostferry_row_md5", strings.Join(hashStrs, ",")) |
| 111 | return t.rowMd5Query |
| 112 | } |
| 113 | |
| 114 | type TableSchemaCache map[string]*TableSchema |
| 115 | |