Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vlGi5-009R0Y-16 for pgsql-hackers@arkaria.postgresql.org; Thu, 29 Jan 2026 01:20:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vlGi4-0059bo-01 for pgsql-hackers@arkaria.postgresql.org; Thu, 29 Jan 2026 01:20:36 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vlGi3-0059bW-1u for pgsql-hackers@lists.postgresql.org; Thu, 29 Jan 2026 01:20:36 +0000 Received: from sss.pgh.pa.us ([68.162.161.243]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1vlGhz-00000000yu0-0vWc for pgsql-hackers@lists.postgresql.org; Thu, 29 Jan 2026 01:20:35 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 60T1KOrL1127262 for ; Wed, 28 Jan 2026 20:20:24 -0500 From: Tom Lane To: pgsql-hackers@lists.postgresql.org Subject: Decoupling our alignment assumptions about int64 and double MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <1127252.1769649618.0@sss.pgh.pa.us> Date: Wed, 28 Jan 2026 20:20:24 -0500 Message-ID: <1127261.1769649624@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <1127252.1769649618.1@sss.pgh.pa.us> Over in the long-running thread about resurrecting AIX support, one salient concern is that AIX has alignof(int64) = 8 but alignof(double) = 4. This breaks all our code that supposes that ALIGNOF_DOUBLE is the platform's maximum alignment spec. We had coped with this via various unspeakable klugery back when AIX was considered supported, but nobody wants to put back those restrictions if we re-support AIX. (See my gripe at [1], but I believe Heikki and Andres complained of this in more detail long ago.) Here is a modest proposal for fixing that in a clean way. Let's break TYPALIGN_DOUBLE into three values, TYPALIGN_DOUBLE for float8 only, TYPALIGN_INT64 for 64-bit integral types including pointers, and TYPALIGN_MAX to represent MAXALIGN alignment regardless of which of the first two determine it. We need TYPALIGN_MAX because that's the value composite types should use, so that their alignment doesn't change if somebody adds or deletes a column of a relevant type. Given that design, the patch is pretty straightforward, and smaller than I feared it might be. (Though I might have missed a spot or two.) I think this is good cleanup and deserves consideration whether we accept the AIX patch soon or not. A loose end that deserves mention is that I noticed we are very inconsistent about the length/alignment attributed to polymorphic types: select typname, typlen, typalign from pg_type where typname like 'any%'; typname | typlen | typalign -------------------------+--------+---------- any | 4 | i anyarray | -1 | m anycompatible | 4 | i anycompatiblearray | -1 | m anycompatiblemultirange | -1 | m anycompatiblenonarray | 4 | i anycompatiblerange | -1 | m anyelement | 4 | i anyenum | 4 | i anymultirange | -1 | m anynonarray | 4 | i anyrange | -1 | m (12 rows) (Previous to this patch, the 'm' entries were 'd'.) In one sense this doesn't really matter, since no actual value should have any of these types attributed to it; but it annoys me that they're not all alike. I'm tempted to make them all 4/'i' which seems to be the older convention. A more aggressive answer would be to change these to some actually-illegal values, in hopes of catching anyplace where we did try to rely on the values. But that seems like material for a different patch. regards, tom lane [1] https://www.postgresql.org/message-id/581905.1769550155%40sss.pgh.pa.us ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name*0="v1-0001-Decouple-our-alignment-assumptions-about-int64-an.p"; name*1="atch"; charset="us-ascii" Content-ID: <1127252.1769649618.2@sss.pgh.pa.us> Content-Description: v1-0001-Decouple-our-alignment-assumptions-about-int64-an.patch Content-Transfer-Encoding: quoted-printable =46rom 4474db54e4c481c7a919062812b33ba2e703d626 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 28 Jan 2026 19:54:46 -0500 Subject: [PATCH v1] Decouple our alignment assumptions about int64 and dou= ble. Up to now we have assumed that int64 and double have the same alignment requirement, but there are platforms on which that's not true (notably AIX). This assumption is a bit of a wart anyway, since it leads to confusion about which alignment setting to use. Let's break that apart. We actually need to split TYPALIGN_DOUBLE into three values not two, because we need a representation for "the maximum alignment on this platform"; composite types need to use that setting. So this patch invents TYPALIGN_INT64 and TYPALIGN_MAX, and propagates those into all the necessary places. It's pretty straightforward really, though it's certainly possible I missed a few places to change. One of the concerns that prevented this from being done long ago was not wanting to add overhead to tuple forming/deforming. However that concern seems gone now, because we map TYPALIGN_xxx values to numeric alignments in populate_compact_attribute() which is not so performance-critical. It might be worth worrying about the increased cost of att_align_nominal(), but that macro is not that heavily used IMO. An issue not resolved here is that we are not consistent about the pg_type typlen/typalign values for polymorphic types (the "any*" types). Those shouldn't actually matter, but why aren't they all alike? Side notes: I got rid of LONGALIGN[_DOWN] along with the configure probes for ALIGNOF_LONG. We were not using those anywhere and it seems highly unlikely that we'd do so in future. bootstrap.c turns out to have had the wrong alignment value for _aclitem; seems that was missed when we widened AclMode to 64 bits. AFAICT the value wasn't used so there were no ill effects. I fixed a couple of places that were using hard-coded values when they could have used TYPALIGN_xxx macros. This will require a catversion bump. --- configure | 64 +++---------------- configure.ac | 30 +++------ doc/src/sgml/catalogs.sgml | 8 ++- doc/src/sgml/ref/create_type.sgml | 9 ++- meson.build | 31 ++++----- src/backend/access/common/tupdesc.c | 8 ++- src/backend/bootstrap/bootstrap.c | 4 +- src/backend/catalog/Catalog.pm | 10 ++- src/backend/catalog/heap.c | 4 +- src/backend/catalog/pg_type.c | 9 ++- src/backend/commands/typecmds.c | 38 +++++++++-- src/backend/tsearch/ts_typanalyze.c | 2 +- src/backend/utils/adt/arrayfuncs.c | 2 +- src/backend/utils/adt/orderedsetaggs.c | 2 +- src/backend/utils/adt/rangetypes_typanalyze.c | 2 +- src/bin/initdb/initdb.c | 2 +- src/bin/pg_dump/pg_dump.c | 4 ++ src/include/access/tupmacs.h | 12 ++-- src/include/c.h | 4 +- src/include/catalog/pg_type.dat | 62 +++++++++--------- src/include/catalog/pg_type.h | 2 + src/include/pg_config.h.in | 3 - src/pl/plpython/plpy_typeio.c | 4 +- src/test/regress/expected/float8.out | 8 ++- src/test/regress/expected/type_sanity.out | 8 ++- src/test/regress/sql/float8.sql | 6 +- src/test/regress/sql/type_sanity.sql | 8 ++- 27 files changed, 177 insertions(+), 169 deletions(-) diff --git a/configure b/configure index a10a2c85c6a..5adfb3eba45 100755 --- a/configure +++ b/configure @@ -17095,41 +17095,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF = = -# The cast to long int works around a bug in the HP C Compiler, -# see AC_CHECK_SIZEOF for more information. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long" >&5 -$as_echo_n "checking alignment of long... " >&6; } -if ${ac_cv_alignof_long+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof= _, y)" "ac_cv_alignof_long" "$ac_includes_default -#ifndef offsetof -# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *= ) 0) -#endif -typedef struct { char x; long y; } ac__type_alignof_;"; then : - -else - if test "$ac_cv_type_long" =3D yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&= 5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute alignment of long -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_alignof_long=3D0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long" >&5 -$as_echo "$ac_cv_alignof_long" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define ALIGNOF_LONG $ac_cv_alignof_long -_ACEOF - - # The cast to long int works around a bug in the HP C Compiler, # see AC_CHECK_SIZEOF for more information. { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >= &5 @@ -17203,27 +17168,16 @@ _ACEOF = # Compute maximum alignment of any basic type. # -# We require 'double' to have the strictest alignment among the basic typ= es, -# because otherwise the C ABI might impose 8-byte alignment on some of th= e -# other C types that correspond to TYPALIGN_DOUBLE SQL types. That could -# cause a mismatch between the tuple layout and the C struct layout of a -# catalog tuple. We used to carefully order catalog columns such that an= y -# fixed-width, attalign=3D4 columns were at offsets divisible by 8 regard= less -# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platform= s -# where TYPALIGN_DOUBLE !=3D MAXIMUM_ALIGNOF. -# -# We assume without checking that long's alignment is at least as strong = as -# char, short, or int. Note that we intentionally do not consider any ty= pes -# wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be to= o -# much of a penalty for disk and memory space. +# We assume without checking that the maximum alignment requirement is th= at +# of int64_t and/or double. (On most platforms those are the same, but n= ot +# everywhere.) Note that we intentionally do not consider any types wide= r +# than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be too much +# of a penalty for disk and memory space. = -MAX_ALIGNOF=3D$ac_cv_alignof_double - -if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then - as_fn_error $? "alignment of 'long' is greater than the alignment of 'd= ouble'" "$LINENO" 5 -fi -if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then - as_fn_error $? "alignment of 'int64_t' is greater than the alignment of= 'double'" "$LINENO" 5 +if test $ac_cv_alignof_int64_t -gt $ac_cv_alignof_double ; then + MAX_ALIGNOF=3D$ac_cv_alignof_int64_t +else + MAX_ALIGNOF=3D$ac_cv_alignof_double fi = cat >>confdefs.h <<_ACEOF diff --git a/configure.ac b/configure.ac index 814e64a967e..a5eab2e5fff 100644 --- a/configure.ac +++ b/configure.ac @@ -2031,33 +2031,21 @@ AC_CHECK_SIZEOF([intmax_t]) = AC_CHECK_ALIGNOF(short) AC_CHECK_ALIGNOF(int) -AC_CHECK_ALIGNOF(long) AC_CHECK_ALIGNOF(int64_t) AC_CHECK_ALIGNOF(double) = # Compute maximum alignment of any basic type. # -# We require 'double' to have the strictest alignment among the basic typ= es, -# because otherwise the C ABI might impose 8-byte alignment on some of th= e -# other C types that correspond to TYPALIGN_DOUBLE SQL types. That could -# cause a mismatch between the tuple layout and the C struct layout of a -# catalog tuple. We used to carefully order catalog columns such that an= y -# fixed-width, attalign=3D4 columns were at offsets divisible by 8 regard= less -# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platform= s -# where TYPALIGN_DOUBLE !=3D MAXIMUM_ALIGNOF. -# -# We assume without checking that long's alignment is at least as strong = as -# char, short, or int. Note that we intentionally do not consider any ty= pes -# wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be to= o -# much of a penalty for disk and memory space. - -MAX_ALIGNOF=3D$ac_cv_alignof_double +# We assume without checking that the maximum alignment requirement is th= at +# of int64_t and/or double. (On most platforms those are the same, but n= ot +# everywhere.) Note that we intentionally do not consider any types wide= r +# than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be too much +# of a penalty for disk and memory space. = -if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then - AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'dou= ble']) -fi -if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then - AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of '= double']) +if test $ac_cv_alignof_int64_t -gt $ac_cv_alignof_double ; then + MAX_ALIGNOF=3D$ac_cv_alignof_int64_t +else + MAX_ALIGNOF=3D$ac_cv_alignof_double fi AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum = alignment requirement of any C data type.]) = diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 332193565e2..12608d00a18 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -9567,7 +9567,13 @@ SCRAM-SHA-256$<iteration count><= /replaceable>:&l i =3D int alignment (4 byt= es on most machines). - d =3D double alignment (8 = bytes on many machines, but by no means all). + l =3D int64 alignment (8 b= ytes on most machines, but by no means all). + + + d =3D double alignment (8 = bytes on most machines, but by no means all). + + + m =3D maximum alignment (8 bytes on mos= t machines). diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_t= ype.sgml index 994dfc65268..006db624094 100644 --- a/doc/src/sgml/ref/create_type.sgml +++ b/doc/src/sgml/ref/create_type.sgml @@ -748,8 +748,15 @@ CREATE TYPE name The storage alignment requirement of the data type. If specified, it must be char, int2, - int4, or double; the + int4, int8, + double, or max; the default is int4. + int8 and double usually + have the same behavior, but there are platforms on which they are + different because integer and floating-point values have different + requirements. max means the maximum alignment + requirement for any of these types; it is often used for container + types such as records. diff --git a/meson.build b/meson.build index df907b62da3..bb17859fee4 100644 --- a/meson.build +++ b/meson.build @@ -1798,32 +1798,27 @@ endif = # Determine memory alignment requirements for the basic C data types. = -alignof_types =3D ['short', 'int', 'long', 'double'] +alignof_types =3D ['short', 'int', 'int64_t', 'double'] foreach t : alignof_types - align =3D cc.alignment(t, args: test_c_args) + align =3D cc.alignment(t, args: test_c_args, prefix: '#include ') cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align) endforeach = # Compute maximum alignment of any basic type. # -# We require 'double' to have the strictest alignment among the basic typ= es, -# because otherwise the C ABI might impose 8-byte alignment on some of th= e -# other C types that correspond to TYPALIGN_DOUBLE SQL types. That could -# cause a mismatch between the tuple layout and the C struct layout of a -# catalog tuple. We used to carefully order catalog columns such that an= y -# fixed-width, attalign=3D4 columns were at offsets divisible by 8 regard= less -# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platform= s -# where TYPALIGN_DOUBLE !=3D MAXIMUM_ALIGNOF. -# -# We assume without checking that int64_t's alignment is at least as stro= ng -# as long, char, short, or int. Note that we intentionally do not consid= er -# any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 -# would be too much of a penalty for disk and memory space. +# We assume without checking that the maximum alignment requirement is th= at +# of int64_t and/or double. (On most platforms those are the same, but n= ot +# everywhere.) Note that we intentionally do not consider any types wide= r +# than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be too much +# of a penalty for disk and memory space. + +alignof_int64_t =3D cdata.get('ALIGNOF_INT64_T') alignof_double =3D cdata.get('ALIGNOF_DOUBLE') -if cc.alignment('int64_t', args: test_c_args, prefix: '#include ') > alignof_double - error('alignment of int64_t is greater than the alignment of double') +if alignof_int64_t > alignof_double + cdata.set('MAXIMUM_ALIGNOF', alignof_int64_t) +else + cdata.set('MAXIMUM_ALIGNOF', alignof_double) endif -cdata.set('MAXIMUM_ALIGNOF', alignof_double) = cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args)) cdata.set('SIZEOF_LONG_LONG', cc.sizeof('long long', args: test_c_args)) diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/comm= on/tupdesc.c index 94b4f1f9975..49e5cd6c117 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -94,9 +94,15 @@ populate_compact_attribute_internal(Form_pg_attribute s= rc, case TYPALIGN_CHAR: dst->attalignby =3D sizeof(char); break; + case TYPALIGN_INT64: + dst->attalignby =3D ALIGNOF_INT64_T; + break; case TYPALIGN_DOUBLE: dst->attalignby =3D ALIGNOF_DOUBLE; break; + case TYPALIGN_MAX: + dst->attalignby =3D MAXIMUM_ALIGNOF; + break; case TYPALIGN_SHORT: dst->attalignby =3D ALIGNOF_SHORT; break; @@ -994,7 +1000,7 @@ TupleDescInitBuiltinEntry(TupleDesc desc, case INT8OID: att->attlen =3D 8; att->attbyval =3D true; - att->attalign =3D TYPALIGN_DOUBLE; + att->attalign =3D TYPALIGN_INT64; att->attstorage =3D TYPSTORAGE_PLAIN; att->attcompression =3D InvalidCompressionMethod; att->attcollation =3D InvalidOid; diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/boo= tstrap.c index dd57624b4f9..7a3a13a6ec7 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -115,7 +115,7 @@ static const struct typinfo TypInfo[] =3D { F_TEXTIN, F_TEXTOUT}, {"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid, F_OIDIN, F_OIDOUT}, - {"oid8", OID8OID, 0, 8, true, TYPALIGN_DOUBLE, TYPSTORAGE_PLAIN, Invalid= Oid, + {"oid8", OID8OID, 0, 8, true, TYPALIGN_INT64, TYPSTORAGE_PLAIN, InvalidO= id, F_OID8IN, F_OID8OUT}, {"tid", TIDOID, 0, 6, false, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOi= d, F_TIDIN, F_TIDOUT}, @@ -137,7 +137,7 @@ static const struct typinfo TypInfo[] =3D { F_ARRAY_IN, F_ARRAY_OUT}, {"_char", 1002, CHAROID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, I= nvalidOid, F_ARRAY_IN, F_ARRAY_OUT}, - {"_aclitem", 1034, ACLITEMOID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTEN= DED, InvalidOid, + {"_aclitem", 1034, ACLITEMOID, -1, false, TYPALIGN_INT64, TYPSTORAGE_EXT= ENDED, InvalidOid, F_ARRAY_IN, F_ARRAY_OUT} }; = diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.= pm index 219af5884d9..20884f45bd8 100644 --- a/src/backend/catalog/Catalog.pm +++ b/src/backend/catalog/Catalog.pm @@ -464,9 +464,13 @@ sub GenerateArrayTypes $array_type{typname} =3D '_' . $elem_type->{typname}; $array_type{typelem} =3D $elem_type->{typname}; = - # Arrays require INT alignment, unless the element type requires - # DOUBLE alignment. - $array_type{typalign} =3D $elem_type->{typalign} eq 'd' ? 'd' : 'i'; + # Arrays require INT alignment, unless the element type requires more. + $array_type{typalign} =3D + $elem_type->{typalign} eq 'l' ? 'l' + : ( + $elem_type->{typalign} eq 'd' ? 'd' + : ( $elem_type->{typalign} eq 'm' ? 'm' + : 'i')); = # Fill in the rest of the array entry's fields. foreach my $column (@$pgtype_schema) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 606434823cf..27cc09a7680 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -1075,7 +1075,7 @@ AddNewRelationType(const char *typeName, NULL, /* default value - none */ NULL, /* default binary representation */ false, /* passed by reference */ - TYPALIGN_DOUBLE, /* alignment - must be the largest! */ + TYPALIGN_MAX, /* alignment - must be the largest! */ TYPSTORAGE_EXTENDED, /* fully TOASTable */ -1, /* typmod */ 0, /* array dimensions for typBaseType */ @@ -1399,7 +1399,7 @@ heap_create_with_catalog(const char *relname, NULL, /* default value - none */ NULL, /* default binary representation */ false, /* passed by reference */ - TYPALIGN_DOUBLE, /* alignment - must be the largest! */ + TYPALIGN_MAX, /* alignment - must be the largest! */ TYPSTORAGE_EXTENDED, /* fully TOASTable */ -1, /* typmod */ 0, /* array dimensions for typBaseType */ diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index fc369c35aa6..f079fa32b40 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -287,7 +287,9 @@ TypeCreate(Oid newTypeOid, } else if (internalSize =3D=3D (int16) sizeof(int64)) { - if (alignment !=3D TYPALIGN_DOUBLE) + /* We have to trust the user to get this distinction right ... */ + if (!(alignment =3D=3D TYPALIGN_INT64 || + alignment =3D=3D TYPALIGN_DOUBLE)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("alignment \"%c\" is invalid for passed-by-value type of si= ze %d", @@ -303,7 +305,10 @@ TypeCreate(Oid newTypeOid, { /* varlena types must have int align or better */ if (internalSize =3D=3D -1 && - !(alignment =3D=3D TYPALIGN_INT || alignment =3D=3D TYPALIGN_DOUBLE)) + !(alignment =3D=3D TYPALIGN_INT || + alignment =3D=3D TYPALIGN_INT64 || + alignment =3D=3D TYPALIGN_DOUBLE || + alignment =3D=3D TYPALIGN_MAX)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("alignment \"%c\" is invalid for variable-length type", diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecm= ds.c index 288edb25f2f..2f919f764aa 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -117,6 +117,7 @@ static void makeMultirangeConstructors(const char *nam= e, Oid namespace, Oid multirangeOid, Oid rangeOid, Oid rangeArrayOid, Oid *mltrngConstruct0_p, Oid *mltrngConstruct1_p, Oid *mltrng= Construct2_p); +static char containerAlignment(char elemalign); static Oid findTypeInputFunction(List *procname, Oid typeOid); static Oid findTypeOutputFunction(List *procname, Oid typeOid); static Oid findTypeReceiveFunction(List *procname, Oid typeOid); @@ -424,6 +425,9 @@ DefineType(ParseState *pstate, List *names, List *para= meters) pg_strcasecmp(a, "float8") =3D=3D 0 || pg_strcasecmp(a, "pg_catalog.float8") =3D=3D 0) alignment =3D TYPALIGN_DOUBLE; + else if (pg_strcasecmp(a, "int8") =3D=3D 0 || + pg_strcasecmp(a, "pg_catalog.int8") =3D=3D 0) + alignment =3D TYPALIGN_INT64; else if (pg_strcasecmp(a, "int4") =3D=3D 0 || pg_strcasecmp(a, "pg_catalog.int4") =3D=3D 0) alignment =3D TYPALIGN_INT; @@ -433,6 +437,9 @@ DefineType(ParseState *pstate, List *names, List *para= meters) else if (pg_strcasecmp(a, "char") =3D=3D 0 || pg_strcasecmp(a, "pg_catalog.bpchar") =3D=3D 0) alignment =3D TYPALIGN_CHAR; + else if (pg_strcasecmp(a, "max") =3D=3D 0 || + pg_strcasecmp(a, "pg_catalog.max") =3D=3D 0) + alignment =3D TYPALIGN_MAX; else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -611,8 +618,8 @@ DefineType(ParseState *pstate, List *names, List *para= meters) */ array_type =3D makeArrayTypeName(typeName, typeNamespace); = - /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */ - alignment =3D (alignment =3D=3D TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYP= ALIGN_INT; + /* alignment must be TYPALIGN_INT or more for arrays */ + alignment =3D containerAlignment(alignment); = TypeCreate(array_oid, /* force assignment of this type OID */ array_type, /* type name */ @@ -1095,8 +1102,8 @@ DefineDomain(ParseState *pstate, CreateDomainStmt *s= tmt) */ domainArrayName =3D makeArrayTypeName(domainName, domainNamespace); = - /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */ - alignment =3D (alignment =3D=3D TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYP= ALIGN_INT; + /* alignment must be TYPALIGN_INT or more for arrays */ + alignment =3D containerAlignment(alignment); = TypeCreate(domainArrayOid, /* force assignment of this type OID */ domainArrayName, /* type name */ @@ -1557,8 +1564,8 @@ DefineRange(ParseState *pstate, CreateRangeStmt *stm= t) get_typlenbyvalalign(rangeSubtype, &subtyplen, &subtypbyval, &subtypalign); = - /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for ranges */ - alignment =3D (subtypalign =3D=3D TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : T= YPALIGN_INT; + /* alignment must be TYPALIGN_INT or more for ranges */ + alignment =3D containerAlignment(subtypalign); = /* Allocate OID for array type, its multirange, and its multirange array= */ rangeArrayOid =3D AssignTypeArrayOid(); @@ -2005,6 +2012,25 @@ makeMultirangeConstructors(const char *name, Oid na= mespace, pfree(parameterModes); } = +/* + * Compute the appropriate typalign for a container (array or range) + * given the typalign of its members. The container type requires at + * least int alignment, but more if the members need more. + */ +static char +containerAlignment(char elemalign) +{ + switch (elemalign) + { + case TYPALIGN_INT64: + case TYPALIGN_DOUBLE: + case TYPALIGN_MAX: + return elemalign; + default: + return TYPALIGN_INT; + } +} + /* * Find suitable I/O and other support functions for a type. * diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_= typanalyze.c index 0c513d694e7..48ee050e37f 100644 --- a/src/backend/tsearch/ts_typanalyze.c +++ b/src/backend/tsearch/ts_typanalyze.c @@ -444,7 +444,7 @@ compute_tsvector_stats(VacAttrStats *stats, stats->statypid[0] =3D TEXTOID; stats->statyplen[0] =3D -1; /* typlen, -1 for varlena */ stats->statypbyval[0] =3D false; - stats->statypalign[0] =3D 'i'; + stats->statypalign[0] =3D TYPALIGN_INT; } } else diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/ar= rayfuncs.c index e71d32773b5..0d185f5be8a 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -3426,7 +3426,7 @@ construct_array_builtin(Datum *elems, int nelems, Oi= d elmtype) case INT8OID: elmlen =3D sizeof(int64); elmbyval =3D true; - elmalign =3D TYPALIGN_DOUBLE; + elmalign =3D TYPALIGN_INT64; break; = case NAMEOID: diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/ad= t/orderedsetaggs.c index 3b6da8e36ac..27b8cfa7064 100644 --- a/src/backend/utils/adt/orderedsetaggs.c +++ b/src/backend/utils/adt/orderedsetaggs.c @@ -1021,7 +1021,7 @@ percentile_cont_interval_multi_final(PG_FUNCTION_ARG= S) return percentile_cont_multi_final_common(fcinfo, INTERVALOID, /* hard-wired info on type interval */ - 16, false, TYPALIGN_DOUBLE, + 16, false, TYPALIGN_INT64, interval_lerp); } = diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/u= tils/adt/rangetypes_typanalyze.c index 38d12dedbc5..278d4e6941a 100644 --- a/src/backend/utils/adt/rangetypes_typanalyze.c +++ b/src/backend/utils/adt/rangetypes_typanalyze.c @@ -398,7 +398,7 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFe= tchFunc fetchfunc, stats->statypid[slot_idx] =3D FLOAT8OID; stats->statyplen[slot_idx] =3D sizeof(float8); stats->statypbyval[slot_idx] =3D true; - stats->statypalign[slot_idx] =3D 'd'; + stats->statypalign[slot_idx] =3D TYPALIGN_DOUBLE; = /* Store the fraction of empty ranges */ emptyfrac =3D palloc_object(float4); diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a3980e5535f..e550e9cf0a3 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1580,7 +1580,7 @@ bootstrap_template1(void) bki_lines =3D replace_token(bki_lines, "SIZEOF_POINTER", buf); = bki_lines =3D replace_token(bki_lines, "ALIGNOF_POINTER", - (sizeof(Pointer) =3D=3D 4) ? "i" : "d"); + (sizeof(Pointer) =3D=3D 4) ? "i" : "l"); = bki_lines =3D replace_token(bki_lines, "POSTGRES", escape_quotes_bki(username)); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 078ee8500ad..b94121ceb32 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12652,8 +12652,12 @@ dumpBaseType(Archive *fout, const TypeInfo *tyinf= o) appendPQExpBufferStr(q, ",\n ALIGNMENT =3D int2"); else if (*typalign =3D=3D TYPALIGN_INT) appendPQExpBufferStr(q, ",\n ALIGNMENT =3D int4"); + else if (*typalign =3D=3D TYPALIGN_INT64) + appendPQExpBufferStr(q, ",\n ALIGNMENT =3D int8"); else if (*typalign =3D=3D TYPALIGN_DOUBLE) appendPQExpBufferStr(q, ",\n ALIGNMENT =3D double"); + else if (*typalign =3D=3D TYPALIGN_MAX) + appendPQExpBufferStr(q, ",\n ALIGNMENT =3D max"); = if (*typstorage =3D=3D TYPSTORAGE_PLAIN) appendPQExpBufferStr(q, ",\n STORAGE =3D plain"); diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h index 3e5530658c9..c5462d6fba1 100644 --- a/src/include/access/tupmacs.h +++ b/src/include/access/tupmacs.h @@ -146,11 +146,13 @@ fetch_att(const void *T, bool attbyval, int attlen) ( \ ((attalign) =3D=3D TYPALIGN_INT) ? INTALIGN(cur_offset) : \ (((attalign) =3D=3D TYPALIGN_CHAR) ? (uintptr_t) (cur_offset) : \ - (((attalign) =3D=3D TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \ - ( \ - AssertMacro((attalign) =3D=3D TYPALIGN_SHORT), \ - SHORTALIGN(cur_offset) \ - ))) \ + (((attalign) =3D=3D TYPALIGN_INT64) ? INT64ALIGN(cur_offset) : \ + (((attalign) =3D=3D TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \ + (((attalign) =3D=3D TYPALIGN_MAX) ? MAXALIGN(cur_offset) : \ + ( \ + AssertMacro((attalign) =3D=3D TYPALIGN_SHORT), \ + SHORTALIGN(cur_offset) \ + ))))) \ ) = /* diff --git a/src/include/c.h b/src/include/c.h index 48e4087c09c..f802633bde4 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -821,7 +821,7 @@ typedef NameData *Name; = #define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN)) #define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN)) -#define LONGALIGN(LEN) TYPEALIGN(ALIGNOF_LONG, (LEN)) +#define INT64ALIGN(LEN) TYPEALIGN(ALIGNOF_INT64_T, (LEN)) #define DOUBLEALIGN(LEN) TYPEALIGN(ALIGNOF_DOUBLE, (LEN)) #define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN)) /* MAXALIGN covers only built-in types, not buffers */ @@ -833,7 +833,7 @@ typedef NameData *Name; = #define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN)) #define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN)) -#define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN)) +#define INT64ALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT64_T, (LEN)) #define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN)) #define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN)) #define BUFFERALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_BUFFER, (LEN)) diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type= .dat index a1a753d1797..d511493f761 100644 --- a/src/include/catalog/pg_type.dat +++ b/src/include/catalog/pg_type.dat @@ -56,7 +56,7 @@ descr =3D> '~18 digit integer, 8-byte storage', typname =3D> 'int8', typlen =3D> '8', typbyval =3D> 't', typcategory =3D> 'N', typinput =3D> 'int8in', typoutput =3D> 'int8out', - typreceive =3D> 'int8recv', typsend =3D> 'int8send', typalign =3D> 'd' = }, + typreceive =3D> 'int8recv', typsend =3D> 'int8send', typalign =3D> 'l' = }, { oid =3D> '21', array_type_oid =3D> '1005', descr =3D> '-32 thousand to 32 thousand, 2-byte storage', typname =3D> 'int2', typlen =3D> '2', typbyval =3D> 't', typcategory =3D= > 'N', @@ -116,22 +116,22 @@ typname =3D> 'pg_type', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D= > 'c', typcategory =3D> 'C', typrelid =3D> 'pg_type', typinput =3D> 'record_in= ', typoutput =3D> 'record_out', typreceive =3D> 'record_recv', - typsend =3D> 'record_send', typalign =3D> 'd', typstorage =3D> 'x' }, + typsend =3D> 'record_send', typalign =3D> 'm', typstorage =3D> 'x' }, { oid =3D> '75', array_type_oid =3D> '270', typname =3D> 'pg_attribute', typlen =3D> '-1', typbyval =3D> 'f', typty= pe =3D> 'c', typcategory =3D> 'C', typrelid =3D> 'pg_attribute', typinput =3D> 'reco= rd_in', typoutput =3D> 'record_out', typreceive =3D> 'record_recv', - typsend =3D> 'record_send', typalign =3D> 'd', typstorage =3D> 'x' }, + typsend =3D> 'record_send', typalign =3D> 'm', typstorage =3D> 'x' }, { oid =3D> '81', array_type_oid =3D> '272', typname =3D> 'pg_proc', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D= > 'c', typcategory =3D> 'C', typrelid =3D> 'pg_proc', typinput =3D> 'record_in= ', typoutput =3D> 'record_out', typreceive =3D> 'record_recv', - typsend =3D> 'record_send', typalign =3D> 'd', typstorage =3D> 'x' }, + typsend =3D> 'record_send', typalign =3D> 'm', typstorage =3D> 'x' }, { oid =3D> '83', array_type_oid =3D> '273', typname =3D> 'pg_class', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D= > 'c', typcategory =3D> 'C', typrelid =3D> 'pg_class', typinput =3D> 'record_i= n', typoutput =3D> 'record_out', typreceive =3D> 'record_recv', - typsend =3D> 'record_send', typalign =3D> 'd', typstorage =3D> 'x' }, + typsend =3D> 'record_send', typalign =3D> 'm', typstorage =3D> 'x' }, = # OIDS 100 - 199 = @@ -174,7 +174,7 @@ { oid =3D> '5069', array_type_oid =3D> '271', descr =3D> 'full transactio= n id', typname =3D> 'xid8', typlen =3D> '8', typbyval =3D> 't', typcategory =3D> 'U', typinput =3D> 'xid8in', typoutput =3D> 'xid8out', - typreceive =3D> 'xid8recv', typsend =3D> 'xid8send', typalign =3D> 'd' = }, + typreceive =3D> 'xid8recv', typsend =3D> 'xid8send', typalign =3D> 'l' = }, = # OIDS 600 - 699 = @@ -239,7 +239,7 @@ descr =3D> 'monetary amounts, $d,ddd.cc', typname =3D> 'money', typlen =3D> '8', typbyval =3D> 't', typcategory =3D> 'N', typinput =3D> 'cash_in', typoutput =3D> 'cash_out= ', - typreceive =3D> 'cash_recv', typsend =3D> 'cash_send', typalign =3D> 'd= ' }, + typreceive =3D> 'cash_recv', typsend =3D> 'cash_send', typalign =3D> 'l= ' }, = # OIDS 800 - 899 = @@ -270,7 +270,7 @@ { oid =3D> '1033', array_type_oid =3D> '1034', descr =3D> 'access control= list', typname =3D> 'aclitem', typlen =3D> '16', typbyval =3D> 'f', typcategor= y =3D> 'U', typinput =3D> 'aclitemin', typoutput =3D> 'aclitemout', typreceive =3D>= '-', - typsend =3D> '-', typalign =3D> 'd' }, + typsend =3D> '-', typalign =3D> 'l' }, { oid =3D> '1042', array_type_oid =3D> '1014', descr =3D> '\'char(length)\' blank-padded string, fixed storage length'= , typname =3D> 'bpchar', typlen =3D> '-1', typbyval =3D> 'f', typcategory= =3D> 'S', @@ -293,7 +293,7 @@ typname =3D> 'time', typlen =3D> '8', typbyval =3D> 't', typcategory =3D> 'D', typinput =3D> 'time_in', typoutput =3D> 'time_out= ', typreceive =3D> 'time_recv', typsend =3D> 'time_send', typmodin =3D> 't= imetypmodin', - typmodout =3D> 'timetypmodout', typalign =3D> 'd' }, + typmodout =3D> 'timetypmodout', typalign =3D> 'l' }, = # OIDS 1100 - 1199 = @@ -302,21 +302,21 @@ typcategory =3D> 'D', typinput =3D> 'timestamp_in', typoutput =3D> 'tim= estamp_out', typreceive =3D> 'timestamp_recv', typsend =3D> 'timestamp_send', typmodin =3D> 'timestamptypmodin', typmodout =3D> 'timestamptypmodout', - typalign =3D> 'd' }, + typalign =3D> 'l' }, { oid =3D> '1184', array_type_oid =3D> '1185', descr =3D> 'date and time with time zone', typname =3D> 'timestamptz', typlen =3D> '8', typbyval =3D> 't', typcategory =3D> 'D', typispreferred =3D> 't', typinput =3D> 'timestamp= tz_in', typoutput =3D> 'timestamptz_out', typreceive =3D> 'timestamptz_recv', typsend =3D> 'timestamptz_send', typmodin =3D> 'timestamptztypmodin', - typmodout =3D> 'timestamptztypmodout', typalign =3D> 'd' }, + typmodout =3D> 'timestamptztypmodout', typalign =3D> 'l' }, { oid =3D> '1186', array_type_oid =3D> '1187', descr =3D> 'time interval, format \'number units ...\'', typname =3D> 'interval', typlen =3D> '16', typbyval =3D> 'f', typcatego= ry =3D> 'T', typispreferred =3D> 't', typinput =3D> 'interval_in', typoutput =3D> 'i= nterval_out', typreceive =3D> 'interval_recv', typsend =3D> 'interval_send', typmodin =3D> 'intervaltypmodin', typmodout =3D> 'intervaltypmodout', - typalign =3D> 'd' }, + typalign =3D> 'l' }, = # OIDS 1200 - 1299 = @@ -326,7 +326,7 @@ typinput =3D> 'timetz_in', typoutput =3D> 'timetz_out', typreceive =3D> 'timetz_recv', typsend =3D> 'timetz_send', typmodin =3D> 'timetztypmodin', typmodout =3D> 'timetztypmodout', - typalign =3D> 'd' }, + typalign =3D> 'l' }, = # OIDS 1500 - 1599 = @@ -415,7 +415,7 @@ { oid =3D> '3220', array_type_oid =3D> '3221', descr =3D> 'PostgreSQL LSN= ', typname =3D> 'pg_lsn', typlen =3D> '8', typbyval =3D> 't', typcategory =3D> 'U', typinput =3D> 'pg_lsn_in', typoutput =3D> 'pg_lsn= _out', - typreceive =3D> 'pg_lsn_recv', typsend =3D> 'pg_lsn_send', typalign =3D= > 'd' }, + typreceive =3D> 'pg_lsn_recv', typsend =3D> 'pg_lsn_send', typalign =3D= > 'l' }, = # text search { oid =3D> '3614', array_type_oid =3D> '3643', @@ -462,12 +462,12 @@ typname =3D> 'txid_snapshot', typlen =3D> '-1', typbyval =3D> 'f', typcategory =3D> 'U', typinput =3D> 'txid_snapshot_in', typoutput =3D> 'txid_snapshot_out', typreceive =3D> 'txid_snapshot_recv= ', - typsend =3D> 'txid_snapshot_send', typalign =3D> 'd', typstorage =3D> '= x' }, + typsend =3D> 'txid_snapshot_send', typalign =3D> 'l', typstorage =3D> '= x' }, { oid =3D> '5038', array_type_oid =3D> '5039', descr =3D> 'transaction sn= apshot', typname =3D> 'pg_snapshot', typlen =3D> '-1', typbyval =3D> 'f', typcat= egory =3D> 'U', typinput =3D> 'pg_snapshot_in', typoutput =3D> 'pg_snapshot_out', typreceive =3D> 'pg_snapshot_recv', typsend =3D> 'pg_snapshot_send', - typalign =3D> 'd', typstorage =3D> 'x' }, + typalign =3D> 'l', typstorage =3D> 'x' }, = # range types { oid =3D> '3904', array_type_oid =3D> '3905', descr =3D> 'range of integ= ers', @@ -485,13 +485,13 @@ typname =3D> 'tsrange', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D= > 'r', typcategory =3D> 'R', typinput =3D> 'range_in', typoutput =3D> 'range_o= ut', typreceive =3D> 'range_recv', typsend =3D> 'range_send', - typanalyze =3D> 'range_typanalyze', typalign =3D> 'd', typstorage =3D> = 'x' }, + typanalyze =3D> 'range_typanalyze', typalign =3D> 'l', typstorage =3D> = 'x' }, { oid =3D> '3910', array_type_oid =3D> '3911', descr =3D> 'range of timestamps with time zone', typname =3D> 'tstzrange', typlen =3D> '-1', typbyval =3D> 'f', typtype = =3D> 'r', typcategory =3D> 'R', typinput =3D> 'range_in', typoutput =3D> 'range_o= ut', typreceive =3D> 'range_recv', typsend =3D> 'range_send', - typanalyze =3D> 'range_typanalyze', typalign =3D> 'd', typstorage =3D> = 'x' }, + typanalyze =3D> 'range_typanalyze', typalign =3D> 'l', typstorage =3D> = 'x' }, { oid =3D> '3912', array_type_oid =3D> '3913', descr =3D> 'range of dates= ', typname =3D> 'daterange', typlen =3D> '-1', typbyval =3D> 'f', typtype = =3D> 'r', typcategory =3D> 'R', typinput =3D> 'range_in', typoutput =3D> 'range_o= ut', @@ -501,7 +501,7 @@ typname =3D> 'int8range', typlen =3D> '-1', typbyval =3D> 'f', typtype = =3D> 'r', typcategory =3D> 'R', typinput =3D> 'range_in', typoutput =3D> 'range_o= ut', typreceive =3D> 'range_recv', typsend =3D> 'range_send', - typanalyze =3D> 'range_typanalyze', typalign =3D> 'd', typstorage =3D> = 'x' }, + typanalyze =3D> 'range_typanalyze', typalign =3D> 'l', typstorage =3D> = 'x' }, = # multirange types { oid =3D> '4451', array_type_oid =3D> '6150', descr =3D> 'multirange of = integers', @@ -522,14 +522,14 @@ typcategory =3D> 'R', typinput =3D> 'multirange_in', typoutput =3D> 'multirange_out', typreceive =3D> 'multirange_recv', typsend =3D> 'multirange_send', typanalyze =3D> 'multirange_typanalyze'= , - typalign =3D> 'd', typstorage =3D> 'x' }, + typalign =3D> 'l', typstorage =3D> 'x' }, { oid =3D> '4534', array_type_oid =3D> '6153', descr =3D> 'multirange of timestamps with time zone', typname =3D> 'tstzmultirange', typlen =3D> '-1', typbyval =3D> 'f', typ= type =3D> 'm', typcategory =3D> 'R', typinput =3D> 'multirange_in', typoutput =3D> 'multirange_out', typreceive =3D> 'multirange_recv', typsend =3D> 'multirange_send', typanalyze =3D> 'multirange_typanalyze'= , - typalign =3D> 'd', typstorage =3D> 'x' }, + typalign =3D> 'l', typstorage =3D> 'x' }, { oid =3D> '4535', array_type_oid =3D> '6155', descr =3D> 'multirange of = dates', typname =3D> 'datemultirange', typlen =3D> '-1', typbyval =3D> 'f', typ= type =3D> 'm', typcategory =3D> 'R', typinput =3D> 'multirange_in', @@ -541,7 +541,7 @@ typcategory =3D> 'R', typinput =3D> 'multirange_in', typoutput =3D> 'multirange_out', typreceive =3D> 'multirange_recv', typsend =3D> 'multirange_send', typanalyze =3D> 'multirange_typanalyze'= , - typalign =3D> 'd', typstorage =3D> 'x' }, + typalign =3D> 'l', typstorage =3D> 'x' }, = # pseudo-types # types with typtype=3D'p' represent various special cases in the type sy= stem. @@ -556,14 +556,14 @@ typname =3D> 'record', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D= > 'p', typcategory =3D> 'P', typarray =3D> '_record', typinput =3D> 'record_in= ', typoutput =3D> 'record_out', typreceive =3D> 'record_recv', - typsend =3D> 'record_send', typalign =3D> 'd', typstorage =3D> 'x' }, + typsend =3D> 'record_send', typalign =3D> 'm', typstorage =3D> 'x' }, # Arrays of records have typcategory P, so they can't be autogenerated. { oid =3D> '2287', typname =3D> '_record', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D= > 'p', typcategory =3D> 'P', typsubscript =3D> 'array_subscript_handler', typelem =3D> 'record', typinput =3D> 'array_in', typoutput =3D> 'array_= out', typreceive =3D> 'array_recv', typsend =3D> 'array_send', - typanalyze =3D> 'array_typanalyze', typalign =3D> 'd', typstorage =3D> = 'x' }, + typanalyze =3D> 'array_typanalyze', typalign =3D> 'm', typstorage =3D> = 'x' }, { oid =3D> '2275', array_type_oid =3D> '1263', descr =3D> 'C-style string= ', typname =3D> 'cstring', typlen =3D> '-2', typbyval =3D> 'f', typtype =3D= > 'p', typcategory =3D> 'P', typinput =3D> 'cstring_in', typoutput =3D> 'cstri= ng_out', @@ -575,7 +575,7 @@ { oid =3D> '2277', descr =3D> 'pseudo-type representing a polymorphic arr= ay type', typname =3D> 'anyarray', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D= > 'p', typcategory =3D> 'P', typinput =3D> 'anyarray_in', typoutput =3D> 'anya= rray_out', - typreceive =3D> 'anyarray_recv', typsend =3D> 'anyarray_send', typalign= =3D> 'd', + typreceive =3D> 'anyarray_recv', typsend =3D> 'anyarray_send', typalign= =3D> 'm', typstorage =3D> 'x' }, { oid =3D> '2278', descr =3D> 'pseudo-type for the result of a function with no real resul= t', @@ -648,7 +648,7 @@ descr =3D> 'pseudo-type representing a range over a polymorphic base ty= pe', typname =3D> 'anyrange', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D= > 'p', typcategory =3D> 'P', typinput =3D> 'anyrange_in', typoutput =3D> 'anyr= ange_out', - typreceive =3D> '-', typsend =3D> '-', typalign =3D> 'd', typstorage =3D= > 'x' }, + typreceive =3D> '-', typsend =3D> '-', typalign =3D> 'm', typstorage =3D= > 'x' }, { oid =3D> '5077', descr =3D> 'pseudo-type representing a polymorphic common type', typname =3D> 'anycompatible', typlen =3D> '4', typbyval =3D> 't', typty= pe =3D> 'p', @@ -661,7 +661,7 @@ typtype =3D> 'p', typcategory =3D> 'P', typinput =3D> 'anycompatiblearr= ay_in', typoutput =3D> 'anycompatiblearray_out', typreceive =3D> 'anycompatiblearray_recv', typsend =3D> 'anycompatiblea= rray_send', - typalign =3D> 'd', typstorage =3D> 'x' }, + typalign =3D> 'm', typstorage =3D> 'x' }, { oid =3D> '5079', descr =3D> 'pseudo-type representing a polymorphic common type that is = not an array', typname =3D> 'anycompatiblenonarray', typlen =3D> '4', typbyval =3D> 't= ', @@ -673,19 +673,19 @@ typname =3D> 'anycompatiblerange', typlen =3D> '-1', typbyval =3D> 'f', typtype =3D> 'p', typcategory =3D> 'P', typinput =3D> 'anycompatibleran= ge_in', typoutput =3D> 'anycompatiblerange_out', typreceive =3D> '-', typsend =3D= > '-', - typalign =3D> 'd', typstorage =3D> 'x' }, + typalign =3D> 'm', typstorage =3D> 'x' }, { oid =3D> '4537', descr =3D> 'pseudo-type representing a polymorphic base type that is a = multirange', typname =3D> 'anymultirange', typlen =3D> '-1', typbyval =3D> 'f', typt= ype =3D> 'p', typcategory =3D> 'P', typinput =3D> 'anymultirange_in', typoutput =3D> 'anymultirange_out', typreceive =3D> '-', typsend =3D> '= -', - typalign =3D> 'd', typstorage =3D> 'x' }, + typalign =3D> 'm', typstorage =3D> 'x' }, { oid =3D> '4538', descr =3D> 'pseudo-type representing a multirange over a polymorphic co= mmon type', typname =3D> 'anycompatiblemultirange', typlen =3D> '-1', typbyval =3D>= 'f', typtype =3D> 'p', typcategory =3D> 'P', typinput =3D> 'anycompatiblemul= tirange_in', typoutput =3D> 'anycompatiblemultirange_out', typreceive =3D> '-', typs= end =3D> '-', - typalign =3D> 'd', typstorage =3D> 'x' }, + typalign =3D> 'm', typstorage =3D> 'x' }, { oid =3D> '4600', descr =3D> 'pseudo-type representing BRIN bloom summar= y', typname =3D> 'pg_brin_bloom_summary', typlen =3D> '-1', typbyval =3D> '= f', typcategory =3D> 'Z', typinput =3D> 'brin_bloom_summary_in', @@ -704,5 +704,5 @@ descr =3D> 'object identifier(oid8), 8 bytes', typname =3D> 'oid8', typlen =3D> '8', typbyval =3D> 't', typcategory =3D= > 'N', typinput =3D> 'oid8in', typoutput =3D> 'oid8out', typreceive =3D> 'oid8= recv', - typsend =3D> 'oid8send', typalign =3D> 'd' }, + typsend =3D> 'oid8send', typalign =3D> 'l' }, ] diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 70d4a20c02b..b749a47d651 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -302,7 +302,9 @@ MAKE_SYSCACHE(TYPENAMENSP, pg_type_typname_nsp_index, = 64); #define TYPALIGN_CHAR 'c' /* char alignment (i.e. unaligned) */ #define TYPALIGN_SHORT 's' /* short alignment (typically 2 bytes) */ #define TYPALIGN_INT 'i' /* int alignment (typically 4 bytes) */ +#define TYPALIGN_INT64 'l' /* int64 alignment (often 8 bytes) */ #define TYPALIGN_DOUBLE 'd' /* double alignment (often 8 bytes) */ +#define TYPALIGN_MAX 'm' /* maximum alignment (usually 8 bytes) */ = #define TYPSTORAGE_PLAIN 'p' /* type not prepared for toasting */ #define TYPSTORAGE_EXTERNAL 'e' /* toastable, don't try to compress */ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 339268dc8ef..5699c033ade 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -12,9 +12,6 @@ /* The normal alignment of `int64_t', in bytes. */ #undef ALIGNOF_INT64_T = -/* The normal alignment of `long', in bytes. */ -#undef ALIGNOF_LONG - /* The normal alignment of `PG_INT128_TYPE', in bytes. */ #undef ALIGNOF_PG_INT128_TYPE = diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c index 1f69109b081..91e40327788 100644 --- a/src/pl/plpython/plpy_typeio.c +++ b/src/pl/plpython/plpy_typeio.c @@ -329,7 +329,7 @@ PLy_output_setup_func(PLyObToDatum *arg, MemoryContext= arg_mcxt, /* hard-wired knowledge about type RECORD: */ arg->typbyval =3D false; arg->typlen =3D -1; - arg->typalign =3D TYPALIGN_DOUBLE; + arg->typalign =3D TYPALIGN_MAX; } = /* @@ -452,7 +452,7 @@ PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext = arg_mcxt, /* hard-wired knowledge about type RECORD: */ arg->typbyval =3D false; arg->typlen =3D -1; - arg->typalign =3D TYPALIGN_DOUBLE; + arg->typalign =3D TYPALIGN_MAX; } = /* diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expec= ted/float8.out index 9c519f1a1a1..a688cbc3c83 100644 --- a/src/test/regress/expected/float8.out +++ b/src/test/regress/expected/float8.out @@ -1088,8 +1088,10 @@ LINE 1: ...8 (input =3D xfloat8in, output =3D xfloa= t8out, like =3D no_such_ty... create type xfloat8 (input =3D xfloat8in, output =3D xfloat8out, like =3D= float8); create cast (xfloat8 as float8) without function; create cast (float8 as xfloat8) without function; -create cast (xfloat8 as bigint) without function; -create cast (bigint as xfloat8) without function; +-- this hack depends on bigint and float8 having the same pass-by-value-n= ess: +create function bigint_xfloat8(bigint) returns xfloat8 immutable strict + language internal as 'int8up'; +create cast (bigint as xfloat8) with function bigint_xfloat8(bigint); -- float8: seeeeeee eeeeeeee eeeeeeee mmmmmmmm mmmmmmmm(x4) -- we don't care to assume the platform's strtod() handles subnormals -- correctly; those are "use at your own risk". However we do test @@ -1503,5 +1505,5 @@ DETAIL: drop cascades to function xfloat8in(cstring= ) drop cascades to function xfloat8out(xfloat8) drop cascades to cast from xfloat8 to double precision drop cascades to cast from double precision to xfloat8 -drop cascades to cast from xfloat8 to bigint +drop cascades to function bigint_xfloat8(bigint) drop cascades to cast from bigint to xfloat8 diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/= expected/type_sanity.out index 1d21d3eb446..936fa36a600 100644 --- a/src/test/regress/expected/type_sanity.out +++ b/src/test/regress/expected/type_sanity.out @@ -23,7 +23,7 @@ WHERE t1.typnamespace =3D 0 OR (t1.typlen <=3D 0 AND t1.typlen !=3D -1 AND t1.typlen !=3D -2) OR (t1.typtype not in ('b', 'c', 'd', 'e', 'm', 'p', 'r')) OR NOT t1.typisdefined OR - (t1.typalign not in ('c', 's', 'i', 'd')) OR + (t1.typalign not in ('c', 's', 'i', 'l', 'd', 'm')) OR (t1.typstorage not in ('p', 'x', 'e', 'm')); oid | typname = -----+--------- @@ -36,7 +36,7 @@ WHERE t1.typbyval AND (t1.typlen !=3D 1 OR t1.typalign !=3D 'c') AND (t1.typlen !=3D 2 OR t1.typalign !=3D 's') AND (t1.typlen !=3D 4 OR t1.typalign !=3D 'i') AND - (t1.typlen !=3D 8 OR t1.typalign !=3D 'd'); + (t1.typlen !=3D 8 OR (t1.typalign !=3D 'l' AND t1.typalign !=3D 'd'))= ; oid | typname = -----+--------- (0 rows) @@ -108,6 +108,8 @@ FROM pg_type as t1 LEFT JOIN pg_type as t2 ON rngsubtype =3D t2.oid WHERE t1.typtype =3D 'r' AND (t1.typalign !=3D (CASE WHEN t2.typalign =3D 'd' THEN 'd'::"char" + WHEN t2.typalign =3D 'l' THEN 'l'::"char" + WHEN t2.typalign =3D 'm' THEN 'm'::"char" ELSE 'i'::"char" END) OR t2.oid IS NULL); oid | typname | typalign | typname | typalign = @@ -423,6 +425,8 @@ SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2= .typalign FROM pg_type AS t1, pg_type AS t2 WHERE t1.typarray =3D t2.oid AND t2.typalign !=3D (CASE WHEN t1.typalign =3D 'd' THEN 'd'::"char" + WHEN t1.typalign =3D 'l' THEN 'l'::"char" + WHEN t1.typalign =3D 'm' THEN 'm'::"char" ELSE 'i'::"char" END); oid | typname | typalign | typname | typalign = -----+---------+----------+---------+---------- diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8= .sql index 0ef271f2702..c6b59a322ab 100644 --- a/src/test/regress/sql/float8.sql +++ b/src/test/regress/sql/float8.sql @@ -355,8 +355,10 @@ create type xfloat8 (input =3D xfloat8in, output =3D = xfloat8out, like =3D no_such_type create type xfloat8 (input =3D xfloat8in, output =3D xfloat8out, like =3D= float8); create cast (xfloat8 as float8) without function; create cast (float8 as xfloat8) without function; -create cast (xfloat8 as bigint) without function; -create cast (bigint as xfloat8) without function; +-- this hack depends on bigint and float8 having the same pass-by-value-n= ess: +create function bigint_xfloat8(bigint) returns xfloat8 immutable strict + language internal as 'int8up'; +create cast (bigint as xfloat8) with function bigint_xfloat8(bigint); = -- float8: seeeeeee eeeeeeee eeeeeeee mmmmmmmm mmmmmmmm(x4) = diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/t= ype_sanity.sql index 95d5b6e0915..625305c42bc 100644 --- a/src/test/regress/sql/type_sanity.sql +++ b/src/test/regress/sql/type_sanity.sql @@ -28,7 +28,7 @@ WHERE t1.typnamespace =3D 0 OR (t1.typlen <=3D 0 AND t1.typlen !=3D -1 AND t1.typlen !=3D -2) OR (t1.typtype not in ('b', 'c', 'd', 'e', 'm', 'p', 'r')) OR NOT t1.typisdefined OR - (t1.typalign not in ('c', 's', 'i', 'd')) OR + (t1.typalign not in ('c', 's', 'i', 'l', 'd', 'm')) OR (t1.typstorage not in ('p', 'x', 'e', 'm')); = -- Look for "pass by value" types that can't be passed by value. @@ -39,7 +39,7 @@ WHERE t1.typbyval AND (t1.typlen !=3D 1 OR t1.typalign !=3D 'c') AND (t1.typlen !=3D 2 OR t1.typalign !=3D 's') AND (t1.typlen !=3D 4 OR t1.typalign !=3D 'i') AND - (t1.typlen !=3D 8 OR t1.typalign !=3D 'd'); + (t1.typlen !=3D 8 OR (t1.typalign !=3D 'l' AND t1.typalign !=3D 'd'))= ; = -- Look for "toastable" types that aren't varlena. = @@ -90,6 +90,8 @@ FROM pg_type as t1 LEFT JOIN pg_type as t2 ON rngsubtype =3D t2.oid WHERE t1.typtype =3D 'r' AND (t1.typalign !=3D (CASE WHEN t2.typalign =3D 'd' THEN 'd'::"char" + WHEN t2.typalign =3D 'l' THEN 'l'::"char" + WHEN t2.typalign =3D 'm' THEN 'm'::"char" ELSE 'i'::"char" END) OR t2.oid IS NULL); = @@ -302,6 +304,8 @@ SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2= .typalign FROM pg_type AS t1, pg_type AS t2 WHERE t1.typarray =3D t2.oid AND t2.typalign !=3D (CASE WHEN t1.typalign =3D 'd' THEN 'd'::"char" + WHEN t1.typalign =3D 'l' THEN 'l'::"char" + WHEN t1.typalign =3D 'm' THEN 'm'::"char" ELSE 'i'::"char" END); = -- Check for typelem set without a handler -- = 2.43.7 ------- =_aaaaaaaaaa0--