db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r1039272 - in /db/derby/code/branches/10.7: ./ java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java java/tools/org/apache/derby/impl/tools/planexporter/AccessDatabase.java
Date Fri, 26 Nov 2010 08:45:26 GMT
Author: kahatlen
Date: Fri Nov 26 08:45:25 2010
New Revision: 1039272

URL: http://svn.apache.org/viewvc?rev=1039272&view=rev
Log:
DERBY-4903: Plan exporter tool produces broken output if query contains less-than operator

Merged fix from trunk (revisions 1039084 and 1039268).

Modified:
    db/derby/code/branches/10.7/   (props changed)
    db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java
    db/derby/code/branches/10.7/java/tools/org/apache/derby/impl/tools/planexporter/AccessDatabase.java

Propchange: db/derby/code/branches/10.7/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Nov 26 08:45:25 2010
@@ -1 +1 @@
-/db/derby/code/trunk:1035603,1036769,1038813
+/db/derby/code/trunk:1035603,1036769,1038813,1039084,1039268

Modified: db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java?rev=1039272&r1=1039271&r2=1039272&view=diff
==============================================================================
--- db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java
(original)
+++ db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java
Fri Nov 26 08:45:25 2010
@@ -632,6 +632,28 @@ public class XplainStatisticsTest extend
     
     /**
      * Added by DERBY-4587
+     * Returns the stmt_id for this particular statement
+     * @param s Statement
+     * @return stmt_id
+     * */
+    private String[] getStmtIDArray(Statement s, int length) throws SQLException{
+        ResultSet rs;
+        String[] stmt_id = new String[length];
+        int i=0;
+        rs = s.executeQuery(
+            "select stmt_id from XPLTEST.sysxplain_statements");
+        while(rs.next()){
+            stmt_id[i] = rs.getString(1);
+            i++;
+            if (i==length)
+                assertFalse(rs.next());
+        }
+        rs.close();
+        return stmt_id;
+    }
+
+    /**
+     * Added by DERBY-4587
      * @param file name of the XML file - without extension
      * @return a Document object
      * @throws Exception
@@ -2380,6 +2402,27 @@ public class XplainStatisticsTest extend
         }
         assertEquals("Captured wrong number of statements?",
                 searches.length, matchedStatements);
+
+        /* * This test is added by DERBY-4587, to verify the content
+         * of the XML file generated by the new tool, PlanExporter.
+         * This test specially checks the behaviour of the tool
+         * when the query executed contains special XML characters
+         * such as <,> etc.
+         * */
+        if(XML.classpathMeetsXMLReqs()){
+
+            //getting the stmt_ids, because files are generated using
+            //stmt_id as their name.
+            String[] stmt_id = getStmtIDArray(s, searches.length);
+
+            for(int i=0;i<stmt_id.length;i++){
+                //testing the <statement> element
+                Assert.assertEquals(
+                        searches[i],
+                        readStatement(stmt_id[i]));
+            }
+        }
+
     }
 
     /**
@@ -2512,6 +2555,53 @@ public class XplainStatisticsTest extend
     }
 
     /**
+     * Test that queries that contain characters with a special meaning in
+     * XML are not garbled by the plan exporter tool. Regression test case
+     * for DERBY-4903.
+     */
+    public void testPlanExporterHandlingSpecialCharacters() throws Exception{
+        String table =
+                "A \"double\" and 'single' quoted table name " +
+                "with some other special characters, like <, > and &";
+
+        String escapedTable = JDBC.escape(table);
+
+        String queryText =
+                "SELECT * FROM " + escapedTable +
+                " WHERE X < LENGTH('a & b') AND X > 1";
+
+        Statement s = createStatement();
+        s.execute("CREATE TABLE " + escapedTable + "(X INT)");
+
+        enableXplainStyle(s);
+        JDBC.assertEmpty(s.executeQuery(queryText));
+        disableXplainStyle(s);
+
+        ResultSet rs = s.executeQuery(
+        "SELECT STMT_ID, STMT_TEXT FROM XPLTEST.SYSXPLAIN_STATEMENTS");
+        assertTrue(rs.next());
+        String stmtId = rs.getString(1);
+        assertEquals(queryText, rs.getString(2));
+        assertFalse(rs.next());
+        rs.close();
+
+        if (XML.classpathMeetsXMLReqs()) {
+            assertEquals(queryText, readStatement(stmtId));
+
+            //testing the root <node> element's name attributes
+            Assert.assertEquals(
+                    "TABLESCAN|",
+                    getNodeName(stmtId));
+
+            //for TABLESCAN node, test scanned_object entry
+            //is exist and verify its value correctly replaced
+            //by special XML symbols.
+            assertEquals(table, getNodeAttribute(stmtId, "scanned_object", 0));
+        }
+
+    }
+
+    /**
      * Abstract class for a thread executing a database action (i.e. a query).
      */
     private static abstract class AbstractMTThread

Modified: db/derby/code/branches/10.7/java/tools/org/apache/derby/impl/tools/planexporter/AccessDatabase.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/tools/org/apache/derby/impl/tools/planexporter/AccessDatabase.java?rev=1039272&r1=1039271&r2=1039272&view=diff
==============================================================================
--- db/derby/code/branches/10.7/java/tools/org/apache/derby/impl/tools/planexporter/AccessDatabase.java
(original)
+++ db/derby/code/branches/10.7/java/tools/org/apache/derby/impl/tools/planexporter/AccessDatabase.java
Fri Nov 26 08:45:25 2010
@@ -260,6 +260,7 @@ public class AccessDatabase {
         for(int i=0;i<data.length;i++){
             //assume only one root element for any query
             if(data[i].getDepth()==0){//root element
+
                 xmlDetails += indent(1);
                 xmlDetails += data[i].toString();
                 getChildren(1, data[i].getId());
@@ -374,7 +375,13 @@ public class AccessDatabase {
         while(results.next())
         {
             String text= results.getString(1);
+
             if(text != null){
+
+                /*Removing possible occurrences of special XML characters
+                 * from XML node attributes in XML representation.*/
+                text = escapeInAttribute(text);
+
                 switch(x){
                 case ID:
                     data[i].setId(text+" ");
@@ -466,32 +473,64 @@ public class AccessDatabase {
         String statement = results.getString(1);
         results.close();
         ps.close();
-        /*Removing possible less than and greater than characters
-         * in a query statement with XML representation.*/
-        if(statement.indexOf('<')!= -1){
-            statement = replace(statement, "<","&lt;");
-        }
-        if(statement.indexOf('>')!= -1){
-            statement = replace(statement, ">","&gt;");
-        }
+
+        /*Removing possible occurrences of special XML characters
+         * from a query statement with XML representation.*/
+        statement = escapeForXML(statement);
+
         return "<statement>"+statement+"</statement>\n";
     }
 
     /**
+     * Escape characters that have a special meaning in XML.
+     *
+     * @param text the text to escape
+     * @return the text with special characters escaped
+     */
+    private static String escapeForXML(String text) {
+        StringBuffer sb = new StringBuffer();
+
+        for (int i = 0; i < text.length(); i++) {
+            char ch = text.charAt(i);
+            switch (ch) {
+                case '&':
+                    sb.append("&amp;");
+                    break;
+                case '<':
+                    sb.append("&lt;");
+                    break;
+                case '>':
+                    sb.append("&gt;");
+                    break;
+                case '\'':
+                    sb.append("&apos;");
+                    break;
+                case '"':
+                    sb.append("&quot;");
+                    break;
+                default:
+                    sb.append(ch);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * This method is needed since in the case of XML attributes
+     * we have to filter the quotation (&quot;) marks that is compulsory.
+     * eg:
+     * scanned_object="A &quot;quoted&quot;  table name";
      *
-     * @param stmt statement to be changed
-     * @param expr string to be removed
-     * @param replace string to be added
+     * @param text attribute string to be checked
      * @return modified string
      */
-    private String replace(String stmt, String expr, String replace){
-    	 int idx = stmt.indexOf(expr);
-    	 while (idx >= 0)
-    	 {
-    	   stmt = stmt.substring(0, idx) + replace + stmt.substring(idx+1);
-    	   idx = stmt.indexOf(expr);
-    	 }
-    	 return stmt;
+    private String escapeInAttribute(String text) {
+        if (text.indexOf('"') == -1)
+            return text;
+        String correctXMLString = escapeForXML(
+                text.substring(text.indexOf('"') + 1, text.length() - 1));
+        return text.substring(0,text.indexOf('"')+1)+correctXMLString+"\"";
     }
    
     /**



Mime
View raw message