2000-09-05 22:25:14 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* quote.c
|
|
|
|
* Functions for quoting identifiers and literals
|
|
|
|
*
|
2001-01-24 20:43:33 +01:00
|
|
|
* Portions Copyright (c) 2000, PostgreSQL Global Development Group
|
2000-09-05 22:25:14 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2001-01-24 20:43:33 +01:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v 1.3 2001/01/24 19:43:14 momjian Exp $
|
2000-09-05 22:25:14 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#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
|
|
|
|
*/
|
|
|
|
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);
|
|
|
|
|
2000-09-12 21:39:42 +02:00
|
|
|
PG_RETURN_TEXT_P(result);
|
2000-09-05 22:25:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* quote_literal -
|
|
|
|
* returns a properly quoted literal
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
quote_literal(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
text *t = PG_GETARG_TEXT_P(0);
|
|
|
|
text *result;
|
|
|
|
|
|
|
|
result = do_quote_literal(t);
|
|
|
|
|
|
|
|
PG_FREE_IF_COPY(t, 0);
|
|
|
|
|
2000-09-12 21:39:42 +02:00
|
|
|
PG_RETURN_TEXT_P(result);
|
2000-09-05 22:25:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MULTIBYTE dependant internal functions follow
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef MULTIBYTE
|
|
|
|
|
|
|
|
/* Check if a given identifier needs quoting */
|
|
|
|
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 (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
while((++cp) < ep)
|
|
|
|
{
|
|
|
|
if (*cp >= 'a' && *cp <= 'z') continue;
|
|
|
|
if (*cp >= '0' && *cp <= '9') continue;
|
|
|
|
if (*cp == '_') continue;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
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++ = '"';
|
|
|
|
while(len-- > 0)
|
|
|
|
{
|
|
|
|
if (*cp1 == '"')
|
|
|
|
*cp2++ = '"';
|
|
|
|
if (*cp1 == '\\')
|
|
|
|
*cp2++ = '\\';
|
|
|
|
*cp2++ = *cp1++;
|
|
|
|
}
|
|
|
|
*cp2++ = '"';
|
|
|
|
|
|
|
|
VARATT_SIZEP(result) = cp2 - ((char *)result);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return a properly quoted literal value */
|
|
|
|
static text *
|
|
|
|
do_quote_literal(text *lptr)
|
|
|
|
{
|
|
|
|
text *result;
|
|
|
|
char *cp1;
|
|
|
|
char *cp2;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = VARSIZE(lptr) - VARHDRSZ;
|
|
|
|
result = (text *)palloc(len * 2 + VARHDRSZ + 2);
|
|
|
|
|
|
|
|
cp1 = VARDATA(lptr);
|
|
|
|
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;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return a properly quoted identifier (MULTIBYTE version) */
|
|
|
|
static text *
|
|
|
|
do_quote_ident(text *iptr)
|
|
|
|
{
|
|
|
|
text *result;
|
|
|
|
char *cp1;
|
|
|
|
char *cp2;
|
|
|
|
int len;
|
|
|
|
int wl;
|
|
|
|
|
|
|
|
len = VARSIZE(iptr) - VARHDRSZ;
|
|
|
|
result = (text *)palloc(len * 2 + VARHDRSZ + 2);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return a properly quoted literal value (MULTIBYTE version) */
|
|
|
|
static text *
|
|
|
|
do_quote_literal(text *lptr)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|