[svn:DBD-Pg] r12781 - in DBD-Pg/trunk: . t

[email protected]
Newsgroups gmane.comp.db.postgresql.dbdpg.cvs
Message-ID <[email protected]>
Author: turnstep
Date: Mon May 18 18:48:10 2009
New Revision: 12781

Modified:
   DBD-Pg/trunk/quote.c
   DBD-Pg/trunk/quote.h
   DBD-Pg/trunk/t/12placeholders.t
   DBD-Pg/trunk/types.c

Log:
More work on fixing up the quoting issues.
Mostly done: quote_int, quote_float, quote_name


Modified: DBD-Pg/trunk/quote.c
==============================================================================
--- DBD-Pg/trunk/quote.c	(original)
+++ DBD-Pg/trunk/quote.c	Mon May 18 18:48:10 2009
@@ -286,24 +286,26 @@
 {
 	dTHX;
 	char * result;
-	double val;
+	char * endpoint;
+	float val;
 
 	/*
-	  We do minimal checking here, and let Postgres do the heavy lifting 
-	  Out job is to simply filter out bad characters
+	  We let strtof do the heavy lifting here, despite it having some 
+	  issues according to the PG source
 	*/
 
-	while (*string != '\0' && isspace((unsigned char) *string))
-		*string++;
+	/* Empty string is always an error. Here for dumb compilers. */
+	if (len<1)
+		croak("Invalid number");
 
 	errno = 0;
-	val = strtod(string, &result);
+	val = strtof(string, &endpoint);
 
-	if (result == string || errno != 0) {
-		/* Allow exactly three strings, otherwise bail */
-		if (0 != strncasecmp(string, "NaN", 3)
-			&& 0 != strncasecmp(string, "Infinity", 8)
-			&& 0 != strncasecmp(string, "-Infinity", 9)
+	if (0!=*endpoint || errno != 0) {
+		/* Just in case the compiler used has a crappy strtof */
+		if (0 != strncasecmp(string, "NaN", 4)
+			&& 0 != strncasecmp(string, "Infinity", 9)
+			&& 0 != strncasecmp(string, "-Infinity", 10)
 			) {
 			croak("Invalid number");
 		}
@@ -320,17 +322,67 @@
 {
 	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`)
+	*/
 
-	croak ("Not handled yet");
+	/* 1. It starts with anything other than [a-z_] */
+	safe = ((string[0] >= 'a' && string[0] <= 'z') || '_' == string[0]);
 
-	New(0, result, len+1, char);
-	strcpy(result,string);
-	*retlen = len;
+	/* 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;
@@ -419,7 +471,6 @@
 }
 
 
-
 void null_dequote(const char *string, STRLEN *retlen, int estring)
 {
 	dTHX;
@@ -427,4 +478,499 @@
 
 }
 
+bool is_keyword(const char *string)
+{
+
+	int max_keyword_length = 17;
+	STRLEN len;
+	int i;
+	char word[64];
+
+	len = strlen(string);
+	if (len > max_keyword_length || len > 64) {
+		return DBDPG_FALSE;
+	}
+
+	/* Because of locale issues, we manually downcase A-Z only */
+	for (i = 0; i < len; i++) {
+		char ch = string[i];
+		if (ch >= 'A' && ch <= 'Z')
+			ch += 'a' - 'A';
+		word[i] = ch;
+	}
+	word[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__
+
+ */
+

Modified: DBD-Pg/trunk/quote.h
==============================================================================
--- DBD-Pg/trunk/quote.h	(original)
+++ DBD-Pg/trunk/quote.h	Mon May 18 18:48:10 2009
@@ -17,3 +17,4 @@
 void dequote_sql_binary(char *string, STRLEN *retlen, int estring);
 void dequote_bool(char *string, STRLEN *retlen, int estring);
 void null_dequote(const char *string, STRLEN *retlen, int estring);
+bool is_keyword(const char *string);

Modified: DBD-Pg/trunk/t/12placeholders.t
==============================================================================
--- DBD-Pg/trunk/t/12placeholders.t	(original)
+++ DBD-Pg/trunk/t/12placeholders.t	Mon May 18 18:48:10 2009
@@ -8,6 +8,7 @@
 use Test::More;
 use lib 't','.';
 use DBI qw/:sql_types/;
+use DBD::Pg qw/:pg_types/;
 require 'dbdpg_test_setup.pl';
 select(($|=1,select(STDERR),$|=1)[1]);
 
@@ -16,7 +17,7 @@
 if (! defined $dbh) {
 	plan skip_all => 'Connection to database failed, cannot continue testing';
 }
-plan tests => 45;
+plan tests => 129;
 
 my $t='Connect to database for placeholder testing';
 isnt ($dbh, undef, $t);
@@ -309,28 +310,57 @@
 	is ($@, q{}, $t);
 }
 
+
+$t='Valid integer works when quoting with SQL_INTEGER';
 my $val;
 $val = $dbh->quote('123', SQL_INTEGER);
-is ($val,123, 'GO?');
+is ($val, 123, $t);
 
+$t='Invalid integer fails to pass through when quoting with SQL_INTEGER';
+$val = -1;
 eval {
 	$val = $dbh->quote('123abc', SQL_INTEGER);
 };
-like ($@, qr{Invalid integer}, 'Invalid integer fails to pass through');
+like ($@, qr{Invalid integer}, $t);
+is($val, -1, $t);
 
+my $prefix = 'Valid float value works when quoting with SQL_FLOAT';
+for my $float ('123','0.00','0.234','23.31562', '1.23e04','6.54e+02','4e-3','NaN','Infinity','-infinity') {
+	$t = "$prefix (value=$float)";
+	$val = -1;
+	eval { $val = $dbh->quote($float, SQL_FLOAT); };
+	is ($@, q{}, $t);
+	is ($val, $float, $t);
 
-$val = $dbh->quote('123', SQL_INTEGER);
-is ($val,123, 'GO?');
+	next unless $float =~ /\w/;
 
-eval {
-	$val = $dbh->quote('123abc', SQL_FLOAT);
-};
-like ($@, qr{Invalid integer}, 'Invalid integer fails to pass through');
+	my $lcfloat = lc $float;
+	$t = "$prefix (value=$lcfloat)";
+	$val = -1;
+	eval { $val = $dbh->quote($lcfloat, SQL_FLOAT); };
+	is ($@, q{}, $t);
+	is ($val, $lcfloat, $t);
+
+	my $ucfloat = uc $float;
+	$t = "$prefix (value=$ucfloat)";
+	$val = -1;
+	eval { $val = $dbh->quote($ucfloat, SQL_FLOAT); };
+	is ($@, q{}, $t);
+	is ($val, $ucfloat, $t);
+}
 
-exit;
+my $prefix = 'Invalid float value fails when quoting with SQL_FLOAT';
+for my $float ('3abc','123abc','','123e+04e+34','NaNum','-infinitee') {
+	$t = "$prefix (value=$float)";
+	$val = -1;
+	eval { $val = $dbh->quote($float, SQL_FLOAT); };
+	like ($@, qr{Invalid number}, $t);
+	is ($val, -1, $t);
+}
 
 $dbh->rollback();
-## Test placeholerds plus binding
+
+## Test placeholders plus binding
 $t='Bound placeholders enforce data types when not using server side prepares';
 $dbh->trace(0);
 $dbh->{pg_server_prepare} = 0;
@@ -341,6 +371,23 @@
 };
 like ($@, qr{Invalid integer}, 'Invalid integer test 2');
 
+## Test quoting of the "name" type
+$prefix = q{The 'name' data type does correct quoting};
+
+for my $word (qw/User user USER trigger Trigger/) {
+	$t = qq{$prefix for the word "$word"};
+	my $got = $dbh->quote($word, { pg_type => PG_NAME });
+	$expected = qq{"$word"};
+	is($got, $expected, $t);
+}
+
+for my $word (qw/auser userz user-user/) {
+	$t = qq{$prefix for the word "$word"};
+	my $got = $dbh->quote($word, { pg_type => PG_NAME });
+	$expected = qq{$word};
+	is($got, $expected, $t);
+}
+
 ## Begin custom type testing
 
 $dbh->rollback();

Modified: DBD-Pg/trunk/types.c
==============================================================================
--- DBD-Pg/trunk/types.c	(original)
+++ DBD-Pg/trunk/types.c	Mon May 18 18:48:10 2009
@@ -721,7 +721,7 @@
 bpchar   quote_string  dequote_char    SQL_CHAR                  1  0
 cid      quote_string  dequote_string  0                         0  0
 
-## Things that get no quoting at all (e.g. numbers)
+## Things that get special quoting
 int2     quote_int     null_dequote    SQL_SMALLINT|SQL_TINYINT  1  1
 int4     quote_int     null_dequote    SQL_INTEGER               1  1
 int8     quote_int     null_dequote    SQL_BIGINT                1  0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.