/*------------------------------------------------------------------------- * * quote.c * Functions for quoting identifiers and literals * * Portions Copyright (c) 2000, PostgreSQL Global Development Group * * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v 1.3 2001/01/24 19:43:14 momjian Exp $ * *------------------------------------------------------------------------- */ #include #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); 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); } /* * 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