Skip to content

Commit

Permalink
Add handler functions for Datum/Bools arrays
Browse files Browse the repository at this point in the history
When updating catalog tables we rely on low level functions instead of
SQL statements and in order to read/write data from/to those tables we
frequent do something like:

```CPP
Datum values[natts] = { 0 };
bool nulls[natts] = { false };
char *char_value = "foo";

if (char_value != NULL)
    values[AttrNumberGetAttrOffset(text_value_offset)] =
        PointerGetDatum(cstring_to_text(char_value);
else
    null[AttrNumberGetAttrOffset(char_value_offset)] = true;
```

So instead of using a pair of Datum and bool arrays we'll replace it by
using arrays of `NullableDatum` that contains both members and introduce
some accessor functions to encapsulate the logic to fill the proper
values, like:

```CPP
ts_datum_set_text(int index, NullableDatum *datums, text *value);
ts_datum_set_bool(int index, NullableDatum *datums, bool value);
```

We also introduce a new `ts_heap_form_tuple` that essentially to the
same as Postgres `heap_form_tuple` but using array of `NullableDatum`
instead of Datum and bool arrays.

In this first commit we added only the necessary accessor functions to
refactor the existing `create_cagg_validate_query_datum` as example.
More accessor functions to deal with other C types should be introduced
in the future.
  • Loading branch information
fabriziomello committed Mar 7, 2024
1 parent 30d4bc0 commit 898f18b
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 32 deletions.
20 changes: 20 additions & 0 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1727,3 +1727,23 @@ ts_makeaclitem(PG_FUNCTION_ARGS)

PG_RETURN_ACLITEM_P(result);
}

/*
* heap_form_tuple using NullableDatum array instead of two arrays for
* values and nulls
*/
HeapTuple
ts_heap_form_tuple(TupleDesc tupleDescriptor, NullableDatum *datums)
{
int numElements = tupleDescriptor->natts;
Datum *values = palloc0(sizeof(Datum) * numElements);
bool *nulls = palloc0(sizeof(bool) * numElements);

for (int i = 0; i < numElements; i++)
{
values[i] = datums[i].value;
nulls[i] = datums[i].isnull;
}

return heap_form_tuple(tupleDescriptor, values, nulls);
}
29 changes: 26 additions & 3 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
#pragma once

#include <postgres.h>

#include <access/htup_details.h>
#include <catalog/pg_proc.h>
#include <catalog/namespace.h>
#include <catalog/pg_proc.h>
#include <common/int.h>
#include <debug_assert.h>
#include <foreign/foreign.h>
#include <nodes/pathnodes.h>
#include <nodes/extensible.h>
#include <nodes/pathnodes.h>
#include <utils/builtins.h>
#include <utils/datetime.h>
#include <debug_assert.h>

#include "compat/compat.h"

Expand Down Expand Up @@ -240,3 +242,24 @@ ts_get_relation_relid(char const *schema_name, char const *relation_name, bool r
}

void replace_now_mock_walker(PlannerInfo *root, Node *clause, Oid funcid);

extern TSDLLEXPORT HeapTuple ts_heap_form_tuple(TupleDesc tupleDescriptor, NullableDatum *datums);

static inline void
ts_datum_set_text_from_cstring(const AttrNumber attno, NullableDatum *datums, const char *value)
{
if (value != NULL)
{
datums[AttrNumberGetAttrOffset(attno)].value = PointerGetDatum(cstring_to_text(value));
datums[AttrNumberGetAttrOffset(attno)].isnull = false;
}
else
datums[AttrNumberGetAttrOffset(attno)].isnull = true;
}

static inline void
ts_datum_set_bool(const AttrNumber attno, NullableDatum *datums, const bool value)
{
datums[AttrNumberGetAttrOffset(attno)].value = BoolGetDatum(value);
datums[AttrNumberGetAttrOffset(attno)].isnull = false;
}
52 changes: 23 additions & 29 deletions tsl/src/continuous_aggs/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,6 @@

#include "utils.h"

static void
fill_values_text(int index, Datum *values, bool *nulls, char *value)
{
if (value)
{
values[AttrNumberGetAttrOffset(index)] = PointerGetDatum(cstring_to_text(value));
nulls[AttrNumberGetAttrOffset(index)] = false;
}
else
nulls[AttrNumberGetAttrOffset(index)] = true;
}

enum
{
Anum_cagg_validate_query_valid = 1,
Expand All @@ -29,31 +17,37 @@ enum
_Anum_cagg_validate_query_max
};

#define Natts_cagg_validate_query (_Anum_cagg_validate_query_max - 1)

static Datum
create_cagg_validate_query_datum(TupleDesc tupdesc, const bool is_valid_query,
const ErrorData *edata)
{
Datum values[_Anum_cagg_validate_query_max] = { 0 };
bool nulls[_Anum_cagg_validate_query_max] = { false };
NullableDatum datums[Natts_cagg_validate_query] = { 0 };
HeapTuple tuple;

tupdesc = BlessTupleDesc(tupdesc);

values[AttrNumberGetAttrOffset(Anum_cagg_validate_query_valid)] = BoolGetDatum(is_valid_query);

fill_values_text(Anum_cagg_validate_query_error_level,
values,
nulls,
edata->elevel > 0 ? (char *) error_severity(edata->elevel) : NULL);
fill_values_text(Anum_cagg_validate_query_error_code,
values,
nulls,
edata->sqlerrcode > 0 ? unpack_sql_state(edata->sqlerrcode) : NULL);
fill_values_text(Anum_cagg_validate_query_error_message, values, nulls, edata->message);
fill_values_text(Anum_cagg_validate_query_error_detail, values, nulls, edata->detail);
fill_values_text(Anum_cagg_validate_query_error_hint, values, nulls, edata->hint);

tuple = heap_form_tuple(tupdesc, values, nulls);
ts_datum_set_bool(Anum_cagg_validate_query_valid, datums, is_valid_query);
ts_datum_set_text_from_cstring(Anum_cagg_validate_query_error_level,
datums,
edata->elevel > 0 ? error_severity(edata->elevel) : NULL);
ts_datum_set_text_from_cstring(Anum_cagg_validate_query_error_code,
datums,
edata->sqlerrcode > 0 ? unpack_sql_state(edata->sqlerrcode) :
NULL);
ts_datum_set_text_from_cstring(Anum_cagg_validate_query_error_message,
datums,
edata->message ? edata->message : NULL);
ts_datum_set_text_from_cstring(Anum_cagg_validate_query_error_detail,
datums,
edata->detail ? edata->detail : NULL);
ts_datum_set_text_from_cstring(Anum_cagg_validate_query_error_hint,
datums,
edata->hint ? edata->hint : NULL);

Assert(tupdesc->natts == Natts_cagg_validate_query);
tuple = ts_heap_form_tuple(tupdesc, datums);

return HeapTupleGetDatum(tuple);
}
Expand Down

0 comments on commit 898f18b

Please sign in to comment.