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 rh...@apache.org on 2013/01/10 18:48:58 UTC
svn commit: r1431526 - in /db/derby/code/trunk/java:
engine/org/apache/derby/catalog/
testing/org/apache/derbyTesting/functionTests/tests/lang/
Author: rhillegas
Date: Thu Jan 10 17:48:58 2013
New Revision: 1431526
URL: http://svn.apache.org/viewvc?rev=1431526&view=rev
Log:
DERBY-6022: Add ability to load/unload custom tool packages via syscs_util.syscs_register_tool().
Added:
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolExample.java (with props)
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/catalog/Java5SystemProcedures.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolsTest.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/build.xml
Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/Java5SystemProcedures.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/Java5SystemProcedures.java?rev=1431526&r1=1431525&r2=1431526&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/Java5SystemProcedures.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/Java5SystemProcedures.java Thu Jan 10 17:48:58 2013
@@ -50,6 +50,9 @@ public class Java5SystemProcedures
private static final int TOOL_NAME = 0;
private static final int TOOL_CLASS_NAME = TOOL_NAME + 1;
+ /** Generic name for all user-supplied tools: the first optional arg is the tool class name */
+ private static final String CUSTOM_TOOL_CLASS_NAME = "customTool";
+
///////////////////////////////////////////////////////////////////////////////////
//
// STATE
@@ -59,8 +62,8 @@ public class Java5SystemProcedures
/** Mapping of tool names to their implementing classes for use by SYSCS_REGISTER_TOOL */
private static final String[][] OPTIONAL_TOOLS = new String[][]
{
- { "dbmd", "org.apache.derby.impl.tools.optional.DBMDWrapper" },
- { "fdbv", "org.apache.derby.impl.tools.optional.ForeignDBViews" },
+ { "databaseMetaData", "org.apache.derby.impl.tools.optional.DBMDWrapper" },
+ { "foreignViews", "org.apache.derby.impl.tools.optional.ForeignDBViews" },
};
///////////////////////////////////////////////////////////////////////////////////
@@ -71,7 +74,9 @@ public class Java5SystemProcedures
/**
* <p>
- * Load or unload an optional tool package.
+ * Load or unload an optional tool package. If the tool name is the special
+ * CUSTOM_TOOL_CLASS_NAME tool, then the first optionalArg is the name
+ * of a user-supplied class which implements OptionalTool.
* </p>
*
* @param toolName Name of the tool package.
@@ -90,7 +95,7 @@ public class Java5SystemProcedures
CompilerContext cc = (CompilerContext) ContextService.getContext( CompilerContext.CONTEXT_ID );
ClassFactory classFactory = cc.getClassFactory();
- String toolClassName = findToolClassName( toolName );
+ String toolClassName = findToolClassName( toolName, optionalArgs );
OptionalTool tool = null;
try {
@@ -100,20 +105,60 @@ public class Java5SystemProcedures
catch (InstantiationException ie) { throw wrap( ie ); }
catch (IllegalAccessException iae) { throw wrap( iae ); }
+ // Strip the custom tool class name from the optional args as necessary
+ if ( CUSTOM_TOOL_CLASS_NAME.equals( toolName ) )
+ {
+ optionalArgs = stripCustomClassName( optionalArgs );
+ }
+
if ( register ) { tool.loadTool( optionalArgs ); }
else { tool.unloadTool( optionalArgs ); }
}
catch (StandardException se) { throw PublicAPI.wrapStandardException( se ); }
}
/** Lookup the class name corresponding to the name of an optional tool */
- private static String findToolClassName( String toolName ) throws StandardException
+ private static String findToolClassName( String toolName, String... optionalArgs ) throws StandardException
{
+ //
+ // For a user-supplied tool, the first optional arg is the name of a user-supplied class
+ // which implements OptionalTool
+ //
+ if ( CUSTOM_TOOL_CLASS_NAME.equals( toolName ) )
+ {
+ if ( (optionalArgs == null) || (optionalArgs.length == 0) )
+ {
+ throw badTool( "null" );
+ }
+ else { return optionalArgs[ 0 ]; }
+ }
+
for ( String[] descriptor : OPTIONAL_TOOLS )
{
if ( descriptor[ TOOL_NAME ].equals( toolName ) ) { return descriptor[ TOOL_CLASS_NAME ]; }
}
- throw StandardException.newException( SQLState.LANG_UNKNOWN_TOOL_NAME, toolName );
+ throw badTool( toolName );
+ }
+ private static StandardException badTool( String toolName )
+ {
+ return StandardException.newException( SQLState.LANG_UNKNOWN_TOOL_NAME, toolName );
+ }
+
+ /**
+ * <p>
+ * For a custom tool, we strip the first arg from the list of optional args. By
+ * the time we get to this method, it has already been determined that there is
+ * at least one arg and it is the name of a class which implements OptionalTool.
+ * </p>
+ */
+ private static String[] stripCustomClassName( String... optionalArgs )
+ {
+ int count = optionalArgs.length - 1;
+ String[] retval = new String[ count ];
+
+ for ( int i = 0; i < count; i++ ) { retval[ i ] = optionalArgs[ i + 1 ]; }
+
+ return retval;
}
///////////////////////////////////////////////////////////////////////////////////
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolExample.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolExample.java?rev=1431526&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolExample.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolExample.java Thu Jan 10 17:48:58 2013
@@ -0,0 +1,118 @@
+/*
+
+ Derby - Class org.apache.derbyTesting.functionTests.tests.lang.OptionalToolExample
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.functionTests.tests.lang;
+
+import org.apache.derby.iapi.sql.dictionary.OptionalTool;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * <p>
+ * Simple OptionalTool.
+ * </p>
+ */
+public class OptionalToolExample implements OptionalTool
+{
+ ///////////////////////////////////////////////////////////////////////////////////
+ //
+ // CONSTANTS
+ //
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ //
+ // STATE
+ //
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ //
+ // CONSTRUCTOR
+ //
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ /** 0-arg constructor required by the OptionalTool contract */
+ public OptionalToolExample() {}
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ //
+ // OptionalTool BEHAVIOR
+ //
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public void loadTool( String... configurationParameters )
+ throws SQLException
+ { loadToolMinion( "toString" ); }
+
+ public void unloadTool( String... configurationParameters )
+ throws SQLException
+ { unloadToolMinion( "toString" ); }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ //
+ // MINIONS
+ //
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ protected void loadToolMinion( String functionName )
+ throws SQLException
+ {
+ getDerbyConnection().prepareStatement
+ (
+ "create function " + functionName + "( intVal int ) returns varchar( 32672 )\n" +
+ "language java parameter style java no sql\n" +
+ "external name 'java.lang.Integer.toString'"
+ ).execute();
+
+ }
+
+ protected void unloadToolMinion( String functionName )
+ throws SQLException
+ {
+ getDerbyConnection().prepareStatement( "drop function " + functionName ).execute();
+ }
+
+ private Connection getDerbyConnection() throws SQLException
+ {
+ return DriverManager.getConnection( "jdbc:default:connection" );
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ //
+ // NESTED CLASS
+ //
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public static final class VariableName extends OptionalToolExample
+ {
+ public void loadTool( String... configurationParameters )
+ throws SQLException
+ { loadToolMinion( configurationParameters[ 0 ] ); }
+
+ public void unloadTool( String... configurationParameters )
+ throws SQLException
+ { unloadToolMinion( configurationParameters[ 0 ] ); }
+ }
+
+}
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolExample.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolsTest.java?rev=1431526&r1=1431525&r2=1431526&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolsTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OptionalToolsTest.java Thu Jan 10 17:48:58 2013
@@ -56,6 +56,8 @@ public class OptionalToolsTest extends
protected static final String NO_SUCH_TABLE_FUNCTION = "42ZB4";
protected static final String UNEXPECTED_USER_EXCEPTION = "38000";
protected static final String MISSING_SCHEMA = "42Y07";
+ protected static final String UNKNOWN_TOOL = "X0Y88";
+ protected static final String UNKNOWN_ROUTINE = "42Y03";
private static final String TEST_DBO = "TEST_DBO";
private static final String RUTH = "RUTH";
@@ -129,7 +131,7 @@ public class OptionalToolsTest extends
(
ruthConnection,
LACK_EXECUTE_PRIV,
- "call syscs_util.syscs_register_tool( 'dbmd', true )"
+ "call syscs_util.syscs_register_tool( 'databaseMetaData', true )"
);
// create a dummy table just to force the schema to be created
@@ -139,7 +141,7 @@ public class OptionalToolsTest extends
expectCompilationError( dboConnection, NO_SUCH_TABLE_FUNCTION, getTypeInfo );
// now register the database metadata wrappers
- goodStatement( dboConnection, "call syscs_util.syscs_register_tool( 'dbmd', true )" );
+ goodStatement( dboConnection, "call syscs_util.syscs_register_tool( 'databaseMetaData', true )" );
// now the routine exists
assertResults
@@ -175,7 +177,7 @@ public class OptionalToolsTest extends
);
// now unregister the database metadata wrappers
- goodStatement( dboConnection, "call syscs_util.syscs_register_tool( 'dbmd', false )" );
+ goodStatement( dboConnection, "call syscs_util.syscs_register_tool( 'databaseMetaData', false )" );
// the routines don't exist anymore
expectCompilationError( dboConnection, NO_SUCH_TABLE_FUNCTION, getTypeInfo );
@@ -252,7 +254,7 @@ public class OptionalToolsTest extends
(
dboConnection,
UNEXPECTED_USER_EXCEPTION,
- "call syscs_util.syscs_register_tool( 'fdbv', true )"
+ "call syscs_util.syscs_register_tool( 'foreignViews', true )"
);
// should fail because the view and its schema don't exist
@@ -273,7 +275,7 @@ public class OptionalToolsTest extends
goodStatement
(
dboConnection,
- "call syscs_util.syscs_register_tool( 'fdbv', true, '" + foreignURL + "' )"
+ "call syscs_util.syscs_register_tool( 'foreignViews', true, '" + foreignURL + "' )"
);
// views should have been created against the foreign database
@@ -297,14 +299,14 @@ public class OptionalToolsTest extends
(
dboConnection,
UNEXPECTED_USER_EXCEPTION,
- "call syscs_util.syscs_register_tool( 'fdbv', false )"
+ "call syscs_util.syscs_register_tool( 'foreignViews', false )"
);
// should work
goodStatement
(
dboConnection,
- "call syscs_util.syscs_register_tool( 'fdbv', false, '" + foreignURL + "' )"
+ "call syscs_util.syscs_register_tool( 'foreignViews', false, '" + foreignURL + "' )"
);
// should fail because the view and its schema were dropped when the tool was unloaded
@@ -325,14 +327,14 @@ public class OptionalToolsTest extends
goodStatement
(
dboConnection,
- "call syscs_util.syscs_register_tool( 'fdbv', false, '" + foreignURL + "' )"
+ "call syscs_util.syscs_register_tool( 'foreignViews', false, '" + foreignURL + "' )"
);
// register with a schema prefix
goodStatement
(
dboConnection,
- "call syscs_util.syscs_register_tool( 'fdbv', true, '" + foreignURL + "', 'XYZ_' )"
+ "call syscs_util.syscs_register_tool( 'foreignViews', true, '" + foreignURL + "', 'XYZ_' )"
);
employeeSelect = "select * from xyz_frank.employee order by employeeID";
starSelect = "select * from xyz_alice.stars order by starID";
@@ -357,7 +359,7 @@ public class OptionalToolsTest extends
goodStatement
(
dboConnection,
- "call syscs_util.syscs_register_tool( 'fdbv', false, '" + foreignURL + "', 'XYZ_' )"
+ "call syscs_util.syscs_register_tool( 'foreignViews', false, '" + foreignURL + "', 'XYZ_' )"
);
expectCompilationError
(
@@ -372,6 +374,144 @@ public class OptionalToolsTest extends
starSelect
);
}
+
+ /**
+ * <p>
+ * Test loading custom, user-supplied tools.
+ * </p>
+ */
+ public void test_03_customTool() throws Exception
+ {
+ Connection dboConnection = openUserConnection( TEST_DBO );
+
+ // unknown tool name
+ expectExecutionError
+ (
+ dboConnection,
+ UNKNOWN_TOOL,
+ "call syscs_util.syscs_register_tool( 'uknownToolName', true )"
+ );
+
+ // no custom class name supplied
+ expectExecutionError
+ (
+ dboConnection,
+ UNKNOWN_TOOL,
+ "call syscs_util.syscs_register_tool( 'customTool', true )"
+ );
+
+ // supplied class does not implement OptionalTool
+ expectExecutionError
+ (
+ dboConnection,
+ UNEXPECTED_USER_EXCEPTION,
+ "call syscs_util.syscs_register_tool( 'customTool', true, 'java.lang.String' )"
+ );
+
+ //
+ // Register a custom tool.
+ //
+
+ // first verify that the tool hasn't been run yet
+ expectCompilationError
+ (
+ dboConnection,
+ UNKNOWN_ROUTINE,
+ "values toString( 100 )"
+ );
+
+ // now register the tool
+ goodStatement
+ (
+ dboConnection,
+ "call syscs_util.syscs_register_tool( 'customTool', true, 'org.apache.derbyTesting.functionTests.tests.lang.OptionalToolExample' )"
+ );
+
+ // run it
+ assertResults
+ (
+ dboConnection,
+ "values toString( 100 )",
+ new String[][]
+ {
+ { "100" },
+ },
+ false
+ );
+
+ // unregister the tool
+ goodStatement
+ (
+ dboConnection,
+ "call syscs_util.syscs_register_tool( 'customTool', false, 'org.apache.derbyTesting.functionTests.tests.lang.OptionalToolExample' )"
+ );
+
+ // verify that the tool was unregistered
+ expectCompilationError
+ (
+ dboConnection,
+ UNKNOWN_ROUTINE,
+ "values toString( 100 )"
+ );
+
+ //
+ // Register a custom tool with a custom parameter.
+ //
+
+ // first verify that the tool hasn't been run yet
+ expectCompilationError
+ (
+ dboConnection,
+ UNKNOWN_ROUTINE,
+ "values foobar( 100 )"
+ );
+
+ // now register the tool
+ goodStatement
+ (
+ dboConnection,
+ "call syscs_util.syscs_register_tool\n" +
+ "(\n" +
+ " 'customTool',\n" +
+ " true,\n" +
+ " 'org.apache.derbyTesting.functionTests.tests.lang.OptionalToolExample$VariableName',\n" +
+ " 'foobar'\n" +
+ ")\n"
+ );
+
+ // run it
+ assertResults
+ (
+ dboConnection,
+ "values foobar( 100 )",
+ new String[][]
+ {
+ { "100" },
+ },
+ false
+ );
+
+ // unregister the tool
+ goodStatement
+ (
+ dboConnection,
+ "call syscs_util.syscs_register_tool\n" +
+ "(\n" +
+ " 'customTool',\n" +
+ " false,\n" +
+ " 'org.apache.derbyTesting.functionTests.tests.lang.OptionalToolExample$VariableName',\n" +
+ " 'foobar'\n" +
+ ")\n"
+ );
+
+ // verify that the tool was unregistered
+ expectCompilationError
+ (
+ dboConnection,
+ UNKNOWN_ROUTINE,
+ "values foobar( 100 )"
+ );
+
+ }
}
-
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/build.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/build.xml?rev=1431526&r1=1431525&r2=1431526&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/build.xml (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/build.xml Thu Jan 10 17:48:58 2013
@@ -100,6 +100,7 @@
<exclude name="${this.dir}/unaryArithmeticDynamicParameter.java"/>
<exclude name="${this.dir}/_Suite.java"/>
<exclude name="${this.dir}/VarargsRoutines.java"/>
+ <exclude name="${this.dir}/OptionalToolExample.java"/>
</javac>
</target>
<target name="compilet2" depends="compilet1">
@@ -174,6 +175,7 @@
<include name="${this.dir}/ModeAggregate.java"/>
<include name="${this.dir}/LobMode.java"/>
<include name="${this.dir}/VarargsRoutines.java"/>
+ <include name="${this.dir}/OptionalToolExample.java"/>
</javac>
</target>