@@ -39,6 +39,11 @@ public abstract class Statement {
39
39
40
40
protected boolean escapeProcessing = true ;
41
41
42
+ // Static variables for parsing SQL when escapeProcessing is true.
43
+ private static final short IN_SQLCODE = 0 ;
44
+ private static final short IN_STRING = 1 ;
45
+ private static final short BACKSLASH =2 ;
46
+ private static final short ESC_TIMEDATE = 3 ;
42
47
43
48
public Statement () {
44
49
}
@@ -226,26 +231,76 @@ public void close() throws SQLException {
226
231
}
227
232
228
233
/**
229
- * This is an attempt to implement SQL Escape clauses
234
+ * Filter the SQL string of Java SQL Escape clauses.
235
+ *
236
+ * Currently implemented Escape clauses are those mentioned in 11.3
237
+ * in the specification. Basically we look through the sql string for
238
+ * {d xxx}, {t xxx} or {ts xxx} in non-string sql code. When we find
239
+ * them, we just strip the escape part leaving only the xxx part.
240
+ * So, something like "select * from x where d={d '2001-10-09'}" would
241
+ * return "select * from x where d= '2001-10-09'".
230
242
*/
231
- protected static String escapeSQL (String sql ) {
232
- // If we find a "{d", assume we have a date escape.
233
- //
234
- // Since the date escape syntax is very close to the
235
- // native Postgres date format, we just remove the escape
236
- // delimiters.
237
- //
238
- // This implementation could use some optimization, but it has
239
- // worked in practice for two years of solid use.
240
- int index = sql .indexOf ("{d" );
241
- while (index != -1 ) {
242
- StringBuffer buf = new StringBuffer (sql );
243
- buf .setCharAt (index , ' ' );
244
- buf .setCharAt (index + 1 , ' ' );
245
- buf .setCharAt (sql .indexOf ('}' , index ), ' ' );
246
- sql = new String (buf );
247
- index = sql .indexOf ("{d" );
248
- }
249
- return sql ;
243
+ protected static String escapeSQL (String sql )
244
+ {
245
+ // Since escape codes can only appear in SQL CODE, we keep track
246
+ // of if we enter a string or not.
247
+ StringBuffer newsql = new StringBuffer ();
248
+ short state = IN_SQLCODE ;
249
+
250
+ int i = -1 ;
251
+ int len = sql .length ();
252
+ while (++i < len )
253
+ {
254
+ char c = sql .charAt (i );
255
+ switch (state )
256
+ {
257
+ case IN_SQLCODE :
258
+ if (c == '\'' ) // start of a string?
259
+ state = IN_STRING ;
260
+ else if (c == '{' ) // start of an escape code?
261
+ if (i +1 < len )
262
+ {
263
+ char next = sql .charAt (i +1 );
264
+ if (next == 'd' )
265
+ {
266
+ state = ESC_TIMEDATE ;
267
+ i ++;
268
+ break ;
269
+ }
270
+ else if (next == 't' )
271
+ {
272
+ state = ESC_TIMEDATE ;
273
+ i += (i +2 < len && sql .charAt (i +2 ) == 's' ) ? 2 : 1 ;
274
+ break ;
275
+ }
276
+ }
277
+ newsql .append (c );
278
+ break ;
279
+
280
+ case IN_STRING :
281
+ if (c == '\'' ) // end of string?
282
+ state = IN_SQLCODE ;
283
+ else if (c == '\\' ) // a backslash?
284
+ state = BACKSLASH ;
285
+
286
+ newsql .append (c );
287
+ break ;
288
+
289
+ case BACKSLASH :
290
+ state = IN_STRING ;
291
+
292
+ newsql .append (c );
293
+ break ;
294
+
295
+ case ESC_TIMEDATE :
296
+ if (c == '}' )
297
+ state = IN_SQLCODE ; // end of escape code.
298
+ else
299
+ newsql .append (c );
300
+ break ;
301
+ } // end switch
302
+ }
303
+
304
+ return newsql .toString ();
250
305
}
251
306
}
0 commit comments