Reduce the alignment requirement of type "name" from int to char, and arrange
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Jun 2008 17:58:27 +0000 (17:58 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Jun 2008 17:58:27 +0000 (17:58 +0000)
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.

src/backend/bootstrap/bootstrap.c
src/backend/utils/adt/name.c
src/include/c.h
src/include/catalog/catversion.h
src/include/catalog/pg_attribute.h
src/include/catalog/pg_opclass.h
src/include/catalog/pg_type.h
src/include/pg_config_manual.h

index 14cb38558de4f6832cb8095e930ac710d9161e2a..5ff9d52491b7e3b1886c0d0649cc4fe7c5132bf4 100644 (file)
@@ -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},
index 684d9147a6e0a75d738abbd1473f4b043119dfd6..ea268e39618363c7cb51a60ac0f3d2c984e0bc9c 100644 (file)
@@ -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);
 }
index 1a003092818e267673c3fc4723a4045090a4539f..6fb48c6979185f165c18e3cd173d9dc7b959b9b8 100644 (file)
@@ -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;
 
index 673f050009483b54cae91a781d09900ba5278adb..3d99517ba5279084a35242bdec8e3f5dd595328d 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200806171
+#define CATALOG_VERSION_NO     200806241
 
 #endif
index 7fe8f855cf4425fba0a93d209c9c00bdb100c097..8fef5486744b7ea90a70e3195a41bb0382abeca3 100644 (file)
@@ -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));
index 543d0a1ae1d187c031689f1a112027c471441369..115069b4325cd6e6b3478a95b6f8d72b290a692a 100644 (file)
@@ -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 ));
index 16ea859a9935edd283fb62fea3cbf1f3a700c0ef..9b18ea3b147517dd46bf0cb284530653f1973162 100644 (file)
@@ -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
 
index ff543992d3f3835b87e203bfc318b238832f6b3c..a3ced75a43b15ecaef1f274f2b751b61381a4de4 100644 (file)
@@ -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.
  */