Skip to content

Commit

Permalink
sql: clean up mutable not-null columns hack
Browse files Browse the repository at this point in the history
Mutation columns in some cases need to be scanned even if they haven't
been backfilled yet, which means that we may retrieve NULL values even
if they are market as not-nullable.

We currently have a hack in the table descriptor which changes the
nullable flags in the column descriptors when `ReadableColumns()` is
used. It is very surprising that we can get different descriptors for
a given ColumnID depending if we look for it in `ReadableColumns()` or
in `AllColumns()` (e.g. via FindColumnWithID.

This commit cleans this up, changing the scanning code to check for
`Public()` instead.

Release note: None
  • Loading branch information
RaduBerinde committed Jan 18, 2022
1 parent 5ad21e3 commit b2e4fb5
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 19 deletions.
5 changes: 2 additions & 3 deletions pkg/sql/catalog/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,9 +447,8 @@ type TableDescriptor interface {
// details.
AccessibleColumns() []Column
// ReadableColumns is a list of columns (including those undergoing a schema
// change) which can be scanned. Columns in the process of a schema change
// are all set to nullable while column backfilling is still in
// progress, as mutation columns may have NULL values.
// change) which can be scanned. Note that mutation columns may produce NULL
// values when scanned, even if they are marked as not nullable.
ReadableColumns() []Column
// UserDefinedTypeColumns returns a slice of Column interfaces
// containing the table's columns with user defined types, in the
Expand Down
12 changes: 2 additions & 10 deletions pkg/sql/catalog/tabledesc/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,23 +315,15 @@ func newColumnCache(desc *descpb.TableDescriptor, mutations *mutationCache) *col
c.writable = c.public
c.nonDrop = c.public
} else {
readableDescs := make([]descpb.ColumnDescriptor, 0, numMutations)
readableBackingStructs := make([]column, 0, numMutations)
//readableDescs := make([]descpb.ColumnDescriptor, 0, numMutations)
//readableBackingStructs := make([]column, 0, numMutations)
for _, col := range c.deletable {
if !col.DeleteOnly() {
lazyAllocAppendColumn(&c.writable, col, numDeletable)
}
if !col.Dropped() {
lazyAllocAppendColumn(&c.nonDrop, col, numDeletable)
}
if !col.Public() && !col.IsNullable() {
j := len(readableDescs)
readableDescs = append(readableDescs, *col.ColumnDesc())
readableDescs[j].Nullable = true
readableBackingStructs = append(readableBackingStructs, *col.(*column))
readableBackingStructs[j].desc = &readableDescs[j]
col = &readableBackingStructs[j]
}
lazyAllocAppendColumn(&c.readable, col, numDeletable)
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/colfetcher/cfetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -1379,7 +1379,7 @@ func (rf *cFetcher) fillNulls() error {
if table.compositeIndexColOrdinals.Contains(i) {
continue
}
if !table.cols[i].IsNullable() {
if !table.cols[i].IsNullable() && table.cols[i].Public() {
var indexColValues strings.Builder
rf.writeDecodedCols(&indexColValues, table.indexColOrdinals, ',')
return scrub.WrapError(scrub.UnexpectedNullValueError, errors.Errorf(
Expand Down
11 changes: 6 additions & 5 deletions pkg/sql/row/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -1215,15 +1215,16 @@ func (rf *Fetcher) finalizeRow() error {
}

// Fill in any missing values with NULLs
for i := range table.cols {
for i, col := range table.cols {
if rf.valueColsFound == table.neededValueCols {
// Found all cols - done!
return nil
}
if table.neededCols.Contains(int(table.cols[i].GetID())) && table.row[i].IsUnset() {
if table.neededCols.Contains(int(col.GetID())) && table.row[i].IsUnset() {
// If the row was deleted, we'll be missing any non-primary key
// columns, including nullable ones, but this is expected.
if !table.cols[i].IsNullable() && !table.rowIsDeleted && !rf.IgnoreUnexpectedNulls {
// columns, including nullable ones, but this is expected. If the column
// is not yet active, we can also expect NULLs.
if !col.IsNullable() && !table.rowIsDeleted && !rf.IgnoreUnexpectedNulls && col.Public() {
var indexColValues []string
for _, idx := range table.indexColIdx {
if idx != -1 {
Expand All @@ -1234,7 +1235,7 @@ func (rf *Fetcher) finalizeRow() error {
}
return errors.AssertionFailedf(
"Non-nullable column \"%s:%s\" with no value! Index scanned was %q with the index key columns (%s) and the values (%s)",
table.desc.GetName(), table.cols[i].GetName(), table.index.GetName(),
table.desc.GetName(), col.GetName(), table.index.GetName(),
strings.Join(table.index.IndexDesc().KeyColumnNames, ","), strings.Join(indexColValues, ","))
}
table.row[i] = rowenc.EncDatum{
Expand Down

0 comments on commit b2e4fb5

Please sign in to comment.