]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/adt/rowtypes.c
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / backend / utils / adt / rowtypes.c
index 622bb88beb532219dc8a4ad7803f5f19a25da4c6..ea3e40a369429d7b0f2f04fb0a5c062898b2bd65 100644 (file)
@@ -3,7 +3,7 @@
  * rowtypes.c
  *       I/O and comparison functions for generic composite types.
  *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
 
 #include <ctype.h>
 
+#include "access/detoast.h"
 #include "access/htup_details.h"
-#include "access/tuptoaster.h"
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
+#include "utils/datum.h"
 #include "utils/lsyscache.h"
 #include "utils/typcache.h"
 
@@ -100,7 +101,7 @@ record_in(PG_FUNCTION_ARGS)
        if (tupType == RECORDOID && tupTypmod < 0)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                  errmsg("input of anonymous composite types is not implemented")));
+                                errmsg("input of anonymous composite types is not implemented")));
 
        /*
         * This comes from the composite type's pg_type.oid and stores system oids
@@ -159,12 +160,13 @@ record_in(PG_FUNCTION_ARGS)
 
        for (i = 0; i < ncolumns; i++)
        {
+               Form_pg_attribute att = TupleDescAttr(tupdesc, i);
                ColumnIOData *column_info = &my_extra->columns[i];
-               Oid                     column_type = tupdesc->attrs[i]->atttypid;
+               Oid                     column_type = att->atttypid;
                char       *column_data;
 
                /* Ignore dropped columns in datatype, but fill with nulls */
-               if (tupdesc->attrs[i]->attisdropped)
+               if (att->attisdropped)
                {
                        values[i] = (Datum) 0;
                        nulls[i] = true;
@@ -252,7 +254,7 @@ record_in(PG_FUNCTION_ARGS)
                values[i] = InputFunctionCall(&column_info->proc,
                                                                          column_data,
                                                                          column_info->typioparam,
-                                                                         tupdesc->attrs[i]->atttypmod);
+                                                                         att->atttypmod);
 
                /*
                 * Prep for next column
@@ -367,15 +369,16 @@ record_out(PG_FUNCTION_ARGS)
 
        for (i = 0; i < ncolumns; i++)
        {
+               Form_pg_attribute att = TupleDescAttr(tupdesc, i);
                ColumnIOData *column_info = &my_extra->columns[i];
-               Oid                     column_type = tupdesc->attrs[i]->atttypid;
+               Oid                     column_type = att->atttypid;
                Datum           attr;
                char       *value;
                char       *tmp;
                bool            nq;
 
                /* Ignore dropped columns in datatype */
-               if (tupdesc->attrs[i]->attisdropped)
+               if (att->attisdropped)
                        continue;
 
                if (needComma)
@@ -476,7 +479,7 @@ record_recv(PG_FUNCTION_ARGS)
        if (tupType == RECORDOID && tupTypmod < 0)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                  errmsg("input of anonymous composite types is not implemented")));
+                                errmsg("input of anonymous composite types is not implemented")));
 
        tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
        ncolumns = tupdesc->natts;
@@ -519,7 +522,7 @@ record_recv(PG_FUNCTION_ARGS)
        validcols = 0;
        for (i = 0; i < ncolumns; i++)
        {
-               if (!tupdesc->attrs[i]->attisdropped)
+               if (!TupleDescAttr(tupdesc, i)->attisdropped)
                        validcols++;
        }
        if (usercols != validcols)
@@ -531,8 +534,9 @@ record_recv(PG_FUNCTION_ARGS)
        /* Process each column */
        for (i = 0; i < ncolumns; i++)
        {
+               Form_pg_attribute att = TupleDescAttr(tupdesc, i);
                ColumnIOData *column_info = &my_extra->columns[i];
-               Oid                     column_type = tupdesc->attrs[i]->atttypid;
+               Oid                     column_type = att->atttypid;
                Oid                     coltypoid;
                int                     itemlen;
                StringInfoData item_buf;
@@ -540,7 +544,7 @@ record_recv(PG_FUNCTION_ARGS)
                char            csave;
 
                /* Ignore dropped columns in datatype, but fill with nulls */
-               if (tupdesc->attrs[i]->attisdropped)
+               if (att->attisdropped)
                {
                        values[i] = (Datum) 0;
                        nulls[i] = true;
@@ -605,7 +609,7 @@ record_recv(PG_FUNCTION_ARGS)
                values[i] = ReceiveFunctionCall(&column_info->proc,
                                                                                bufptr,
                                                                                column_info->typioparam,
-                                                                               tupdesc->attrs[i]->atttypmod);
+                                                                               att->atttypmod);
 
                if (bufptr)
                {
@@ -712,28 +716,29 @@ record_send(PG_FUNCTION_ARGS)
        validcols = 0;
        for (i = 0; i < ncolumns; i++)
        {
-               if (!tupdesc->attrs[i]->attisdropped)
+               if (!TupleDescAttr(tupdesc, i)->attisdropped)
                        validcols++;
        }
-       pq_sendint(&buf, validcols, 4);
+       pq_sendint32(&buf, validcols);
 
        for (i = 0; i < ncolumns; i++)
        {
+               Form_pg_attribute att = TupleDescAttr(tupdesc, i);
                ColumnIOData *column_info = &my_extra->columns[i];
-               Oid                     column_type = tupdesc->attrs[i]->atttypid;
+               Oid                     column_type = att->atttypid;
                Datum           attr;
                bytea      *outputbytes;
 
                /* Ignore dropped columns in datatype */
-               if (tupdesc->attrs[i]->attisdropped)
+               if (att->attisdropped)
                        continue;
 
-               pq_sendint(&buf, column_type, sizeof(Oid));
+               pq_sendint32(&buf, column_type);
 
                if (nulls[i])
                {
                        /* emit -1 data length to signify a NULL */
-                       pq_sendint(&buf, -1, 4);
+                       pq_sendint32(&buf, -1);
                        continue;
                }
 
@@ -752,7 +757,7 @@ record_send(PG_FUNCTION_ARGS)
 
                attr = values[i];
                outputbytes = SendFunctionCall(&column_info->proc, attr);
-               pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
+               pq_sendint32(&buf, VARSIZE(outputbytes) - VARHDRSZ);
                pq_sendbytes(&buf, VARDATA(outputbytes),
                                         VARSIZE(outputbytes) - VARHDRSZ);
        }
@@ -873,18 +878,20 @@ record_cmp(FunctionCallInfo fcinfo)
        i1 = i2 = j = 0;
        while (i1 < ncolumns1 || i2 < ncolumns2)
        {
+               Form_pg_attribute att1;
+               Form_pg_attribute att2;
                TypeCacheEntry *typentry;
                Oid                     collation;
 
                /*
                 * Skip dropped columns
                 */
-               if (i1 < ncolumns1 && tupdesc1->attrs[i1]->attisdropped)
+               if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped)
                {
                        i1++;
                        continue;
                }
-               if (i2 < ncolumns2 && tupdesc2->attrs[i2]->attisdropped)
+               if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped)
                {
                        i2++;
                        continue;
@@ -892,24 +899,26 @@ record_cmp(FunctionCallInfo fcinfo)
                if (i1 >= ncolumns1 || i2 >= ncolumns2)
                        break;                          /* we'll deal with mismatch below loop */
 
+               att1 = TupleDescAttr(tupdesc1, i1);
+               att2 = TupleDescAttr(tupdesc2, i2);
+
                /*
                 * Have two matching columns, they must be same type
                 */
-               if (tupdesc1->attrs[i1]->atttypid !=
-                       tupdesc2->attrs[i2]->atttypid)
+               if (att1->atttypid != att2->atttypid)
                        ereport(ERROR,
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
                                         errmsg("cannot compare dissimilar column types %s and %s at record column %d",
-                                                       format_type_be(tupdesc1->attrs[i1]->atttypid),
-                                                       format_type_be(tupdesc2->attrs[i2]->atttypid),
+                                                       format_type_be(att1->atttypid),
+                                                       format_type_be(att2->atttypid),
                                                        j + 1)));
 
                /*
                 * If they're not same collation, we don't complain here, but the
                 * comparison function might.
                 */
-               collation = tupdesc1->attrs[i1]->attcollation;
-               if (collation != tupdesc2->attrs[i2]->attcollation)
+               collation = att1->attcollation;
+               if (collation != att2->attcollation)
                        collation = InvalidOid;
 
                /*
@@ -917,15 +926,15 @@ record_cmp(FunctionCallInfo fcinfo)
                 */
                typentry = my_extra->columns[j].typentry;
                if (typentry == NULL ||
-                       typentry->type_id != tupdesc1->attrs[i1]->atttypid)
+                       typentry->type_id != att1->atttypid)
                {
-                       typentry = lookup_type_cache(tupdesc1->attrs[i1]->atttypid,
+                       typentry = lookup_type_cache(att1->atttypid,
                                                                                 TYPECACHE_CMP_PROC_FINFO);
                        if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
                                ereport(ERROR,
                                                (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                               errmsg("could not identify a comparison function for type %s",
-                                          format_type_be(typentry->type_id))));
+                                                errmsg("could not identify a comparison function for type %s",
+                                                               format_type_be(typentry->type_id))));
                        my_extra->columns[j].typentry = typentry;
                }
 
@@ -934,7 +943,7 @@ record_cmp(FunctionCallInfo fcinfo)
                 */
                if (!nulls1[i1] || !nulls2[i2])
                {
-                       FunctionCallInfoData locfcinfo;
+                       LOCAL_FCINFO(locfcinfo, 2);
                        int32           cmpresult;
 
                        if (nulls1[i1])
@@ -951,14 +960,14 @@ record_cmp(FunctionCallInfo fcinfo)
                        }
 
                        /* Compare the pair of elements */
-                       InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+                       InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2,
                                                                         collation, NULL, NULL);
-                       locfcinfo.arg[0] = values1[i1];
-                       locfcinfo.arg[1] = values2[i2];
-                       locfcinfo.argnull[0] = false;
-                       locfcinfo.argnull[1] = false;
-                       locfcinfo.isnull = false;
-                       cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+                       locfcinfo->args[0].value = values1[i1];
+                       locfcinfo->args[0].isnull = false;
+                       locfcinfo->args[1].value = values2[i2];
+                       locfcinfo->args[1].isnull = false;
+                       locfcinfo->isnull = false;
+                       cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo));
 
                        if (cmpresult < 0)
                        {
@@ -1111,20 +1120,22 @@ record_eq(PG_FUNCTION_ARGS)
        i1 = i2 = j = 0;
        while (i1 < ncolumns1 || i2 < ncolumns2)
        {
+               LOCAL_FCINFO(locfcinfo, 2);
+               Form_pg_attribute att1;
+               Form_pg_attribute att2;
                TypeCacheEntry *typentry;
                Oid                     collation;
-               FunctionCallInfoData locfcinfo;
                bool            oprresult;
 
                /*
                 * Skip dropped columns
                 */
-               if (i1 < ncolumns1 && tupdesc1->attrs[i1]->attisdropped)
+               if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped)
                {
                        i1++;
                        continue;
                }
-               if (i2 < ncolumns2 && tupdesc2->attrs[i2]->attisdropped)
+               if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped)
                {
                        i2++;
                        continue;
@@ -1132,24 +1143,26 @@ record_eq(PG_FUNCTION_ARGS)
                if (i1 >= ncolumns1 || i2 >= ncolumns2)
                        break;                          /* we'll deal with mismatch below loop */
 
+               att1 = TupleDescAttr(tupdesc1, i1);
+               att2 = TupleDescAttr(tupdesc2, i2);
+
                /*
                 * Have two matching columns, they must be same type
                 */
-               if (tupdesc1->attrs[i1]->atttypid !=
-                       tupdesc2->attrs[i2]->atttypid)
+               if (att1->atttypid != att2->atttypid)
                        ereport(ERROR,
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
                                         errmsg("cannot compare dissimilar column types %s and %s at record column %d",
-                                                       format_type_be(tupdesc1->attrs[i1]->atttypid),
-                                                       format_type_be(tupdesc2->attrs[i2]->atttypid),
+                                                       format_type_be(att1->atttypid),
+                                                       format_type_be(att2->atttypid),
                                                        j + 1)));
 
                /*
                 * If they're not same collation, we don't complain here, but the
                 * equality function might.
                 */
-               collation = tupdesc1->attrs[i1]->attcollation;
-               if (collation != tupdesc2->attrs[i2]->attcollation)
+               collation = att1->attcollation;
+               if (collation != att2->attcollation)
                        collation = InvalidOid;
 
                /*
@@ -1157,15 +1170,15 @@ record_eq(PG_FUNCTION_ARGS)
                 */
                typentry = my_extra->columns[j].typentry;
                if (typentry == NULL ||
-                       typentry->type_id != tupdesc1->attrs[i1]->atttypid)
+                       typentry->type_id != att1->atttypid)
                {
-                       typentry = lookup_type_cache(tupdesc1->attrs[i1]->atttypid,
+                       typentry = lookup_type_cache(att1->atttypid,
                                                                                 TYPECACHE_EQ_OPR_FINFO);
                        if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
                                ereport(ERROR,
                                                (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                               errmsg("could not identify an equality operator for type %s",
-                                          format_type_be(typentry->type_id))));
+                                                errmsg("could not identify an equality operator for type %s",
+                                                               format_type_be(typentry->type_id))));
                        my_extra->columns[j].typentry = typentry;
                }
 
@@ -1181,14 +1194,14 @@ record_eq(PG_FUNCTION_ARGS)
                        }
 
                        /* Compare the pair of elements */
-                       InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+                       InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
                                                                         collation, NULL, NULL);
-                       locfcinfo.arg[0] = values1[i1];
-                       locfcinfo.arg[1] = values2[i2];
-                       locfcinfo.argnull[0] = false;
-                       locfcinfo.argnull[1] = false;
-                       locfcinfo.isnull = false;
-                       oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
+                       locfcinfo->args[0].value = values1[i1];
+                       locfcinfo->args[0].isnull = false;
+                       locfcinfo->args[1].value = values2[i2];
+                       locfcinfo->args[1].isnull = false;
+                       locfcinfo->isnull = false;
+                       oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
                        if (!oprresult)
                        {
                                result = false;
@@ -1370,15 +1383,18 @@ record_image_cmp(FunctionCallInfo fcinfo)
        i1 = i2 = j = 0;
        while (i1 < ncolumns1 || i2 < ncolumns2)
        {
+               Form_pg_attribute att1;
+               Form_pg_attribute att2;
+
                /*
                 * Skip dropped columns
                 */
-               if (i1 < ncolumns1 && tupdesc1->attrs[i1]->attisdropped)
+               if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped)
                {
                        i1++;
                        continue;
                }
-               if (i2 < ncolumns2 && tupdesc2->attrs[i2]->attisdropped)
+               if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped)
                {
                        i2++;
                        continue;
@@ -1386,24 +1402,25 @@ record_image_cmp(FunctionCallInfo fcinfo)
                if (i1 >= ncolumns1 || i2 >= ncolumns2)
                        break;                          /* we'll deal with mismatch below loop */
 
+               att1 = TupleDescAttr(tupdesc1, i1);
+               att2 = TupleDescAttr(tupdesc2, i2);
+
                /*
                 * Have two matching columns, they must be same type
                 */
-               if (tupdesc1->attrs[i1]->atttypid !=
-                       tupdesc2->attrs[i2]->atttypid)
+               if (att1->atttypid != att2->atttypid)
                        ereport(ERROR,
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
                                         errmsg("cannot compare dissimilar column types %s and %s at record column %d",
-                                                       format_type_be(tupdesc1->attrs[i1]->atttypid),
-                                                       format_type_be(tupdesc2->attrs[i2]->atttypid),
+                                                       format_type_be(att1->atttypid),
+                                                       format_type_be(att2->atttypid),
                                                        j + 1)));
 
                /*
                 * The same type should have the same length (or both should be
                 * variable).
                 */
-               Assert(tupdesc1->attrs[i1]->attlen ==
-                          tupdesc2->attrs[i2]->attlen);
+               Assert(att1->attlen == att2->attlen);
 
                /*
                 * We consider two NULLs equal; NULL > not-NULL.
@@ -1426,7 +1443,7 @@ record_image_cmp(FunctionCallInfo fcinfo)
                        }
 
                        /* Compare the pair of elements */
-                       if (tupdesc1->attrs[i1]->attlen == -1)
+                       if (att1->attlen == -1)
                        {
                                Size            len1,
                                                        len2;
@@ -1449,53 +1466,16 @@ record_image_cmp(FunctionCallInfo fcinfo)
                                if ((Pointer) arg2val != (Pointer) values2[i2])
                                        pfree(arg2val);
                        }
-                       else if (tupdesc1->attrs[i1]->attbyval)
+                       else if (att1->attbyval)
                        {
-                               switch (tupdesc1->attrs[i1]->attlen)
-                               {
-                                       case 1:
-                                               if (GET_1_BYTE(values1[i1]) !=
-                                                       GET_1_BYTE(values2[i2]))
-                                               {
-                                                       cmpresult = (GET_1_BYTE(values1[i1]) <
-                                                                                GET_1_BYTE(values2[i2])) ? -1 : 1;
-                                               }
-                                               break;
-                                       case 2:
-                                               if (GET_2_BYTES(values1[i1]) !=
-                                                       GET_2_BYTES(values2[i2]))
-                                               {
-                                                       cmpresult = (GET_2_BYTES(values1[i1]) <
-                                                                                GET_2_BYTES(values2[i2])) ? -1 : 1;
-                                               }
-                                               break;
-                                       case 4:
-                                               if (GET_4_BYTES(values1[i1]) !=
-                                                       GET_4_BYTES(values2[i2]))
-                                               {
-                                                       cmpresult = (GET_4_BYTES(values1[i1]) <
-                                                                                GET_4_BYTES(values2[i2])) ? -1 : 1;
-                                               }
-                                               break;
-#if SIZEOF_DATUM == 8
-                                       case 8:
-                                               if (GET_8_BYTES(values1[i1]) !=
-                                                       GET_8_BYTES(values2[i2]))
-                                               {
-                                                       cmpresult = (GET_8_BYTES(values1[i1]) <
-                                                                                GET_8_BYTES(values2[i2])) ? -1 : 1;
-                                               }
-                                               break;
-#endif
-                                       default:
-                                               Assert(false);  /* cannot happen */
-                               }
+                               if (values1[i1] != values2[i2])
+                                       cmpresult = (values1[i1] < values2[i2]) ? -1 : 1;
                        }
                        else
                        {
                                cmpresult = memcmp(DatumGetPointer(values1[i1]),
                                                                   DatumGetPointer(values2[i2]),
-                                                                  tupdesc1->attrs[i1]->attlen);
+                                                                  att1->attlen);
                        }
 
                        if (cmpresult < 0)
@@ -1647,15 +1627,18 @@ record_image_eq(PG_FUNCTION_ARGS)
        i1 = i2 = j = 0;
        while (i1 < ncolumns1 || i2 < ncolumns2)
        {
+               Form_pg_attribute att1;
+               Form_pg_attribute att2;
+
                /*
                 * Skip dropped columns
                 */
-               if (i1 < ncolumns1 && tupdesc1->attrs[i1]->attisdropped)
+               if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped)
                {
                        i1++;
                        continue;
                }
-               if (i2 < ncolumns2 && tupdesc2->attrs[i2]->attisdropped)
+               if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped)
                {
                        i2++;
                        continue;
@@ -1663,16 +1646,18 @@ record_image_eq(PG_FUNCTION_ARGS)
                if (i1 >= ncolumns1 || i2 >= ncolumns2)
                        break;                          /* we'll deal with mismatch below loop */
 
+               att1 = TupleDescAttr(tupdesc1, i1);
+               att2 = TupleDescAttr(tupdesc2, i2);
+
                /*
                 * Have two matching columns, they must be same type
                 */
-               if (tupdesc1->attrs[i1]->atttypid !=
-                       tupdesc2->attrs[i2]->atttypid)
+               if (att1->atttypid != att2->atttypid)
                        ereport(ERROR,
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
                                         errmsg("cannot compare dissimilar column types %s and %s at record column %d",
-                                                       format_type_be(tupdesc1->attrs[i1]->atttypid),
-                                                       format_type_be(tupdesc2->attrs[i2]->atttypid),
+                                                       format_type_be(att1->atttypid),
+                                                       format_type_be(att2->atttypid),
                                                        j + 1)));
 
                /*
@@ -1687,67 +1672,7 @@ record_image_eq(PG_FUNCTION_ARGS)
                        }
 
                        /* Compare the pair of elements */
-                       if (tupdesc1->attrs[i1]->attlen == -1)
-                       {
-                               Size            len1,
-                                                       len2;
-
-                               len1 = toast_raw_datum_size(values1[i1]);
-                               len2 = toast_raw_datum_size(values2[i2]);
-                               /* No need to de-toast if lengths don't match. */
-                               if (len1 != len2)
-                                       result = false;
-                               else
-                               {
-                                       struct varlena *arg1val;
-                                       struct varlena *arg2val;
-
-                                       arg1val = PG_DETOAST_DATUM_PACKED(values1[i1]);
-                                       arg2val = PG_DETOAST_DATUM_PACKED(values2[i2]);
-
-                                       result = (memcmp(VARDATA_ANY(arg1val),
-                                                                        VARDATA_ANY(arg2val),
-                                                                        len1 - VARHDRSZ) == 0);
-
-                                       /* Only free memory if it's a copy made here. */
-                                       if ((Pointer) arg1val != (Pointer) values1[i1])
-                                               pfree(arg1val);
-                                       if ((Pointer) arg2val != (Pointer) values2[i2])
-                                               pfree(arg2val);
-                               }
-                       }
-                       else if (tupdesc1->attrs[i1]->attbyval)
-                       {
-                               switch (tupdesc1->attrs[i1]->attlen)
-                               {
-                                       case 1:
-                                               result = (GET_1_BYTE(values1[i1]) ==
-                                                                 GET_1_BYTE(values2[i2]));
-                                               break;
-                                       case 2:
-                                               result = (GET_2_BYTES(values1[i1]) ==
-                                                                 GET_2_BYTES(values2[i2]));
-                                               break;
-                                       case 4:
-                                               result = (GET_4_BYTES(values1[i1]) ==
-                                                                 GET_4_BYTES(values2[i2]));
-                                               break;
-#if SIZEOF_DATUM == 8
-                                       case 8:
-                                               result = (GET_8_BYTES(values1[i1]) ==
-                                                                 GET_8_BYTES(values2[i2]));
-                                               break;
-#endif
-                                       default:
-                                               Assert(false);  /* cannot happen */
-                               }
-                       }
-                       else
-                       {
-                               result = (memcmp(DatumGetPointer(values1[i1]),
-                                                                DatumGetPointer(values2[i2]),
-                                                                tupdesc1->attrs[i1]->attlen) == 0);
-                       }
+                       result = datum_image_eq(values1[i1], values2[i2], att1->attbyval, att2->attlen);
                        if (!result)
                                break;
                }