Hi,

With the help of Cédric, here's a patch changing the TRUNCATE TABLE
command, adding the IF EXISTS option to allow the presence in the list
of tables of a missing or invisible table.

This meets the needs of scripts that should be run in different stages,
and do not always have the same visibility on the tables, as well as
DROP TABLE. Rather than rollback the entire TRUNCATE or transaction, we
prefer to ignore the absence of the table.

It is a small patch which changes very little code, but that could be
quite useful.

Regards,

-- 
Sébastien Lardière
PostgreSQL DBA Team Manager
Hi-Media
diff --git a/doc/src/sgml/ref/truncate.sgml b/doc/src/sgml/ref/truncate.sgml
index 7b9c2f3..8af9f0b 100644
--- a/doc/src/sgml/ref/truncate.sgml
+++ b/doc/src/sgml/ref/truncate.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-TRUNCATE [ TABLE ] [ ONLY ] <replaceable class="PARAMETER">name</replaceable> [ * ] [, ... ]
+TRUNCATE [ TABLE ] [ IF EXISTS ] [ ONLY ] <replaceable class="PARAMETER">name</replaceable> [ * ] [, ... ]
     [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
 </synopsis>
  </refsynopsisdiv>
@@ -44,6 +44,16 @@ TRUNCATE [ TABLE ] [ ONLY ] <replaceable class="PARAMETER">name</replaceable> [
 
   <variablelist>
    <varlistentry>
+    <term><literal>IF EXISTS</literal></term>
+    <listitem>
+     <para>
+      Do not throw an error if a table does not exist. A notice is issued
+      in this case.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
     <term><replaceable class="PARAMETER">name</replaceable></term>
     <listitem>
      <para>
@@ -222,7 +232,8 @@ TRUNCATE othertable CASCADE;
    also appear in that standard, but have slightly different though related
    meanings.  Some of the concurrency behavior of this command is left
    implementation-defined by the standard, so the above notes should be
-   considered and compared with other implementations if necessary.
+   considered and compared with other implementations if necessary. The
+   <literal>IF EXISTS</> option is a <productname>PostgreSQL</> extension.
   </para>
  </refsect1>
 </refentry>
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 359d478..f48dbf8 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -948,6 +948,9 @@ ExecuteTruncate(TruncateStmt *stmt)
 	ResultRelInfo *resultRelInfo;
 	SubTransactionId mySubid;
 	ListCell   *cell;
+	ListCell   *prev;
+
+	prev = NULL;
 
 	/*
 	 * Open, exclusive-lock, and check all the explicitly-specified relations
@@ -959,7 +962,22 @@ ExecuteTruncate(TruncateStmt *stmt)
 		bool		recurse = interpretInhOption(rv->inhOpt);
 		Oid			myrelid;
 
-		rel = heap_openrv(rv, AccessExclusiveLock);
+		rel = heap_openrv_extended(rv, AccessExclusiveLock, stmt->missing_ok);
+		/* TODO : if oid is not valid
+		 * NOTICE with table name
+		 * invalid oid in the list 
+		 */
+		if(rel == NULL) {
+		  ereport(NOTICE, 
+			  (errcode(ERRCODE_UNDEFINED_TABLE), 
+			   errmsg("relation %s does not exist", rv->relname )
+			   ) 
+			  );
+		  list_delete_cell(stmt->relations, cell, prev) ;
+		  continue;
+		}
+		prev = cell;
+
 		myrelid = RelationGetRelid(rel);
 		/* don't throw error for "TRUNCATE foo, foo" */
 		if (list_member_oid(relids, myrelid))
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e4ff76e..f6a03f3 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -5065,6 +5065,16 @@ TruncateStmt:
 					n->relations = $3;
 					n->restart_seqs = $4;
 					n->behavior = $5;
+					n->missing_ok = false; 
+					$$ = (Node *)n;
+				}
+                        | TRUNCATE opt_table IF_P EXISTS relation_expr_list opt_restart_seqs opt_drop_behavior
+				{
+					TruncateStmt *n = makeNode(TruncateStmt);
+					n->relations = $5;
+					n->restart_seqs = $6;
+					n->behavior = $7;
+					n->missing_ok = true; 
 					$$ = (Node *)n;
 				}
 		;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 09b15e7..814b129 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1954,6 +1954,7 @@ typedef struct TruncateStmt
 	List	   *relations;		/* relations (RangeVars) to be truncated */
 	bool		restart_seqs;	/* restart owned sequences? */
 	DropBehavior behavior;		/* RESTRICT or CASCADE behavior */
+	bool		missing_ok;		/* skip error if object is missing? */
 } TruncateStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/truncate.out b/src/test/regress/expected/truncate.out
index 5c5277e..839104d 100644
--- a/src/test/regress/expected/truncate.out
+++ b/src/test/regress/expected/truncate.out
@@ -420,3 +420,13 @@ SELECT nextval('truncate_a_id1'); -- fail, seq should have been dropped
 ERROR:  relation "truncate_a_id1" does not exist
 LINE 1: SELECT nextval('truncate_a_id1');
                        ^
+-- test IF EXISTS
+CREATE TABLE truncate_a(id int);
+INSERT INTO truncate_a VALUES ( 1 ); 
+TRUNCATE TABLE IF EXISTS truncate_a ; 
+INSERT INTO truncate_a VALUES ( 1 ); 
+TRUNCATE TABLE IF EXISTS truncate_a, truncate_b ; 
+NOTICE:  relation truncate_b does not exist
+DROP TABLE truncate_a ; 
+TRUNCATE TABLE IF EXISTS truncate_a ; 
+NOTICE:  relation truncate_a does not exist
diff --git a/src/test/regress/sql/truncate.sql b/src/test/regress/sql/truncate.sql
index a3d6f53..ed39360 100644
--- a/src/test/regress/sql/truncate.sql
+++ b/src/test/regress/sql/truncate.sql
@@ -215,3 +215,16 @@ SELECT * FROM truncate_a;
 DROP TABLE truncate_a;
 
 SELECT nextval('truncate_a_id1'); -- fail, seq should have been dropped
+
+-- test IF EXISTS
+
+CREATE TABLE truncate_a(id int);
+
+INSERT INTO truncate_a VALUES ( 1 ); 
+TRUNCATE TABLE IF EXISTS truncate_a ; 
+
+INSERT INTO truncate_a VALUES ( 1 ); 
+TRUNCATE TABLE IF EXISTS truncate_a, truncate_b ; 
+
+DROP TABLE truncate_a ; 
+TRUNCATE TABLE IF EXISTS truncate_a ; 
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to