diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 0e604b7..c129979 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -1121,6 +1121,10 @@ ProcessCopyOptions(CopyState cstate,
 		}
 		else if (strcmp(defel->defname, "encoding") == 0)
 		{
+			if (cstate->binary)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("cannot specify ENCODING in BINARY mode")));
 			if (cstate->file_encoding >= 0)
 				ereport(ERROR,
 						(errcode(ERRCODE_SYNTAX_ERROR),
@@ -1153,10 +1157,18 @@ ProcessCopyOptions(CopyState cstate,
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("cannot specify NULL in BINARY mode")));
 
+	if (cstate->binary && cstate->escape)
+		ereport(ERROR,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("cannot specify ESCAPE in BINARY mode")));
+
 	/* Set defaults for omitted options */
 	if (!cstate->delim)
 		cstate->delim = cstate->csv_mode ? "," : "\t";
 
+	if (!cstate->csv_mode && !cstate->escape)
+		cstate->escape = "\\";
+
 	if (!cstate->null_print)
 		cstate->null_print = cstate->csv_mode ? "" : "\\N";
 	cstate->null_print_len = strlen(cstate->null_print);
@@ -1227,16 +1239,15 @@ ProcessCopyOptions(CopyState cstate,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("COPY delimiter and quote must be different")));
 
-	/* Check escape */
-	if (!cstate->csv_mode && cstate->escape != NULL)
-		ereport(ERROR,
+	if (cstate->csv_mode && strlen(cstate->escape) != 1)
+		ereport(ERROR,de
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("COPY escape available only in CSV mode")));
+				 errmsg("COPY escape must be a single one-byte character in CSV mode")));
 
-	if (cstate->csv_mode && strlen(cstate->escape) != 1)
+	if (strlen(cstate->escape) > 1)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("COPY escape must be a single one-byte character")));
+				 errmsg("COPY escape must be empty or a single one-byte charactor")));
 
 	/* Check force_quote */
 	if (!cstate->csv_mode && (cstate->force_quote || cstate->force_quote_all))
@@ -3596,6 +3607,7 @@ static int
 CopyReadAttributesText(CopyState cstate)
 {
 	char		delimc = cstate->delim[0];
+	char		escapec = cstate->escape[0];
 	int			fieldno;
 	char	   *output_ptr;
 	char	   *cur_ptr;
@@ -3677,7 +3689,7 @@ CopyReadAttributesText(CopyState cstate)
 				found_delim = true;
 				break;
 			}
-			if (c == '\\')
+			if (c == escapec)
 			{
 				if (cur_ptr >= line_end_ptr)
 					break;
@@ -4055,6 +4067,7 @@ CopyAttributeOutText(CopyState cstate, char *string)
 	char	   *start;
 	char		c;
 	char		delimc = cstate->delim[0];
+	char        escapec = cstate->escape[0];
 
 	if (cstate->need_transcoding)
 		ptr = pg_server_to_any(string, strlen(string), cstate->file_encoding);
@@ -4119,14 +4132,14 @@ CopyAttributeOutText(CopyState cstate, char *string)
 				}
 				/* if we get here, we need to convert the control char */
 				DUMPSOFAR();
-				CopySendChar(cstate, '\\');
+				CopySendChar(cstate, escapec);
 				CopySendChar(cstate, c);
 				start = ++ptr;	/* do not include char in next run */
 			}
-			else if (c == '\\' || c == delimc)
+			else if (c == escapec || c == delimc)
 			{
 				DUMPSOFAR();
-				CopySendChar(cstate, '\\');
+				CopySendChar(cstate, escapec);
 				start = ptr++;	/* we include char in next run */
 			}
 			else if (IS_HIGHBIT_SET(c))
@@ -4179,14 +4192,14 @@ CopyAttributeOutText(CopyState cstate, char *string)
 				}
 				/* if we get here, we need to convert the control char */
 				DUMPSOFAR();
-				CopySendChar(cstate, '\\');
+				CopySendChar(cstate, escapec);
 				CopySendChar(cstate, c);
 				start = ++ptr;	/* do not include char in next run */
 			}
-			else if (c == '\\' || c == delimc)
+			else if (c == escapec || c == delimc)
 			{
 				DUMPSOFAR();
-				CopySendChar(cstate, '\\');
+				CopySendChar(cstate, escapec);
 				start = ptr++;	/* we include char in next run */
 			}
 			else
diff --git a/src/test/regress/input/copy.source b/src/test/regress/input/copy.source
index cb13606..be6dc9e 100644
--- a/src/test/regress/input/copy.source
+++ b/src/test/regress/input/copy.source
@@ -133,3 +133,19 @@ this is just a line full of junk that would error out if parsed
 \.
 
 copy copytest3 to stdout csv header;
+
+CREATE TEMP TABLE t (d json);
+COPY t from stdin;
+{"key": "value"}
+\.
+COPY t from stdin;
+{"key": "val\"ue"}
+\.
+COPY t from stdin with escape '';
+{"key": "val\"ue"}
+\.
+COPY t from stdin with escape '';
+{"key": "value"}
+\.
+DROP TABLE t;
+
diff --git a/src/test/regress/output/copy.source b/src/test/regress/output/copy.source
index b7e372d..ced39eb 100644
--- a/src/test/regress/output/copy.source
+++ b/src/test/regress/output/copy.source
@@ -95,3 +95,13 @@ copy copytest3 to stdout csv header;
 c1,"col with , comma","col with "" quote"
 1,a,1
 2,b,2
+CREATE TEMP TABLE t (d json);
+COPY t from stdin;
+COPY t from stdin;
+ERROR:  invalid input syntax for type json
+DETAIL:  Token "ue" is invalid.
+CONTEXT:  JSON data, line 1: {"key": "val"ue...
+COPY t, line 1, column d: "{"key": "val"ue"}"
+COPY t from stdin with escape '';
+COPY t from stdin with escape '';
+DROP TABLE t;
