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.