Add coccinele checking for AttrNumberGetAttrOffset

Postgres has `AttrNumberGetAttrOffset()` macro to proper access Datum
array members, so added a new coccinele static analysis to check for
missing macro usage.

Example:
`datum[attrno - 1]` should be `datum[AttrNumberGetAttrOffset(attrno)]`

Reference:
* https://github.com/postgres/postgres/blob/master/src/include/access/attnum.h)
This commit is contained in:
Fabrízio de Royes Mello 2024-02-15 18:06:59 -03:00
parent aa4dac195d
commit 89af50d886
4 changed files with 54 additions and 21 deletions

View File

@ -0,0 +1,30 @@
//
// find missing `AttrNumberGetAttrOffset` usage
//
// Postgres has `AttrNumberGetAttrOffset()` macro to proper access Datum array members
// (see https://github.com/postgres/postgres/blob/master/src/include/access/attnum.h).
//
// For example:
// `datum[attrno - 1]` should be `datum[AttrNumberGetAttrOffset(attrno)]`
//
@@
typedef Datum;
expression attrno;
Datum [] datum;
@@
- datum[attrno - 1]
+ /* use AttrNumberGetAttrOffset() for acessing Datum array members */
+ datum[AttrNumberGetAttrOffset(attrno)]
@@
typedef bool;
expression attrno;
bool [] isnull;
@@
- isnull[attrno - 1]
+ /* use AttrNumberGetAttrOffset() for acessing bool array members */
+ isnull[AttrNumberGetAttrOffset(attrno)]

View File

@ -192,8 +192,8 @@ dimension_fill_in_from_tuple(Dimension *d, TupleInfo *ti, Oid main_table_relid)
DatumGetName(values[AttrNumberGetAttrOffset(Anum_dimension_column_name)]), DatumGetName(values[AttrNumberGetAttrOffset(Anum_dimension_column_name)]),
NAMEDATALEN); NAMEDATALEN);
if (!isnull[Anum_dimension_partitioning_func_schema - 1] && if (!isnull[AttrNumberGetAttrOffset(Anum_dimension_partitioning_func_schema)] &&
!isnull[Anum_dimension_partitioning_func - 1]) !isnull[AttrNumberGetAttrOffset(Anum_dimension_partitioning_func)])
{ {
MemoryContext old; MemoryContext old;
@ -218,8 +218,8 @@ dimension_fill_in_from_tuple(Dimension *d, TupleInfo *ti, Oid main_table_relid)
MemoryContextSwitchTo(old); MemoryContextSwitchTo(old);
} }
if (!isnull[Anum_dimension_integer_now_func_schema - 1] && if (!isnull[AttrNumberGetAttrOffset(Anum_dimension_integer_now_func_schema)] &&
!isnull[Anum_dimension_integer_now_func - 1]) !isnull[AttrNumberGetAttrOffset(Anum_dimension_integer_now_func)])
{ {
namestrcpy(&d->fd.integer_now_func_schema, namestrcpy(&d->fd.integer_now_func_schema,
DatumGetCString( DatumGetCString(
@ -230,12 +230,13 @@ dimension_fill_in_from_tuple(Dimension *d, TupleInfo *ti, Oid main_table_relid)
} }
if (IS_CLOSED_DIMENSION(d)) if (IS_CLOSED_DIMENSION(d))
d->fd.num_slices = DatumGetInt16(values[Anum_dimension_num_slices - 1]); d->fd.num_slices =
DatumGetInt16(values[AttrNumberGetAttrOffset(Anum_dimension_num_slices)]);
else else
{ {
d->fd.interval_length = d->fd.interval_length =
DatumGetInt64(values[AttrNumberGetAttrOffset(Anum_dimension_interval_length)]); DatumGetInt64(values[AttrNumberGetAttrOffset(Anum_dimension_interval_length)]);
if (!isnull[Anum_dimension_compress_interval_length - 1]) if (!isnull[AttrNumberGetAttrOffset(Anum_dimension_compress_interval_length)])
d->fd.compress_interval_length = DatumGetInt64( d->fd.compress_interval_length = DatumGetInt64(
values[AttrNumberGetAttrOffset(Anum_dimension_compress_interval_length)]); values[AttrNumberGetAttrOffset(Anum_dimension_compress_interval_length)]);
} }

View File

@ -426,27 +426,29 @@ continuous_agg_fill_bucket_function(int32 mat_hypertable_id, ContinuousAggsBucke
*/ */
heap_deform_tuple(tuple, ts_scan_iterator_tupledesc(&iterator), values, isnull); heap_deform_tuple(tuple, ts_scan_iterator_tupledesc(&iterator), values, isnull);
Assert(!isnull[Anum_continuous_aggs_bucket_function_experimental - 1]); Assert(!isnull[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_experimental)]);
bf->experimental = bf->experimental = DatumGetBool(
DatumGetBool(values[Anum_continuous_aggs_bucket_function_experimental - 1]); values[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_experimental)]);
Assert(!isnull[Anum_continuous_aggs_bucket_function_name - 1]); Assert(!isnull[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_name)]);
bf->name = TextDatumGetCString(values[Anum_continuous_aggs_bucket_function_name - 1]); bf->name = TextDatumGetCString(
values[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_name)]);
/* /*
* So far bucket_width is stored as TEXT for flexibility, but it's type * So far bucket_width is stored as TEXT for flexibility, but it's type
* most likely is going to change to Interval when the variable-sized * most likely is going to change to Interval when the variable-sized
* buckets feature will stabilize. * buckets feature will stabilize.
*/ */
Assert(!isnull[Anum_continuous_aggs_bucket_function_bucket_width - 1]); Assert(!isnull[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_bucket_width)]);
bucket_width_str = bucket_width_str = TextDatumGetCString(
TextDatumGetCString(values[Anum_continuous_aggs_bucket_function_bucket_width - 1]); values[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_bucket_width)]);
Assert(strlen(bucket_width_str) > 0); Assert(strlen(bucket_width_str) > 0);
bf->bucket_width = DatumGetIntervalP( bf->bucket_width = DatumGetIntervalP(
DirectFunctionCall3(interval_in, CStringGetDatum(bucket_width_str), InvalidOid, -1)); DirectFunctionCall3(interval_in, CStringGetDatum(bucket_width_str), InvalidOid, -1));
Assert(!isnull[Anum_continuous_aggs_bucket_function_origin - 1]); Assert(!isnull[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_origin)]);
origin_str = TextDatumGetCString(values[Anum_continuous_aggs_bucket_function_origin - 1]); origin_str = TextDatumGetCString(
values[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_origin)]);
if (strlen(origin_str) == 0) if (strlen(origin_str) == 0)
TIMESTAMP_NOBEGIN(bf->origin); TIMESTAMP_NOBEGIN(bf->origin);
else else
@ -455,9 +457,9 @@ continuous_agg_fill_bucket_function(int32 mat_hypertable_id, ContinuousAggsBucke
ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1))); Int32GetDatum(-1)));
Assert(!isnull[Anum_continuous_aggs_bucket_function_timezone - 1]); Assert(!isnull[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_timezone)]);
bf->timezone = bf->timezone = TextDatumGetCString(
TextDatumGetCString(values[Anum_continuous_aggs_bucket_function_timezone - 1]); values[AttrNumberGetAttrOffset(Anum_continuous_aggs_bucket_function_timezone)]);
count++; count++;

View File

@ -1543,8 +1543,8 @@ ts_copy_relation_acl(const Oid source_relid, const Oid target_relid, const Oid o
bool new_repl[Natts_pg_class] = { false }; bool new_repl[Natts_pg_class] = { false };
Acl *acl = DatumGetAclP(acl_datum); Acl *acl = DatumGetAclP(acl_datum);
new_repl[Anum_pg_class_relacl - 1] = true; new_repl[AttrNumberGetAttrOffset(Anum_pg_class_relacl)] = true;
new_val[Anum_pg_class_relacl - 1] = PointerGetDatum(acl); new_val[AttrNumberGetAttrOffset(Anum_pg_class_relacl)] = PointerGetDatum(acl);
/* Find the tuple for the target in `pg_class` */ /* Find the tuple for the target in `pg_class` */
target_tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(target_relid)); target_tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(target_relid));