@@ -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
- unsignedint opos ,npos ;
644
+ unsignedint 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