Class ConditionalDDR

java.lang.Object
org.postgresql.pljava.example.annotation.ConditionalDDR

@SQLAction(provides={"LifeIsGood","LifeIsNotGood"},install="SELECT CASE 42 WHEN 42 THEN set_config(\'pljava.implementors\', \'LifeIsGood,\' || current_setting(\'pljava.implementors\'), true) ELSE set_config(\'pljava.implementors\', \'LifeIsNotGood,\' || current_setting(\'pljava.implementors\'), true) END") @SQLAction(implementor="LifeIsGood",install="SELECT javatest.logmessage(\'INFO\', \'ConditionalDDR looking good!\')") @SQLAction(implementor="LifeIsNotGood",install="SELECT javatest.logmessage(\'WARNING\', \'ConditionalDDR: This should not be executed\')") @SQLAction(provides="postgresql_ge_100000",install="SELECT CASE WHEN 100000 <= CAST(current_setting(\'server_version_num\') AS integer) THEN set_config(\'pljava.implementors\', \'postgresql_ge_100000,\' || current_setting(\'pljava.implementors\'), true) END") public class ConditionalDDR extends Object
Test of a very simple form of conditional execution in the deployment descriptor using only the <implementor name> specified for an <implementor block>.

When a deployment descriptor is executed, the config setting pljava.implementors determines which <implementor block>s will be executed (in addition to all of the plain <SQL statement>s that are not tagged with an implementor name). The default setting of pljava.implementors is simply postgresql.

In this example, an SQLAction (with the default implementor name PostgreSQL so it should always execute) tests some condition and, based on the result, adds LifeIsGood to the list of recognized implementor names.

Later SQLActions with that implementor name should also be executed, while those with a different, unrecognized implementor should not.

That is what happens at deployment (or undeployment) time, when the jar has been loaded into the target database and the deployment descriptor is being processed.

The provides attributes matter at compile time: they are hints to the DDR generator so it will be sure to write the SQLAction that tests the condition ahead of whatever depends on the condition having been tested. The example illustrates that implementor is treated also as an implicit requires.

Note: while ISO SQL/JRT specifies that an <implementor name> is an SQL identifier, which would match case-insensitively unless quoted, PL/Java treats provides elements as arbitrary strings that can only be matched with identical spelling and case. Therefore, the matching of the implicit requires of an <implementor name> and the explicit provides on an SQLAction depends on the implementor and provides values being supplied with identical spelling and case,

The dependency created when matching implementor to provides differs in three ways from an explicit dependency between requires and provides:

  • It is weak: if there is nothing declared that provides it, that's not an error; affected <implementor block>s will just be placed as late in the generated DDR as other dependencies allow, in case something in the preceding actions will be setting those implementor names.
  • It does not have its sense reversed when generating the REMOVE actions of the deployment descriptor. Ordinary requirements do, so the dependent objects get dropped before the things they depend on. But the code for setting a conditional implementor name has to be placed ahead of the uses of the name, whether deploying or undeploying.
  • An SQLAction setting an implementor name does not need to have any remove= actions. If it does not (the usual case), its install= actions will be used in both sections of the deployment descriptor.

This example adds LifeIsGood ahead of the prior content of pljava.implementors. Simply replacing the value would stop the default implementor PostgreSQL being recognized, probably not what's wanted. The final true argument to set_config makes the setting local, so it is reverted when the transaction completes.

In addition to the goodness-of-life examples, this file also generates one or more statements setting PostgreSQL-version-based implementor names that are relied on by various other examples in this directory.

  • Method Details

    • presentOnClassPath

      @Function(variadic=true, provides="presentOnClassPath") public static boolean presentOnClassPath(String[] className)
      Tests class names in the supplied order, returning false as soon as any cannot be found by the class loader(s) available to the examples jar, or true if all can be found.