Home » db-derby-10.5.3.0 » org.apache.derby.iapi.sql.depend » [javadoc | source]

    1   /*
    2   
    3      Derby - Class org.apache.derby.iapi.sql.depend.DependencyManager
    4   
    5      Licensed to the Apache Software Foundation (ASF) under one or more
    6      contributor license agreements.  See the NOTICE file distributed with
    7      this work for additional information regarding copyright ownership.
    8      The ASF licenses this file to you under the Apache License, Version 2.0
    9      (the "License"); you may not use this file except in compliance with
   10      the License.  You may obtain a copy of the License at
   11   
   12         http://www.apache.org/licenses/LICENSE-2.0
   13   
   14      Unless required by applicable law or agreed to in writing, software
   15      distributed under the License is distributed on an "AS IS" BASIS,
   16      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   17      See the License for the specific language governing permissions and
   18      limitations under the License.
   19   
   20    */
   21   
   22   package org.apache.derby.iapi.sql.depend;
   23   
   24   import org.apache.derby.iapi.services.context.ContextManager;
   25   
   26   import org.apache.derby.iapi.error.StandardException;
   27   
   28   import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
   29   
   30   import org.apache.derby.iapi.store.access.TransactionController;
   31   
   32   /**
   33   	Dependency Manager Interface
   34   	<p>
   35   	The dependency manager tracks needs that dependents have of providers. This
   36   	is a general purpose interface which is associated with a
   37   	DataDictinary object; infact the dependencymanager is really the
   38   	datadictionary keeping track of dependcies between objects that it handles
   39   	(descriptors) as well as prepared statements.
   40   	<p>
   41   	The primary example of this is a prepared statement's needs of 
   42   	schema objects such as tables.
   43   	<p>
   44   	Dependencies are used so that we can determine when we
   45   	need to recompile a statement; compiled statements depend
   46   	on schema objects like tables and constraints, and may
   47   	no longer be executable when those tables or constraints are
   48   	altered. For example, consider an insert statement.
   49   	<p>
   50   	An insert statement is likely to have dependencies on the table it
   51   	inserts into, any tables it selects from (including
   52   	subqueries), the authorities it uses to do this,
   53   	and any constraints or triggers it needs to check.
   54   	<p>
   55   	A prepared insert statement has a dependency on the target table 
   56   	of the insert. When it is compiled, that dependency is registered 
   57   	from the prepared statement on the data dictionary entry for the
   58   	table. This dependency is added to the prepared statement's dependency
   59   	list, which is also accessible from an overall dependency pool.
   60   	<p>
   61   	A DDL statement will mark invalid any prepared statement that
   62   	depends on the schema object the DDL statement is altering or
   63   	dropping.  We tend to want to track at the table level rather than
   64   	the column or constraint level, so that we are not overburdened
   65   	with dependencies.  This does mean that we may invalidate when in
   66   	fact we do not need to; for example, adding a column to a table may
   67   	not actually cause an insert statement compiled for that table
   68   	to stop working; but our level of granularity may force us to
   69   	invalidate the insert because it has to invalidate all statements
   70   	that depend on the table due to some of them actually no longer
   71   	being valid.
   72   
   73   	It is up to the user of the dependency system at what granularity
   74   	to track dependencies, where to hang them, and how to identify when
   75   	objects become invalid.  The dependency system is basically supplying
   76   	the ability to find out who is interested in knowing about
   77   	other, distinct operations.  The primary user is the language system,
   78   	and its primary use is for invalidating prepared statements when
   79   	DDL occurs.
   80   	<p>
   81   	The insert will recompile itself when its next execution
   82   	is requested (not when it is invalidated). We don't want it to
   83   	recompile when the DDL is issued, as that would increase the time
   84   	of execution of the DDL command unacceptably.  Note that the DDL 
   85   	command is also allowed to proceed even if it would make the 
   86   	statement no longer compilable.  It can be useful to have a way
   87   	to recompile invalid statements during idle time in the system,
   88   	but our first implementation will simply recompile at the next
   89   	execution.
   90   	<p>
   91   	The start of a recompile will release the connection to
   92   	all dependencies when it releases the activation class and 
   93   	generates a new one.
   94   	<p>
   95   	The Dependency Manager is capable of storing dependencies to
   96   	ensure that other D.M.s can see them and invalidate them
   97   	appropriately. The dependencies in memory only the current
   98   	D.M. can see; the stored dependencies are visible to other D.M.s
   99   	once the transaction in which they were stored is committed.
  100   	<p>
  101   	REVISIT: Given that statements are compiled in a separate top-transaction
  102   	from their execution, we may need/want some intermediate memory
  103   	storage that makes the dependencies visible to all D.M.s in the
  104   	system, without requiring that they be stored.
  105   	<p>
  106   	To ensure that dependencies are cleaned up when a statement is undone,
  107   	the compiler context needs to keep track of what dependent it was
  108   	creating dependencies for, and if it is informed of a statement
  109   	exception that causes it to throw out the statement it was compiling,
  110   	it should also call the dependency manager to have the
  111   	dependencies removed.
  112   	<p>
  113   	Several expansions of the basic interface may be desirable:
  114   	<ul>
  115   	<li> to note a type of dependency, and to invalidate or perform
  116   	  an invalidation action based on dependency type
  117   	<li> to note a type of invalidation, so the revalidation could 
  118   	  actually take some action other than recompilation, such as 
  119   	  simply ensuring the provider objects still existed.
  120   	<li> to control the order of invalidation, so that if (for example)
  121   	  the invalidation action actually includes the revalidation attempt,
  122   	  revalidation is not attempted until all invalidations have occurred.
  123   	<li> to get a list of dependencies that a Dependent or 
  124   	  a Provider has (this is included in the above, although the
  125   	  basic system does not need to expose the list).
  126   	<li> to find out which of the dependencies for a dependent were marked 
  127   	  invalid.
  128   	</ul>
  129   	<p>
  130   	To provide a simple interface that satisfies the basic need,
  131   	and yet supply more advanced functionality as well, we will present
  132   	the simple functionality as defaults and provide ways to specify the
  133   	more advanced functionality.
  134   
  135   	<pre>
  136   	interface Dependent {
  137   		boolean isValid();
  138   		InvalidType getInvalidType(); // returns what it sees
  139   						// as the "most important"
  140   						// of its invalid types.
  141   		void makeInvalid( );
  142   		void makeInvalid( DependencyType dt, InvalidType it );
  143   		void makeValid();
  144   	}
  145   
  146   	interface Provider() {
  147   	}
  148   
  149   	interface Dependency() {
  150   		Provider getProvider();
  151   		Dependent getDependent();
  152   		DependencyType getDependencyType();
  153   		boolean isValid();
  154   		InvalidType getInvalidType(); // returns what it sees
  155   						// as the "most important"
  156   						// of its invalid types.
  157   	}
  158   
  159   	interface DependencyManager() {
  160   		void addDependency(Dependent d, Provider p, ContextManager cm);
  161   		void invalidateFor(Provider p);
  162   		void invalidateFor(Provider p, DependencyType dt, InvalidType it);
  163   		void clearDependencies(Dependent d);
  164   		void clearDependencies(Dependent d, DependencyType dt);
  165   		Enumeration getProviders (Dependent d);
  166   		Enumeration getProviders (Dependent d, DependencyType dt);
  167   		Enumeration getInvalidDependencies (Dependent d, 
  168   			DependencyType dt, InvalidType it);
  169   		Enumeration getDependents (Provider p);
  170   		Enumeration getDependents (Provider p, DependencyType dt);
  171   		Enumeration getInvalidDependencies (Provider p, 
  172   			DependencyType dt, InvalidType it);
  173   	}
  174   	</pre>
  175   	<p>
  176   	The simplest things for DependencyType and InvalidType to be are 
  177   	integer id's or strings, rather than complex objects.
  178   	<p>
  179   	In terms of ensuring that no makeInvalid calls are made until we have 
  180   	identified all objects that could be, so that the calls will be made 
  181   	from "leaf" invalid objects (those not in turn relied on by other 
  182   	dependents) to dependent objects upon which others depend, the 
  183   	dependency manager will need to maintain an internal queue of 
  184   	dependencies and make the calls once it has completes its analysis 
  185   	of the dependencies of which it is aware.  Since it is much simpler 
  186   	and potentially faster for makeInvalid calls to be made as soon
  187   	as the dependents are identified, separate implementations may be
  188   	called for, or separate interfaces to trigger the different
  189   	styles of invalidation.
  190   	<p>
  191   	In terms of separate interfaces, the DependencyManager might have
  192   	two methods,
  193   	<pre>
  194   		void makeInvalidImmediate();
  195   		void makeInvalidOrdered();
  196   	</pre>
  197   	or a flag on the makeInvalid method to choose the style to use.
  198   	<p>
  199   	In terms of separate implementations, the ImmediateInvalidate
  200   	manager might have simpler internal structures for 
  201   	tracking dependencies than the OrderedInvalidate manager.
  202   	<p>
  203   	The language system doesn't tend to suffer from this ordering problem,
  204   	as it tends to handle the impact of invalidation by simply deferring
  205   	recompilation until the next execution.  So, a prepared statement
  206   	might be invalidated several times by a transaction that contains
  207   	several DDL operations, and only recompiled once, at its next 
  208   	execution.  This is sufficient for the common use of a system, where
  209   	DDL changes tend to be infrequent and clustered.
  210   	<p>
  211   	There could be ways to push this "ordering problem" out of the 
  212   	dependency system, but since it knows when it starts and when it
  213   	finished finding all of the invalidating actions, it is likely
  214   	the best home for this.
  215   	<p>
  216   	One other problem that could arise is multiple invalidations occurring
  217   	one after another.  The above design of the dependency system can 
  218   	really only react to each invalidation request as a unit, not 
  219   	to multiple invalidation requests.
  220   	<p>
  221   	Another extension that might be desired is for the dependency manager
  222   	to provide for cascading invalidations -- that is, if it finds
  223   	and marks one Dependent object as invalid, if that object can also
  224   	be a provider, to look for its dependent objects and cascade the
  225   	dependency on to them.  This can be a way to address the 
  226   	multiple-invalidation request need, if it should arise.  The simplest
  227   	way to do this is to always cascade the same invalidation type;
  228   	otherwise, dependents need to be able to say what a certain type
  229   	of invalidation type gets changed to when it is handed on.
  230   	<p>
  231   	The basic language system does not need support for cascaded 
  232   	dependencies -- statements do not depend on other statements
  233   	in a way that involves the dependency system.
  234   	<p>
  235   	I do not know if it would be worthwhile to consider using the 
  236   	dependency manager to aid in the implementation of the SQL DROP
  237   	statements or not. Past implementations
  238   	of database systems have not used the dependency system to implement
  239   	this functionality, but have instead hard-coded the lookups like so:
  240   
  241   	<pre>
  242   		in DropTable:
  243   			scan the TableAuthority table looking for authorities on
  244   		this table; drop any that are found.
  245   			scan the ColumnAuthority table looking for authorities on
  246   		this table; drop any that are found.
  247   			scan the View table looking for views on
  248   		this table; drop any that are found.
  249   			scan the Column table looking for rows for columns of
  250   		this table; drop any that are found.
  251   			scan the Constraint table looking for rows for constraints of
  252   		this table; drop any that are found.
  253   			scan the Index table looking for rows for indexes of
  254   		this table; drop the indexes, and any rows that are found.
  255   		drop the table's conglomerate
  256   		drop the table's row in the Table table.
  257   		</pre>
  258   	<p>
  259   	The direct approach such as that outlined in the example will
  260   	probably be quicker and is definitely "known technology" over
  261   	the use of a dependency system in this area.
  262    */
  263   
  264   public interface DependencyManager {
  265   
  266   	/* NOTE - every value in this group (actions) must have a matching
  267   	 * String in the implementation of getActionString().
  268   	 */
  269   	public static final int COMPILE_FAILED = 0;
  270   	public static final int DROP_TABLE = 1;
  271   	public static final int DROP_INDEX = 2;
  272   	public static final int CREATE_INDEX = 3;
  273   	public static final int ROLLBACK = 4;
  274   	public static final int CHANGED_CURSOR = 5;
  275   	public static final int DROP_METHOD_ALIAS = 6;
  276   	public static final int DROP_VIEW = 9;
  277   	public static final int CREATE_VIEW = 10;
  278   	public static final int PREPARED_STATEMENT_RELEASE = 11;
  279   	public static final int ALTER_TABLE = 12;
  280   	public static final int DROP_SPS = 13;
  281   	public static final int USER_RECOMPILE_REQUEST = 14; 
  282   	public static final int BULK_INSERT = 15; 
  283   	public static final int DROP_JAR = 17;
  284   	public static final int REPLACE_JAR = 18;
  285   	public static final int DROP_CONSTRAINT = 19; 
  286   	public static final int SET_CONSTRAINTS_ENABLE = 20;
  287   	public static final int SET_CONSTRAINTS_DISABLE = 21;
  288   	public static final int CREATE_CONSTRAINT = 22;
  289   	public static final int INTERNAL_RECOMPILE_REQUEST = 23;
  290   	public static final int DROP_TRIGGER = 27;
  291   	public static final int CREATE_TRIGGER = 28;
  292   	public static final int SET_TRIGGERS_ENABLE = 29;
  293   	public static final int SET_TRIGGERS_DISABLE = 30;
  294   	public static final int MODIFY_COLUMN_DEFAULT = 31;
  295   	public static final int DROP_SCHEMA = 32;
  296   	public static final int COMPRESS_TABLE = 33;
  297   	//using same action for rename table/column
  298   	public static final int RENAME = 34;
  299   	public static final int DROP_COLUMN = 37;
  300   	public static final int DROP_STATISTICS = 39;
  301   	public static final int UPDATE_STATISTICS = 40;
  302   	//rename index dependency behavior is not as stringent as rename table and column and
  303   	//hence we need a different action for rename index. Rename index tries to imitate the
  304   	//drop index behavior for dependency which is not very strict.
  305   	public static final int RENAME_INDEX = 41;
  306   
  307   	public static final int TRUNCATE_TABLE = 42;
  308   	public static final int DROP_SYNONYM = 43;
  309   	//A generic revoke action for TRIGGER, REFERENCES, SELECT, INSERT,
  310   	//  UPDATE and DELETE privileges. For all these privilege types,
  311   	//  a revoke statement causes the dependents to drop
  312   	public static final int REVOKE_PRIVILEGE = 44;
  313   	
  314   	//This special revoke action is for when revoke should fail if
  315   	//  there are dependents on the privilege being revoked. When
  316   	//  such an action type is received by any dependents, they 
  317   	//  should throw an exception. Such a form of revoke will succeed
  318   	//  only if there are no dependents on the privilege being revoked.
  319   	//
  320   	//Currently, this is supported only for execute privilege on a
  321   	//  routine. In Derby, at this point, execute privilege on a
  322   	//  routine can be revoked only if there are no dependents on
  323   	//  that privilege. So, when a revoke execute..,restrict is
  324   	//  issued, this invalidation action will be sent to all
  325   	//  it's dependents.
  326   	public static final int REVOKE_PRIVILEGE_RESTRICT = 45;
  327   	public static final int DROP_COLUMN_RESTRICT = 46;
  328   
  329   	// Revoke action when a granted role is dropped/revoked. A revoke statement
  330   	// causes the dependents to drop.
  331   	public static final int REVOKE_ROLE = 47;
  332   
  333   	// Action when the current role is changed in a session. Used to force
  334   	// rechecking of privileges for prepared statements that depend on the
  335   	// current role for privileges by recreating the activation.
  336   	public static final int RECHECK_PRIVILEGES = 48;
  337   
  338   	/**
  339        * Extensions to this interface may use action codes > MAX_ACTION_CODE without fear of
  340        * clashing with action codes in this base interface.
  341        */
  342       public static final int MAX_ACTION_CODE = 0XFFFF;
  343   
  344   	/**
  345   		adds a dependency from the dependent on the provider.
  346   		This will be considered to be the default type of
  347   		dependency, when dependency types show up.
  348   		<p>
  349   		Implementations of addDependency should be fast --
  350   		performing alot of extra actions to add a dependency would
  351   		be a detriment.
  352   
  353   		@param d	the dependent
  354   		@param p	the provider
  355   		@param cm	Current ContextManager
  356   
  357   		@exception StandardException thrown if something goes wrong
  358   	 */
  359   	void addDependency(Dependent d, Provider p, ContextManager cm) throws StandardException; 
  360   
  361   	/**
  362   		mark all dependencies on the named provider as invalid.
  363   		When invalidation types show up, this will use the default
  364   		invalidation type. The dependencies will still exist once
  365   		they are marked invalid; clearDependencies should be used
  366   		to remove dependencies that a dependent has or provider gives.
  367   		<p>
  368   		Implementations of this can take a little time, but are not
  369   		really expected to recompile things against any changes
  370   		made to the provider that caused the invalidation. The
  371   		dependency system makes no guarantees about the state of
  372   		the provider -- implementations can call this before or
  373   		after actually changing the provider to its new state.
  374   		<p>
  375   		Implementations should throw DependencyStatementException
  376   		if the invalidation should be disallowed.
  377   
  378   		@param p the provider
  379   		@param action	The action causing the invalidate
  380   		@param lcc		The LanguageConnectionContext
  381   
  382   		@exception StandardException thrown if unable to make it invalid
  383   	 */
  384   	void invalidateFor(Provider p, int action, LanguageConnectionContext lcc) 
  385   		throws StandardException;
  386   
  387   
  388   
  389   	/**
  390   		Erases all of the dependencies the dependent has, be they
  391   		valid or invalid, of any dependency type.  This action is
  392   		usually performed as the first step in revalidating a
  393   		dependent; it first erases all the old dependencies, then
  394   		revalidates itself generating a list of new dependencies,
  395   		and then marks itself valid if all its new dependencies are
  396   		valid.
  397   		<p>
  398   		There might be a future want to clear all dependencies for
  399   		a particular provider, e.g. when destroying the provider.
  400   		However, at present, they are assumed to stick around and
  401   		it is the responsibility of the dependent to erase them when
  402   		revalidating against the new version of the provider.
  403   		<p>
  404   		clearDependencies will delete dependencies if they are
  405   		stored; the delete is finalized at the next commit.
  406   
  407   		@param lcc	Compiler state
  408   		@param d the dependent
  409   	 *
  410   	 * @exception StandardException		Thrown on failure
  411   	 */
  412   	void clearDependencies(LanguageConnectionContext lcc, Dependent d) throws StandardException;
  413   
  414   	/**
  415   	 * Clear the specified in memory dependency.
  416   	 * This is useful for clean-up when an exception occurs.
  417   	 * (We clear all in-memory dependencies added in the current
  418   	 * StatementContext.)
  419   	   This method will handle Dependency's that have already been
  420   	   removed from the DependencyManager.
  421   	 */
  422   	public void clearInMemoryDependency(Dependency dy);
  423   
  424   	/**
  425   	 * Get a new array of ProviderInfos representing all the persistent
  426   	 * providers for the given dependent.
  427   	 *
  428   	 * @exception StandardException		Thrown on error.
  429   	 */
  430   	public ProviderInfo[] getPersistentProviderInfos(Dependent dependent)
  431   			throws StandardException;
  432   
  433   	/**
  434   	 * Get a new array of ProviderInfos representing all the persistent
  435   	 * providers from the given list of providers.
  436   	 *
  437   	 * @exception StandardException		Thrown on error.
  438   	 */
  439   	public ProviderInfo[] getPersistentProviderInfos(ProviderList pl)
  440   			throws StandardException;
  441   
  442   	/**
  443   	 * Clear the in memory column bit map information in any table descriptor
  444   	 * provider in a provider list.  This function needs to be called before
  445   	 * the table descriptor is reused as provider in column dependency.  For
  446   	 * example, this happens in "create publication" statement with target-only
  447   	 * DDL where more than one views are defined and they all reference one
  448   	 * table.
  449   	 *
  450   	 * @exception StandardException		Thrown on error.
  451   	 */
  452   	public void clearColumnInfoInProviders(ProviderList pl)
  453   			throws StandardException;
  454   
  455   
  456   	/**
  457    	 * Copy dependencies from one dependent to another.
  458   	 *
  459   	 * @param copy_From the dependent to copy from	
  460   	 * @param copyTo the dependent to copy to
  461   	 * @param persistentOnly only copy persistent dependencies
  462   	 * @param cm			Current ContextManager
  463   	 *
  464   	 * @exception StandardException		Thrown on error.
  465   	 */
  466   	public void copyDependencies(
  467   									Dependent	copy_From, 
  468   									Dependent	copyTo,
  469   									boolean		persistentOnly,
  470   									ContextManager cm)
  471   			throws StandardException;
  472   	
  473   	/**
  474   	 * Returns a string representation of the SQL action, hence no
  475   	 * need to internationalize, which is causing the invokation
  476   	 * of the Dependency Manager.
  477   	 *
  478   	 * @param action		The action
  479   	 *
  480   	 * @return String	The String representation
  481   	 */
  482   	String getActionString(int action);
  483   
  484   	/**
  485   	 * Count the number of active dependencies, both stored and in memory,
  486   	 * in the system.
  487   	 *
  488   	 * @return int		The number of active dependencies in the system.
  489   
  490   		@exception StandardException thrown if something goes wrong
  491   	 */
  492   	public int countDependencies() 		throws StandardException;
  493   
  494   	/**
  495   	 * Dump out debugging info on all of the dependencies currently
  496   	 * within the system.
  497   	 *
  498   	 * @return String	Debugging info on the dependencies.
  499   	 *					(null if SanityManger.DEBUG is false)
  500   
  501   		@exception StandardException thrown if something goes wrong
  502   		@exception java.sql.SQLException thrown if something goes wrong
  503   	 */
  504   	public String dumpDependencies() throws StandardException, java.sql.SQLException;
  505   	
  506   	/**
  507   	 	Erases all of the dependencies the dependent has, be they
  508   	 	valid or invalid, of any dependency type.  This action is
  509   	 	usually performed as the first step in revalidating a
  510   	 	dependent; it first erases all the old dependencies, then
  511   	 	revalidates itself generating a list of new dependencies,
  512   	 	and then marks itself valid if all its new dependencies are
  513   	 	valid.
  514   	 	<p>
  515   	 	There might be a future want to clear all dependencies for
  516   	 	a particular provider, e.g. when destroying the provider.
  517   	 	However, at present, they are assumed to stick around and
  518   	 	it is the responsibility of the dependent to erase them when
  519   	 	revalidating against the new version of the provider.
  520   	 	<p>
  521   	 	clearDependencies will delete dependencies if they are
  522   	 	stored; the delete is finalized at the next commit.
  523   
  524   		@param lcc	Compiler state
  525   		@param d the dependent
  526   		@param tc transaction controller
  527   	
  528   		@exception StandardException		Thrown on failure
  529   	*/
  530   	public void clearDependencies(LanguageConnectionContext lcc, 
  531   									Dependent d, 
  532   									TransactionController tc) 
  533   		throws StandardException;
  534   
  535   
  536   	/**
  537    	 * Copy dependencies from one dependent to another.
  538   	 *
  539   	 * @param copy_From the dependent to copy from	
  540   	 * @param copyTo the dependent to copy to
  541   	 * @param persistentOnly only copy persistent dependencies
  542   	 * @param cm			Current ContextManager
  543   	 * @param tc            Transaction Controller
  544   	 *
  545   	 * @exception StandardException		Thrown on error.
  546   	 */
  547   	public void copyDependencies(
  548   									Dependent	copy_From, 
  549   									Dependent	copyTo,
  550   									boolean		persistentOnly,
  551   									ContextManager cm, 
  552   									TransactionController tc)
  553   			throws StandardException;
  554   	
  555   }

Home » db-derby-10.5.3.0 » org.apache.derby.iapi.sql.depend » [javadoc | source]