diff --git a/org/postgresql/PGResultSetMetaData.java b/org/postgresql/PGResultSetMetaData.java
index 56dc1c9..0b3fd77 100644
--- a/org/postgresql/PGResultSetMetaData.java
+++ b/org/postgresql/PGResultSetMetaData.java
@@ -9,6 +9,8 @@ package org.postgresql;
 
 import java.sql.SQLException;
 
+import org.postgresql.core.Field;
+
 public interface PGResultSetMetaData
 {
 
@@ -36,4 +38,12 @@ public interface PGResultSetMetaData
      */
     public String getBaseSchemaName(int column) throws SQLException;
 
+    /**
+     * Is a column Text or Binary?
+     *
+     * @see Field#BINARY_FORMAT
+     * @see Field#TEXT_FORMAT
+     * @since 9.4
+     */
+    public int getFormat(int column) throws SQLException;
 }
diff --git a/org/postgresql/jdbc2/AbstractJdbc2ResultSetMetaData.java b/org/postgresql/jdbc2/AbstractJdbc2ResultSetMetaData.java
index 160f2d1..84a08a3 100644
--- a/org/postgresql/jdbc2/AbstractJdbc2ResultSetMetaData.java
+++ b/org/postgresql/jdbc2/AbstractJdbc2ResultSetMetaData.java
@@ -335,6 +335,17 @@ public abstract class AbstractJdbc2ResultSetMetaData implements PGResultSetMetaD
     }
 
     /*
+     * Is a column Text or Binary?
+     *
+     * @param column the first column is 1, the second is 2...
+     * @return column name, or "" if not applicable
+     * @exception SQLException if a database access error occurs
+     */
+    public int getFormat(int column) throws SQLException {
+        return getField(column).getFormat();
+    }
+
+    /*
      * Whats is the column's data source specific type name?
      *
      * @param column the first column is 1, the second is 2, etc.
diff --git a/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/org/postgresql/jdbc2/AbstractJdbc2Statement.java
index 7671cf6..0ccc7b1 100644
--- a/org/postgresql/jdbc2/AbstractJdbc2Statement.java
+++ b/org/postgresql/jdbc2/AbstractJdbc2Statement.java
@@ -525,7 +525,8 @@ public abstract class AbstractJdbc2Statement implements BaseStatement
                 flags &= ~(QueryExecutor.QUERY_NO_RESULTS);
         }
 
-        // Only use named statements after we hit the threshold
+        // Only use named statements after we hit the threshold. Note that only
+        // named statements can be transferred in binary format.
         if (preparedQuery != null)
         {
             ++m_useCount; // We used this statement once more.
@@ -540,7 +541,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement
         if (concurrency != ResultSet.CONCUR_READ_ONLY)
             flags |= QueryExecutor.QUERY_NO_BINARY_TRANSFER;
 
-        if (ForceBinaryTransfers) {
+        if (ForceBinaryTransfers || (flags & QueryExecutor.QUERY_ONESHOT) == 0) {
                 int flags2 = flags | QueryExecutor.QUERY_DESCRIBE_ONLY;
                 StatementResultHandler handler2 = new StatementResultHandler();
                 connection.getQueryExecutor().execute(queryToExecute, queryParameters, handler2, 0, 0, flags2);
diff --git a/org/postgresql/test/jdbc4/BinaryTest.java b/org/postgresql/test/jdbc4/BinaryTest.java
new file mode 100644
index 0000000..fddfa75
--- /dev/null
+++ b/org/postgresql/test/jdbc4/BinaryTest.java
@@ -0,0 +1,94 @@
+package org.postgresql.test.jdbc4;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.postgresql.PGConnection;
+import org.postgresql.PGResultSetMetaData;
+import org.postgresql.PGStatement;
+import org.postgresql.core.Field;
+import org.postgresql.test.TestUtil;
+
+import junit.framework.TestCase;
+
+/**
+ * We don't want to use the binary protocol for one-off queries as it involves
+ * another round-trip to the server to 'describe' the query. If we use the query
+ * enough times (see {@link PGConnection#setPrepareThreshold(int)} then we'll
+ * change to using the binary protocol to save bandwidth and reduce decoding
+ * time.
+ */
+public class BinaryTest extends TestCase {
+    private Connection connection;
+    private ResultSet results;
+    private PreparedStatement statement;
+
+    public BinaryTest(String name) {
+        super(name);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        connection = TestUtil.openDB();
+        statement = connection.prepareStatement("select 1");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        TestUtil.closeDB(connection);
+    }
+
+    public void testPreparedStatement_3() throws Exception {
+        ((PGStatement) statement).setPrepareThreshold(3);
+
+        results = statement.executeQuery();
+        assertEquals(Field.TEXT_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.TEXT_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.BINARY_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.BINARY_FORMAT, getFormat(results));
+    }
+
+    public void testPreparedStatement_1() throws Exception {
+        ((PGStatement) statement).setPrepareThreshold(1);
+
+        results = statement.executeQuery();
+        assertEquals(Field.BINARY_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.BINARY_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.BINARY_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.BINARY_FORMAT, getFormat(results));
+    }
+
+    public void testPreparedStatement_0() throws Exception {
+        ((PGStatement) statement).setPrepareThreshold(0);
+
+        results = statement.executeQuery();
+        assertEquals(Field.TEXT_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.TEXT_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.TEXT_FORMAT, getFormat(results));
+
+        results = statement.executeQuery();
+        assertEquals(Field.TEXT_FORMAT, getFormat(results));
+    }
+
+    private int getFormat(ResultSet results) throws SQLException {
+        return ((PGResultSetMetaData) results.getMetaData()).getFormat(1);
+    }
+}
diff --git a/org/postgresql/test/jdbc4/Jdbc4TestSuite.java b/org/postgresql/test/jdbc4/Jdbc4TestSuite.java
index 0bf8b30..ca0b175 100644
--- a/org/postgresql/test/jdbc4/Jdbc4TestSuite.java
+++ b/org/postgresql/test/jdbc4/Jdbc4TestSuite.java
@@ -31,6 +31,7 @@ public class Jdbc4TestSuite extends TestSuite
         suite.addTestSuite(ArrayTest.class);
         suite.addTestSuite(ConnectionTest.class);
         suite.addTestSuite(WrapperTest.class);
+        suite.addTestSuite(BinaryTest.class);
 
         Connection connection = TestUtil.openDB();
         try
