@@ -39,6 +39,11 @@ public abstract class Statement {
3939
4040 protected boolean escapeProcessing = true ;
4141
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 ;
4247
4348 public Statement () {
4449 }
@@ -226,26 +231,76 @@ public void close() throws SQLException {
226231 }
227232
228233 /**
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'".
230242 */
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 ();
250305 }
251306}
0 commit comments