From 022417740094620880488dd9b04fbb96ff11694b Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 7 Aug 2000 20:16:13 +0000
Subject: [PATCH] TOAST mop-up work: update comments for tuple-size-related
 symbols such as MaxHeapAttributeNumber.  Increase MaxAttrSize to something
 more reasonable (given what it's used for, namely checking char(n)
 declarations, I didn't make it the full 1G that it could theoretically be ---
 10Mb seemed a more reasonable number).  Improve calculation of MaxTupleSize.

---
 src/backend/parser/gram.y             | 18 ++++++-----
 src/backend/utils/adt/varbit.c        |  6 ++--
 src/include/access/htup.h             | 43 ++++++++++++++++++++++-----
 src/include/config.h.in               | 20 +++++++++----
 src/include/storage/bufmgr.h          | 17 +----------
 src/include/storage/itemid.h          | 36 ++++++++++++++--------
 src/include/utils/varbit.h            |  2 --
 src/interfaces/ecpg/preproc/preproc.y | 11 +++----
 8 files changed, 93 insertions(+), 60 deletions(-)

diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0d2461f50d4..2ec136afe81 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.183 2000/08/07 06:54:51 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.184 2000/08/07 20:16:13 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -4153,10 +4153,11 @@ Bit:  bit '(' Iconst ')'
 					$$ = makeNode(TypeName);
 					$$->name = $1;
 					if ($3 < 1)
-						elog(ERROR,"length for type '%s' must be at least 1",$1);
-					else if ($3 > (MaxAttrSize * sizeof(char)))
-						elog(ERROR,"length for type '%s' cannot exceed %ld",$1,
-							 (MaxAttrSize * sizeof(char)));
+						elog(ERROR,"length for type '%s' must be at least 1",
+							 $1);
+					else if ($3 > (MaxAttrSize * BITSPERBYTE))
+						elog(ERROR,"length for type '%s' cannot exceed %d",
+							 $1, (MaxAttrSize * BITSPERBYTE));
 					$$->typmod = $3;
 				}
 		| bit
@@ -4187,10 +4188,11 @@ Character:  character '(' Iconst ')'
 					$$ = makeNode(TypeName);
 					$$->name = $1;
 					if ($3 < 1)
-						elog(ERROR,"length for type '%s' must be at least 1",$1);
+						elog(ERROR,"length for type '%s' must be at least 1",
+							 $1);
 					else if ($3 > MaxAttrSize)
-						elog(ERROR,"length for type '%s' cannot exceed %ld",$1,
-							 MaxAttrSize);
+						elog(ERROR,"length for type '%s' cannot exceed %d",
+							 $1, MaxAttrSize);
 
 					/* we actually implement these like a varlen, so
 					 * the first 4 bytes is the length. (the difference
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index b238bce5312..cba4085bd2a 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -4,7 +4,7 @@
  *	  Functions for the built-in type bit() and varying bit().
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.6 2000/07/28 02:13:31 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.7 2000/08/07 20:15:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -107,7 +107,7 @@ zpbit_in(char *s, int dummy, int32 atttypmod)
 
 	if (len > MaxAttrSize)
 		elog(ERROR, "zpbit_in: length of bit() must be less than %ld",
-			 (MaxAttrSize - VARHDRSZ - VARBITHDRSZ) * BITSPERBYTE);
+			 (long) ((MaxAttrSize - VARHDRSZ - VARBITHDRSZ) * BITSPERBYTE));
 
 	result = (bits8 *) palloc(len);
 	/* set to 0 so that *r is always initialised and strin is zero-padded */
@@ -338,7 +338,7 @@ varbit_in(char *s, int dummy, int32 atttypmod)
 
 	if (len > MaxAttrSize)
 		elog(ERROR, "varbit_in: length of bit() must be less than %ld",
-			 (MaxAttrSize - VARHDRSZ - VARBITHDRSZ) * BITSPERBYTE);
+			 (long) ((MaxAttrSize - VARHDRSZ - VARBITHDRSZ) * BITSPERBYTE));
 
 	result = (bits8 *) palloc(len);
 	/* set to 0 so that *r is always initialised and strin is zero-padded */
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index cf8f9dddcb6..73e6655634c 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: htup.h,v 1.33 2000/07/04 01:49:43 vadim Exp $
+ * $Id: htup.h,v 1.34 2000/08/07 20:15:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,8 +18,16 @@
 
 #define MinHeapTupleBitmapSize	32		/* 8 * 4 */
 
-/* check these, they are likely to be more severely limited by t_hoff */
-
+/*
+ * MaxHeapAttributeNumber limits the number of (user) columns in a table.
+ * The key limit on this value is that the size of the fixed overhead for
+ * a tuple, plus the size of the null-values bitmap (at 1 bit per column),
+ * plus MAXALIGN alignment, must fit into t_hoff which is uint8.  On most
+ * machines the absolute upper limit without making t_hoff wider would be
+ * about 1700.  Note, however, that depending on column data types you will
+ * likely also be running into the disk-block-based limit on overall tuple
+ * size if you have more than a thousand or so columns.  TOAST won't help.
+ */
 #define MaxHeapAttributeNumber	1600	/* 8 * 200 */
 
 /*
@@ -130,13 +138,32 @@ typedef struct xl_heap_move
 
 #endif	/* XLOG */
 
-#define MinTupleSize	(MAXALIGN(sizeof (PageHeaderData)) + \
-						 MAXALIGN(sizeof(HeapTupleHeaderData)) + \
-						 MAXALIGN(sizeof(char)))
 
-#define MaxTupleSize	(BLCKSZ - MinTupleSize)
+/*
+ * MaxTupleSize is the maximum allowed size of a tuple, including header and
+ * MAXALIGN alignment padding.  Basically it's BLCKSZ minus the other stuff
+ * that has to be on a disk page.  The "other stuff" includes access-method-
+ * dependent "special space", which we assume will be no more than
+ * MaxSpecialSpace bytes (currently, on heap pages it's actually zero).
+ *
+ * NOTE: we do not need to count an ItemId for the tuple because
+ * sizeof(PageHeaderData) includes the first ItemId on the page.
+ */
+#define MaxSpecialSpace  32
+
+#define MaxTupleSize	\
+	(BLCKSZ - MAXALIGN(sizeof(PageHeaderData) + MaxSpecialSpace))
+
+
+/*
+ * MaxAttrSize is a somewhat arbitrary upper limit on the declared size of
+ * data fields of char(n) and similar types.  It need not have anything
+ * directly to do with the *actual* upper limit of varlena values, which
+ * is currently 1Gb (see struct varattrib in postgres.h).  I've set it
+ * at 10Mb which seems like a reasonable number --- tgl 8/6/00.
+ */
+#define MaxAttrSize		(10 * 1024 * 1024)
 
-#define MaxAttrSize		(MaxTupleSize - MAXALIGN(sizeof(HeapTupleHeaderData)))
 
 #define SelfItemPointerAttributeNumber			(-1)
 #define ObjectIdAttributeNumber					(-2)
diff --git a/src/include/config.h.in b/src/include/config.h.in
index 63c7c21b7b8..904cf0602ee 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -8,7 +8,7 @@
  * or in config.h afterwards.  Of course, if you edit config.h, then your
  * changes will be overwritten the next time you run configure.
  *
- * $Id: config.h.in,v 1.129 2000/08/07 00:51:38 tgl Exp $
+ * $Id: config.h.in,v 1.130 2000/08/07 20:15:44 tgl Exp $
  */
 
 #ifndef CONFIG_H
@@ -106,12 +106,16 @@
 #define DEF_NBUFFERS (DEF_MAXBACKENDS > 8 ? DEF_MAXBACKENDS * 2 : 16)
 
 /*
- * Size of a disk block --- currently, this limits the size of a tuple.
- * You can set it bigger if you need bigger tuples.
+ * Size of a disk block --- this also limits the size of a tuple.
+ * You can set it bigger if you need bigger tuples (although TOAST
+ * should reduce the need to have large tuples, since fields can now
+ * be spread across multiple tuples).
  *
- * CAUTION: changing BLCKSZ requires an initdb.
+ * The maximum possible value of BLCKSZ is currently 2^15 (32768).
+ * This is determined by the 15-bit widths of the lp_off and lp_len
+ * fields in ItemIdData (see include/storage/itemid.h).
  *
- * currently must be <= 32k bjm
+ * CAUTION: changing BLCKSZ requires an initdb.
  */
 #define BLCKSZ	8192
 
@@ -213,6 +217,12 @@
  */
 #define DEFAULT_MAX_EXPR_DEPTH	10000
 
+/*
+ * You can try changing this if you have a machine with bytes of another
+ * size, but no guarantee...
+ */
+#define BITSPERBYTE		8
+
 /*
  *------------------------------------------------------------------------
  * These hand-configurable symbols are for enabling debugging code,
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index a72b06f3898..1a06953f513 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -7,36 +7,21 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: bufmgr.h,v 1.39 2000/06/15 03:33:00 momjian Exp $
+ * $Id: bufmgr.h,v 1.40 2000/08/07 20:15:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef BUFMGR_H
 #define BUFMGR_H
 
-
 #include "storage/buf_internals.h"
 
-/*
- * the maximum size of a disk block for any possible installation.
- *
- * in theory this could be anything, but in practice this is actually
- * limited to 2^13 bytes because we have limited ItemIdData.lp_off and
- * ItemIdData.lp_len to 13 bits (see itemid.h).
- *
- * limit is now 2^15.  Took four bits from ItemIdData.lp_flags and gave
- * two apiece to ItemIdData.lp_len and lp_off. darrenk 01/06/98
- *
- */
-
-#define MAXBLCKSZ		32768
 
 typedef void *Block;
 
 /* special pageno for bget */
 #define P_NEW	InvalidBlockNumber		/* grow the file to get a new page */
 
-typedef bits16 BufferLock;
 
 /**********************************************************************
 
diff --git a/src/include/storage/itemid.h b/src/include/storage/itemid.h
index 51af7f49f30..87aa82ac3c6 100644
--- a/src/include/storage/itemid.h
+++ b/src/include/storage/itemid.h
@@ -7,38 +7,48 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: itemid.h,v 1.10 2000/01/26 05:58:33 momjian Exp $
+ * $Id: itemid.h,v 1.11 2000/08/07 20:15:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef ITEMID_H
 #define ITEMID_H
 
-typedef uint16 ItemOffset;
-typedef uint16 ItemLength;
-
-typedef bits16 ItemIdFlags;
-
-
 
+/*
+ * An item pointer (also called line pointer) on a buffer page
+ */
 typedef struct ItemIdData
 {								/* line pointers */
-	unsigned	lp_off:15,		/* offset to find tup */
-	/* can be reduced by 2 if necc. */
-				lp_flags:2,		/* flags on tuple */
+	unsigned	lp_off:15,		/* offset to start of tuple */
+				lp_flags:2,		/* flags for tuple */
 				lp_len:15;		/* length of tuple */
 } ItemIdData;
 
-typedef struct ItemIdData *ItemId;
+typedef ItemIdData *ItemId;
 
-#ifndef LP_USED
+/*
+ * lp_flags contains these flags:
+ */
 #define LP_USED			0x01	/* this line pointer is being used */
-#endif
+/* currently, there is one unused flag bit ... */
+
+
+/*
+ * Item offsets, lengths, and flags are represented by these types when
+ * they're not actually stored in an ItemIdData.
+ */
+typedef uint16 ItemOffset;
+typedef uint16 ItemLength;
+
+typedef bits16 ItemIdFlags;
+
 
 /* ----------------
  *		support macros
  * ----------------
  */
+
 /*
  *		ItemIdGetLength
  */
diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h
index 172cb4c6c4d..06f51f429cb 100644
--- a/src/include/utils/varbit.h
+++ b/src/include/utils/varbit.h
@@ -18,8 +18,6 @@ struct varbita
 	bits8		vl_dat[1];
 };
 
-#undef BITSPERBYTE				/* sometimes declared in <values.h> */
-#define BITSPERBYTE		8
 #define VARBITHDRSZ		sizeof(int32)
 /* Number of bits in this bit string */
 #define VARBITLEN(PTR)		(((struct varbita *)VARDATA(PTR))->vl_len)
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index d45322ac17c..0d12a10b8ea 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -3114,12 +3114,13 @@ Bit:  bit '(' Iconst ')'
                                         if (atol($3) < 1)
 					{
                                                 sprintf(errortext,"length for type '%s' must be at least 1",$1);  
-						mmerror(ET_ERROR, errortext);
+												mmerror(ET_ERROR, errortext);
 					}
-                                        else if (atol($3) > (MaxAttrSize *sizeof(char)))
+                                        else if (atol($3) > (MaxAttrSize * BITSPERBYTE))
 					{
-                                                sprintf(errortext, "length for type '%s' cannot exceed %ld", $1,    
-                                                         (MaxAttrSize * sizeof(char)));
+                                                sprintf(errortext, "length for type '%s' cannot exceed %d", $1,
+                                                         (MaxAttrSize * BITSPERBYTE));
+												mmerror(ET_ERROR, errortext);
 					}
                                 }
                 | bit
@@ -3147,7 +3148,7 @@ Character:  character '(' Iconst ')'
 					}
 					else if (atol($3) > MaxAttrSize)
 					{
-						sprintf(errortext, "length for type '%s' cannot exceed %ld", $1, MaxAttrSize);
+						sprintf(errortext, "length for type '%s' cannot exceed %d", $1, MaxAttrSize);
 						mmerror(ET_ERROR, errortext);
 					}
 
-- 
GitLab