/*
$Id: quote.c 13129 2009-07-27 21:57:32Z turnstep $
Copyright (c) 2003-2009 Greg Sabino Mullane and others: see the Changes file
You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.
*/
#include "Pg.h"
#if defined (_WIN32) && !defined (strncasecmp)
int
strncasecmp(const char *s1, const char *s2, size_t n)
{
while(n > 0
&& toupper((unsigned char)*s1) == toupper((unsigned char)*s2))
{
if(*s1 == '\0')
return 0;
s1++;
s2++;
n--;
}
if(n == 0)
return 0;
return toupper((unsigned char)*s1) - toupper((unsigned char)*s2);
}
#endif
/*
The 'estring' indicates if the server is capable of using the E'' syntax
In other words, is it 8.1 or better?
It must arrive as 0 or 1
*/
char * null_quote(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char *result;
New(0, result, len+1, char);
strncpy(result,string,len);
result[len]='\0';
*retlen = len;
return result;
}
char * quote_string(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
STRLEN oldlen = len;
const char * const tmp = string;
(*retlen) = 2;
while (len > 0 && *string != '\0') {
if (*string == '\'')
(*retlen)++;
else if (*string == '\\') {
if (estring == 1)
estring = 2;
(*retlen)++;
}
(*retlen)++;
string++;
len--;
}
if (estring == 2)
(*retlen)++;
string = tmp;
New(0, result, 1+(*retlen), char);
if (estring == 2)
*result++ = 'E';
*result++ = '\'';
len = oldlen;
while (len > 0 && *string != '\0') {
if (*string == '\'' || *string == '\\') {
*result++ = *string;
}
*result++ = *string++;
len--;
}
*result++ = '\'';
*result = '\0';
return result - (*retlen);
}
/* Quote a geometric constant. */
/* Note: we only verify correct characters here, not for 100% valid input */
/* Covers: points, lines, lsegs, boxes, polygons */
char * quote_geom(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
const char *tmp;
len = 0; /* stops compiler warnings. Remove entirely someday */
tmp = string;
(*retlen) = 2;
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string != ')'
&& *string != '-' && *string != '+' && *string != '.'
&& *string != 'e' && *string != 'E'
&& *string != ',' && (*string < '0' || *string > '9'))
croak("Invalid input for geometric type");
(*retlen)++;
string++;
}
string = tmp;
New(0, result, 1+(*retlen), char);
*result++ = '\'';
while (*string != '\0') {
*result++ = *string++;
}
*result++ = '\'';
*result = '\0';
return result - (*retlen);
}
/* Same as quote_geom, but also allows square brackets */
char * quote_path(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
const char * const tmp = string;
len = 0; /* stops compiler warnings. Remove entirely someday */
(*retlen) = 2;
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string != ')'
&& *string != '-' && *string != '+' && *string != '.'
&& *string != 'e' && *string != 'E'
&& *string != '[' && *string != ']'
&& *string != ',' && (*string < '0' || *string > '9'))
croak("Invalid input for path type");
(*retlen)++;
string++;
}
string = tmp;
New(0, result, 1+(*retlen), char);
*result++ = '\'';
while (*string != '\0') {
*result++ = *string++;
}
*result++ = '\'';
*result = '\0';
return result - (*retlen);
}
/* Same as quote_geom, but also allows less than / greater than signs */
char * quote_circle(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
const char * const tmp = string;
len = 0; /* stops compiler warnings. Remove entirely someday */
(*retlen) = 2;
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string != ')'
&& *string != '-' && *string != '+' && *string != '.'
&& *string != 'e' && *string != 'E'
&& *string != '<' && *string != '>'
&& *string != ',' && (*string < '0' || *string > '9'))
croak("Invalid input for circle type");
(*retlen)++;
string++;
}
string = tmp;
New(0, result, 1+(*retlen), char);
*result++ = '\'';
while (*string != '\0') {
*result++ = *string++;
}
*result++ = '\'';
*result = '\0';
return result - (*retlen);
}
char * quote_bytea(char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
STRLEN oldlen = len;
/* For this one, always use the E'' format if we can */
result = string;
(*retlen) = 2;
while (len > 0) {
if (*string == '\'') {
(*retlen) += 2;
}
else if (*string == '\\') {
(*retlen) += 4;
}
else if (*string < 0x20 || *string > 0x7e) {
(*retlen) += 5;
}
else {
(*retlen)++;
}
string++;
len--;
}
string = result;
if (estring)
(*retlen)++;
New(0, result, 1+(*retlen), char);
if (estring)
*result++ = 'E';
*result++ = '\'';
len = oldlen;
while (len > 0) {
if (*string == '\'') { /* Single quote becomes double quotes */
*result++ = *string;
*result++ = *string++;
}
else if (*string == '\\') { /* Backslash becomes 4 backslashes */
*result++ = *string;
*result++ = *string++;
*result++ = '\\';
*result++ = '\\';
}
else if (*string < 0x20 || *string > 0x7e) {
(void) snprintf((char *)result, 6, "\\\\%03o", (unsigned char)*string++);
result += 5;
}
else {
*result++ = *string++;
}
len--;
}
*result++ = '\'';
*result = '\0';
return (char *)result - (*retlen);
}
char * quote_sql_binary(char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
/* We are going to return a quote_bytea() for backwards compat but
we warn first */
warn("Use of SQL_BINARY invalid in quote()");
return quote_bytea(string, len, retlen, estring);
}
/* Return TRUE, FALSE, or throws an error */
char * quote_bool(const char *value, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char *result;
/* Things that are true: t, T, 1, true, TRUE, 0E0, 0 but true */
if (
(1 == len && (0 == strncasecmp(value, "t", 1) || '1' == *value))
||
(4 == len && 0 == strncasecmp(value, "true", 4))
||
(3 == len && 0 == strncasecmp(value, "0e0", 3))
||
(10 == len && 0 == strncasecmp(value, "0 but true", 10))
) {
New(0, result, 5, char);
strncpy(result,"TRUE\0",5);
*retlen = 4;
return result;
}
/* Things that are false: f, F, 0, false, FALSE, 0, zero-length string */
if (
(1 == len && (0 == strncasecmp(value, "f", 1) || '0' == *value))
||
(5 == len && 0 == strncasecmp(value, "false", 5))
||
(0 == len)
) {
New(0, result, 6, char);
strncpy(result,"FALSE\0",6);
*retlen = 5;
return result;
}
croak("Invalid boolean value");
}
char * quote_int(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
New(0, result, len+1, char);
strcpy(result,string);
*retlen = len;
while (len > 0 && *string != '\0') {
len--;
if (isdigit(*string) || ' ' == *string || '+' == *string || '-' == *string) {
string++;
continue;
}
croak("Invalid integer");
}
return result;
}
char * quote_float(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
/* Empty string is always an error. Here for dumb compilers. */
if (len<1)
croak("Invalid float");
result = string;
*retlen = len;
/* Allow some standard strings in */
if (0 != strncasecmp(string, "NaN", 4)
&& 0 != strncasecmp(string, "Infinity", 9)
&& 0 != strncasecmp(string, "-Infinity", 10)) {
while (len > 0 && *string != '\0') {
len--;
if (isdigit(*string)
|| '.' == *string
|| ' ' == *string
|| '+' == *string
|| '-' == *string
|| 'e' == *string
|| 'E' == *string) {
string++;
continue;
}
croak("Invalid float");
}
}
string = result;
New(0, result, 1+(*retlen), char);
strcpy(result,string);
return result;
}
char * quote_name(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
const char *ptr;
int nquotes = 0;
int x;
bool safe;
/* We throw double quotes around the whole thing, if:
1. It starts with anything other than [a-z_]
OR
2. It has characters other than [a-z_0-9]
OR
3. It is a reserved word (e.g. `user`)
*/
/* 1. It starts with anything other than [a-z_] */
safe = ((string[0] >= 'a' && string[0] <= 'z') || '_' == string[0]);
/* 2. It has characters other than [a-z_0-9] (also count number of quotes) */
for (ptr = string; *ptr; ptr++) {
char ch = *ptr;
if (
(ch < 'a' && ch > 'z')
&&
(ch < '0' && ch > '9')
&&
ch != '_') {
safe = DBDPG_FALSE;
if (ch == '"')
nquotes++;
}
}
/* 3. Is it a reserved word (e.g. `user`) */
if (safe) {
if (! is_keyword(string)) {
New(0, result, len+1, char);
strcpy(result,string);
*retlen = len;
return result;
}
}
/* Need room for the string, the outer quotes, any inner quotes (which get doubled) and \0 */
*retlen = len + 2 + nquotes;
New(0, result, *retlen + 1, char);
x=0;
result[x++] = '"';
for (ptr = string; *ptr; ptr++) {
char ch = *ptr;
result[x++] = ch;
if (ch == '"')
result[x++] = '"';
}
result[x++] = '"';
result[x] = '\0';
return result;
}
void dequote_char(const char *string, STRLEN *retlen, int estring)
{
dTHX;
/* TODO: chop_blanks if requested */
*retlen = strlen(string);
}
void dequote_string(const char *string, STRLEN *retlen, int estring)
{
dTHX;
*retlen = strlen(string);
}
void dequote_bytea(char *string, STRLEN *retlen, int estring)
{
dTHX;
char *result;
(*retlen) = 0;
if (NULL == string)
return;
result = string;
while (*string != '\0') {
(*retlen)++;
if ('\\' == *string) {
if ('\\' == *(string+1)) {
*result++ = '\\';
string +=2;
}
else if (
(*(string+1) >= '0' && *(string+1) <= '3') &&
(*(string+2) >= '0' && *(string+2) <= '7') &&
(*(string+3) >= '0' && *(string+3) <= '7'))
{
*result++ = (*(string+1)-'0')*64 + (*(string+2)-'0')*8 + (*(string+3)-'0');
string += 4;
}
else { /* Invalid escape sequence - ignore the backslash */
(*retlen)--;
string++;
}
}
else {
*result++ = *string++;
}
}
*result = '\0';
return;
}
/*
This one is not used in PG, but since we have a quote_sql_binary,
it might be nice to let people go the other way too. Say when talking
to something that uses SQL_BINARY
*/
void dequote_sql_binary(char *string, STRLEN *retlen, int estring)
{
dTHX;
/* We are going to return a dequote_bytea(), just in case */
warn("Use of SQL_BINARY invalid in dequote()");
dequote_bytea(string, retlen, estring);
return;
/* Put dequote_sql_binary function here at some point */
}
void dequote_bool(char *string, STRLEN *retlen, int estring)
{
dTHX;
switch(*string){
case 'f': *string = '0'; break;
case 't': *string = '1'; break;
default:
croak("I do not know how to deal with %c as a bool", *string);
}
*retlen = 1;
}
void null_dequote(const char *string, STRLEN *retlen, int estring)
{
dTHX;
*retlen = strlen(string);
}
bool is_keyword(const char *string)
{
int max_keyword_length = 17;
int keyword_len;
int i;
char word[64];
keyword_len = (int)strlen(string);
if (keyword_len > max_keyword_length || keyword_len > 64) {
return DBDPG_FALSE;
}
/* Because of locale issues, we manually downcase A-Z only */
for (i = 0; i < keyword_len; i++) {
char ch = string[i];
if (ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
word[i] = ch;
}
word[keyword_len] = '\0';
/* Check for each reserved word */
if (0==strcmp(word, "abort")) return DBDPG_TRUE;
if (0==strcmp(word, "absolute")) return DBDPG_TRUE;
if (0==strcmp(word, "access")) return DBDPG_TRUE;
if (0==strcmp(word, "action")) return DBDPG_TRUE;
if (0==strcmp(word, "add")) return DBDPG_TRUE;
if (0==strcmp(word, "admin")) return DBDPG_TRUE;
if (0==strcmp(word, "after")) return DBDPG_TRUE;
if (0==strcmp(word, "aggregate")) return DBDPG_TRUE;
if (0==strcmp(word, "all")) return DBDPG_TRUE;
if (0==strcmp(word, "also")) return DBDPG_TRUE;
if (0==strcmp(word, "alter")) return DBDPG_TRUE;
if (0==strcmp(word, "always")) return DBDPG_TRUE;
if (0==strcmp(word, "analyse")) return DBDPG_TRUE;
if (0==strcmp(word, "analyze")) return DBDPG_TRUE;
if (0==strcmp(word, "and")) return DBDPG_TRUE;
if (0==strcmp(word, "any")) return DBDPG_TRUE;
if (0==strcmp(word, "array")) return DBDPG_TRUE;
if (0==strcmp(word, "as")) return DBDPG_TRUE;
if (0==strcmp(word, "asc")) return DBDPG_TRUE;
if (0==strcmp(word, "assertion")) return DBDPG_TRUE;
if (0==strcmp(word, "assignment")) return DBDPG_TRUE;
if (0==strcmp(word, "asymmetric")) return DBDPG_TRUE;
if (0==strcmp(word, "at")) return DBDPG_TRUE;
if (0==strcmp(word, "authorization")) return DBDPG_TRUE;
if (0==strcmp(word, "backward")) return DBDPG_TRUE;
if (0==strcmp(word, "before")) return DBDPG_TRUE;
if (0==strcmp(word, "begin")) return DBDPG_TRUE;
if (0==strcmp(word, "between")) return DBDPG_TRUE;
if (0==strcmp(word, "bigint")) return DBDPG_TRUE;
if (0==strcmp(word, "binary")) return DBDPG_TRUE;
if (0==strcmp(word, "bit")) return DBDPG_TRUE;
if (0==strcmp(word, "boolean")) return DBDPG_TRUE;
if (0==strcmp(word, "both")) return DBDPG_TRUE;
if (0==strcmp(word, "by")) return DBDPG_TRUE;
if (0==strcmp(word, "cache")) return DBDPG_TRUE;
if (0==strcmp(word, "called")) return DBDPG_TRUE;
if (0==strcmp(word, "cascade")) return DBDPG_TRUE;
if (0==strcmp(word, "cascaded")) return DBDPG_TRUE;
if (0==strcmp(word, "case")) return DBDPG_TRUE;
if (0==strcmp(word, "cast")) return DBDPG_TRUE;
if (0==strcmp(word, "catalog")) return DBDPG_TRUE;
if (0==strcmp(word, "chain")) return DBDPG_TRUE;
if (0==strcmp(word, "char")) return DBDPG_TRUE;
if (0==strcmp(word, "character")) return DBDPG_TRUE;
if (0==strcmp(word, "characteristics")) return DBDPG_TRUE;
if (0==strcmp(word, "check")) return DBDPG_TRUE;
if (0==strcmp(word, "checkpoint")) return DBDPG_TRUE;
if (0==strcmp(word, "class")) return DBDPG_TRUE;
if (0==strcmp(word, "close")) return DBDPG_TRUE;
if (0==strcmp(word, "cluster")) return DBDPG_TRUE;
if (0==strcmp(word, "coalesce")) return DBDPG_TRUE;
if (0==strcmp(word, "collate")) return DBDPG_TRUE;
if (0==strcmp(word, "column")) return DBDPG_TRUE;
if (0==strcmp(word, "comment")) return DBDPG_TRUE;
if (0==strcmp(word, "commit")) return DBDPG_TRUE;
if (0==strcmp(word, "committed")) return DBDPG_TRUE;
if (0==strcmp(word, "concurrently")) return DBDPG_TRUE;
if (0==strcmp(word, "configuration")) return DBDPG_TRUE;
if (0==strcmp(word, "connection")) return DBDPG_TRUE;
if (0==strcmp(word, "constraint")) return DBDPG_TRUE;
if (0==strcmp(word, "constraints")) return DBDPG_TRUE;
if (0==strcmp(word, "content")) return DBDPG_TRUE;
if (0==strcmp(word, "continue")) return DBDPG_TRUE;
if (0==strcmp(word, "conversion")) return DBDPG_TRUE;
if (0==strcmp(word, "copy")) return DBDPG_TRUE;
if (0==strcmp(word, "cost")) return DBDPG_TRUE;
if (0==strcmp(word, "create")) return DBDPG_TRUE;
if (0==strcmp(word, "createdb")) return DBDPG_TRUE;
if (0==strcmp(word, "createrole")) return DBDPG_TRUE;
if (0==strcmp(word, "createuser")) return DBDPG_TRUE;
if (0==strcmp(word, "cross")) return DBDPG_TRUE;
if (0==strcmp(word, "csv")) return DBDPG_TRUE;
if (0==strcmp(word, "current")) return DBDPG_TRUE;
if (0==strcmp(word, "current_catalog")) return DBDPG_TRUE;
if (0==strcmp(word, "current_date")) return DBDPG_TRUE;
if (0==strcmp(word, "current_role")) return DBDPG_TRUE;
if (0==strcmp(word, "current_schema")) return DBDPG_TRUE;
if (0==strcmp(word, "current_time")) return DBDPG_TRUE;
if (0==strcmp(word, "current_timestamp")) return DBDPG_TRUE;
if (0==strcmp(word, "current_user")) return DBDPG_TRUE;
if (0==strcmp(word, "cursor")) return DBDPG_TRUE;
if (0==strcmp(word, "cycle")) return DBDPG_TRUE;
if (0==strcmp(word, "data")) return DBDPG_TRUE;
if (0==strcmp(word, "database")) return DBDPG_TRUE;
if (0==strcmp(word, "day")) return DBDPG_TRUE;
if (0==strcmp(word, "deallocate")) return DBDPG_TRUE;
if (0==strcmp(word, "dec")) return DBDPG_TRUE;
if (0==strcmp(word, "decimal")) return DBDPG_TRUE;
if (0==strcmp(word, "declare")) return DBDPG_TRUE;
if (0==strcmp(word, "default")) return DBDPG_TRUE;
if (0==strcmp(word, "defaults")) return DBDPG_TRUE;
if (0==strcmp(word, "deferrable")) return DBDPG_TRUE;
if (0==strcmp(word, "deferred")) return DBDPG_TRUE;
if (0==strcmp(word, "definer")) return DBDPG_TRUE;
if (0==strcmp(word, "delete")) return DBDPG_TRUE;
if (0==strcmp(word, "delimiter")) return DBDPG_TRUE;
if (0==strcmp(word, "delimiters")) return DBDPG_TRUE;
if (0==strcmp(word, "desc")) return DBDPG_TRUE;
if (0==strcmp(word, "dictionary")) return DBDPG_TRUE;
if (0==strcmp(word, "disable")) return DBDPG_TRUE;
if (0==strcmp(word, "discard")) return DBDPG_TRUE;
if (0==strcmp(word, "distinct")) return DBDPG_TRUE;
if (0==strcmp(word, "do")) return DBDPG_TRUE;
if (0==strcmp(word, "document")) return DBDPG_TRUE;
if (0==strcmp(word, "domain")) return DBDPG_TRUE;
if (0==strcmp(word, "double")) return DBDPG_TRUE;
if (0==strcmp(word, "drop")) return DBDPG_TRUE;
if (0==strcmp(word, "each")) return DBDPG_TRUE;
if (0==strcmp(word, "else")) return DBDPG_TRUE;
if (0==strcmp(word, "enable")) return DBDPG_TRUE;
if (0==strcmp(word, "encoding")) return DBDPG_TRUE;
if (0==strcmp(word, "encrypted")) return DBDPG_TRUE;
if (0==strcmp(word, "end")) return DBDPG_TRUE;
if (0==strcmp(word, "enum")) return DBDPG_TRUE;
if (0==strcmp(word, "escape")) return DBDPG_TRUE;
if (0==strcmp(word, "except")) return DBDPG_TRUE;
if (0==strcmp(word, "excluding")) return DBDPG_TRUE;
if (0==strcmp(word, "exclusive")) return DBDPG_TRUE;
if (0==strcmp(word, "execute")) return DBDPG_TRUE;
if (0==strcmp(word, "exists")) return DBDPG_TRUE;
if (0==strcmp(word, "explain")) return DBDPG_TRUE;
if (0==strcmp(word, "external")) return DBDPG_TRUE;
if (0==strcmp(word, "extract")) return DBDPG_TRUE;
if (0==strcmp(word, "false")) return DBDPG_TRUE;
if (0==strcmp(word, "family")) return DBDPG_TRUE;
if (0==strcmp(word, "fetch")) return DBDPG_TRUE;
if (0==strcmp(word, "first")) return DBDPG_TRUE;
if (0==strcmp(word, "float")) return DBDPG_TRUE;
if (0==strcmp(word, "following")) return DBDPG_TRUE;
if (0==strcmp(word, "for")) return DBDPG_TRUE;
if (0==strcmp(word, "force")) return DBDPG_TRUE;
if (0==strcmp(word, "foreign")) return DBDPG_TRUE;
if (0==strcmp(word, "forward")) return DBDPG_TRUE;
if (0==strcmp(word, "freeze")) return DBDPG_TRUE;
if (0==strcmp(word, "from")) return DBDPG_TRUE;
if (0==strcmp(word, "full")) return DBDPG_TRUE;
if (0==strcmp(word, "function")) return DBDPG_TRUE;
if (0==strcmp(word, "global")) return DBDPG_TRUE;
if (0==strcmp(word, "grant")) return DBDPG_TRUE;
if (0==strcmp(word, "granted")) return DBDPG_TRUE;
if (0==strcmp(word, "greatest")) return DBDPG_TRUE;
if (0==strcmp(word, "group")) return DBDPG_TRUE;
if (0==strcmp(word, "handler")) return DBDPG_TRUE;
if (0==strcmp(word, "having")) return DBDPG_TRUE;
if (0==strcmp(word, "header")) return DBDPG_TRUE;
if (0==strcmp(word, "hold")) return DBDPG_TRUE;
if (0==strcmp(word, "hour")) return DBDPG_TRUE;
if (0==strcmp(word, "identity")) return DBDPG_TRUE;
if (0==strcmp(word, "if")) return DBDPG_TRUE;
if (0==strcmp(word, "ilike")) return DBDPG_TRUE;
if (0==strcmp(word, "immediate")) return DBDPG_TRUE;
if (0==strcmp(word, "immutable")) return DBDPG_TRUE;
if (0==strcmp(word, "implicit")) return DBDPG_TRUE;
if (0==strcmp(word, "in")) return DBDPG_TRUE;
if (0==strcmp(word, "including")) return DBDPG_TRUE;
if (0==strcmp(word, "increment")) return DBDPG_TRUE;
if (0==strcmp(word, "index")) return DBDPG_TRUE;
if (0==strcmp(word, "indexes")) return DBDPG_TRUE;
if (0==strcmp(word, "inherit")) return DBDPG_TRUE;
if (0==strcmp(word, "inherits")) return DBDPG_TRUE;
if (0==strcmp(word, "initially")) return DBDPG_TRUE;
if (0==strcmp(word, "inner")) return DBDPG_TRUE;
if (0==strcmp(word, "inout")) return DBDPG_TRUE;
if (0==strcmp(word, "input")) return DBDPG_TRUE;
if (0==strcmp(word, "insensitive")) return DBDPG_TRUE;
if (0==strcmp(word, "insert")) return DBDPG_TRUE;
if (0==strcmp(word, "instead")) return DBDPG_TRUE;
if (0==strcmp(word, "int")) return DBDPG_TRUE;
if (0==strcmp(word, "integer")) return DBDPG_TRUE;
if (0==strcmp(word, "intersect")) return DBDPG_TRUE;
if (0==strcmp(word, "interval")) return DBDPG_TRUE;
if (0==strcmp(word, "into")) return DBDPG_TRUE;
if (0==strcmp(word, "invoker")) return DBDPG_TRUE;
if (0==strcmp(word, "is")) return DBDPG_TRUE;
if (0==strcmp(word, "isnull")) return DBDPG_TRUE;
if (0==strcmp(word, "isolation")) return DBDPG_TRUE;
if (0==strcmp(word, "join")) return DBDPG_TRUE;
if (0==strcmp(word, "key")) return DBDPG_TRUE;
if (0==strcmp(word, "lancompiler")) return DBDPG_TRUE;
if (0==strcmp(word, "language")) return DBDPG_TRUE;
if (0==strcmp(word, "large")) return DBDPG_TRUE;
if (0==strcmp(word, "last")) return DBDPG_TRUE;
if (0==strcmp(word, "lc_collate")) return DBDPG_TRUE;
if (0==strcmp(word, "lc_ctype")) return DBDPG_TRUE;
if (0==strcmp(word, "leading")) return DBDPG_TRUE;
if (0==strcmp(word, "least")) return DBDPG_TRUE;
if (0==strcmp(word, "left")) return DBDPG_TRUE;
if (0==strcmp(word, "level")) return DBDPG_TRUE;
if (0==strcmp(word, "like")) return DBDPG_TRUE;
if (0==strcmp(word, "limit")) return DBDPG_TRUE;
if (0==strcmp(word, "listen")) return DBDPG_TRUE;
if (0==strcmp(word, "load")) return DBDPG_TRUE;
if (0==strcmp(word, "local")) return DBDPG_TRUE;
if (0==strcmp(word, "localtime")) return DBDPG_TRUE;
if (0==strcmp(word, "localtimestamp")) return DBDPG_TRUE;
if (0==strcmp(word, "location")) return DBDPG_TRUE;
if (0==strcmp(word, "lock")) return DBDPG_TRUE;
if (0==strcmp(word, "login")) return DBDPG_TRUE;
if (0==strcmp(word, "mapping")) return DBDPG_TRUE;
if (0==strcmp(word, "match")) return DBDPG_TRUE;
if (0==strcmp(word, "maxvalue")) return DBDPG_TRUE;
if (0==strcmp(word, "minute")) return DBDPG_TRUE;
if (0==strcmp(word, "minvalue")) return DBDPG_TRUE;
if (0==strcmp(word, "mode")) return DBDPG_TRUE;
if (0==strcmp(word, "month")) return DBDPG_TRUE;
if (0==strcmp(word, "move")) return DBDPG_TRUE;
if (0==strcmp(word, "name")) return DBDPG_TRUE;
if (0==strcmp(word, "names")) return DBDPG_TRUE;
if (0==strcmp(word, "national")) return DBDPG_TRUE;
if (0==strcmp(word, "natural")) return DBDPG_TRUE;
if (0==strcmp(word, "nchar")) return DBDPG_TRUE;
if (0==strcmp(word, "new")) return DBDPG_TRUE;
if (0==strcmp(word, "next")) return DBDPG_TRUE;
if (0==strcmp(word, "no")) return DBDPG_TRUE;
if (0==strcmp(word, "nocreatedb")) return DBDPG_TRUE;
if (0==strcmp(word, "nocreaterole")) return DBDPG_TRUE;
if (0==strcmp(word, "nocreateuser")) return DBDPG_TRUE;
if (0==strcmp(word, "noinherit")) return DBDPG_TRUE;
if (0==strcmp(word, "nologin")) return DBDPG_TRUE;
if (0==strcmp(word, "none")) return DBDPG_TRUE;
if (0==strcmp(word, "nosuperuser")) return DBDPG_TRUE;
if (0==strcmp(word, "not")) return DBDPG_TRUE;
if (0==strcmp(word, "nothing")) return DBDPG_TRUE;
if (0==strcmp(word, "notify")) return DBDPG_TRUE;
if (0==strcmp(word, "notnull")) return DBDPG_TRUE;
if (0==strcmp(word, "nowait")) return DBDPG_TRUE;
if (0==strcmp(word, "null")) return DBDPG_TRUE;
if (0==strcmp(word, "nullif")) return DBDPG_TRUE;
if (0==strcmp(word, "nulls")) return DBDPG_TRUE;
if (0==strcmp(word, "numeric")) return DBDPG_TRUE;
if (0==strcmp(word, "object")) return DBDPG_TRUE;
if (0==strcmp(word, "of")) return DBDPG_TRUE;
if (0==strcmp(word, "off")) return DBDPG_TRUE;
if (0==strcmp(word, "offset")) return DBDPG_TRUE;
if (0==strcmp(word, "oids")) return DBDPG_TRUE;
if (0==strcmp(word, "old")) return DBDPG_TRUE;
if (0==strcmp(word, "on")) return DBDPG_TRUE;
if (0==strcmp(word, "only")) return DBDPG_TRUE;
if (0==strcmp(word, "operator")) return DBDPG_TRUE;
if (0==strcmp(word, "option")) return DBDPG_TRUE;
if (0==strcmp(word, "options")) return DBDPG_TRUE;
if (0==strcmp(word, "or")) return DBDPG_TRUE;
if (0==strcmp(word, "order")) return DBDPG_TRUE;
if (0==strcmp(word, "out")) return DBDPG_TRUE;
if (0==strcmp(word, "outer")) return DBDPG_TRUE;
if (0==strcmp(word, "over")) return DBDPG_TRUE;
if (0==strcmp(word, "overlaps")) return DBDPG_TRUE;
if (0==strcmp(word, "overlay")) return DBDPG_TRUE;
if (0==strcmp(word, "owned")) return DBDPG_TRUE;
if (0==strcmp(word, "owner")) return DBDPG_TRUE;
if (0==strcmp(word, "parser")) return DBDPG_TRUE;
if (0==strcmp(word, "partial")) return DBDPG_TRUE;
if (0==strcmp(word, "partition")) return DBDPG_TRUE;
if (0==strcmp(word, "password")) return DBDPG_TRUE;
if (0==strcmp(word, "placing")) return DBDPG_TRUE;
if (0==strcmp(word, "plans")) return DBDPG_TRUE;
if (0==strcmp(word, "position")) return DBDPG_TRUE;
if (0==strcmp(word, "preceding")) return DBDPG_TRUE;
if (0==strcmp(word, "precision")) return DBDPG_TRUE;
if (0==strcmp(word, "prepare")) return DBDPG_TRUE;
if (0==strcmp(word, "prepared")) return DBDPG_TRUE;
if (0==strcmp(word, "preserve")) return DBDPG_TRUE;
if (0==strcmp(word, "primary")) return DBDPG_TRUE;
if (0==strcmp(word, "prior")) return DBDPG_TRUE;
if (0==strcmp(word, "privileges")) return DBDPG_TRUE;
if (0==strcmp(word, "procedural")) return DBDPG_TRUE;
if (0==strcmp(word, "procedure")) return DBDPG_TRUE;
if (0==strcmp(word, "quote")) return DBDPG_TRUE;
if (0==strcmp(word, "range")) return DBDPG_TRUE;
if (0==strcmp(word, "read")) return DBDPG_TRUE;
if (0==strcmp(word, "real")) return DBDPG_TRUE;
if (0==strcmp(word, "reassign")) return DBDPG_TRUE;
if (0==strcmp(word, "recheck")) return DBDPG_TRUE;
if (0==strcmp(word, "recursive")) return DBDPG_TRUE;
if (0==strcmp(word, "references")) return DBDPG_TRUE;
if (0==strcmp(word, "reindex")) return DBDPG_TRUE;
if (0==strcmp(word, "relative")) return DBDPG_TRUE;
if (0==strcmp(word, "release")) return DBDPG_TRUE;
if (0==strcmp(word, "rename")) return DBDPG_TRUE;
if (0==strcmp(word, "repeatable")) return DBDPG_TRUE;
if (0==strcmp(word, "replace")) return DBDPG_TRUE;
if (0==strcmp(word, "replica")) return DBDPG_TRUE;
if (0==strcmp(word, "reset")) return DBDPG_TRUE;
if (0==strcmp(word, "restart")) return DBDPG_TRUE;
if (0==strcmp(word, "restrict")) return DBDPG_TRUE;
if (0==strcmp(word, "returning")) return DBDPG_TRUE;
if (0==strcmp(word, "returns")) return DBDPG_TRUE;
if (0==strcmp(word, "revoke")) return DBDPG_TRUE;
if (0==strcmp(word, "right")) return DBDPG_TRUE;
if (0==strcmp(word, "role")) return DBDPG_TRUE;
if (0==strcmp(word, "rollback")) return DBDPG_TRUE;
if (0==strcmp(word, "row")) return DBDPG_TRUE;
if (0==strcmp(word, "rows")) return DBDPG_TRUE;
if (0==strcmp(word, "rule")) return DBDPG_TRUE;
if (0==strcmp(word, "savepoint")) return DBDPG_TRUE;
if (0==strcmp(word, "schema")) return DBDPG_TRUE;
if (0==strcmp(word, "scroll")) return DBDPG_TRUE;
if (0==strcmp(word, "search")) return DBDPG_TRUE;
if (0==strcmp(word, "second")) return DBDPG_TRUE;
if (0==strcmp(word, "security")) return DBDPG_TRUE;
if (0==strcmp(word, "select")) return DBDPG_TRUE;
if (0==strcmp(word, "sequence")) return DBDPG_TRUE;
if (0==strcmp(word, "serializable")) return DBDPG_TRUE;
if (0==strcmp(word, "server")) return DBDPG_TRUE;
if (0==strcmp(word, "session")) return DBDPG_TRUE;
if (0==strcmp(word, "session_user")) return DBDPG_TRUE;
if (0==strcmp(word, "set")) return DBDPG_TRUE;
if (0==strcmp(word, "setof")) return DBDPG_TRUE;
if (0==strcmp(word, "share")) return DBDPG_TRUE;
if (0==strcmp(word, "show")) return DBDPG_TRUE;
if (0==strcmp(word, "similar")) return DBDPG_TRUE;
if (0==strcmp(word, "simple")) return DBDPG_TRUE;
if (0==strcmp(word, "smallint")) return DBDPG_TRUE;
if (0==strcmp(word, "some")) return DBDPG_TRUE;
if (0==strcmp(word, "stable")) return DBDPG_TRUE;
if (0==strcmp(word, "standalone")) return DBDPG_TRUE;
if (0==strcmp(word, "start")) return DBDPG_TRUE;
if (0==strcmp(word, "statement")) return DBDPG_TRUE;
if (0==strcmp(word, "statistics")) return DBDPG_TRUE;
if (0==strcmp(word, "stdin")) return DBDPG_TRUE;
if (0==strcmp(word, "stdout")) return DBDPG_TRUE;
if (0==strcmp(word, "storage")) return DBDPG_TRUE;
if (0==strcmp(word, "strict")) return DBDPG_TRUE;
if (0==strcmp(word, "strip")) return DBDPG_TRUE;
if (0==strcmp(word, "substring")) return DBDPG_TRUE;
if (0==strcmp(word, "superuser")) return DBDPG_TRUE;
if (0==strcmp(word, "symmetric")) return DBDPG_TRUE;
if (0==strcmp(word, "sysid")) return DBDPG_TRUE;
if (0==strcmp(word, "system")) return DBDPG_TRUE;
if (0==strcmp(word, "table")) return DBDPG_TRUE;
if (0==strcmp(word, "tablespace")) return DBDPG_TRUE;
if (0==strcmp(word, "temp")) return DBDPG_TRUE;
if (0==strcmp(word, "template")) return DBDPG_TRUE;
if (0==strcmp(word, "temporary")) return DBDPG_TRUE;
if (0==strcmp(word, "text")) return DBDPG_TRUE;
if (0==strcmp(word, "then")) return DBDPG_TRUE;
if (0==strcmp(word, "time")) return DBDPG_TRUE;
if (0==strcmp(word, "timestamp")) return DBDPG_TRUE;
if (0==strcmp(word, "to")) return DBDPG_TRUE;
if (0==strcmp(word, "trailing")) return DBDPG_TRUE;
if (0==strcmp(word, "transaction")) return DBDPG_TRUE;
if (0==strcmp(word, "treat")) return DBDPG_TRUE;
if (0==strcmp(word, "trigger")) return DBDPG_TRUE;
if (0==strcmp(word, "trim")) return DBDPG_TRUE;
if (0==strcmp(word, "true")) return DBDPG_TRUE;
if (0==strcmp(word, "truncate")) return DBDPG_TRUE;
if (0==strcmp(word, "trusted")) return DBDPG_TRUE;
if (0==strcmp(word, "type")) return DBDPG_TRUE;
if (0==strcmp(word, "unbounded")) return DBDPG_TRUE;
if (0==strcmp(word, "uncommitted")) return DBDPG_TRUE;
if (0==strcmp(word, "unencrypted")) return DBDPG_TRUE;
if (0==strcmp(word, "union")) return DBDPG_TRUE;
if (0==strcmp(word, "unique")) return DBDPG_TRUE;
if (0==strcmp(word, "unknown")) return DBDPG_TRUE;
if (0==strcmp(word, "unlisten")) return DBDPG_TRUE;
if (0==strcmp(word, "until")) return DBDPG_TRUE;
if (0==strcmp(word, "update")) return DBDPG_TRUE;
if (0==strcmp(word, "user")) return DBDPG_TRUE;
if (0==strcmp(word, "using")) return DBDPG_TRUE;
if (0==strcmp(word, "vacuum")) return DBDPG_TRUE;
if (0==strcmp(word, "valid")) return DBDPG_TRUE;
if (0==strcmp(word, "validator")) return DBDPG_TRUE;
if (0==strcmp(word, "value")) return DBDPG_TRUE;
if (0==strcmp(word, "values")) return DBDPG_TRUE;
if (0==strcmp(word, "varchar")) return DBDPG_TRUE;
if (0==strcmp(word, "variadic")) return DBDPG_TRUE;
if (0==strcmp(word, "varying")) return DBDPG_TRUE;
if (0==strcmp(word, "verbose")) return DBDPG_TRUE;
if (0==strcmp(word, "version")) return DBDPG_TRUE;
if (0==strcmp(word, "view")) return DBDPG_TRUE;
if (0==strcmp(word, "volatile")) return DBDPG_TRUE;
if (0==strcmp(word, "when")) return DBDPG_TRUE;
if (0==strcmp(word, "where")) return DBDPG_TRUE;
if (0==strcmp(word, "whitespace")) return DBDPG_TRUE;
if (0==strcmp(word, "window")) return DBDPG_TRUE;
if (0==strcmp(word, "with")) return DBDPG_TRUE;
if (0==strcmp(word, "without")) return DBDPG_TRUE;
if (0==strcmp(word, "work")) return DBDPG_TRUE;
if (0==strcmp(word, "wrapper")) return DBDPG_TRUE;
if (0==strcmp(word, "write")) return DBDPG_TRUE;
if (0==strcmp(word, "xml")) return DBDPG_TRUE;
if (0==strcmp(word, "xmlattributes")) return DBDPG_TRUE;
if (0==strcmp(word, "xmlconcat")) return DBDPG_TRUE;
if (0==strcmp(word, "xmlelement")) return DBDPG_TRUE;
if (0==strcmp(word, "xmlforest")) return DBDPG_TRUE;
if (0==strcmp(word, "xmlparse")) return DBDPG_TRUE;
if (0==strcmp(word, "xmlpi")) return DBDPG_TRUE;
if (0==strcmp(word, "xmlroot")) return DBDPG_TRUE;
if (0==strcmp(word, "xmlserialize")) return DBDPG_TRUE;
if (0==strcmp(word, "year")) return DBDPG_TRUE;
if (0==strcmp(word, "yes")) return DBDPG_TRUE;
if (0==strcmp(word, "zone")) return DBDPG_TRUE;
/* We made it! */
return DBDPG_FALSE;
}
/* end of quote.c */
/*
#!perl
## Autogenerate the list of reserved keywords
## You should only run this if you are developing DBD::Pg and
## understand what this script does
## Usage: perl -x $0 "path-to-pgsql-source"
use strict;
use warnings;
my $arg = shift || die "Usage: $0 path-to-pgsql-source\n";
-d $arg or die qq{Sorry, but "$arg" is not a directory!\n};
my $file = "$arg/src/include/parser/kwlist.h";
open my $fh, '<', $file or die qq{Could not open file "$file": $!\n};
my @word;
my $maxlen = 10;
while (<$fh>) {
next unless /^PG_KEYWORD\("(.+?)"/;
## We don't care what type of word it is - when in doubt, quote it!
my $word = $1;
push @word => $word;
$maxlen = length $word if length $word > $maxlen;
}
close $fh or die qq{Could not close "$file": $!\n};
my $tempfile = 'quote.c.tmp';
open my $fh2, '>', $tempfile or die qq{Could not open "$tempfile": $!\n};
seek(DATA,0,0);
my $gotlist = 0;
while (<DATA>) {
s/(int max_keyword_length =) \d+/$1 $maxlen/;
if (!$gotlist) {
if (/Check for each reserved word/) {
$gotlist = 1;
print $fh2 $_;
for my $word (@word) {
print $fh2 qq{ if (0==strcmp(word, "$word")) return DBDPG_TRUE;\n};
}
print $fh2 "\n";
next;
}
}
elsif (1==$gotlist) {
if (/We made it/) {
$gotlist = 2;
}
else {
next;
}
}
print $fh2 $_;
}
close $fh2 or die qq{Could not close "$tempfile": $!\n};
my $ofile = 'quote.c';
system("mv $tempfile $ofile");
print "Wrote $ofile\n";
exit;
__END__
*/