You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by my...@apache.org on 2014/10/13 23:06:08 UTC
svn commit: r1631551 - in /db/derby/code/branches/10.10: ./
java/testing/org/apache/derbyTesting/functionTests/tests/lang/
java/tools/org/apache/derby/impl/tools/planexporter/
java/tools/org/apache/derby/tools/
Author: myrnavl
Date: Mon Oct 13 21:06:08 2014
New Revision: 1631551
URL: http://svn.apache.org/r1631551
Log:
DERBY-6629; Restrict privileged operation in CreateXMLFile
backport of revision 1605021 from trunk.
Modified:
db/derby/code/branches/10.10/ (props changed)
db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java
db/derby/code/branches/10.10/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java
db/derby/code/branches/10.10/java/tools/org/apache/derby/tools/PlanExporter.java
Propchange: db/derby/code/branches/10.10/
------------------------------------------------------------------------------
Merged /db/derby/code/trunk:r1605021
Modified: db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java?rev=1631551&r1=1631550&r2=1631551&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java (original)
+++ db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java Mon Oct 13 21:06:08 2014
@@ -21,11 +21,14 @@
package org.apache.derbyTesting.functionTests.tests.lang;
+import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintStream;
import java.net.MalformedURLException;
import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -47,7 +50,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.derby.impl.tools.planexporter.AccessDatabase;
-import org.apache.derby.impl.tools.planexporter.CreateXMLFile;
+import org.apache.derby.tools.PlanExporter;
import org.apache.derbyTesting.junit.BaseJDBCTestCase;
import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
import org.apache.derbyTesting.junit.JDBC;
@@ -535,9 +538,11 @@ public class XplainStatisticsTest extend
/**
*
* @param s
+ * @param exportPlan whether or not the PlanExporter tool should be used
+ * to export the plan of the recorded statements
* @throws Exception
*/
- private static void disableXplainStyle(Statement s)
+ private static void disableXplainStyle(Statement s, boolean exportPlan)
throws Exception
{
s.execute("call SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(0)");
@@ -546,31 +551,22 @@ public class XplainStatisticsTest extend
* Added by DERBY-4587 to test the generation of XML files
* from PlanExporter tool.
*/
- String stmt_id="";
- ResultSet rs;
- AccessDatabase access;
+ if (exportPlan) {
+ String dbUrl = s.getConnection().getMetaData().getURL();
+
+ ResultSet rs = s.executeQuery(
+ "select stmt_id from XPLTEST.sysxplain_statements");
+ while (rs.next()) {
+ String stmt_id = rs.getString(1);
+ String output = invokePlanExporterTool(
+ dbUrl, "XPLTEST", stmt_id, "-xml",
+ SupportFilesSetup.getReadWriteFileName(stmt_id + ".xml"));
+
+ // Expect the plan exporter tool to print nothing on success.
+ assertEquals("Unexpected output from PlanExporter", "", output);
+ }
+ }
- rs = s.executeQuery(
- "select stmt_id from XPLTEST.sysxplain_statements");
- while (rs.next())
- {
- stmt_id = rs.getString(1);
- access =
- new AccessDatabase(s.getConnection(), "XPLTEST", stmt_id);
- if(access.initializeDataArray()){
- access.createXMLFragment();
- access.markTheDepth();
-
- CreateXMLFile xml_file = new CreateXMLFile(access);
- xml_file.writeTheXMLFile(
- access.statement(),
- access.time(),
- access.getData(),
- SupportFilesSetup.getReadWriteURL(stmt_id + ".xml")
- .getPath(),
- null);
- }
- }
s.execute("call syscs_util.syscs_set_xplain_schema('')");
}
@@ -600,6 +596,53 @@ public class XplainStatisticsTest extend
rs.close();
}
+ /**
+ * Invoke the PlanExporter tool.
+ *
+ * @param args the command line arguments to pass to the tool
+ * @return the output printed by the tool (typically an empty string
+ * on successful execution)
+ */
+ private static String invokePlanExporterTool(
+ String arg1, String arg2, String arg3, String arg4, String arg5) {
+ final PrintStream out = System.out;
+ final PrintStream err = System.err;
+
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ final PrintStream testOutput = new PrintStream(byteOut);
+
+ // Redirect System.out and System.err so that the output
+ // can be captured.
+// System.setOut(testOutput);
+// System.setErr(testOutput);
+ ByteArrayOutputStream serverOutputBOS = new ByteArrayOutputStream();
+ final PrintStream serverOutputOut = new PrintStream( serverOutputBOS);
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ System.setOut(new PrintStream(testOutput));
+ System.setErr(new PrintStream(testOutput));
+ return null;
+ }
+ });
+
+ try {
+ String args[] = {arg1, arg2, arg3, arg4, arg5};
+ PlanExporter.main(args);
+ } finally {
+ // Restore the original out streams
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ System.setOut(out);
+ System.setErr(err);
+ return null;
+ }
+ });
+ }
+
+ testOutput.flush();
+ return byteOut.toString();
+ }
+
// Can be used internally when diagnosing failed tests.
//
private void dumpResultSets(Statement s)
@@ -805,24 +848,29 @@ public class XplainStatisticsTest extend
public void testPlanExporterIllegalFileAccess()
throws Exception
{
- AccessDatabase access =
- new AccessDatabase(getConnection(), "NoSuchSchema", "nostmt");
- CreateXMLFile xml_file = new CreateXMLFile(access);
- try
- {
- xml_file.writeTheXMLFile("nostmt", "notime", null,
- "/illegal.xml", null);
- fail("Expected exception for illegal file access");
- }
- catch (java.security.AccessControlException ace)
- {
- // Expected this exception to be thrown
- }
- catch (Exception e)
- {
- e.printStackTrace();
- fail(e.getMessage());
- }
+ // Make sure there is a statement with recorded statistics.
+ Statement s = createStatement();
+ enableXplainStyle(s);
+ JDBC.assertDrainResults(s.executeQuery("values 1"));
+ disableXplainStyle(s, true);
+
+ // Get the id of the statement.
+ ResultSet rs = s.executeQuery(
+ "select stmt_id from XPLTEST.sysxplain_statements");
+ assertTrue("no statements", rs.next());
+ String stmt_id = rs.getString("stmt_id");
+ JDBC.assertEmpty(rs);
+
+ // Try to write the plan to a file that the tool does not have
+ // permission to write to.
+ String output = invokePlanExporterTool(
+ getConnection().getMetaData().getURL(), "XPLTEST",
+ stmt_id, "-xml", "/illegal.xml");
+
+ // The plan exporter tool should fail with a permission error.
+ if (!output.contains("java.security.AccessControlException")) {
+ fail("Unexpected output from PlanExporter: " + output);
+ }
}
/**
@@ -867,21 +915,18 @@ public class XplainStatisticsTest extend
rs.close();
// Create the XML file. This used to result in a syntax error.
- AccessDatabase access =
- new AccessDatabase(getConnection(), schema, stmtId);
- assertTrue(access.initializeDataArray());
- access.createXMLFragment();
- access.markTheDepth();
- CreateXMLFile create = new CreateXMLFile(access);
- create.writeTheXMLFile(
- access.statement(),
- access.time(),
- access.getData(),
- SupportFilesSetup.getReadWriteURL(stmtId + ".xml").getPath(),
- null);
+ String output = invokePlanExporterTool(
+ getConnection().getMetaData().getURL(),
+ schema,
+ stmtId,
+ "-xml",
+ SupportFilesSetup.getReadWriteFileName(stmtId + ".xml"));
+
+ // Expect empty output on successful execution of the tool.
+ assertEquals("Unexpected output from PlanExporter", "", output);
// If we have the required libraries for parsing XML files, verify
- // that the output contains valid data.
+ // that the XML file contains valid data.
if (XML.classpathMeetsXMLReqs()) {
assertEquals(query, readStatement(stmtId));
}
@@ -963,7 +1008,7 @@ public class XplainStatisticsTest extend
new String[][] { {"Belize"}, {"Costa Rica"}, {"El Salvador"},
{"Guatemala"}, {"Honduras"}, {"Nicaragua"} } );
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// The statement should have been executed as a PROJECTION
// wrapped around a TABLESCAN. The TABLESCAN should have had
@@ -1111,7 +1156,7 @@ public class XplainStatisticsTest extend
"SELECT country from countries "+
"WHERE region = 'Central America'" ));
clearXplainOnlyMode(s);
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// dumpStatements(s);
// dumpResultSets(s);
@@ -1145,7 +1190,7 @@ public class XplainStatisticsTest extend
"select sql_text from syscs_diag.transaction_table " +
"where status != 'IDLE'" ));
clearXplainOnlyMode(s);
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
//dumpStatements(s);
//dumpResultSets(s);
@@ -1180,7 +1225,7 @@ public class XplainStatisticsTest extend
JDBC.assertEmpty(s.executeQuery(selectStatement));
clearXplainOnlyMode(s);
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
//dumpStatements(s);
//dumpResultSets(s);
@@ -1238,7 +1283,7 @@ public class XplainStatisticsTest extend
enableXplainOnlyMode(s);
JDBC.assertEmpty(ps.executeQuery());
clearXplainOnlyMode(s);
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
//dumpStatements(s);
//dumpResultSets(s);
@@ -1302,7 +1347,7 @@ public class XplainStatisticsTest extend
enableXplainOnlyMode(s);
JDBC.assertEmpty(ps.executeQuery());
clearXplainOnlyMode(s);
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// Verify that statistics were collected.
JDBC.assertDrainResults(
@@ -1332,7 +1377,7 @@ public class XplainStatisticsTest extend
{"Europe", "29"}, {"Middle East", "7"},
{"North Africa", "5"}, {"North America", "3"},
{"Pacific Islands", "3"}, {"South America", "11"} } );
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
//dumpStatements(s);
//dumpResultSets(s);
@@ -1573,7 +1618,7 @@ public class XplainStatisticsTest extend
JDBC.assertUnorderedResultSet(s.executeQuery(selectStatement),
new String[][] { {"AA1112"}, {"AA1114"}, {"AA1116"} } );
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// This query should have been executed as a PROJECTION whose child
// is a ROWIDSCAN whose child is an INDEXSCAN. The INDEXSCAN should
@@ -1668,7 +1713,7 @@ public class XplainStatisticsTest extend
"SELECT region from countries where country = 'Cameroon'";
JDBC.assertSingleValueResultSet(s.executeQuery(selectStatement),
"Africa");
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
JDBC.assertUnorderedResultSet(s.executeQuery(
"select op_identifier from xpltest.sysxplain_resultsets"),
new String[][] {
@@ -1743,7 +1788,7 @@ public class XplainStatisticsTest extend
{"North Africa", "5"}, {"North America", "3"},
{"Pacific Islands", "3"}, {"South America", "11"} } );
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// This statement is executed as a PROJECTION with a child GROUPBY
// with a child PROJECTION with a child TABLESCAN. The TABLESCAN
@@ -1842,7 +1887,7 @@ public class XplainStatisticsTest extend
// Execute the statement and throw away the results. We just want
// to look at the statistics.
s.executeQuery(selectStatement).close();
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
JDBC.assertSingleValueResultSet(s.executeQuery(
"select count(*) from xpltest.sysxplain_sort_props"), "1");
@@ -1906,7 +1951,7 @@ public class XplainStatisticsTest extend
String selectStatement =
"select count(distinct region) from countries";
JDBC.assertSingleValueResultSet(s.executeQuery(selectStatement), "12");
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// The above statement results in the query execution:
// PROJECTION(AGGREGATION(PROJECTION(TABLESCAN)))
@@ -1968,7 +2013,7 @@ public class XplainStatisticsTest extend
"insert into AIRLINES values " +
"('AA','Amazonian Airways',0.18,0.03,0.5,1.5,20,10,5)";
int numRows = s.executeUpdate(insertStatement);
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
assertEquals("Failed to insert into AIRLINES", 1, numRows);
JDBC.assertUnorderedResultSet(s.executeQuery(
"select stmt_type, stmt_text " +
@@ -2061,7 +2106,7 @@ public class XplainStatisticsTest extend
enableXplainStyle(s);
numRows = s.executeUpdate(updateStatement);
assertEquals("Failed to update AIRLINES", 1, numRows);
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
JDBC.assertUnorderedResultSet(s.executeQuery(
"select stmt_type, stmt_text " +
" from xpltest.sysxplain_statements"),
@@ -2218,7 +2263,7 @@ public class XplainStatisticsTest extend
enableXplainStyle(s);
numRows = s.executeUpdate(deleteStatement);
assertEquals("Failed to delete from AIRLINES", 1, numRows);
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
JDBC.assertUnorderedResultSet(s.executeQuery(
"select stmt_type, stmt_text " +
" from xpltest.sysxplain_statements"),
@@ -2290,7 +2335,7 @@ public class XplainStatisticsTest extend
String selectStatement =
"select region from countries order by country";
s.executeQuery(selectStatement).close(); // Discard the results
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// The above statement results in the query execution:
// PROJECTION(SORT(PROJECTION(TABLESCAN)))
@@ -2372,7 +2417,7 @@ public class XplainStatisticsTest extend
" union " +
"select country from countries where region = 'Africa'";
s.executeQuery(selectStatement).close(); // Discard the results
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// The above statement results in the query execution:
// SORT(UNION(PROJECTION(TABLESCAN),PROJECTION(TABLESCAN)))
@@ -2476,7 +2521,11 @@ public class XplainStatisticsTest extend
String ddlStatement =
"create table t1 (a int, b char(10), c timestamp)";
s.executeUpdate(ddlStatement);
- disableXplainStyle(s);
+
+ // Don't run the PlanExporter tool on this statement. There is no
+ // result set graph recorded for DDL statements, so the PlanExporter
+ // tool will complain.
+ disableXplainStyle(s, false);
JDBC.assertUnorderedResultSet(s.executeQuery(
"select stmt_type, stmt_text " +
@@ -2497,7 +2546,7 @@ public class XplainStatisticsTest extend
String selectStatement =
"select max(country_iso_code) from countries";
s.executeQuery(selectStatement).close();
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// The above query is executed as
// PROJECTION(AGGREGATION(PROJECTION(LASTINDEXKEYSCAN)))
@@ -2612,7 +2661,7 @@ public class XplainStatisticsTest extend
{"ABQ",null},{"OKC",null},{"AKL",null},{"HNL",null},
{"AKL",null},{"NRT",null}
});
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// We should get a Nested Loop Outer Join which reads 10 rows
// from the left (SEEN_ROWS), constructs 10 EMPTY_RIGHT_ROWS,
@@ -2707,7 +2756,7 @@ public class XplainStatisticsTest extend
enableXplainStyle(s);
for (int i = 0; i < searches.length; i++)
s.executeQuery(searches[i]).close();
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
ResultSet rs = s.executeQuery(
"select s.stmt_text, sp.start_position, sp.stop_position " +
@@ -2780,7 +2829,7 @@ public class XplainStatisticsTest extend
String selectStatement = "select x from t";
JDBC.assertUnorderedResultSet(s.executeQuery(selectStatement),
new String[][] { {"1"},{"2"},{"4"} });
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// There should be a CONSTRAINTSCAN result set with a SCAN PROPS
// which indicates that we visited 1 deleted row while scanning
@@ -2853,7 +2902,7 @@ public class XplainStatisticsTest extend
Statement s = createStatement();
enableXplainStyle(s);
JDBC.assertEmpty(s.executeQuery(sql));
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
// Now, see if we find the query among the recorded statements.
PreparedStatement ps = prepareStatement(
@@ -2904,7 +2953,7 @@ public class XplainStatisticsTest extend
enableXplainStyle(s);
JDBC.assertEmpty(s.executeQuery(queryText));
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
ResultSet rs = s.executeQuery(
"SELECT STMT_ID, STMT_TEXT FROM XPLTEST.SYSXPLAIN_STATEMENTS");
@@ -2940,7 +2989,7 @@ public class XplainStatisticsTest extend
enableXplainStyle(s);
JDBC.assertEmpty(s.executeQuery(queryText));
- disableXplainStyle(s);
+ disableXplainStyle(s, true);
ResultSet rs = s.executeQuery(
"SELECT STMT_ID, STMT_TEXT FROM XPLTEST.SYSXPLAIN_STATEMENTS");
Modified: db/derby/code/branches/10.10/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java?rev=1631551&r1=1631550&r2=1631551&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java (original)
+++ db/derby/code/branches/10.10/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java Mon Oct 13 21:06:08 2014
@@ -21,14 +21,8 @@
package org.apache.derby.impl.tools.planexporter;
-import java.io.BufferedWriter;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.OutputStreamWriter;
import java.io.Writer;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
/**
* This class is to create the final xml file, that will be used
@@ -46,15 +40,12 @@ public class CreateXMLFile {
/**
* @param stmt statement executed
* @param time time which the statement was executed
- * @param data large xml data string array
- * @param file_name name of the file to be written
+ * @param out where to write the XML file
* @param xsl_sheet_name name of the style sheet
- * @throws PrivilegedActionException
* @throws IOException
- * @throws PrivilegedActionException
*/
public void writeTheXMLFile(String stmt, String time,
- TreeNode[] data, final String file_name, String xsl_sheet_name)
+ Writer out, String xsl_sheet_name)
throws IOException {
String defaultXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
@@ -68,20 +59,6 @@ public class CreateXMLFile {
String childTagStart = "<details>\n";
String childTagEnd = "</details>\n";
- FileOutputStream fos;
- try {
- fos = (FileOutputStream) AccessController.doPrivileged(
- new PrivilegedExceptionAction() {
- public Object run() throws IOException {
- return new FileOutputStream(file_name);
- }
- });
- } catch (PrivilegedActionException pae) {
- throw (IOException) pae.getCause();
- }
-
- Writer out = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
-
out.write(defaultXML);
out.write(embedXSL);
@@ -106,6 +83,5 @@ public class CreateXMLFile {
out.write(childTagEnd);
out.write(parentTagEnd);
- out.close();
}
}
Modified: db/derby/code/branches/10.10/java/tools/org/apache/derby/tools/PlanExporter.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/tools/org/apache/derby/tools/PlanExporter.java?rev=1631551&r1=1631550&r2=1631551&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/tools/org/apache/derby/tools/PlanExporter.java (original)
+++ db/derby/code/branches/10.10/java/tools/org/apache/derby/tools/PlanExporter.java Mon Oct 13 21:06:08 2014
@@ -22,7 +22,13 @@
package org.apache.derby.tools;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import org.apache.derby.impl.tools.planexporter.AccessDatabase;
import org.apache.derby.impl.tools.planexporter.CreateHTMLFile;
import org.apache.derby.impl.tools.planexporter.CreateXMLFile;
@@ -225,22 +231,33 @@ public class PlanExporter {
* @param stmt statement executed
* @param time time which the statement was executed
* @param xsl name of the style sheet
- * @throws Exception
+ * @throws IOException if an error occurs when writing the XML file
*/
private static void generateXML(AccessDatabase access,
- String arg, String stmt, String time, String xsl) throws Exception{
+ String arg, String stmt, String time, String xsl)
+ throws IOException {
CreateXMLFile xmlFile = new CreateXMLFile(access);
- if(arg.toUpperCase().endsWith(".XML")){
- xmlFile.writeTheXMLFile(stmt, time,
- access.getData(),
- arg, xsl);
+ final String fileName = arg.toUpperCase().endsWith(".XML")
+ ? arg : (arg + ".xml");
+
+ Writer out;
+ try {
+ out = (Writer) AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ public Object run() throws IOException {
+ return new OutputStreamWriter(
+ new FileOutputStream(fileName), "UTF-8");
+ }
+ });
+ } catch (PrivilegedActionException pae) {
+ throw (IOException) pae.getCause();
}
- else{
- xmlFile.writeTheXMLFile(stmt, time,
- access.getData(),
- arg.concat(".xml"),
- xsl);
+
+ try {
+ xmlFile.writeTheXMLFile(stmt, time, out, xsl);
+ } finally {
+ out.close();
}
}