@@ -39,6 +39,11 @@ public abstract class Statement {
3939
4040protected 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
4348public 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}