diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 864f195992..2ba511d46f 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -1105,7 +1105,7 @@ SendQuery(const char *query)
 		on_error_rollback_savepoint = true;
 	}
 
-	if (pset.gdesc_flag)
+	if (pset.gdesc_flag || pset.parse_only)
 	{
 		/* Describe query's result columns, without executing it */
 		OK = DescribeQuery(query, &elapsed_msec);
@@ -1285,6 +1285,19 @@ DescribeQuery(const char *query, double *elapsed_msec)
 	}
 	PQclear(result);
 
+	if (pset.parse_only)
+	{
+		/*
+		 * If you wanted to, here would be a good place to output a message.
+		 * By normal practice, success returns nothing, not even a
+		 * command tag, to differentiate from normal execution.
+		 *
+		fprintf(pset.queryFout,
+				_("Parsed successfully.\n"));
+		 */
+		return true;
+	}
+
 	result = PQdescribePrepared(pset.db, "");
 	OK = AcceptResult(result, true) &&
 		(PQresultStatus(result) == PGRES_COMMAND_OK);
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 2399cffa3f..da6c0454cf 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -112,6 +112,7 @@ typedef struct _psqlSettings
 	uint64		stmt_lineno;	/* line number inside the current statement */
 
 	bool		timing;			/* enable timing of all queries */
+	bool		parse_only;		/* enable parse_only mode */
 
 	FILE	   *logfile;		/* session log file handle */
 
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index f5b9e268f2..caeb83bfac 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -520,6 +520,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts *options)
 		{"no-psqlrc", no_argument, NULL, 'X'},
 		{"help", optional_argument, NULL, 1},
 		{"csv", no_argument, NULL, 2},
+		{"parse-only", no_argument, NULL, 3},
 		{NULL, 0, NULL, 0}
 	};
 
@@ -713,6 +714,9 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts *options)
 			case 2:
 				pset.popt.topt.format = PRINT_CSV;
 				break;
+			case 3:
+				pset.parse_only = true;
+				break;
 			default:
 		unknown_option:
 				/* getopt_long already emitted a complaint */
