From a25b94c080a644a66983bbcf82a4e358aa47b7df Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 22 Mar 2002 21:34:44 +0000
Subject: [PATCH] Create the pg_namespace system catalog.  Doesn't do much yet,
 but it's there and CREATE SCHEMA will make entries in it...

---
 doc/src/sgml/catalogs.sgml                 | 57 ++++++++++++++-
 src/backend/catalog/Makefile               | 10 +--
 src/backend/catalog/indexing.c             |  4 +-
 src/backend/catalog/pg_namespace.c         | 85 ++++++++++++++++++++++
 src/backend/commands/command.c             | 11 ++-
 src/backend/utils/cache/syscache.c         | 23 +++++-
 src/include/catalog/catalog.h              |  4 +-
 src/include/catalog/catname.h              |  4 +-
 src/include/catalog/catversion.h           |  4 +-
 src/include/catalog/indexing.h             |  8 +-
 src/include/catalog/pg_namespace.h         | 79 ++++++++++++++++++++
 src/include/utils/syscache.h               | 28 +++----
 src/test/regress/expected/sanity_check.out |  3 +-
 13 files changed, 285 insertions(+), 35 deletions(-)
 create mode 100644 src/backend/catalog/pg_namespace.c
 create mode 100644 src/include/catalog/pg_namespace.h

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index b72b0836179..5371da7ee7e 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.36 2002/03/22 19:20:03 petere Exp $
+ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.37 2002/03/22 21:34:43 tgl Exp $
  -->
 
 <chapter id="catalogs">
@@ -111,6 +111,11 @@
       <entry>asynchronous notification</entry>
      </row>
 
+     <row>
+      <entry>pg_namespace</entry>
+      <entry>namespaces (schemas)</entry>
+     </row>
+
      <row>
       <entry>pg_opclass</entry>
       <entry>index access method operator classes</entry>
@@ -1408,6 +1413,56 @@
  </sect1>
 
 
+ <sect1 id="catalog-pg-namespace">
+  <title>pg_namespace</title>
+
+  <para>
+   A namespace is the structure underlying SQL92 schemas: each namespace
+   can have a separate collection of relations, types, etc without name
+   conflicts.
+  </para>
+
+  <table>
+   <title>pg_namespace Columns</title>
+
+   <tgroup cols=4>
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry>nspname</entry>
+      <entry><type>name</type></entry>
+      <entry></entry>
+      <entry>Name of the namespace</entry>
+     </row>
+
+     <row>
+      <entry>nspowner</entry>
+      <entry><type>int4</type></entry>
+      <entry>pg_shadow.usesysid</entry>
+      <entry>Owner (creator) of the namespace</entry>
+     </row>
+
+     <row>
+      <entry>nspacl</entry>
+      <entry><type>aclitem[]</type></entry>
+      <entry></entry>
+      <entry>Access permissions</entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect1>
+
+
  <sect1 id="catalog-pg-operator">
   <title>pg_operator</title>
 
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 6c5d2aaec2c..d0bc7b37267 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -1,8 +1,8 @@
 #-------------------------------------------------------------------------
 #
-# Makefile for catalog
+# Makefile for backend/catalog
 #
-# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.37 2001/08/25 18:52:41 tgl Exp $
+# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.38 2002/03/22 21:34:43 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -11,8 +11,8 @@ top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
 OBJS = catalog.o heap.o index.o indexing.o aclchk.o \
-       pg_aggregate.o pg_largeobject.o pg_operator.o pg_proc.o \
-       pg_type.o
+       pg_aggregate.o pg_largeobject.o pg_namespace.o \
+       pg_operator.o pg_proc.o pg_type.o
 
 BKIFILES = postgres.bki postgres.description
 
@@ -31,7 +31,7 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
 	pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
 	pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
 	pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h \
-	pg_database.h pg_shadow.h pg_group.h indexing.h \
+	pg_namespace.h pg_database.h pg_shadow.h pg_group.h indexing.h \
     )
 
 pg_includes := $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include)
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index e600eab6a30..fcad116e99d 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.83 2002/02/19 20:11:11 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.84 2002/03/22 21:34:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,6 +57,8 @@ char	   *Name_pg_language_indices[Num_pg_language_indices] =
 {LanguageOidIndex, LanguageNameIndex};
 char	   *Name_pg_largeobject_indices[Num_pg_largeobject_indices] =
 {LargeObjectLOidPNIndex};
+char	   *Name_pg_namespace_indices[Num_pg_namespace_indices] =
+{NamespaceNameIndex, NamespaceOidIndex};
 char	   *Name_pg_opclass_indices[Num_pg_opclass_indices] =
 {OpclassAmNameIndex, OpclassOidIndex};
 char	   *Name_pg_operator_indices[Num_pg_operator_indices] =
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
new file mode 100644
index 00000000000..c340cd02f73
--- /dev/null
+++ b/src/backend/catalog/pg_namespace.c
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_namespace.c
+ *	  routines to support manipulation of the pg_namespace relation
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_namespace.c,v 1.1 2002/03/22 21:34:44 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_namespace.h"
+#include "miscadmin.h"
+#include "utils/builtins.h"
+#include "utils/syscache.h"
+
+
+/* ----------------
+ * NamespaceCreate
+ * ---------------
+ */
+Oid
+NamespaceCreate(const char *nspName)
+{
+	Relation	nspdesc;
+	HeapTuple	tup;
+	Oid			nspoid;
+	char		nulls[Natts_pg_namespace];
+	Datum		values[Natts_pg_namespace];
+	NameData	nname;
+	TupleDesc	tupDesc;
+	int			i;
+
+	/* sanity checks */
+	if (!nspName)
+		elog(ERROR, "no namespace name supplied");
+
+	/* make sure there is no existing namespace of same name */
+	if (SearchSysCacheExists(NAMESPACENAME,
+							 PointerGetDatum(nspName),
+							 0, 0, 0))
+		elog(ERROR, "namespace \"%s\" already exists", nspName);
+
+	/* initialize nulls and values */
+	for (i = 0; i < Natts_pg_namespace; i++)
+	{
+		nulls[i] = ' ';
+		values[i] = (Datum) NULL;
+	}
+	namestrcpy(&nname, nspName);
+	values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
+	values[Anum_pg_namespace_nspowner - 1] = Int32GetDatum(GetUserId());
+	nulls[Anum_pg_namespace_nspacl - 1] = 'n';
+
+	nspdesc = heap_openr(NamespaceRelationName, RowExclusiveLock);
+	tupDesc = nspdesc->rd_att;
+	if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
+											   values,
+											   nulls)))
+		elog(ERROR, "NamespaceCreate: heap_formtuple failed");
+	nspoid = heap_insert(nspdesc, tup);
+	if (!OidIsValid(nspoid))
+		elog(ERROR, "NamespaceCreate: heap_insert failed");
+
+	if (RelationGetForm(nspdesc)->relhasindex)
+	{
+		Relation	idescs[Num_pg_namespace_indices];
+
+		CatalogOpenIndices(Num_pg_namespace_indices, Name_pg_namespace_indices, idescs);
+		CatalogIndexInsert(idescs, Num_pg_namespace_indices, nspdesc, tup);
+		CatalogCloseIndices(Num_pg_namespace_indices, idescs);
+	}
+
+	heap_close(nspdesc, RowExclusiveLock);
+
+	return nspoid;
+}
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index b9741e0f3a5..af9e76e2791 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.164 2002/03/22 02:56:31 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.165 2002/03/22 21:34:44 tgl Exp $
  *
  * NOTES
  *	  The PerformAddAttribute() code, like most of the relation
@@ -28,6 +28,7 @@
 #include "catalog/indexing.h"
 #include "catalog/pg_attrdef.h"
 #include "catalog/pg_index.h"
+#include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_relcheck.h"
 #include "catalog/pg_type.h"
@@ -2008,12 +2009,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
 				 owner_name, authId);
 	}
 
-	/* FIXME FENN: Create the schema here */
-	(void) schemaName;			/* suppress compiler warning for now... */
+	/* Create the schema's namespace */
+	NamespaceCreate(schemaName);
 
-	/*
-	 * Let commands in the schema-element-list know about the schema
-	 */
+	/* Let commands in the schema-element-list know about the schema */
 	CommandCounterIncrement();
 
 	/*
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 8779125d159..c30bbe3090c 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.68 2002/03/21 23:27:24 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.69 2002/03/22 21:34:44 tgl Exp $
  *
  * NOTES
  *	  These routines allow the parser/planner/executor to perform
@@ -32,6 +32,7 @@
 #include "catalog/pg_index.h"
 #include "catalog/pg_inherits.h"
 #include "catalog/pg_language.h"
+#include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
@@ -263,6 +264,26 @@ static struct cachedesc cacheinfo[] = {
 			0,
 			0
 	}},
+	{NamespaceRelationName,		/* NAMESPACENAME */
+		NamespaceNameIndex,
+		0,
+		1,
+		{
+			Anum_pg_namespace_nspname,
+			0,
+			0,
+			0
+	}},
+	{NamespaceRelationName,		/* NAMESPACEOID */
+		NamespaceOidIndex,
+		0,
+		1,
+		{
+			ObjectIdAttributeNumber,
+			0,
+			0,
+			0
+	}},
 	{OperatorRelationName,		/* OPERNAME */
 		OperatorNameIndex,
 		0,
diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h
index 25f6fcb0c5c..62cc5736f7f 100644
--- a/src/include/catalog/catalog.h
+++ b/src/include/catalog/catalog.h
@@ -1,13 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * catalog.h
- *	  prototypes for functions in lib/catalog/catalog.c
+ *	  prototypes for functions in backend/catalog/catalog.c
  *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catalog.h,v 1.21 2001/11/16 23:30:35 tgl Exp $
+ * $Id: catalog.h,v 1.22 2002/03/22 21:34:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
diff --git a/src/include/catalog/catname.h b/src/include/catalog/catname.h
index ecdc81aed1d..bf3bf789756 100644
--- a/src/include/catalog/catname.h
+++ b/src/include/catalog/catname.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catname.h,v 1.23 2001/11/05 17:46:31 momjian Exp $
+ * $Id: catname.h,v 1.24 2002/03/22 21:34:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -15,7 +15,6 @@
 #define CATNAME_H
 
 
-
 #define  AggregateRelationName "pg_aggregate"
 #define  AccessMethodRelationName "pg_am"
 #define  AccessMethodOperatorRelationName "pg_amop"
@@ -29,6 +28,7 @@
 #define  LanguageRelationName "pg_language"
 #define  LargeObjectRelationName "pg_largeobject"
 #define  ListenerRelationName "pg_listener"
+#define  NamespaceRelationName "pg_namespace"
 #define  OperatorClassRelationName "pg_opclass"
 #define  OperatorRelationName "pg_operator"
 #define  ProcedureRelationName "pg_proc"
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index e931772b07c..086df0b2f84 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.109 2002/03/22 02:56:35 tgl Exp $
+ * $Id: catversion.h,v 1.110 2002/03/22 21:34:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200203212
+#define CATALOG_VERSION_NO	200203221
 
 #endif
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 8d0ba9c4b9c..c6291f2a3a4 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: indexing.h,v 1.57 2002/02/19 20:11:19 tgl Exp $
+ * $Id: indexing.h,v 1.58 2002/03/22 21:34:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,6 +34,7 @@
 #define Num_pg_inherits_indices		1
 #define Num_pg_language_indices		2
 #define Num_pg_largeobject_indices	1
+#define Num_pg_namespace_indices	2
 #define Num_pg_opclass_indices		2
 #define Num_pg_operator_indices		2
 #define Num_pg_proc_indices			2
@@ -70,6 +71,8 @@
 #define LanguageNameIndex			"pg_language_name_index"
 #define LanguageOidIndex			"pg_language_oid_index"
 #define LargeObjectLOidPNIndex		"pg_largeobject_loid_pn_index"
+#define NamespaceNameIndex			"pg_namespace_nspname_index"
+#define NamespaceOidIndex			"pg_namespace_oid_index"
 #define OpclassAmNameIndex			"pg_opclass_am_name_index"
 #define OpclassOidIndex				"pg_opclass_oid_index"
 #define OperatorNameIndex			"pg_operator_oprname_l_r_k_index"
@@ -104,6 +107,7 @@ extern char *Name_pg_index_indices[];
 extern char *Name_pg_inherits_indices[];
 extern char *Name_pg_language_indices[];
 extern char *Name_pg_largeobject_indices[];
+extern char *Name_pg_namespace_indices[];
 extern char *Name_pg_opclass_indices[];
 extern char *Name_pg_operator_indices[];
 extern char *Name_pg_proc_indices[];
@@ -165,6 +169,8 @@ DECLARE_UNIQUE_INDEX(pg_inherits_relid_seqno_index on pg_inherits using btree(in
 DECLARE_UNIQUE_INDEX(pg_language_name_index on pg_language using btree(lanname name_ops));
 DECLARE_UNIQUE_INDEX(pg_language_oid_index on pg_language using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_largeobject_loid_pn_index on pg_largeobject using btree(loid oid_ops, pageno int4_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index on pg_namespace using btree(nspname name_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_oid_index on pg_namespace using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_opclass_am_name_index on pg_opclass using btree(opcamid oid_ops, opcname name_ops));
 DECLARE_UNIQUE_INDEX(pg_opclass_oid_index on pg_opclass using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_operator_oid_index on pg_operator using btree(oid oid_ops));
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
new file mode 100644
index 00000000000..8a57cf7977b
--- /dev/null
+++ b/src/include/catalog/pg_namespace.h
@@ -0,0 +1,79 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_namespace.h
+ *	  definition of the system "namespace" relation (pg_namespace)
+ *	  along with the relation's initial contents.
+ *
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: pg_namespace.h,v 1.1 2002/03/22 21:34:44 tgl Exp $
+ *
+ * NOTES
+ *	  the genbki.sh script reads this file and generates .bki
+ *	  information from the DATA() statements.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_NAMESPACE_H
+#define PG_NAMESPACE_H
+
+/* ----------------
+ *		postgres.h contains the system type definitions and the
+ *		CATALOG(), BOOTSTRAP and DATA() sugar words so this file
+ *		can be read by both genbki.sh and the C compiler.
+ * ----------------
+ */
+
+/* ----------------------------------------------------------------
+ *		pg_namespace definition.
+ *
+ *		cpp turns this into typedef struct FormData_pg_namespace
+ *
+ *	nspname				name of the namespace
+ *	nspowner			owner (creator) of the namespace
+ *	nspacl				access privilege list
+ * ----------------------------------------------------------------
+ */
+CATALOG(pg_namespace)
+{
+	NameData	nspname;
+	int4		nspowner;
+    aclitem		nspacl[1];		/* VARIABLE LENGTH FIELD */
+} FormData_pg_namespace;
+
+/* ----------------
+ *		Form_pg_namespace corresponds to a pointer to a tuple with
+ *		the format of pg_namespace relation.
+ * ----------------
+ */
+typedef FormData_pg_namespace *Form_pg_namespace;
+
+/* ----------------
+ *		compiler constants for pg_namespace
+ * ----------------
+ */
+
+#define Natts_pg_namespace				3
+#define Anum_pg_namespace_nspname		1
+#define Anum_pg_namespace_nspowner		2
+#define Anum_pg_namespace_nspacl		3
+
+
+/* ----------------
+ * initial contents of pg_namespace
+ * ---------------
+ */
+
+DATA(insert OID = 11 ( "pg_catalog" PGUID "{=r}" ));
+DESCR("System catalog namespace");
+#define PG_CATALOG_NAMESPACE 11
+
+
+/*
+ * prototypes for functions in pg_namespace.c
+ */
+extern Oid	NamespaceCreate(const char *nspName);
+
+#endif   /* PG_NAMESPACE_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index d4bcd14256e..45de795c9c8 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: syscache.h,v 1.38 2002/03/21 23:27:25 tgl Exp $
+ * $Id: syscache.h,v 1.39 2002/03/22 21:34:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,18 +45,20 @@
 #define INHRELID		14
 #define LANGNAME		15
 #define LANGOID			16
-#define OPERNAME		17
-#define OPEROID			18
-#define PROCNAME		19
-#define PROCOID			20
-#define RELNAME			21
-#define RELOID			22
-#define RULENAME		23
-#define SHADOWNAME		24
-#define SHADOWSYSID		25
-#define STATRELATT		26
-#define TYPENAME		27
-#define TYPEOID			28
+#define NAMESPACENAME	17
+#define NAMESPACEOID	18
+#define OPERNAME		19
+#define OPEROID			20
+#define PROCNAME		21
+#define PROCOID			22
+#define RELNAME			23
+#define RELOID			24
+#define RULENAME		25
+#define SHADOWNAME		26
+#define SHADOWSYSID		27
+#define STATRELATT		28
+#define TYPENAME		29
+#define TYPEOID			30
 
 
 extern void InitCatalogCache(void);
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 47196e55993..7958da84331 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -45,6 +45,7 @@ SELECT relname, relhasindex
  pg_inherits         | t
  pg_language         | t
  pg_largeobject      | t
+ pg_namespace        | t
  pg_opclass          | t
  pg_operator         | t
  pg_proc             | t
@@ -59,5 +60,5 @@ SELECT relname, relhasindex
  shighway            | t
  tenk1               | t
  tenk2               | t
-(49 rows)
+(50 rows)
 
-- 
GitLab