static char *get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals);
 static char *get_sql_delete(Relation rel, int *pkattnums, int pknumatts, char **tgt_pkattvals);
 static char *get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals);
-static char *quote_literal_cstr(char *rawstr);
 static char *quote_ident_cstr(char *rawstr);
 static int get_attnum_pk_pos(int *pkattnums, int pknumatts, int key);
 static HeapTuple get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals);
    return (buf.data);
 }
 
-/*
- * Return a properly quoted literal value.
- * Uses quote_literal in quote.c
- */
-static char *
-quote_literal_cstr(char *rawstr)
-{
-   text       *rawstr_text;
-   text       *result_text;
-   char       *result;
-
-   rawstr_text = cstring_to_text(rawstr);
-   result_text = DatumGetTextP(DirectFunctionCall1(quote_literal,
-                                             PointerGetDatum(rawstr_text)));
-   result = text_to_cstring(result_text);
-
-   return result;
-}
-
 /*
  * Return a properly quoted identifier.
  * Uses quote_ident in quote.c
 
                             MemoryContext per_query_ctx,
                             AttInMetadata *attinmeta,
                             Tuplestorestate *tupstore);
-static char *quote_literal_cstr(char *rawstr);
 
 typedef struct
 {
    /* OK, the two tupdescs are compatible for our purposes */
    return true;
 }
-
-/*
- * Return a properly quoted literal value.
- * Uses quote_literal in quote.c
- */
-static char *
-quote_literal_cstr(char *rawstr)
-{
-   text       *rawstr_text;
-   text       *result_text;
-   char       *result;
-
-   rawstr_text = cstring_to_text(rawstr);
-   result_text = DatumGetTextP(DirectFunctionCall1(quote_literal,
-                                             PointerGetDatum(rawstr_text)));
-   result = text_to_cstring(result_text);
-
-   return result;
-}
 
 }
 
 /*
- * quote_literal -
- *   returns a properly quoted literal
+ * quote_literal_internal -
+ *   helper function for quote_literal and quote_literal_cstr
  *
  * NOTE: think not to make this function's behavior change with
  * standard_conforming_strings.  We don't know where the result
  * will work with either setting.  Take a look at what dblink
  * uses this for before thinking you know better.
  */
+static size_t
+quote_literal_internal(char *dst, char *src, size_t len)
+{
+   char       *s;
+   char       *savedst = dst;
+
+   for (s = src; s < src + len; s++)
+   {
+       if (*s == '\\')
+       {
+           *dst++ = ESCAPE_STRING_SYNTAX;
+           break;
+       }
+   }
+
+   *dst++ = '\'';
+   while (len-- > 0)
+   {
+       if (SQL_STR_DOUBLE(*src, true))
+           *dst++ = *src;
+       *dst++ = *src++;
+   }
+   *dst++ = '\'';
+
+   return dst - savedst;
+}
+
+/*
+ * quote_literal -
+ *   returns a properly quoted literal
+ */
 Datum
 quote_literal(PG_FUNCTION_ARGS)
 {
    cp1 = VARDATA(t);
    cp2 = VARDATA(result);
 
-   for (; len-- > 0; cp1++)
-   {
-       if (*cp1 == '\\')
-       {
-           *cp2++ = ESCAPE_STRING_SYNTAX;
-           break;
-       }
-   }
+   SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len));
 
-   len = VARSIZE(t) - VARHDRSZ;
-   cp1 = VARDATA(t);
+   PG_RETURN_TEXT_P(result);
+}
 
-   *cp2++ = '\'';
-   while (len-- > 0)
-   {
-       if (SQL_STR_DOUBLE(*cp1, true))
-           *cp2++ = *cp1;
-       *cp2++ = *cp1++;
-   }
-   *cp2++ = '\'';
+/*
+ * quote_literal_cstr -
+ *   returns a properly quoted literal
+ */
+char *
+quote_literal_cstr(char *rawstr)
+{
+   char       *result;
+   int         len;
+   int         newlen;
 
-   SET_VARSIZE(result, cp2 - ((char *) result));
+   len = strlen(rawstr);
+   /* We make a worst-case result area; wasting a little space is OK */
+   result = palloc(len * 2 + 3);
 
-   PG_RETURN_TEXT_P(result);
+   newlen = quote_literal_internal(result, rawstr, len);
+   result[newlen] = '\0';
+
+   return result;
 }
 
 /*
 
 /* quote.c */
 extern Datum quote_ident(PG_FUNCTION_ARGS);
 extern Datum quote_literal(PG_FUNCTION_ARGS);
+extern char *quote_literal_cstr(char *rawstr);
 extern Datum quote_nullable(PG_FUNCTION_ARGS);
 
 /* guc.c */
 
   5 | ahoj | ahoj
 (11 rows)
 
+select quote_literal('');
+ quote_literal 
+---------------
+ ''
+(1 row)
+
+select quote_literal('abc''');
+ quote_literal 
+---------------
+ 'abc'''
+(1 row)
+
+select quote_literal(e'\\');
+ quote_literal 
+---------------
+ E'\\'
+(1 row)
+
 
 select concat_ws(NULL,10,20,null,30) is null;
 select reverse('abcde');
 select i, left('ahoj', i), right('ahoj', i) from generate_series(-5, 5) t(i) order by i;
+select quote_literal('');
+select quote_literal('abc''');
+select quote_literal(e'\\');