aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2001-09-17 15:54:50 +0000
committerBruce Momjian <bruce@momjian.us>2001-09-17 15:54:50 +0000
commit6e63468f3a6a4bd00e83cf76e6197ed7d066d0c5 (patch)
treecf255363689486c8c8a55d1555c2bb9a646f5fd5
parentc6cb8701db20245631d6f16c19d98ea3059798b2 (diff)
downloadpostgresql-6e63468f3a6a4bd00e83cf76e6197ed7d066d0c5.tar.gz
postgresql-6e63468f3a6a4bd00e83cf76e6197ed7d066d0c5.zip
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
-rw-r--r--src/interfaces/jdbc/org/postgresql/Statement.java95
1 files changed, 75 insertions, 20 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/Statement.java b/src/interfaces/jdbc/org/postgresql/Statement.java
index 5187bee2484..6acdd8bfa58 100644
--- a/src/interfaces/jdbc/org/postgresql/Statement.java
+++ b/src/interfaces/jdbc/org/postgresql/Statement.java
@@ -39,6 +39,11 @@ public abstract class Statement {
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() {
}
@@ -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.
+ *
+ * Currently implemented Escape clauses are those mentioned in 11.3
+ * 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
+ * them, we just strip the escape part leaving only the xxx part.
+ * So, something like "select * from x where d={d '2001-10-09'}" would
+ * return "select * from x where d= '2001-10-09'".
*/
- protected static String escapeSQL(String sql) {
- // If we find a "{d", assume we have a date escape.
- //
- // Since the date escape syntax is very close to the
- // native Postgres date format, we just remove the escape
- // delimiters.
- //
- // This implementation could use some optimization, but it has
- // worked in practice for two years of solid use.
- int index = sql.indexOf("{d");
- while (index != -1) {
- StringBuffer buf = new StringBuffer(sql);
- buf.setCharAt(index, ' ');
- buf.setCharAt(index + 1, ' ');
- buf.setCharAt(sql.indexOf('}', index), ' ');
- sql = new String(buf);
- index = sql.indexOf("{d");
- }
- return sql;
+ protected static String escapeSQL(String sql)
+ {
+ // Since escape codes can only appear in SQL CODE, we keep track
+ // of if we enter a string or not.
+ StringBuffer newsql = new StringBuffer();
+ short state = IN_SQLCODE;
+
+ int i = -1;
+ int len = sql.length();
+ while(++i < len)
+ {
+ 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();
}
}