@@ -58,19 +58,76 @@ typedef signed char SCHAR;
58
58
59
59
extern GLOBAL_VALUES globals ;
60
60
61
- /* How to map ODBC scalar functions {fn func(args)} to Postgres */
62
- /* This is just a simple substitution */
63
- char * mapFuncs [][2 ] = {
64
- { "CONCAT" , "textcat" },
65
- { "LCASE" , "lower" },
66
- { "LOCATE" , "strpos" },
67
- { "LENGTH" , "textlen" },
68
- { "LTRIM" , "ltrim" },
69
- { "RTRIM" , "rtrim" },
70
- { "SUBSTRING" , "substr" },
71
- { "UCASE" , "upper" },
72
- { "NOW" , "now" },
73
- { 0 , 0 }
61
+ /* How to map ODBC scalar functions {fn func(args)} to Postgres
62
+ * This is just a simple substitution
63
+ * List augmented from
64
+ * http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
65
+ * - thomas 2000-04-03
66
+ */
67
+ char * mapFuncs [][2 ] = {
68
+ // { "ASCII", "ascii" },
69
+ { "CHAR" , "ichar" },
70
+ { "CONCAT" , "textcat" },
71
+ // { "DIFFERENCE", "difference" },
72
+ // { "INSERT", "insert" },
73
+ { "LCASE" , "lower" },
74
+ { "LEFT" , "ltrunc" },
75
+ { "LOCATE" , "strpos" },
76
+ { "LENGTH" , "char_length" },
77
+ // { "LTRIM", "ltrim" },
78
+ { "RIGHT" , "rtrunc" },
79
+ // { "REPEAT", "repeat" },
80
+ // { "REPLACE", "replace" },
81
+ // { "RTRIM", "rtrim" },
82
+ // { "SOUNDEX", "soundex" },
83
+ { "SUBSTRING" , "substr" },
84
+ { "UCASE" , "upper" },
85
+
86
+ // { "ABS", "abs" },
87
+ // { "ACOS", "acos" },
88
+ // { "ASIN", "asin" },
89
+ // { "ATAN", "atan" },
90
+ // { "ATAN2", "atan2" },
91
+ { "CEILING" , "ceil" },
92
+ // { "COS", "cos" },
93
+ // { "COT", "cot" },
94
+ // { "DEGREES", "degrees" },
95
+ // { "EXP", "exp" },
96
+ // { "FLOOR", "floor" },
97
+ { "LOG" , "ln" },
98
+ { "LOG10" , "log" },
99
+ // { "MOD", "mod" },
100
+ // { "PI", "pi" },
101
+ { "POWER" , "pow" },
102
+ // { "RADIANS", "radians" },
103
+ { "RAND" , "random" },
104
+ // { "ROUND", "round" },
105
+ // { "SIGN", "sign" },
106
+ // { "SIN", "sin" },
107
+ // { "SQRT", "sqrt" },
108
+ // { "TAN", "tan" },
109
+ // { "TRUNCATE", "truncate" },
110
+
111
+ // { "CURDATE", "curdate" },
112
+ // { "CURTIME", "curtime" },
113
+ // { "DAYNAME", "dayname" },
114
+ // { "DAYOFMONTH", "dayofmonth" },
115
+ // { "DAYOFWEEK", "dayofweek" },
116
+ // { "DAYOFYEAR", "dayofyear" },
117
+ // { "HOUR", "hour" },
118
+ // { "MINUTE", "minute" },
119
+ // { "MONTH", "month" },
120
+ // { "MONTHNAME", "monthname" },
121
+ // { "NOW", "now" },
122
+ // { "QUARTER", "quarter" },
123
+ // { "SECOND", "second" },
124
+ // { "WEEK", "week" },
125
+ // { "YEAR", "year" },
126
+
127
+ // { "DATABASE", "database" },
128
+ { "IFNULL" , "coalesce" },
129
+ { "USER" , "odbc_user" },
130
+ { 0 , 0 }
74
131
};
75
132
76
133
char * mapFunction (char * func );
584
641
copy_statement_with_parameters (StatementClass * stmt )
585
642
{
586
643
static char * func = "copy_statement_with_parameters" ;
587
- unsigned int opos , npos ;
644
+ unsigned int opos , npos , oldstmtlen ;
588
645
char param_string [128 ], tmp [256 ], cbuf [TEXT_FIELD_SIZE + 5 ];
589
646
int param_number ;
590
647
Int2 param_ctype , param_sqltype ;
@@ -629,14 +686,17 @@ int lobj_fd, retval;
629
686
630
687
param_number = -1 ;
631
688
632
- for (opos = 0 ; opos < strlen (old_statement ); opos ++ ) {
689
+ oldstmtlen = strlen (old_statement );
690
+
691
+ for (opos = 0 ; opos < oldstmtlen ; opos ++ ) {
633
692
634
693
// Squeeze carriage-returns/linfeed pairs to linefeed only
635
- if (old_statement [opos ] == '\r' && opos + 1 < strlen (old_statement ) && old_statement [opos + 1 ] == '\n' ) {
694
+ if (old_statement [opos ] == '\r' && opos + 1 < oldstmtlen &&
695
+ old_statement [opos + 1 ] == '\n' ) {
636
696
continue ;
637
697
}
638
698
639
- // Handle literals (date, time, timestamp)
699
+ // Handle literals (date, time, timestamp) and ODBC scalar functions
640
700
else if (old_statement [opos ] == '{' ) {
641
701
char * esc ;
642
702
char * begin = & old_statement [opos + 1 ];
@@ -1056,37 +1116,69 @@ int i;
1056
1116
return NULL ;
1057
1117
}
1058
1118
1059
- // This function returns a pointer to static memory!
1119
+ /* convert_escape()
1120
+ * This function returns a pointer to static memory!
1121
+ */
1060
1122
char *
1061
1123
convert_escape (char * value )
1062
1124
{
1063
- char key [32 ], val [256 ];
1064
1125
static char escape [1024 ];
1065
- char func [32 ], the_rest [1024 ];
1066
- char * mapFunc ;
1067
-
1068
- sscanf (value , "%s %[^\r]" , key , val );
1126
+ char key [33 ];
1069
1127
1070
- mylog ("convert_escape: key='%s', val='%s'\n" , key , val );
1128
+ /* Separate off the key, skipping leading and trailing whitespace */
1129
+ while ((* value != '\0' ) && isspace (* value )) value ++ ;
1130
+ sscanf (value , "%32s" , key );
1131
+ while ((* value != '\0' ) && (! isspace (* value ))) value ++ ;
1132
+ while ((* value != '\0' ) && isspace (* value )) value ++ ;
1071
1133
1072
- if ( ! strcmp (key , "d" ) ||
1073
- ! strcmp (key , "t" ) ||
1074
- ! strcmp (key , "ts" )) {
1134
+ mylog ("convert_escape: key='%s', val='%s'\n" , key , value );
1075
1135
1076
- strcpy (escape , val );
1136
+ if ( (strcmp (key , "d" ) == 0 ) ||
1137
+ (strcmp (key , "t" ) == 0 ) ||
1138
+ (strcmp (key , "ts" ) == 0 )) {
1139
+ /* Literal; return the escape part as-is */
1140
+ strncpy (escape , value , sizeof (escape )- 1 );
1077
1141
}
1078
- else if ( ! strcmp (key , "fn" )) {
1079
- sscanf (val , "%[^(]%[^\r]" , func , the_rest );
1080
- mapFunc = mapFunction (func );
1081
- if ( ! mapFunc )
1082
- return NULL ;
1083
- else {
1084
- strcpy (escape , mapFunc );
1085
- strcat (escape , the_rest );
1142
+ else if (strcmp (key , "fn" ) == 0 ) {
1143
+ /* Function invocation
1144
+ * Separate off the func name,
1145
+ * skipping trailing whitespace.
1146
+ */
1147
+ char * funcEnd = value ;
1148
+ char svchar ;
1149
+ char * mapFunc ;
1150
+
1151
+ while ((* funcEnd != '\0' ) && (* funcEnd != '(' ) &&
1152
+ (! isspace (* funcEnd ))) funcEnd ++ ;
1153
+ svchar = * funcEnd ;
1154
+ * funcEnd = '\0' ;
1155
+ sscanf (value , "%32s" , key );
1156
+ * funcEnd = svchar ;
1157
+ while ((* funcEnd != '\0' ) && isspace (* funcEnd )) funcEnd ++ ;
1158
+
1159
+ /* We expect left parenthensis here,
1160
+ * else return fn body as-is since it is
1161
+ * one of those "function constants".
1162
+ */
1163
+ if (* funcEnd != '(' ) {
1164
+ strncpy (escape , value , sizeof (escape )- 1 );
1165
+ return escape ;
1086
1166
}
1087
-
1167
+ mapFunc = mapFunction (key );
1168
+ /* We could have mapFunction() return key if not in table...
1169
+ * - thomas 2000-04-03
1170
+ */
1171
+ if (mapFunc == NULL ) {
1172
+ /* If unrecognized function name, return fn body as-is */
1173
+ strncpy (escape , value , sizeof (escape )- 1 );
1174
+ return escape ;
1175
+ }
1176
+ /* copy mapped name and remaining input string */
1177
+ strcpy (escape , mapFunc );
1178
+ strncat (escape , funcEnd , sizeof (escape )- strlen (mapFunc ));
1088
1179
}
1089
1180
else {
1181
+ /* Bogus key, leave untranslated */
1090
1182
return NULL ;
1091
1183
}
1092
1184
0 commit comments