]> granicus.if.org Git - postgresql/commitdiff
Augment the function call map logic with code from Tom Lane.
authorThomas G. Lockhart <lockhart@fourpalms.org>
Tue, 4 Apr 2000 01:07:54 +0000 (01:07 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Tue, 4 Apr 2000 01:07:54 +0000 (01:07 +0000)
 Should be more robust to overflows.
 Pass through an unmapped function unchanged, rather than rejecting it.
Add a few more functions, but comment out those which can go through as-is.
Can be used with contrib/odbc/ package, though that isn't committed yet.

src/interfaces/odbc/convert.c

index 24906e10ff4cdebc14a6cf38c20a72ef8ed97383..f87b91577997816489aa552a94e435eee1093159 100644 (file)
@@ -58,19 +58,76 @@ typedef signed char SCHAR;
 
 extern GLOBAL_VALUES globals;
 
-/*     How to map ODBC scalar functions {fn func(args)} to Postgres */
-/*     This is just a simple substitution */
-char *mapFuncs[][2] = {   
-       { "CONCAT",      "textcat" },
-       { "LCASE",       "lower"   },
-       { "LOCATE",      "strpos"  },
-       { "LENGTH",      "textlen" },
-       { "LTRIM",       "ltrim"   },
-       { "RTRIM",       "rtrim"   },
-       { "SUBSTRING",   "substr"  },
-       { "UCASE",       "upper"   },
-       { "NOW",         "now"     },
-       {    0,             0      }
+/*     How to map ODBC scalar functions {fn func(args)} to Postgres
+ *     This is just a simple substitution
+ *     List augmented from
+ *      http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
+ * - thomas 2000-04-03
+ */
+char *mapFuncs[][2] = {
+//     { "ASCII",       "ascii"      },
+       { "CHAR",        "ichar"      },
+       { "CONCAT",      "textcat"    },
+//     { "DIFFERENCE",  "difference" },
+//     { "INSERT",      "insert"     },
+       { "LCASE",       "lower"      },
+       { "LEFT",        "ltrunc"     },
+       { "LOCATE",      "strpos"     },
+       { "LENGTH",      "char_length"},
+//     { "LTRIM",       "ltrim"      },
+       { "RIGHT",       "rtrunc"     },
+//     { "REPEAT",      "repeat"     },
+//     { "REPLACE",     "replace"    },
+//     { "RTRIM",       "rtrim"      },
+//     { "SOUNDEX",     "soundex"    },
+       { "SUBSTRING",   "substr"     },
+       { "UCASE",       "upper"      },
+
+//     { "ABS",         "abs"        },
+//     { "ACOS",        "acos"       },
+//     { "ASIN",        "asin"       },
+//     { "ATAN",        "atan"       },
+//     { "ATAN2",       "atan2"      },
+       { "CEILING",     "ceil"       },
+//     { "COS",         "cos"        },
+//     { "COT",         "cot"        },
+//     { "DEGREES",     "degrees"    },
+//     { "EXP",         "exp"        },
+//     { "FLOOR",       "floor"      },
+       { "LOG",         "ln"         },
+       { "LOG10",       "log"        },
+//     { "MOD",         "mod"        },
+//     { "PI",          "pi"         },
+       { "POWER",       "pow"        },
+//     { "RADIANS",     "radians"    },
+       { "RAND",        "random"     },
+//     { "ROUND",       "round"      },
+//     { "SIGN",        "sign"       },
+//     { "SIN",         "sin"        },
+//     { "SQRT",        "sqrt"       },
+//     { "TAN",         "tan"        },
+//     { "TRUNCATE",    "truncate"   },
+
+//     { "CURDATE",     "curdate"    },
+//     { "CURTIME",     "curtime"    },
+//     { "DAYNAME",     "dayname"    },
+//     { "DAYOFMONTH",  "dayofmonth" },
+//     { "DAYOFWEEK",   "dayofweek"  },
+//     { "DAYOFYEAR",   "dayofyear"  },
+//     { "HOUR",        "hour"       },
+//     { "MINUTE",      "minute"     },
+//     { "MONTH",       "month"      },
+//     { "MONTHNAME",   "monthname"  },
+//     { "NOW",         "now"        },
+//     { "QUARTER",     "quarter"    },
+//     { "SECOND",      "second"     },
+//     { "WEEK",        "week"       },
+//     { "YEAR",        "year"       },
+
+//     { "DATABASE",    "database"   },
+       { "IFNULL",      "coalesce"   },
+       { "USER",        "odbc_user"  },
+       {    0,             0         }
 };
 
 char *mapFunction(char *func);
@@ -584,7 +641,7 @@ int
 copy_statement_with_parameters(StatementClass *stmt)
 {
 static char *func="copy_statement_with_parameters";
-unsigned int opos, npos;
+unsigned int opos, npos, oldstmtlen;
 char param_string[128], tmp[256], cbuf[TEXT_FIELD_SIZE+5];
 int param_number;
 Int2 param_ctype, param_sqltype;
@@ -629,14 +686,17 @@ int lobj_fd, retval;
 
     param_number = -1;
 
-    for (opos = 0; opos < strlen(old_statement); opos++) {
+       oldstmtlen = strlen(old_statement);
+
+    for (opos = 0; opos <  oldstmtlen; opos++) {
 
                //      Squeeze carriage-returns/linfeed pairs to linefeed only
-               if (old_statement[opos] == '\r' && opos+1<strlen(old_statement) && old_statement[opos+1] == '\n') {
+               if (old_statement[opos] == '\r' && opos+1 < oldstmtlen &&
+                       old_statement[opos+1] == '\n') {
                        continue;
                }
 
-               //      Handle literals (date, time, timestamp)
+               //      Handle literals (date, time, timestamp) and ODBC scalar functions
                else if (old_statement[opos] == '{') {
                        char *esc;
                        char *begin = &old_statement[opos + 1];
@@ -1056,37 +1116,69 @@ int i;
        return NULL;
 }
 
-//     This function returns a pointer to static memory!
+/* convert_escape()
+ * This function returns a pointer to static memory!
+ */
 char *
 convert_escape(char *value)
 {
-char key[32], val[256];
 static char escape[1024];
-char func[32], the_rest[1024];
-char *mapFunc;
-
-       sscanf(value, "%s %[^\r]", key, val);
+char key[33];
 
-       mylog("convert_escape: key='%s', val='%s'\n", key, val);
+       /* Separate off the key, skipping leading and trailing whitespace */
+       while ((*value != '\0') && isspace(*value)) value++;
+       sscanf(value, "%32s", key);
+       while ((*value != '\0') && (! isspace(*value))) value++;
+       while ((*value != '\0') && isspace(*value)) value++;
 
-       if ( ! strcmp(key, "d") ||
-                ! strcmp(key, "t") ||
-                ! strcmp(key, "ts")) {
+       mylog("convert_escape: key='%s', val='%s'\n", key, value);
 
-               strcpy(escape, val);
+       if ( (strcmp(key, "d") == 0) ||
+                (strcmp(key, "t") == 0) ||
+                (strcmp(key, "ts") == 0)) {
+               /* Literal; return the escape part as-is */
+               strncpy(escape, value, sizeof(escape)-1);
        }
-       else if ( ! strcmp(key, "fn")) {
-               sscanf(val, "%[^(]%[^\r]", func, the_rest);
-               mapFunc = mapFunction(func);
-               if ( ! mapFunc)
-                       return NULL;
-               else {
-                       strcpy(escape, mapFunc);
-                       strcat(escape, the_rest);
+       else if (strcmp(key, "fn") == 0) {
+               /* Function invocation
+                * Separate off the func name,
+                * skipping trailing whitespace.
+                */
+               char *funcEnd = value;
+               char svchar;
+               char *mapFunc;
+
+               while ((*funcEnd != '\0') && (*funcEnd != '(') &&
+                          (! isspace(*funcEnd))) funcEnd++;
+               svchar = *funcEnd;
+               *funcEnd = '\0';
+               sscanf(value, "%32s", key);
+               *funcEnd = svchar;
+               while ((*funcEnd != '\0') && isspace(*funcEnd)) funcEnd++;
+
+               /* We expect left parenthensis here,
+                * else return fn body as-is since it is
+                * one of those "function constants".
+                */
+               if (*funcEnd != '(') {
+                       strncpy(escape, value, sizeof(escape)-1);
+                       return escape;
                }
-
+               mapFunc = mapFunction(key);
+               /* We could have mapFunction() return key if not in table...
+                * - thomas 2000-04-03
+                */
+               if (mapFunc == NULL) {
+                       /* If unrecognized function name, return fn body as-is */
+                       strncpy(escape, value, sizeof(escape)-1);
+                       return escape;
+               }
+               /* copy mapped name and remaining input string */
+               strcpy(escape, mapFunc);
+               strncat(escape, funcEnd, sizeof(escape)-strlen(mapFunc));
        }
        else {
+               /* Bogus key, leave untranslated */
                return NULL;
        }