diff options
author | Tom Lane | 2008-06-24 17:58:27 +0000 |
---|---|---|
committer | Tom Lane | 2008-06-24 17:58:27 +0000 |
commit | 386b37bbd8850a446f5bda6d99bffbb8eb4b1e8f (patch) | |
tree | 2c651227aea0636dd6a6343b51f523300cb7b639 | |
parent | 483572b5f9fdf51b5de2e534921e881279d2affe (diff) |
Reduce the alignment requirement of type "name" from int to char, and arrange
to suppress zero-padding of "name" entries in indexes.
The alignment change is unlikely to save any space, but it is really needed
anyway to make the world safe for our widespread practice of passing plain
old C strings to functions that are declared as taking Name. In the previous
coding, the C compiler was entitled to assume that a Name pointer was
word-aligned; but we were failing to guarantee that. I think the reason
we'd not seen failures is that usually the only thing that gets done with
such a pointer is strcmp(), which is hard to optimize in a way that exploits
word-alignment. Still, some enterprising compiler guy will probably think
of a way eventually, or we might change our code in a way that exposes
more-obvious optimization opportunities.
The padding change is accomplished in one-liner fashion by declaring the
"name" index opclasses to use storage type "cstring" in pg_opclass.h.
Normally btree and hash don't allow a nondefault storage type, because they
don't have any provisions for converting the input datum to another type.
However, because name and cstring are effectively the same thing except for
padding, no conversion is needed --- we only need index_form_tuple() to treat
the datum as being cstring not name, and this is sufficient. This seems to
make for about a one-third reduction in the typical sizes of system catalog
indexes that involve "name" columns, of which we have many.
These two changes are only weakly related, but the alignment change makes
me feel safer that the padding change won't introduce problems, so I'm
committing them together.
-rw-r--r-- | src/backend/bootstrap/bootstrap.c | 2 | ||||
-rw-r--r-- | src/backend/utils/adt/name.c | 2 | ||||
-rw-r--r-- | src/include/c.h | 10 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_attribute.h | 16 | ||||
-rw-r--r-- | src/include/catalog/pg_opclass.h | 11 | ||||
-rw-r--r-- | src/include/catalog/pg_type.h | 2 | ||||
-rw-r--r-- | src/include/pg_config_manual.h | 4 |
8 files changed, 26 insertions, 23 deletions
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 14cb38558d..5ff9d52491 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -125,7 +125,7 @@ static const struct typinfo TypInfo[] = { F_INT4IN, F_INT4OUT}, {"float4", FLOAT4OID, 0, 4, FLOAT4PASSBYVAL, 'i', 'p', F_FLOAT4IN, F_FLOAT4OUT}, - {"name", NAMEOID, CHAROID, NAMEDATALEN, false, 'i', 'p', + {"name", NAMEOID, CHAROID, NAMEDATALEN, false, 'c', 'p', F_NAMEIN, F_NAMEOUT}, {"regclass", REGCLASSOID, 0, 4, true, 'i', 'p', F_REGCLASSIN, F_REGCLASSOUT}, diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c index 684d9147a6..ea268e3961 100644 --- a/src/backend/utils/adt/name.c +++ b/src/backend/utils/adt/name.c @@ -315,7 +315,7 @@ current_schemas(PG_FUNCTION_ARGS) NAMEOID, NAMEDATALEN, /* sizeof(Name) */ false, /* Name is not by-val */ - 'i'); /* alignment of Name */ + 'c'); /* alignment of Name */ PG_RETURN_POINTER(array); } diff --git a/src/include/c.h b/src/include/c.h index 1a00309281..6fb48c6979 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -442,16 +442,12 @@ typedef struct } oidvector; /* VARIABLE LENGTH STRUCT */ /* - * We want NameData to have length NAMEDATALEN and int alignment, - * because that's how the data type 'name' is defined in pg_type. - * Use a union to make sure the compiler agrees. Note that NAMEDATALEN - * must be a multiple of sizeof(int), else sizeof(NameData) will probably - * not come out equal to NAMEDATALEN. + * Representation of a Name: effectively just a C string, but null-padded to + * exactly NAMEDATALEN bytes. The use of a struct is historical. */ -typedef union nameData +typedef struct nameData { char data[NAMEDATALEN]; - int alignmentDummy; } NameData; typedef NameData *Name; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 673f050009..3d99517ba5 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200806171 +#define CATALOG_VERSION_NO 200806241 #endif diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 7fe8f855cf..8fef548674 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -217,7 +217,7 @@ typedef FormData_pg_attribute *Form_pg_attribute; * ---------------- */ #define Schema_pg_type \ -{ 1247, {"typname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0 }, \ { 1247, {"typnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1247, {"typowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1247, {"typlen"}, 21, -1, 2, 4, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \ @@ -244,7 +244,7 @@ typedef FormData_pg_attribute *Form_pg_attribute; { 1247, {"typdefaultbin"}, 25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \ { 1247, {"typdefault"}, 25, -1, -1, 26, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 } -DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0)); +DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0)); DATA(insert ( 1247 typnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1247 typowner 26 -1 4 3 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1247 typlen 21 -1 2 4 0 -1 -1 t p s t f f t 0)); @@ -283,7 +283,7 @@ DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); * ---------------- */ #define Schema_pg_proc \ -{ 1255, {"proname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \ +{ 1255, {"proname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0 }, \ { 1255, {"pronamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1255, {"proowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1255, {"prolang"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ @@ -305,7 +305,7 @@ DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); { 1255, {"proconfig"}, 1009, -1, -1, 20, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \ { 1255, {"proacl"}, 1034, -1, -1, 21, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 } -DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0)); +DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0)); DATA(insert ( 1255 pronamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1255 proowner 26 -1 4 3 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1255 prolang 26 -1 4 4 0 -1 -1 t p i t f f t 0)); @@ -340,7 +340,7 @@ DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); */ #define Schema_pg_attribute \ { 1249, {"attrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \ +{ 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0 }, \ { 1249, {"atttypid"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1249, {"attstattarget"}, 23, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1249, {"attlen"}, 21, -1, 2, 5, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \ @@ -358,7 +358,7 @@ DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); { 1249, {"attinhcount"}, 23, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 } DATA(insert ( 1249 attrelid 26 -1 4 1 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p i t f f t 0)); +DATA(insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p c t f f t 0)); DATA(insert ( 1249 atttypid 26 -1 4 3 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1249 attstattarget 23 -1 4 4 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1249 attlen 21 -1 2 5 0 -1 -1 t p s t f f t 0)); @@ -387,7 +387,7 @@ DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); * ---------------- */ #define Schema_pg_class \ -{ 1259, {"relname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \ +{ 1259, {"relname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0 }, \ { 1259, {"relnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1259, {"reltype"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1259, {"relowner"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ @@ -415,7 +415,7 @@ DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); { 1259, {"relacl"}, 1034, -1, -1, 26, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \ { 1259, {"reloptions"}, 1009, -1, -1, 27, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 } -DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0)); +DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0)); DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 reltype 26 -1 4 3 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 relowner 26 -1 4 4 0 -1 -1 t p i t f f t 0)); diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index 543d0a1ae1..115069b432 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -121,8 +121,15 @@ DATA(insert ( 403 interval_ops PGNSP PGUID 1982 1186 t 0 )); DATA(insert ( 405 interval_ops PGNSP PGUID 1983 1186 t 0 )); DATA(insert ( 403 macaddr_ops PGNSP PGUID 1984 829 t 0 )); DATA(insert ( 405 macaddr_ops PGNSP PGUID 1985 829 t 0 )); -DATA(insert ( 403 name_ops PGNSP PGUID 1986 19 t 0 )); -DATA(insert ( 405 name_ops PGNSP PGUID 1987 19 t 0 )); +/* + * Here's an ugly little hack to save space in the system catalog indexes. + * btree and hash don't ordinarily allow a storage type different from input + * type; but cstring and name are the same thing except for trailing padding, + * and we can safely omit that within an index entry. So we declare the + * opclasses for name as using cstring storage type. + */ +DATA(insert ( 403 name_ops PGNSP PGUID 1986 19 t 2275 )); +DATA(insert ( 405 name_ops PGNSP PGUID 1987 19 t 2275 )); DATA(insert ( 403 numeric_ops PGNSP PGUID 1988 1700 t 0 )); DATA(insert ( 405 numeric_ops PGNSP PGUID 1998 1700 t 0 )); DATA(insert OID = 1981 ( 403 oid_ops PGNSP PGUID 1989 26 t 0 )); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 16ea859a99..9b18ea3b14 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -267,7 +267,7 @@ DATA(insert OID = 18 ( char PGNSP PGUID 1 t b t \054 0 0 1002 charin charout DESCR("single character"); #define CHAROID 18 -DATA(insert OID = 19 ( name PGNSP PGUID NAMEDATALEN f b t \054 0 18 1003 namein nameout namerecv namesend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 19 ( name PGNSP PGUID NAMEDATALEN f b t \054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 _null_ _null_ )); DESCR("63-character type for storing system identifiers"); #define NAMEOID 19 diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h index ff543992d3..a3ced75a43 100644 --- a/src/include/pg_config_manual.h +++ b/src/include/pg_config_manual.h @@ -12,8 +12,8 @@ /* * Maximum length for identifiers (e.g. table names, column names, - * function names). It must be a multiple of sizeof(int) (typically - * 4). + * function names). Names actually are limited to one less byte than this, + * because the length must include a trailing zero byte. * * Changing this requires an initdb. */ |