Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6e63468

Browse files
committed
I'm attaching a patch which fixes the corruption in strings caused
by escape processing in the SQL statement. I've tested this for a while now and it appears to work well. Previously string data with {d was getting corrupt as the {d was being stripped regardless of whether it was an escape code or not. I also added checking for time and timestamp escape processing strings as per 11.3 in the specification. The patch is against the latest CVS. Thomas O'Dowd
1 parent c6cb870 commit 6e63468

File tree

1 file changed

+75
-20
lines changed

1 file changed

+75
-20
lines changed

src/interfaces/jdbc/org/postgresql/Statement.java

+75-20
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)