postgresql/src/backend/utils/adt/quote.c

192 lines
3.0 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* quote.c
* Functions for quoting identifiers and literals
*
2005-01-01 06:43:09 +01:00
* Portions Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
2005-01-01 06:43:09 +01:00
* $PostgreSQL: pgsql/src/backend/utils/adt/quote.c,v 1.14 2005/01/01 05:43:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <ctype.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))
2001-03-22 05:01:46 +01:00
result = do_quote_ident(t);
else
{
2001-03-22 05:01:46 +01:00
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;
result = do_quote_literal(t);
PG_FREE_IF_COPY(t, 0);
PG_RETURN_TEXT_P(result);
}
/*
* Check if a given identifier needs quoting
*/
static bool
quote_ident_required(text *iptr)
{
2001-03-22 05:01:46 +01:00
char *cp;
char *ep;
cp = VARDATA(iptr);
2001-03-22 05:01:46 +01:00
ep = VARDATA(iptr) + VARSIZE(iptr) - VARHDRSZ;
if (cp >= ep)
return true;
2001-03-22 05:01:46 +01:00
if (pg_mblen(cp) != 1)
return true;
2001-03-22 05:01:46 +01:00
if (!(*cp == '_' || (*cp >= 'a' && *cp <= 'z')))
return true;
2001-03-22 05:01:46 +01:00
while ((++cp) < ep)
{
if (pg_mblen(cp) != 1)
return true;
2001-03-22 05:01:46 +01:00
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)
{
2001-03-22 05:01:46 +01:00
text *result;
char *cp1;
char *cp2;
int len;
int wl;
2001-03-22 05:01:46 +01:00
len = VARSIZE(iptr) - VARHDRSZ;
result = (text *) palloc(len * 2 + VARHDRSZ + 2);
cp1 = VARDATA(iptr);
cp2 = VARDATA(result);
*cp2++ = '"';
2001-03-22 05:01:46 +01:00
while (len > 0)
{
if ((wl = pg_mblen(cp1)) != 1)
{
len -= wl;
2001-03-22 05:01:46 +01:00
while (wl-- > 0)
*cp2++ = *cp1++;
continue;
}
2001-03-22 05:01:46 +01:00
if (*cp1 == '"')
*cp2++ = '"';
2001-03-22 05:01:46 +01:00
*cp2++ = *cp1++;
len--;
}
*cp2++ = '"';
2001-03-22 05:01:46 +01:00
VARATT_SIZEP(result) = cp2 - ((char *) result);
return result;
}
/*
* Return a properly quoted literal value
*/
static text *
do_quote_literal(text *lptr)
{
2001-03-22 05:01:46 +01:00
text *result;
char *cp1;
char *cp2;
int len;
int wl;
2001-03-22 05:01:46 +01:00
len = VARSIZE(lptr) - VARHDRSZ;
result = (text *) palloc(len * 2 + VARHDRSZ + 2);
cp1 = VARDATA(lptr);
cp2 = VARDATA(result);
*cp2++ = '\'';
2001-03-22 05:01:46 +01:00
while (len > 0)
{
if ((wl = pg_mblen(cp1)) != 1)
{
len -= wl;
2001-03-22 05:01:46 +01:00
while (wl-- > 0)
*cp2++ = *cp1++;
continue;
}
2001-03-22 05:01:46 +01:00
if (*cp1 == '\'')
*cp2++ = '\'';
2001-03-22 05:01:46 +01:00
if (*cp1 == '\\')
*cp2++ = '\\';
2001-03-22 05:01:46 +01:00
*cp2++ = *cp1++;
len--;
}
*cp2++ = '\'';
2001-03-22 05:01:46 +01:00
VARATT_SIZEP(result) = cp2 - ((char *) result);
return result;
}