Patch for jdbc escaped functions - Mailing list pgsql-jdbc
| From | Xavier Poinsard |
|---|---|
| Subject | Patch for jdbc escaped functions |
| Date | |
| Msg-id | cnkudq$37n$1@sea.gmane.org Whole thread Raw |
| Responses |
Re: Patch for jdbc escaped functions
|
| List | pgsql-jdbc |
Hi,
I saw that escaped functions were on the TODO list.
Here is a patch that prepare for adding escaped functions.
It supports nested escapes.
As example I have coded the concat function.
Tests and metadata updates are included.
If the patch is accepted, I will add more functions.
Any comments are welcome.
Index: jdbc2/AbstractJdbc2DatabaseMetaData.java
===================================================================
RCS file: /usr/local/cvsroot/pgjdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2DatabaseMetaData.java,v
retrieving revision 1.16
diff -u -r1.16 AbstractJdbc2DatabaseMetaData.java
--- jdbc2/AbstractJdbc2DatabaseMetaData.java 9 Nov 2004 08:48:31 -0000 1.16
+++ jdbc2/AbstractJdbc2DatabaseMetaData.java 19 Nov 2004 10:17:47 -0000
@@ -475,7 +475,7 @@
{
if (Driver.logDebug)
Driver.debug("getStringFunctions");
- return "";
+ return EscapedFunctions.CONCAT;
}
public String getSystemFunctions() throws SQLException
Index: jdbc2/AbstractJdbc2Statement.java
===================================================================
RCS file: /usr/local/cvsroot/pgjdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v
retrieving revision 1.50
diff -u -r1.50 AbstractJdbc2Statement.java
--- jdbc2/AbstractJdbc2Statement.java 17 Nov 2004 02:43:49 -0000 1.50
+++ jdbc2/AbstractJdbc2Statement.java 19 Nov 2004 10:17:53 -0000
@@ -655,8 +655,9 @@
*
* 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.
+ * {d xxx}, {t xxx}, {ts xxx}, {oj xxx} or {fn 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'".
*/
@@ -728,8 +729,33 @@
newsql.append(c);
break;
- case ESC_TIMEDATE:
case ESC_FUNCTION:
+ // extract function name
+ String functionName;
+ int posArgs = p_sql.indexOf('(',i);
+ if (posArgs!=-1){
+ functionName=p_sql.substring(i,posArgs).trim();
+ // extract arguments
+ i= posArgs+1;// we start the scan after the first (
+ int nestedCount=0;
+ while (i<len && !(p_sql.charAt(i)==')' && 0==nestedCount )){
+ if ('('==p_sql.charAt(i))
+ nestedCount++;
+ else if (')'==p_sql.charAt(i))
+ nestedCount--;
+ i++;
+ }
+ String args=p_sql.substring(posArgs+1,i);
+ // translate the function and parse arguments
+ newsql.append(escapeFunction(functionName,args));
+ }
+ // go to the end of the function copying anything found
+ i++;
+ while (i<len && p_sql.charAt(i)!='}')
+ newsql.append(p_sql.charAt(i));
+ state = IN_SQLCODE; // end of escaped function (or query)
+ break;
+ case ESC_TIMEDATE:
case ESC_OUTERJOIN:
if (c == '}')
state = IN_SQLCODE; // end of escape code.
@@ -746,6 +772,54 @@
return p_sql;
}
}
+ /**
+ * generate sql for escaped functions
+ * @param functionName the escaped function name
+ * @param args the arguments for this functin
+ * @return the right postgreSql sql
+ */
+ protected String escapeFunction(String functionName, String args){
+ // parse function arguments
+ int len = args.length();
+ int i=0;
+ ArrayList parsedArgs = new ArrayList();
+ while (i<len){
+ int nestedCount=0;
+ int lastPos=i;
+ while (i<len && !(args.charAt(i)==',' && 0==nestedCount )){
+ if ('('==args.charAt(i))
+ nestedCount++;
+ else if (')'==args.charAt(i))
+ nestedCount--;
+ i++;
+ }
+ if (lastPos!=i){
+ parsedArgs.add(replaceProcessing(args.substring(lastPos,i)));
+ }
+ i++;
+ }
+ // we can now tranlate escape functions
+ if (EscapedFunctions.CONCAT.equalsIgnoreCase(functionName)){
+ StringBuffer buf = new StringBuffer();
+ for (int iArg = 0;iArg<parsedArgs.size();iArg++){
+ buf.append(parsedArgs.get(iArg));
+ if (iArg!=(parsedArgs.size()-1))
+ buf.append(" || ");
+ }
+ return buf.toString();
+ }else{
+ // by default the function name is kept unchanged
+ StringBuffer buf = new StringBuffer();
+ buf.append(functionName).append('(');
+ for (int iArg = 0;iArg<parsedArgs.size();iArg++){
+ buf.append(parsedArgs.get(iArg));
+ if (iArg!=(parsedArgs.size()-1))
+ buf.append(',');
+ }
+ buf.append(')');
+ return buf.toString();
+ }
+ }
/*
*
Index: test/jdbc2/StatementTest.java
===================================================================
RCS file: /usr/local/cvsroot/pgjdbc/pgjdbc/org/postgresql/test/jdbc2/StatementTest.java,v
retrieving revision 1.9
diff -u -r1.9 StatementTest.java
--- test/jdbc2/StatementTest.java 9 Nov 2004 08:55:11 -0000 1.9
+++ test/jdbc2/StatementTest.java 19 Nov 2004 10:17:54 -0000
@@ -39,6 +39,7 @@
{
super.tearDown();
TestUtil.dropTable( con, "test_statement" );
+ TestUtil.dropTable( con, "escapetest" );
con.close();
}
@@ -116,10 +117,23 @@
count = stmt.executeUpdate("insert into escapetest (t) values ({t '00:00:00'})");
assertEquals(1, count);
-
ResultSet rs = stmt.executeQuery( "select {fn version()} as version" );
assertTrue(rs.next());
-
+
+ // check default replacement as-is
+ rs = stmt.executeQuery( "select {fn log(2,3)} as log" );
+ assertTrue(rs.next());
+
+ // check nested and multiple escaped functions
+ rs = stmt.executeQuery( "select {fn version()} as version, {fn log({fn log(3,2)},3)} as log" );
+ assertTrue(rs.next());
+
+ // check concat
+ rs = stmt.executeQuery( "select {fn concat('ab','cd')} as concat" );
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1),"abcd");
+
+
count = stmt.executeUpdate( "create temp table b (i int)" );
assertEquals(0, count);
Index: jdbc2/EscapedFunctions.java
===================================================================
RCS file: jdbc2/EscapedFunctions.java
diff -N jdbc2/EscapedFunctions.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ jdbc2/EscapedFunctions.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,16 @@
+/*-------------------------------------------------------------------------
+*
+* Copyright (c) 2004, PostgreSQL Global Development Group
+*
+* IDENTIFICATION
+*
+*-------------------------------------------------------------------------
+*/
+package org.postgresql.jdbc2;
+
+/**
+ * this class stores supported escaped function
+ */
+public class EscapedFunctions {
+ public final static String CONCAT="concat";
+}
pgsql-jdbc by date: