Commit 6e63468f authored by Bruce Momjian's avatar Bruce Momjian

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
parent c6cb8701
...@@ -39,6 +39,11 @@ public abstract class Statement { ...@@ -39,6 +39,11 @@ public abstract class Statement {
protected boolean escapeProcessing = true; protected boolean escapeProcessing = true;
// Static variables for parsing SQL when escapeProcessing is true.
private static final short IN_SQLCODE = 0;
private static final short IN_STRING = 1;
private static final short BACKSLASH =2;
private static final short ESC_TIMEDATE = 3;
public Statement() { public Statement() {
} }
...@@ -226,26 +231,76 @@ public abstract class Statement { ...@@ -226,26 +231,76 @@ public abstract class Statement {
} }
/** /**
* This is an attempt to implement SQL Escape clauses * Filter the SQL string of Java SQL Escape clauses.
*/ *
protected static String escapeSQL(String sql) { * Currently implemented Escape clauses are those mentioned in 11.3
// If we find a "{d", assume we have a date escape. * in the specification. Basically we look through the sql string for
// * {d xxx}, {t xxx} or {ts xxx} in non-string sql code. When we find
// Since the date escape syntax is very close to the * them, we just strip the escape part leaving only the xxx part.
// native Postgres date format, we just remove the escape * So, something like "select * from x where d={d '2001-10-09'}" would
// delimiters. * return "select * from x where d= '2001-10-09'".
// */
// This implementation could use some optimization, but it has protected static String escapeSQL(String sql)
// worked in practice for two years of solid use. {
int index = sql.indexOf("{d"); // Since escape codes can only appear in SQL CODE, we keep track
while (index != -1) { // of if we enter a string or not.
StringBuffer buf = new StringBuffer(sql); StringBuffer newsql = new StringBuffer();
buf.setCharAt(index, ' '); short state = IN_SQLCODE;
buf.setCharAt(index + 1, ' ');
buf.setCharAt(sql.indexOf('}', index), ' '); int i = -1;
sql = new String(buf); int len = sql.length();
index = sql.indexOf("{d"); while(++i < len)
} {
return sql; char c = sql.charAt(i);
switch(state)
{
case IN_SQLCODE:
if(c == '\'') // start of a string?
state = IN_STRING;
else if(c == '{') // start of an escape code?
if(i+1 < len)
{
char next = sql.charAt(i+1);
if(next == 'd')
{
state = ESC_TIMEDATE;
i++;
break;
}
else if(next == 't')
{
state = ESC_TIMEDATE;
i += (i+2 < len && sql.charAt(i+2) == 's') ? 2 : 1;
break;
}
}
newsql.append(c);
break;
case IN_STRING:
if(c == '\'') // end of string?
state = IN_SQLCODE;
else if(c == '\\') // a backslash?
state = BACKSLASH;
newsql.append(c);
break;
case BACKSLASH:
state = IN_STRING;
newsql.append(c);
break;
case ESC_TIMEDATE:
if(c == '}')
state = IN_SQLCODE; // end of escape code.
else
newsql.append(c);
break;
} // end switch
}
return newsql.toString();
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment