summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas G. Lockhart2000-04-04 01:07:54 +0000
committerThomas G. Lockhart2000-04-04 01:07:54 +0000
commit8cdabf074118ab0c86423891cc0b85c9c94939e7 (patch)
tree37c4a869717e96f8c52527f280e6d82190453a42
parent51cfdae50ff91d99d9f1fd1dc9756a5335ee91fb (diff)
Augment the function call map logic with code from Tom Lane.
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.
-rw-r--r--src/interfaces/odbc/convert.c166
1 files changed, 129 insertions, 37 deletions
diff --git a/src/interfaces/odbc/convert.c b/src/interfaces/odbc/convert.c
index 24906e10ff4..f87b9157799 100644
--- a/src/interfaces/odbc/convert.c
+++ b/src/interfaces/odbc/convert.c
@@ -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;
}