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 ab...@apache.org on 2007/01/10 22:24:46 UTC

svn commit: r494993 - in /db/derby/code/trunk/java/engine/org/apache/derby: iapi/sql/compile/ iapi/sql/dictionary/ impl/sql/catalog/ impl/sql/compile/

Author: abrown
Date: Wed Jan 10 13:24:45 2007
New Revision: 494993

URL: http://svn.apache.org/viewvc?view=rev&rev=494993
Log:
DERBY-2152: Clean-up patch that does the following:

  1. Creates a new "init()" method for NewInvocationNode that is specifically
targeted for mapping VTI "tables" and VTI "table functions" to their
corresponding class names. The new init() method takes both a TableDescriptor
and a TableName, exactly one of which must be null. If the TableDescriptor
is null then we will resolve the TableName to a VTI "table function"; if the
TableName is null then we will resolve the TableDescriptor to a VTI "table".
Thus VTI classes are now consistently resolved inside the NewInvocationNode
class.

  2. Updates NodeFactory.mapTableAsVTI() to make use of the new "init()"
method in NewInvocationNode. mapTableAsVTI() used to take as a parameter the
resolved VTI class name; now it just passes the received TableDescriptor to
the new init() method in NewInvocationNode and the latter resolves the VTI
class.

  3. Combines the getVTIClassForTable() and getVTIClassForTableFunction()
methods of DataDictionary into a new method, "getVTIClass()", that takes a
TableDescriptor and a boolean value. The boolean indicates the kind of
mapping to do--"table" or "table function"--while the TableDescriptor holds
the schema and name information used for resolving the class. This resolves
the inconsistency between the argument styles used in the old getVTIClassFor*()
methods.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/NodeFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NewInvocationNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/NodeFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/NodeFactory.java?view=diff&rev=494993&r1=494992&r2=494993
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/NodeFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/NodeFactory.java Wed Jan 10 13:24:45 2007
@@ -610,7 +610,6 @@
 	 * Used to convert from system diagnostic tables
 	 * to VTI scans.
 	 * @param td Table that is really a vti
-	 * @param vtiClass Java class name for virtual table
 	 * @param correlationName Correlation name of table clause
 	 * @param resultColumns Columns extracted from table.
 	 * @param tableProperties Properties being passed onto the table scan
@@ -618,7 +617,6 @@
 	 */
 	public abstract ResultSetNode mapTableAsVTI(
 			TableDescriptor td,
-			String vtiClass,
 			String correlationName,
 			ResultColumnList resultColumns,
 			Properties tableProperties,		

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java?view=diff&rev=494993&r1=494992&r2=494993
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java Wed Jan 10 13:24:45 2007
@@ -1681,25 +1681,43 @@
     throws StandardException;
 
 	/**
-	 * Return the Java class to use for the VTI for
-	 * the virtual table. Assumes the descriptor is
-	 * of type TableDescriptor.VTI_TYPE.
+	 * Return the Java class to use for the VTI to which the received
+	 * table descriptor maps.
+	 *
+	 * There are two kinds of VTI mappings that we do: the first is for
+	 * "table names", the second is for "table function names".  Table
+	 * names can only be mapped to VTIs that do not accept any arguments;
+	 * any VTI that has at least one constructor which accepts one or more
+	 * arguments must be mapped from a table *function* name.
+	 *
+	 * An example of a VTI "table name" is the following:
+	 *
+	 *   select * from SYSCS_DIAG.LOCK_TABLE
+	 *
+	 * In this case "SYSCS_DIAG.LOCK_TABLE" is the table name that we want
+	 * to map.  Since the corresonding VTI does not accept any arguments,
+	 * this VTI table name can be used anywhere a normal base table name
+	 * can be used.
+	 *
+	 * An example of a VTI "table function name" is the following:
+	 *
+	 *   select * from TABLE(SYSCS_DIAG.SPACE_TABLE(?)) x
+	 *
+	 * In this case "SYSCS_DIAG.SPACE_TABLE" is the table function name that
+	 * we want to map.  Since the corresponding VTI can take either one or
+	 * two arguments we have to use the TABLE constructor syntax to pass the
+	 * argument(s) in as if we were making a function call.  Hence the term
+	 * "table function".
+	 *
+	 * @param td Table descriptor used for the VTI look-up.
+	 * @param asTableFunction If false then treat td's descriptor name as a
+	 *  VTI "table name"; if true, treat the descriptor name as a VTI "table
+	 *  function name".
+	 * @return Java class name to which "td" maps, or null if no mapping
+	 *  is found.
 	 */
-	public String getVTIClassForTable(TableDescriptor td)
+	public String getVTIClass(TableDescriptor td, boolean asTableFunction)
 		throws StandardException;
-
-	/**
-	 * Return the Java class to use for the VTI to which the received table
-	 * function name maps.  The table function name is a qualified name and
-	 * thus has two parts: a schema name and a function name.
-	 *
-	 * @param funcSchema Schema part of the function name
-	 * @param funcName Actual name of the function
-	 * @return Java class name to which <funcSchema>.<funcName> maps, or
-	 *  null if no mapping is found.
-	 */
-	public String getVTIClassForTableFunction(String funcSchema,
-		String funcName) throws StandardException;
 
 	/**
 	 * Adds a descriptor to a system catalog identified by the catalogNumber. 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java?view=diff&rev=494993&r1=494992&r2=494993
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java Wed Jan 10 13:24:45 2007
@@ -1700,7 +1700,7 @@
 						TableDescriptor.DEFAULT_LOCK_GRANULARITY);
 			
 			// ensure a vti class exists
-			if (getVTIClassForTable(td) != null)
+			if (getVTIClass(td, false) != null)
 				return td;
 			
 			// otherwise just standard search
@@ -10345,43 +10345,36 @@
 	};
 
 	/**
-	 * @see DataDictionary#getVTIClassForTable(TableDescriptor)
+	 * @see DataDictionary#getVTIClass(TableDescriptor, boolean)
 	 */
-	public String getVTIClassForTable(TableDescriptor td)
-		throws StandardException {
-		
+	public String getVTIClass(TableDescriptor td, boolean asTableFunction)
+		throws StandardException
+	{
 		if (SanityManager.DEBUG)
 		{
 			if (td.getTableType() != TableDescriptor.VTI_TYPE)
 				SanityManager.THROWASSERT("getVTIClass: Invalid table type " + td);
 		}
 		
-		for (int i = 0; i < DIAG_VTI_TABLE_CLASSES.length; i++)
-		{
-			String[] entry = DIAG_VTI_TABLE_CLASSES[i];
-			if (entry[0].equals(td.getDescriptorName()))
-				return entry[1];	
-		}	
-		
-		return null;
-	}
-
-	/**
-	 * @see DataDictionary#getVTIClassForTableFunction(String, String)
-	 */
-	public String getVTIClassForTableFunction(String funcSchema,
-		String funcName) throws StandardException
-	{
-		/* For now we only recognize table function names that are in
-		 * the "SYSCS_DIAG" schema; for anything else just return null.
+		/* For now we only recognize VTI table (or table function) names
+		 * that are in the "SYSCS_DIAG" schema; for anything else just
+		 * return null.  Note that if no schema was specified then the
+		 * call to "td.getSchemaName()" will return the current schema.
 		 */
-		if (!SchemaDescriptor.STD_SYSTEM_DIAG_SCHEMA_NAME.equals(funcSchema))
+		if (!SchemaDescriptor.STD_SYSTEM_DIAG_SCHEMA_NAME.equals(
+			td.getSchemaName()))
+		{
 			return null;
+		}
 
-		for (int i = 0; i < DIAG_VTI_TABLE_FUNCTION_CLASSES.length; i++)
+		String [][] vtiMappings = asTableFunction
+			? DIAG_VTI_TABLE_FUNCTION_CLASSES
+			: DIAG_VTI_TABLE_CLASSES;
+
+		for (int i = 0; i < vtiMappings.length; i++)
 		{
-			String[] entry = DIAG_VTI_TABLE_FUNCTION_CLASSES[i];
-			if (entry[0].equals(funcName))
+			String[] entry = vtiMappings[i];
+			if (entry[0].equals(td.getDescriptorName()))
 				return entry[1];	
 		}	
 		

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java?view=diff&rev=494993&r1=494992&r2=494993
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java Wed Jan 10 13:24:45 2007
@@ -2110,7 +2110,6 @@
 		if (tableDescriptor.getTableType() == TableDescriptor.VTI_TYPE) {
 			ResultSetNode vtiNode = getNodeFactory().mapTableAsVTI(
 					tableDescriptor,
-					dataDictionary.getVTIClassForTable(tableDescriptor),
 					getCorrelationName(),
 					resultColumns,
 					getProperties(),

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NewInvocationNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NewInvocationNode.java?view=diff&rev=494993&r1=494992&r2=494993
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NewInvocationNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NewInvocationNode.java Wed Jan 10 13:24:45 2007
@@ -36,7 +36,7 @@
 
 import org.apache.derby.iapi.sql.compile.CompilerContext;
 
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
 
 import org.apache.derby.iapi.reference.SQLState;
 
@@ -68,9 +68,7 @@
 	 * Initializer for a NewInvocationNode. Parameters are:
 	 *
 	 * <ul>
-	 * <li>javaClassName		The full package.class name of the class
-	 * 	                    	(as a String), or else a TableName object
-	 *                  		that maps to the full class name </li>
+	 * <li>javaClassName		The full package.class name of the class</li>
 	 * <li>parameterList		The parameter list for the constructor</li>
 	 * </ul>
 	 *
@@ -85,48 +83,107 @@
 		super.init("<init>");
 		addParms((Vector) params);
 
-		/* If javaClassName is a String then it is the full package
-		 * class name for the class to be invoked, so just store it
-		 * locally.
+		this.javaClassName = (String) javaClassName;
+		this.delimitedIdentifier =
+				 ((Boolean) delimitedIdentifier).booleanValue();
+	}
+
+	/* This version of the "init" method is used for mapping a table name
+	 * or table function name to a corresponding VTI class name.  The VTI
+	 * is then invoked as a regular NEW invocation node.
+	 *
+	 * There are two kinds of VTI mappings that we do: the first is for
+	 * "table names", the second is for "table function names".  Table
+	 * names can only be mapped to VTIs that do not accept any arguments;
+	 * any VTI that has at least one constructor which accepts one or more
+	 * arguments must be mapped from a table *function* name.  The way we
+	 * tell the difference is by looking at the received arguments: if
+	 * the vtiTableFuncName that we receive is null then we are mapping
+	 * a "table name" and tableDescriptor must be non-null; if the
+	 * vtiTableFuncName is non-null then we are mapping a "table
+	 * function name" and tableDescriptor must be null.
+	 *
+	 * Note that we could have just used a single "init()" method and
+	 * performed the mappings based on what type of Object "javaClassName"
+	 * was (String, TableDescriptor, or TableName), but making this VTI
+	 * mapping method separate from the "normal" init() method seems
+	 * cleaner...
+	 *
+	 * @param vtiTableFuncName A TableName object holding a qualified name
+	 *  that maps to a VTI which accepts arguments.  If vtiTableFuncName is
+	 *  null then tableDescriptor must NOT be null.
+	 * @param tableDescriptor A table descriptor that corresponds to a
+	 *  table name (as opposed to a table function name) that will be
+	 *  mapped to a no-argument VTI.  If tableDescriptor is null then
+	 *  vtiTableFuncName should not be null.
+	 * @param params Parameter list for the VTI constructor.
+	 * @param delimitedIdentifier Whether or not the target class name
+	 *  is a delimited identifier.
+	 */
+	public void init(
+					Object vtiTableFuncName,
+					Object tableDescriptor,
+					Object params,
+					Object delimitedIdentifier)
+		throws StandardException
+	{
+		super.init("<init>");
+		addParms((Vector) params);
+
+		if (SanityManager.DEBUG)
+		{
+			// Exactly one of vtiTableFuncName or tableDescriptor should
+			// be null.
+			SanityManager.ASSERT(
+				((vtiTableFuncName == null) && (tableDescriptor != null)) ||
+				((vtiTableFuncName != null) && (tableDescriptor == null)),
+				"Exactly one of vtiTableFuncName or tableDescriptor should " +
+				"be null, but neither or both of them were null.");
+		}
+
+		TableName vtiName = (TableName)vtiTableFuncName;
+		TableDescriptor td = (TableDescriptor)tableDescriptor;
+		boolean isTableFunctionVTI = (vtiTableFuncName != null);
+		if (isTableFunctionVTI)
+		{
+			// We have to create a generic TableDescriptor to
+			// pass to the data dictionary.
+			td = new TableDescriptor(getDataDictionary(),
+					vtiName.getTableName(),
+					getSchemaDescriptor(vtiName.getSchemaName()),
+					TableDescriptor.VTI_TYPE,
+					TableDescriptor.DEFAULT_LOCK_GRANULARITY);
+		}
+
+		/* Use the table descriptor to figure out what the corresponding
+		 * VTI class name is; we let the data dictionary do the mapping
+		 * for us.
+		 */
+		this.javaClassName = getDataDictionary().getVTIClass(
+			td, isTableFunctionVTI);
+
+		/* If javaClassName is still null at this point then we
+		 * could not find the target class for the received table
+		 * (or table function) name.  So throw the appropriate
+		 * error.
 		 */
-		if (javaClassName instanceof String)
-			this.javaClassName = (String) javaClassName;
-		else
+		if (this.javaClassName == null)
 		{
-			/* javaClassName is a TableName object representing a table
-			 * function name that maps to some VTI class name.  For
-			 * example, in the following query:
-			 *
-			 *   select * from TABLE(SYSCS_DIAG.SPACE_TABLE(?)) x
-			 *
-			 * javaClassName will be a TableName object representing
-			 * the table function name "SYSCS_DIAG.SPACE_TABLE".  So
-			 * we need to look up that TableName to figure out what
-			 * the corresponding target class name should be.  We
-			 * figure that out by using the data dictionary.
-			 */
-			TableName funcName = (TableName)javaClassName;
-
-			/* If no schema was specified then we want to default to the
-			 * current schema; that's what the following line does.
-			 */
-			String funcSchema =
-				getSchemaDescriptor(funcName.getSchemaName()).getSchemaName();
-
-			this.javaClassName =
-				getDataDictionary().getVTIClassForTableFunction(
-					funcSchema, funcName.getTableName());
-
-			/* If javaClassName is still null at this point then we
-			 * could not find the target class for the received
-			 * table function name.
-			 */
-			if (this.javaClassName == null)
+			if (!isTableFunctionVTI)
 			{
-				throw StandardException.newException(
-					SQLState.LANG_NO_SUCH_METHOD_ALIAS,
-					funcName.getFullTableName());
+				/* Create a TableName object from the table descriptor
+				 * that we received.  This gives us the name to use
+				 * in the error message.
+				 */
+				vtiName = makeTableName(td.getSchemaName(),
+					td.getDescriptorName());
 			}
+
+			throw StandardException.newException(
+				isTableFunctionVTI
+					? SQLState.LANG_NO_SUCH_METHOD_ALIAS
+					: SQLState.LANG_TABLE_NOT_FOUND,
+				vtiName.getFullTableName());
 		}
 
 		this.delimitedIdentifier =

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java?view=diff&rev=494993&r1=494992&r2=494993
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java Wed Jan 10 13:24:45 2007
@@ -678,7 +678,9 @@
 
 	/**
 	 * Return a node that represents invocation of the virtual table
-	 * for the given table descriptor using the passed in vti class name.
+	 * for the given table descriptor.  The mapping of the table descriptor
+	 * to a specific VTI class name will occur as part of the "init"
+	 * phase for the NewInvocationNode that we create here.
 	 * <P>
 	 * Currently only handles no argument vtis corresponding to a subset
 	 * of the diagnostic tables. (e.g. lock_table).
@@ -690,7 +692,6 @@
 	 */
 	public ResultSetNode mapTableAsVTI(
 			TableDescriptor td,
-			String vtiClass,
 			String correlationName,
 			ResultColumnList resultColumns,
 			Properties tableProperties,		
@@ -698,9 +699,18 @@
 		throws StandardException {
 		
 	
-		QueryTreeNode newNode = getNode(C_NodeTypes.NEW_INVOCATION_NODE, 
-				vtiClass,
-				emptyVector, Boolean.FALSE,
+		/* The fact that we pass a non-null table descriptor to the
+		 * following call is an indication that we are mapping to a
+		 * no-argument VTI.  Since we have the table descriptor we
+		 * do not need to pass in a TableName. See NewInvocationNode
+		 * for more.
+		 */
+		QueryTreeNode newNode =
+			getNode(C_NodeTypes.NEW_INVOCATION_NODE, 
+				null,	// TableName
+				td,     // TableDescriptor
+				emptyVector,
+				Boolean.FALSE,
 				cm);
 		
 		 QueryTreeNode vtiNode;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj?view=diff&rev=494993&r1=494992&r2=494993
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj Wed Jan 10 13:24:45 2007
@@ -7411,8 +7411,16 @@
         methodCallParameterList(parameterList)
     <RIGHT_PAREN>
     {
+		/* The fact that we pass a NULL table descriptor to the
+		 * following call is an indication that we are mapping to a
+		 * VTI table function (i.e. one that accepts arguments).
+		 * Since we have the table name we do not need to pass in a
+		 * TableDescriptor--we'll just create one from the table
+		 * name. See NewInvocationNode for more.
+		 */
         newNode = nodeFactory.getNode(C_NodeTypes.NEW_INVOCATION_NODE,
-                    vtiTableName,
+                    vtiTableName,  // TableName
+                    null,          // TableDescriptor
                     parameterList, 
                     lastTokenDelimitedIdentifier,
                     getContextManager());