>If the user owns objects, that will prevent this from working also.  I
>have the feeling that adding DROP OWNED BY and/or REASSIGNED OWNED BY
>calls to this utility would be a bit excessive, but who knows.

Please find attached the first attempt to drop drop the client connections.

I have added an option -k, --kill instead of force since killing client 
connection does not guarantee -drop force-.  

Regards




On Tuesday, January 14, 2014 8:06 PM, Alvaro Herrera <alvhe...@2ndquadrant.com> 
wrote:
 
salah jubeh wrote:

> For the sake of completeness:
> 1. I think also, I need also to temporary disallow conecting to the database, 
> is that right?
> 2. Is there other factors can hinder dropping database?

If the user owns objects, that will prevent this from working also.  I
have the feeling that adding DROP OWNED BY and/or REASSIGNED OWNED BY
calls to this utility would be a bit excessive, but who knows.


> 3. Should I write two patches one for pg_version>=9.2 and one for 
> pg_version<9.2  

No point -- nothing gets applied to branches older than current
development anyway.

-- 
Álvaro Herrera                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--- dropdb_orig.c	2014-01-16 15:21:51.059243617 +0100
+++ dropdb.c	2014-01-16 16:38:57.419414200 +0100
@@ -32,6 +32,7 @@
 		{"echo", no_argument, NULL, 'e'},
 		{"interactive", no_argument, NULL, 'i'},
 		{"if-exists", no_argument, &if_exists, 1},
+		{"kill", no_argument, NULL, 'k'},
 		{"maintenance-db", required_argument, NULL, 2},
 		{NULL, 0, NULL, 0}
 	};
@@ -48,6 +49,8 @@
 	enum trivalue prompt_password = TRI_DEFAULT;
 	bool		echo = false;
 	bool		interactive = false;
+	bool		kill = false;
+	char *database_conn_limit = "-1";
 
 	PQExpBufferData sql;
 
@@ -59,7 +62,7 @@
 
 	handle_help_version_opts(argc, argv, "dropdb", help);
 
-	while ((c = getopt_long(argc, argv, "h:p:U:wWei", long_options, &optindex)) != -1)
+	while ((c = getopt_long(argc, argv, "h:p:U:wWeik", long_options, &optindex)) != -1)
 	{
 		switch (c)
 		{
@@ -84,6 +87,9 @@
 			case 'i':
 				interactive = true;
 				break;
+			case 'k':
+				kill = true;
+				break;
 			case 0:
 				/* this covers the long options */
 				break;
@@ -121,8 +127,6 @@
 
 	initPQExpBuffer(&sql);
 
-	appendPQExpBuffer(&sql, "DROP DATABASE %s%s;\n",
-					  (if_exists ? "IF EXISTS " : ""), fmtId(dbname));
 
 	/* Avoid trying to drop postgres db while we are connected to it. */
 	if (maintenance_db == NULL && strcmp(dbname, "postgres") == 0)
@@ -131,11 +135,64 @@
 	conn = connectMaintenanceDatabase(maintenance_db,
 							host, port, username, prompt_password, progname);
 
+	/*disallow database connections and terminate client connections*/
+	if (kill) 
+	{
+		appendPQExpBuffer(&sql, "SELECT datconnlimit FROM pg_database WHERE datname= '%s';",fmtId(dbname));
+		result = executeQuery(conn, sql.data, progname, echo);
+		// get the datconnĺimit to do cleanup in case of dropdb fail
+		if (PQntuples(result) == 1)
+		{
+			database_conn_limit = PQgetvalue(result, 0, 0);
+		} else 
+		{
+			fprintf(stderr, _("%s: database removal failed: %s\n"),
+			progname, dbname);
+			PQclear(result);
+			PQfinish(conn);
+			exit(1);
+		}
+		PQclear(result);
+		resetPQExpBuffer(&sql);
+		//new connections are not allowed 
+		appendPQExpBuffer(&sql, "UPDATE pg_database SET datconnlimit = 0 WHERE datname= '%s';\n",fmtId(dbname));
+		if (echo)
+			printf("%s", sql.data);
+		result = PQexec(conn, sql.data);
+		if (PQresultStatus(result) != PGRES_COMMAND_OK)
+		{
+			fprintf(stderr, _("%s: database removal failed: %s\n"),
+			progname, dbname);
+			PQclear(result);
+			PQfinish(conn);
+			exit(1);
+		}
+		PQclear(result);
+		resetPQExpBuffer(&sql);
+		// terminate client connections
+		appendPQExpBuffer(&sql, "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname ='%s';",fmtId(dbname));
+		result = executeQuery(conn, sql.data, progname, echo);
+		PQclear(result);
+		resetPQExpBuffer(&sql);
+	}
+
+	appendPQExpBuffer(&sql, "DROP DATABASE %s%s;\n",
+					  (if_exists ? "IF EXISTS " : ""), fmtId(dbname));
+
 	if (echo)
 		printf("%s", sql.data);
 	result = PQexec(conn, sql.data);
 	if (PQresultStatus(result) != PGRES_COMMAND_OK)
 	{
+		//cleanup: reset datconnlimit	
+		if (kill)
+		{
+			resetPQExpBuffer(&sql);
+			appendPQExpBuffer(&sql, "UPDATE pg_database SET datconnlimit = %s WHERE datname= '%s';",database_conn_limit,fmtId(dbname));
+			if (echo)
+				printf("%s", sql.data);
+			result = PQexec(conn, sql.data);
+		}
 		fprintf(stderr, _("%s: database removal failed: %s"),
 				progname, PQerrorMessage(conn));
 		PQfinish(conn);
@@ -159,6 +216,7 @@
 	printf(_("  -i, --interactive         prompt before deleting anything\n"));
 	printf(_("  -V, --version             output version information, then exit\n"));
 	printf(_("  --if-exists               don't report error if database doesn't exist\n"));
+	printf(_("  -k, --kill                kill client connections\n"));
 	printf(_("  -?, --help                show this help, then exit\n"));
 	printf(_("\nConnection options:\n"));
 	printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
-- 
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