Plugin mechanism - hudec/sql-processor GitHub Wiki

Table of Contents

Plugin mechanism
Simple usage

Plugin mechanism

The plugins are used to alter the behaviour of the SQL Processor. They are defined for the most volatile behaviour of the SQL Processor runtime. Every database has a specific features and sometimes it's not possible to find a unique common solution for all of them. The plugins can be taken as an extension of the SQL Processor optional features.

The next plugins' contracts are defined:

  • IsEmptyPlugin to alter the behaviour of the isNotEmpty function. This function is described in Basic META SQL. The interface definition is IsEmptyPlugin.
  • IsTruePlugin to alter the behaviour of the isTrue function. This function is described in Basic META SQL. The interface definition is IsTruePlugin.
  • SqlCountPlugin for the COUNT SQL construction. It is based on the transformation from the SELECT command. The interface definition is SqlCountPlugin.
  • SqlFromToPlugin for the FROM-TO SQL construction. It is based on the database specific transformation using the SQL Processor optional features. The interface definition is SqlFromToPlugin.
  • SqlIdentityPlugin for the identity SELECT SQL construction. It is based on the database specific transformation using the SQL Processor optional features. The interface definition is SqlIdentityPlugin.
  • SqlSequencePlugin for the sequence SELECT SQL construction. It is based on the database specific transformation using the SQL Processor optional features. The interface definition is SqlSequencePlugin.

The standard implementation of the SQL Processor plugins is DefaultSqlPlugins. This implementation can be overridden partially for any plugin using the factory mechanism.

Simple usage

Let's have a table PERSON and a POJO Person as in the Simple Tutorial. We'd like to have a list of all people in this table, which were created by some end user. We want to ignore all records, which we created by SYSTEM. The META SQL query can be for example:

ALL_PEOPLE_CREATED_BY(QRY)=
  select p.ID @id, p.NAME_FIRST @name.first, p.NAME_LAST @name.last
  from PERSON p
  {= where
    p.id = :id(type=long,any)
    {& p.CREATED_BY = :createdBy(type=string,!zero)}
  }
;

There's a new META SQL statement modifier !zero. The goal is to change the isNotEmpty function implementation for the case the input value is accompanied with this modifier. For the case the input value is String and has a value other than 0, it's true and the SQL fragment AND p.CREATED_BY = :createdBy will become a part of the final ANSI SQL statement. The implementation can be a slight modification of the standard implementation:

public class CustomizedSqlPlugin extends DefaultSqlPlugins {
  private static final String MODIFIER_ZERO = "zero";
  private static final String MODIFIER_NOTZERO = "notzero";

  @Override
  public boolean isNotEmpty(String attributeName, Object obj, Object parentObj, SqlMetaType sqlMetaType,
    String inOutModifier, boolean inSqlSetOrInsert, Map<String, String> values, Map<String, Object> features)
    throws IllegalArgumentException {

    if (MODIFIER_ZERO.equalsIgnoreCase(inOutModifier)) {
        if (obj != null) {
            if (obj instanceof String) {
                final String str = ((String) obj).trim();
                return ("0".equals(str));
            }
        } else {
            throw new IllegalArgumentException("obj with sqlMetaTypeExt '" + MODIFIER_ZERO + "' should not be null");
        }
    }
    if (MODIFIER_NOTZERO.equalsIgnoreCase(inOutModifier)) {
        if (obj != null) {
            if (obj instanceof String) {
                final String str = ((String) obj).trim();
                return (!"0".equals(str));
            }
        } else {
            throw new IllegalArgumentException("obj with sqlMetaTypeExt '" + MODIFIER_ZERO + "' should not be null");
        }
    }

    return super.isNotEmpty(attributeName, obj, parentObj, sqlMetaType, inOutModifier, inSqlSetOrInsert, values, features);
}

To activate this plugin, the SimpleSqlPluginFactory can be utilized:

<beans ...>
   ...
   <bean id="customizedIsEmptyPlugin" class="mypackage.CustomizedSqlPlugin" />

   <bean id="pluginFactory" class="org.sqlproc.engine.plugin.SimpleSqlPluginFactory" factory-method="getInstance" >
     <property name="isEmptyPlugin" ref="customizedIsEmptyPlugin" />
   </bean>

   <bean id="sqlFactory" class="org.sqlproc.engine.jdbc.JdbcEngineFactory" init-method="init">
     <property name="metaFilesNames">
       <list>
         <value>statements.qry</value>
       </list>
     </property>
     <property name="pluginFactory" ref="pluginFactory" />
   </bean>
 </beans>

Without the Spring DI it can be:

JdbcEngineFactory factory = new JdbcEngineFactory();
factory.setMetaFilesNames("statements.qry");
SimpleSqlPluginFactory pluginFactory = SimpleSqlPluginFactory.getInstance();
pluginFactory.setIsEmptyPlugin(new CustomizedSqlPlugin());
factory.setPluginFactory(pluginFactory);
SqlQueryEngine sqlEngine = sqlFactory.getQueryEngine("ALL_PEOPLE_CREATED_BY");

The rest is simple:

Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:sqlproc", "sa", "");
SqlSession session = new JdbcSimpleSession(connection);
Person person = new Person();
person.setCreatedBy("Jan");
List<Person> list = sqlEngine.query(session, Person.class, person, SqlQueryEngine.ASC_ORDER);

The tutorial is updated for SQLP 2.2

⚠️ **GitHub.com Fallback** ⚠️