]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/adt/quote.c
Add support for EUI-64 MAC addresses as macaddr8
[postgresql] / src / backend / utils / adt / quote.c
index 45e4c1133dc4049544019b9dc19a84784eb24f48..43e5bb79621e28c3c1829b79adf25dfb5be751af 100644 (file)
@@ -3,27 +3,19 @@
  * quote.c
  *       Functions for quoting identifiers and literals
  *
- * Portions Copyright (c) 2000, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2000-2017, PostgreSQL Global Development Group
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v 1.5 2001/10/25 05:49:45 momjian Exp $
+ *       src/backend/utils/adt/quote.c
  *
  *-------------------------------------------------------------------------
  */
-#include <ctype.h>
-
 #include "postgres.h"
 
-#include "mb/pg_wchar.h"
 #include "utils/builtins.h"
 
 
-static bool quote_ident_required(text *iptr);
-static text *do_quote_ident(text *iptr);
-static text *do_quote_literal(text *iptr);
-
-
 /*
  * quote_ident -
  *       returns a properly quoted identifier
@@ -31,262 +23,109 @@ static text *do_quote_literal(text *iptr);
 Datum
 quote_ident(PG_FUNCTION_ARGS)
 {
-       text       *t = PG_GETARG_TEXT_P(0);
-       text       *result;
-
-       if (quote_ident_required(t))
-               result = do_quote_ident(t);
-       else
-       {
-               result = (text *) palloc(VARSIZE(t));
-               memcpy(result, t, VARSIZE(t));
-       }
-
-       PG_FREE_IF_COPY(t, 0);
-
-       PG_RETURN_TEXT_P(result);
-}
-
-/*
- * quote_literal -
- *       returns a properly quoted literal
- */
-Datum
-quote_literal(PG_FUNCTION_ARGS)
-{
-       text       *t = PG_GETARG_TEXT_P(0);
-       text       *result;
+       text       *t = PG_GETARG_TEXT_PP(0);
+       const char *qstr;
+       char       *str;
 
-       result = do_quote_literal(t);
-
-       PG_FREE_IF_COPY(t, 0);
-
-       PG_RETURN_TEXT_P(result);
+       str = text_to_cstring(t);
+       qstr = quote_identifier(str);
+       PG_RETURN_TEXT_P(cstring_to_text(qstr));
 }
 
-
 /*
- * MULTIBYTE dependant internal functions follow
+ * 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
+ * literal will be used, and so we must generate a result that
+ * will work with either setting.  Take a look at what dblink
+ * uses this for before thinking you know better.
  */
-
-
-#ifndef MULTIBYTE
-
-/* Check if a given identifier needs quoting */
-static bool
-quote_ident_required(text *iptr)
+static size_t
+quote_literal_internal(char *dst, const char *src, size_t len)
 {
-       char       *cp;
-       char       *ep;
+       const char *s;
+       char       *savedst = dst;
 
-       cp = VARDATA(iptr);
-       ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
-
-       if (cp >= ep)
-               return true;
-
-       if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
-               return true;
-
-       while ((++cp) < ep)
+       for (s = src; s < src + len; s++)
        {
-               if (*cp >= 'a' && *cp <= 'z')
-                       continue;
-               if (*cp >= '0' && *cp <= '9')
-                       continue;
-               if (*cp == '_')
-                       continue;
-
-               return true;
+               if (*s == '\\')
+               {
+                       *dst++ = ESCAPE_STRING_SYNTAX;
+                       break;
+               }
        }
 
-       return false;
-}
-
-/* Return a properly quoted identifier */
-static text *
-do_quote_ident(text *iptr)
-{
-       text       *result;
-       char       *cp1;
-       char       *cp2;
-       int                     len;
-
-       len = VARSIZE(iptr) - VARHDRSZ;
-       result = (text *) palloc(len * 2 + VARHDRSZ + 2);
-
-       cp1 = VARDATA(iptr);
-       cp2 = VARDATA(result);
-
-       *cp2++ = '"';
+       *dst++ = '\'';
        while (len-- > 0)
        {
-               if (*cp1 == '"')
-                       *cp2++ = '"';
-               if (*cp1 == '\\')
-                       *cp2++ = '\\';
-               *cp2++ = *cp1++;
+               if (SQL_STR_DOUBLE(*src, true))
+                       *dst++ = *src;
+               *dst++ = *src++;
        }
-       *cp2++ = '"';
-
-       VARATT_SIZEP(result) = cp2 - ((char *) result);
+       *dst++ = '\'';
 
-       return result;
+       return dst - savedst;
 }
 
-/* Return a properly quoted literal value */
-static text *
-do_quote_literal(text *lptr)
+/*
+ * quote_literal -
+ *       returns a properly quoted literal
+ */
+Datum
+quote_literal(PG_FUNCTION_ARGS)
 {
+       text       *t = PG_GETARG_TEXT_PP(0);
        text       *result;
        char       *cp1;
        char       *cp2;
        int                     len;
 
-       len = VARSIZE(lptr) - VARHDRSZ;
-       result = (text *) palloc(len * 2 + VARHDRSZ + 2);
+       len = VARSIZE_ANY_EXHDR(t);
+       /* We make a worst-case result area; wasting a little space is OK */
+       result = (text *) palloc(len * 2 + 3 + VARHDRSZ);
 
-       cp1 = VARDATA(lptr);
+       cp1 = VARDATA_ANY(t);
        cp2 = VARDATA(result);
 
-       *cp2++ = '\'';
-       while (len-- > 0)
-       {
-               if (*cp1 == '\'')
-                       *cp2++ = '\'';
-               if (*cp1 == '\\')
-                       *cp2++ = '\\';
-               *cp2++ = *cp1++;
-       }
-       *cp2++ = '\'';
-
-       VARATT_SIZEP(result) = cp2 - ((char *) result);
-
-       return result;
-}
-
-#else
-
-/* Check if a given identifier needs quoting (MULTIBYTE version) */
-static bool
-quote_ident_required(text *iptr)
-{
-       char       *cp;
-       char       *ep;
-
-       cp = VARDATA(iptr);
-       ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
-
-       if (cp >= ep)
-               return true;
-
-       if (pg_mblen(cp) != 1)
-               return true;
-       if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
-               return true;
-
-       while ((++cp) < ep)
-       {
-               if (pg_mblen(cp) != 1)
-                       return true;
-
-               if (*cp >= 'a' && *cp <= 'z')
-                       continue;
-               if (*cp >= '0' && *cp <= '9')
-                       continue;
-               if (*cp == '_')
-                       continue;
+       SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len));
 
-               return true;
-       }
-
-       return false;
+       PG_RETURN_TEXT_P(result);
 }
 
-/* Return a properly quoted identifier (MULTIBYTE version) */
-static text *
-do_quote_ident(text *iptr)
+/*
+ * quote_literal_cstr -
+ *       returns a properly quoted literal
+ */
+char *
+quote_literal_cstr(const char *rawstr)
 {
-       text       *result;
-       char       *cp1;
-       char       *cp2;
+       char       *result;
        int                     len;
-       int                     wl;
+       int                     newlen;
 
-       len = VARSIZE(iptr) - VARHDRSZ;
-       result = (text *) palloc(len * 2 + VARHDRSZ + 2);
+       len = strlen(rawstr);
+       /* We make a worst-case result area; wasting a little space is OK */
+       result = palloc(len * 2 + 3 + 1);
 
-       cp1 = VARDATA(iptr);
-       cp2 = VARDATA(result);
-
-       *cp2++ = '"';
-       while (len > 0)
-       {
-               if ((wl = pg_mblen(cp1)) != 1)
-               {
-                       len -= wl;
-
-                       while (wl-- > 0)
-                               *cp2++ = *cp1++;
-                       continue;
-               }
-
-               if (*cp1 == '"')
-                       *cp2++ = '"';
-               if (*cp1 == '\\')
-                       *cp2++ = '\\';
-               *cp2++ = *cp1++;
-
-               len--;
-       }
-       *cp2++ = '"';
-
-       VARATT_SIZEP(result) = cp2 - ((char *) result);
+       newlen = quote_literal_internal(result, rawstr, len);
+       result[newlen] = '\0';
 
        return result;
 }
 
-/* Return a properly quoted literal value (MULTIBYTE version) */
-static text *
-do_quote_literal(text *lptr)
+/*
+ * quote_nullable -
+ *       Returns a properly quoted literal, with null values returned
+ *       as the text string 'NULL'.
+ */
+Datum
+quote_nullable(PG_FUNCTION_ARGS)
 {
-       text       *result;
-       char       *cp1;
-       char       *cp2;
-       int                     len;
-       int                     wl;
-
-       len = VARSIZE(lptr) - VARHDRSZ;
-       result = (text *) palloc(len * 2 + VARHDRSZ + 2);
-
-       cp1 = VARDATA(lptr);
-       cp2 = VARDATA(result);
-
-       *cp2++ = '\'';
-       while (len > 0)
-       {
-               if ((wl = pg_mblen(cp1)) != 1)
-               {
-                       len -= wl;
-
-                       while (wl-- > 0)
-                               *cp2++ = *cp1++;
-                       continue;
-               }
-
-               if (*cp1 == '\'')
-                       *cp2++ = '\'';
-               if (*cp1 == '\\')
-                       *cp2++ = '\\';
-               *cp2++ = *cp1++;
-
-               len--;
-       }
-       *cp2++ = '\'';
-
-       VARATT_SIZEP(result) = cp2 - ((char *) result);
-
-       return result;
+       if (PG_ARGISNULL(0))
+               PG_RETURN_TEXT_P(cstring_to_text("NULL"));
+       else
+               PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
+                                                                                       PG_GETARG_DATUM(0)));
 }
-#endif