Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distinguish missing compressed values from NULLs #7777

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 41 additions & 9 deletions tsl/src/nodes/decompress_chunk/compressed_batch.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,28 +170,60 @@ decompress_column(DecompressContext *dcontext, DecompressBatchState *batch_state
const int value_bytes = get_typlen(column_description->typid);
Assert(value_bytes != 0);

bool isnull;
Datum value = slot_getattr(compressed_slot, column_description->compressed_scan_attno, &isnull);

if (isnull)
/*
* We have to distinguish the missing compressed column values (after
* an ALTER that adds a column) from the NULL (for batches where all values
* are NULL). This means we have to reimplement here a part of
* slot_getsomeattrs_int().
*
* First, try to destructure the tuple up to the required attribute number
* by calling the corresponding tts_ops method.
*/
if (compressed_slot->tts_nvalid < column_description->compressed_scan_attno)
{
/*
* The column will have a default value for the entire batch,
* set it now.
*/
column_values->decompression_type = DT_Scalar;
compressed_slot->tts_ops->getsomeattrs(compressed_slot,
column_description->compressed_scan_attno);
}

if (compressed_slot->tts_nvalid < column_description->compressed_scan_attno)
{
/*
* The tuple destructuring operator couldn't produce the required
* attribute number, this means this attribute is missing in the tuple.
* This happens after an ALTER that has added a column, so in this
* batch the column has the value that is the "default for missing"
* (pg_attribute.attrmissingval).
*
* We might use a custom targetlist-based scan tuple which has no
* default values, so the default values are fetched from the
* uncompressed chunk tuple descriptor.
*/
column_values->decompression_type = DT_Scalar;
*column_values->output_value = getmissingattr(dcontext->uncompressed_chunk_tdesc,
column_description->uncompressed_chunk_attno,
column_values->output_isnull);
return;
}

/*
* We verified above that the compressed column is not missing, so now we
* can use the normal Postgres slot_getattr function to get the compressed
* column value.
*/
bool isnull;
Datum value = slot_getattr(compressed_slot, column_description->compressed_scan_attno, &isnull);
if (isnull)
{
/*
* The compressed data is null, so the column has null value in this
* batch.
*/
column_values->decompression_type = DT_Scalar;
*column_values->output_isnull = true;
*column_values->output_value = 0;
return;
}

/* Detoast the compressed datum. */
value = PointerGetDatum(detoaster_detoast_attr_copy((struct varlena *) DatumGetPointer(value),
&dcontext->detoaster,
Expand Down
Loading