diff --git a/lib/modules/Sql.pmod/pgsql_util.pmod b/lib/modules/Sql.pmod/pgsql_util.pmod
index 521b7f49763bb28d104a6170040b28c842c5f046..3e17ddc331c411e4b00bf62b2c01efbd12be8533 100644
--- a/lib/modules/Sql.pmod/pgsql_util.pmod
+++ b/lib/modules/Sql.pmod/pgsql_util.pmod
@@ -750,33 +750,40 @@ class sql_result {
   //! Returns the command-complete status for this query.
   //!
   //! @note
-  //!  This method should normally be called after EOF has been reached.
-  //!  If it is called before, all unfetched result rows will be discarded.
-  //!
-  //! @note
   //! This function is PostgreSQL-specific.
   //!
-  //!  @[affected_rows()], @[eof()]
+  //! @seealso
+  //!  @[affected_rows()]
   /*semi*/final string status_command_complete() {
-    if (!statuscmdcomplete)
-      while (fetch_row_array());
+    if (!statuscmdcomplete) {
+      if (!datarowtypes)
+        waitfordescribe();
+      {
+        Thread.MutexKey lock = closemux->lock();
+        if (_fetchlimit)
+          _sendexecute(_fetchlimit = 0);
+        lock = _ddescribemux->lock();
+        if (!statuscmdcomplete)
+          PT(_ddescribe->wait(lock));
+      }
+      if (this)		// If object already destructed, skip the next call
+        trydelayederror();	// since you cannot call functions anymore
+      else
+        error(LOSTERROR);
+    }
     return statuscmdcomplete;
   }
 
   //! Returns the number of affected rows by this query.
   //!
   //! @note
-  //!  This method should normally be called after EOF has been reached.
-  //!  If it is called before, all unfetched result rows will be discarded.
-  //!
-  //! @note
   //! This function is PostgreSQL-specific.
   //!
   //! @seealso
-  //!  @[status_command_complete()], @[eof()]
+  //!  @[num_rows()], @[status_command_complete()]
   /*semi*/final int affected_rows() {
     int rows;
-    sscanf(status_command_complete(), "%*s %d %d", rows, rows);
+    sscanf(status_command_complete() || "", "%*s %d %d", rows, rows);
     return rows;
   }
 
@@ -1380,8 +1387,11 @@ class sql_result {
 
   final void _releasesession(void|string statusccomplete) {
     c->runningportals[this] = 0;
-    if (statusccomplete && !statuscmdcomplete)
+    if (statusccomplete && !statuscmdcomplete) {
+      Thread.MutexKey lock = _ddescribemux->lock();
       statuscmdcomplete = statusccomplete;
+      _ddescribe->broadcast();
+    }
     inflight = 0;
     conxsess plugbuffer;
     if (!catch(plugbuffer = c->start()))
@@ -2458,9 +2468,9 @@ class proxy {
   final void close() {
     throwdelayederror(this);
     {
-      Thread.MutexKey lock;
-      while (qportals && qportals->size())
-        sleep(0.1, 1);			// Drain portal queue to completion
+      Thread.MutexKey lock = shortmux->lock();
+      portalsinflight->wait_till_drained(lock);	// Drain portal queue to completion
+      lock = 0;
       if (unnamedstatement)
         termlock = unnamedstatement->lock(1);
       if (c)				// Prevent trivial backtraces