-
Language:
English
-
Language:
English
Red Hat Training
A Red Hat training course is available for Red Hat JBoss Data Virtualization
Development Guide Volume 4: Server Development
This guide is intended for developers
Red Hat Customer Content Services
Abstract
Chapter 1. Read Me
1.1. Back Up Your Data
Warning
1.2. Variable Name: EAP_HOME
EAP_HOME
refers to the root directory of the Red Hat JBoss Enterprise Application Platform installation on which JBoss Data Virtualization has been deployed.
1.3. Variable Name: MODE
MODE
will either be standalone
or domain
depending on whether JBoss Data Virtualization is running in standalone or domain mode. Substitute one of these whenever you see MODE
in a file path in this documentation. (You need to set this variable yourself, based on where the product has been installed in your directory structure.)
1.4. Red Hat Documentation Site
Chapter 2. Embedded JBoss Data Virtualization (Technology Preview)
2.1. Technology Preview
Warning
Note
2.2. Embedded JBoss Data Virtualization
Note
EmbeddedServer
for more guidance.
2.3. Configuration
EmbeddedConfiguration
class. It is provided to the EmbeddedServer
at start-up. From there the running server instance can have translators and VDBs deployed as needed.
Note
features:addurl mvn:org.jboss.teiid/teiid/8.6.0.Final/xml/karaf-features features:install -v teiid
<dependency> <groupId>org.jboss.teiid</groupId> <artifactId>teiid-runtime</artifactId> </dependency> <dependency> <groupId>org.jboss.teiid</groupId> <artifactId>teiid-admin</artifactId> </dependency> <dependency> <groupId>org.jboss.teiid.connectors</groupId> <artifactId>translator-SOURCE</artifactId> </dependency> <dependency> <groupId>org.jboss.teiid.connectors</groupId> <artifactId>connector-SOURCE</artifactId> <classifier>lib</classifier> </dependency>
2.4. VDB Deployment
EmbeddedServer.deployVDB
method).
InputStream
may be given to a vdb.xml file. See the EmbeddedServer.deployVDB(InputStream)
method.
URL
may be given to a ZIP file. See the EmbeddedServer.deployVDBZip
method. The use of the ZIP lib for dependency loading is not enabled in the embedded version.
2.5. Translators
vdb.xml
file; however, for Embedded JBoss Data Virtualization, instances of translators are scoped to the entire EmbeddedServer
and must be registered via the EmbeddedServer.addTranslator
method. A new server instance does not assume any translators are deployed and does not perform any library scanning to find translators.
2.6. Sources
EmbeddedServer
will still attempt to lookup the given JNDI connection factory names via JNDI. In most non-container environments it is likely that no such bindings exist. In this case the embedded server instance must have ConnectionFactoryProvider
instances manually registered using the EmbeddedServer.addConnectionFactoryProvider
method. Note that the embedded server does not have built-in pooling logic, so to make better use of a standard javax.sql.DataSource
or to enable proper use of javax.sql.XADataSource
you must first configure the instance via a third-party connection pool.
2.7. Example Deployment
EmbeddedServer es = new EmbeddedServer(); EmbeddedConfiguration ec = new EmbeddedConfiguration(); //set any configuration properties ec.setUseDisk(false); es.start(ec); //example of adding a translator by class - this will make a default instance available with the default name of oracle es.addTranslator(OracleExecutionFactory.class); //add a translator by instance - this is functionally equivalent to using a vdb.xml translator override OracleExecutionFactory oef = new OracleExecutionFactory(); //configure and start the instance oef.setDatabaseVersion("11.0"); oef.start(); es.addTranslator("my-oracle", oef); //add a connection factory provider if needed //the default is to perform a jndi lookup of the datasource names given //however out of a container you will likely need to manually inject the necessary connection factory ConnectionFactoryProvider<DataSource> cfp = new EmbeddedServer.SimpleConnectionFactoryProvider<DataSource>(...); es.addConnectionFactoryProvider("ora-ds", cfp); //add a vdb //physical model ModelMetaData mmd = new ModelMetaData(); mmd.setName("my-schema"); mmd.addSourceMapping("my-schema", "my-oracle", "ora-ds"); //virtual model ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("virt"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view \"my-view\" OPTIONS (UPDATABLE 'true') as select * from \"my-table\""); es.deployVDB("test", mmd, mmd1);
2.8. Transactions
TransactionManager
used to start the EmbeddedServer
must be set in the EmbeddedConfiguration
. A client facing javax.sql.DataSource
is not provided for Embedded JBoss Data Virtualization. However, the use of java.sql.Driver
should be sufficient as, by default, the embedded server can detect thread bound transactions and appropriately propagate the transaction to threads launched as part of request processing. Use of local connections is also permitted.
2.9. Other Differences Between the Embedded and EAP Deployments
- There is no JDBC/ODBC socket transport in Embedded JBoss Data Virtualization. You are expected to obtain a
Driver
connection via theEmbeddedServer.getDriver
method. - When running JBoss Data Virtualization with JBoss EAP, a
MetadataRepository
is scoped to a VDB, but for Embedded JBoss Data Virtualization is scoped to the entireEmbeddedServer
instance and must be registered via theEmbeddedServer.addMetadataRepository
method. - MDC logging values are not available as Java logging lacks the concept of a mapped diagnostic context.
Chapter 3. Developing for JBoss Data Virtualization
3.1. Developing for JBoss Data Virtualization
3.2. JBoss Data Virtualization Connector Architecture
- a translator (mandatory) and
- a resource adapter (optional), also known as a connector. Most of the time, this will be a Java EE Connector Architecture (JCA) Adapter.
- translate JBoss Data Virtualization commands into commands understood by the datasource for which the translator is being used,
- execute those commands,
- return batches of results from the datasource, translated into the formats that JBoss Data Virtualization is expecting.
- handles all communications with individual enterprise information systems, (which can include databases, data feeds, flat files and so forth),
- can be a JCA Adapter or any other custom connection provider (the JCA specification ensures the writing, packaging and configuration are undertaken in a consistent manner),
Note
Many software vendors provide JCA Adapters to access different systems. Red Hat recommends using vendor-supplied JCA Adapters when using JMS with JCA. See http://docs.oracle.com/cd/E21764_01/integration.1111/e10231/adptr_jms.htm - removes concerns such as connection information, resource pooling, and authentication for translators.
3.3. Translators in JBoss Data Virtualization
- Apache Cassandra (Technical Preview Only)
Warning
Technology Preview features are not supported, may not be functionally complete, and are not intended for production use. These features are included to provide customers with early access to upcoming product innovations, enabling them to test functionality and provide feedback during the development process.Support of Apache Cassandra brings support for the popular columnar NoSQL database to JDV customers.- Apache Solr
- With Apache Solr, JDV customers will be able to take advantage of enterprise search capabilities for organized retrieval of structured and unstructured data.
- Cloudera Impala
- Cloudera Impala support provides for fast SQL query access to data stored in Hadoop.
- JDBC Translator
- The JDBC Translator works with many relational databases.
- File Translator
- The File Translator provides a procedural way to access the file system in order to handle text files.
- Google Spreadsheet Translator
- The Google Spreadsheet Translator is used to connect to a Google Spreadsheet.
- JBoss Data Grid 6.3
- You can perform reads and writes to JDG. You can use it as an embedded cache or a remote cache.
- LDAP Translator
- The LDAP Translator provides access to LDAP directory services.
- MongoDB Translator
- The MongoDB translator, known by the type name mongodb, provides a relational view of data that resides in a MongoDB database. This translator is capable of converting JBoss Data Virtualization SQL queries into MongoDB based queries. It supports a full range of SELECT, INSERT, UPDATE and DELETE calls.
- Object Translator
- The Object translator is a bridge for reading Java objects from external sources such as JBoss Data Grid (
infinispan-cache
) or Map Cache and delivering them to the engine for processing. - OData Translator
- The OData translator exposes the OData V2 and V3 data sources and uses the JBoss Data Virtualization WS resource adapter for making web service calls. This translator is an extension of the WS Translator.
- OLAP Translator
- The OLAP Services translator exposes stored procedures for calling analysis services backed by an OLAP server using MDX query language.
- Salesforce Translator
- The Salesforce Translator works with Salesforce interfaces.
- Web Services Translator
- The Web Services Translator provides procedural access to XML content by using web services.
3.4. Resource Adapters in JBoss Data Virtualization
- File Adapter -
file
- Google Spreadsheet Adapter -
google
- Red Hat JBoss Data Grid (6.1 & 6.2) Adapter -
infinispan
- LDAP Adapter -
ldap
- Salesforce Adapter -
salesforce
- Web Services Adapter -
webservice
- Mongo DB Adapter (technical preview) -
mongodb
Note
3.5. Other JBoss Data Virtualization Development
- You can add user defined functions. See Section 12.1, “User Defined Functions”.
- You can adapt logging to your requirements, which is especially useful for custom audit or command logging. See Section 14.1, “Customized Logging”.
- A delegating translator can be used to add custom code to all methods for a given translator. See Section 9.3, “Delegating Translator”.
- You can also customize authentication and authorization modules. See the Red Hat JBoss Data Virtualization Security Guide.
3.6. Setting the Development Environment
<dependencies> <dependency> <groupId>org.jboss.teiid</groupId> <artifactId>teiid-api</artifactId> <version>${teiid-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.teiid</groupId> <artifactId>teiid-common-core</artifactId> <version>${teiid-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.resource</groupId> <artifactId>connector-api</artifactId> <version>${connector-api-version}</version> <scope>provided</scope> </dependency> </dependencies>
teiid-version
property must be set to the expected version. You must also add the new declared property connector-api-version. You can find relevant artifacts in the Maven repository.
3.7. Maven Repository Location
- File System
- JBoss Data Virtualization -
file:///path/to/repo/jboss-dv-6.2.0-maven-repository
- Apache Web Server
http://maven.repository.redhat.com/techpreview/all/
Chapter 4. Resource Adapter Development
4.1. Developing Custom Adapters
Note
- Define a Managed Connection Factory by extending the
BasicManagedConnectionFactory
class - Define a Connection Factory by extending the
BasicConnectionFactory
class - Define a Connection by extending the
BasicConnection
class - Specify configuration properties in an
ra.xml
file
Note
teiid/connectors
directory of the JBoss Data Virtualization VERSION Source Code ZIP file. This ZIP file can be downloaded from the Red Hat Customer Portal at https://access.redhat.com.
4.2. Define a Managed Connection Factory
- Extend the
org.teiid.resource.spi.BasicManagedConnectionFactory
class, providing an implementation for thecreateConnectionFactory()
method. This method will create and return an instance of a Connection Factory. - Define an attribute for each configuration variable, and then provide both "getter" and "setter" methods for them. This class will define various configuration variables (such as user, password, and URL) used to connect to the datasource.
public class MyManagedConnectionFactory extends BasicManagedConnectionFactory { @Override public Object createConnectionFactory() throws ResourceException { return new MyConnectionFactory(); } // config property name (metadata for these are defined inside the ra.xml) String userName; public String getUserName() { return this.userName; } public void setUserName(String name){ this.userName = name; } // config property count (metadata for these are defined inside the ra.xml) Integer count; public Integer getCount() { return this.count; } public void setCount(Integer value) { this.count = value; } }
Important
java.lang
objects as the attributes. DO NOT use Java primitives for defining and accessing the properties.
4.3. Define a Connection Factory
org.teiid.resourse.spi.BasicConnectionFactory
class, and provide an implementation for the getConnection()
method. This method will create and return an instance of a connection.
public class MyConnectionFactory extends BasicConnectionFactory { @Override public MyConnection getConnection() throws ResourceException { return new MyConnection(); } }
getConnection()
method can pass credentials to the requesting application. Therefore, the Connection Factory can reference the calling user's javax.security.auth.Subject
from within the getConnection()
method.
Subject subject = ConnectionContext.getSubject();
Subject
can give access to logged-in user's credentials and roles that are defined. This may be null
.
Note
4.4. Define a Connection
org.teiid.resource.spi.BasicConnection
class, and provide an implementation based on your access of the Connection object in your translator. If your connection is stateful, override the isAlive()
and cleanup()
methods with suitable implementations. These methods are called to check if a connection is stale and needs flushing from the connection pool by the application server.
public class MyConnection extends BasicConnection { public void doSomeOperation(command) { // do some operation with requesting application.. // This is method you use in the Translator, you should know // what need to be done here for your source.. } @Override public boolean isAlive() { return true; } @Override public void cleanUp() { } }
4.5. XA Transactions
Connection
object must override the getXAResource()
method and provide the XAResource
object for the application. To participate in crash recovery you must also extend the BasicResourceAdapter
class and implement the public XAResource[] getXAResources(ActivationSpec[] specs)
method.
4.6. Specify Configuration Properties in an ra.xml File
ra.xml
file. These properties are used to configure each instance of the connector.
ra.xml
file is located in EAP_HOME/modules/system/layers/dv/org/jboss/teiid/resource-adapter/ADAPTER-NAME/main/META-INF
. An example file is provided in Section C.1, “Template for ra.xml”.
<config-property> <description> {$display:"display-name",$description:"description", $allowed:"allowed", $required:"true|false", $defaultValue:"default-value"} </description> <config-property-name>property-name</config-property-name> <config-property-type>property-type</config-property-type> <config-property-value>optional-property-value</config-property-value> </config-property>
<config-property> <description> {$display:"User Name",$description:"The name of the user.", $required="true"} </description> <config-property-name>UserName</config-property-name> <config-property-type>java.lang.String</config-property-type> </config-property>
<description>
element may be used as extended metadata for tooling. This use of the special format and all properties is optional and must follow these rules:
- The special format must begin and end with curly braces e.g.
{ }
. - Property names begin with
$
. - Property names and the associated value are separated with a colon (
:
). - Double quotes (
"
) identifies a single value. - A pair of square brackets (
[ ]
), containing comma separated double quoted entries indicates a list value.
$display
: Display name of the property.$description
: Description about the property.$required
: The property is a required property; or optional and a default is supplied.$allowed
: If property value must be in certain set of legal values, this defines all the allowed values.$masked
: The tools need to mask the property; Do not show in plain text; used for passwords.$advanced
: Notes this as Advanced property.$readOnly
: Property is set to read-only.
Note
4.7. Packaging the Adapter
Note
- JBoss Developer Studio
- If you create a Java Connector project in JBoss Developer Studio, it will include a build target that produces a RAR file.
- Apache Ant
- When using Apache Ant, you can use the standard
rar
build task. - Apache Maven
- When using Apache Maven, set the value of the
<packaging>
element torar
. Since JBoss Data Virtualization uses Maven, you can refer to any of the Connector projects; for example,pom.xml
shown below.<project> <modelVersion>4.0.0</modelVersion> <artifactId>connector-{name}</artifactId> <groupId>org.company.project</groupId> <name>Name Connector</name> <packaging>rar</packaging> <description>This connector is a sample</description> <dependencies> <dependency> <groupId>org.jboss.teiid</groupId> <artifactId>teiid-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.teiid</groupId> <artifactId>teiid-common-core</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.resource</groupId> <artifactId>connector-api</artifactId> <scope>provided</scope> </dependency> </dependencies>
META-INF
directory must contain the ra.xml
file. If you are using Apache Maven, see http://maven.apache.org/plugins/maven-rar-plugin/. In the root of the RAR file, you can embed the JAR file containing your connector code and any dependent library JAR files.
4.8. Adding Dependent Libraries
MANIFEST.MF
file into the META-INF
directory, and the following line to add the core JBoss Data Virtualization API dependencies for the resource adapter.
Dependencies: org.jboss.teiid.common-core,org.jboss.teiid.api,javax.api
MANIFEST.MF
file to specify them as dependencies.
4.9. Deploying the Adapter
- Edit the server configuration file and add the following XML in the "resource-adapters" subsystem.
<!-- If susbsytem is already defined, only copy the contents under it and edit to suit your needs --> <subsystem xmlns="urn:jboss:domain:resource-adapters:1.0"> <resource-adapters> <resource-adapter> <archive>teiid-connector-sample.rar</archive> <transaction-support>NoTransaction</transaction-support> <connection-definitions> <connection-definition class-name="org.teiid.resource.adapter.MyManagedConnectionFactory" jndi-name="${jndi-name}" enabled="true" use-java-context="true" pool-name="sample-ds"> <config-property name="UserName">jdoe</config-property> <config-property name="Count">12</config-property> </connection-definition> </connection-definitions> </resource-adapter> </resource-adapters> </subsystem>
There are more properties that you can define in this file; for example, for pooling, transactions, and security. Refer to the Red Hat JBoss Enterprise Application Platform documentation for all the available properties. See https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/. - You can use the web-based Management Console to create a new
ConnectionFactory
.
Chapter 5. Translator Development
5.1. Developing Custom Translators
- Create a new (or reuse an existing) resource adapter for the datasource, to be used with this translator.
- Decide whether to use the Teiid archetype template to create your initial custom translator project and classes or manually create your environment.
- Create an
ExecutionFactory
by:- extending the
org.teiid.translator.ExecutionFactory
class or - extending the
org.teiid.translator.jdbc.JDBCExecutionFactory
class .
- Package the translator.
- Deploy your translator.
- Deploy a Virtual Database (VDB) that uses your translator.
- Execute queries via the Teiid engine.
teiid/connectors
directory of the JBoss Data Virtualization VERSION Source Code ZIP file which can be downloaded from the Red Hat Customer Portal at https://access.redhat.com.
<dependencies> <dependency> <groupId>org.jboss.teiid</groupId> <artifactId>teiid-api</artifactId> <version>${teiid-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.teiid</groupId> <artifactId>teiid-common-core</artifactId> <version>${teiid-version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.resource</groupId> <artifactId>connector-api</artifactId> <version>${version.connector.api}</version> <scope>provided</scope> </dependency> </dependencies>
Procedure 5.1. Create a Project in JBDS
- Open the Java perspective
- From the menu select File - New - Other.
- In the tree, expand Maven and select Maven Project.
- Click Next.
- On the "Select project name and Location" window, you can accept the defaults, so click Next
- On the "Select an Archetype" window, click the Configure button
- Add the remote catalog found at https://repository.jboss.org/nexus/content/repositories/releases/ then click OK to return.
- Enter "teiid" in the filter to see the Teiid archetypes.
- Select the translator-archetype 8.7.x and then click Next.
- Enter all the information (such as Group ID and, Artifact ID) needed to generate the project.
- Click Finish.
Procedure 5.2. Create a Project Using the Command Line
- Issue the following template command:
mvn archetype:generate \ -DarchetypeGroupId=org.jboss.teiid.arche-types \ -DarchetypeArtifactId=translator-archetype \ -DarchetypeVersion=8.7.0 \ -DgroupId=${groupId} \ -DartifactId=translator-${translator-name} \ -Dpackage=org.teiid.translator.${translator-name} \ -Dversion=${version} \ -Dtranslator-name=${translator-name} \ -Dteiid-version=${teiid-version}
This is what the instructions mean:- -DarchetypeGroupId - is the group ID for the archetype to use to generate
- -DarchetypeArtifactId - is the artifact ID for the archetype to use to generate
- -DarchetypeVersion - is the version for the archetype to use to generate
- -DgroupId - (user defined) group ID for the new translator project pom.xml
- -DartifactId - (user defined) artifact ID for the new translator project pom.xml
- -Dpackage - (user defined) the package structure where the java and resource files will be created
- -Dversion - (user defined) the version that the new connector project pom.xml will be
- -Dtranslator-name - (user defined) the name (type) of the new translator project, used to create the java class names
- -Dteiid-version - the Teiid version upon which the connector will depend.
Here is a sample command:mvn archetype:generate \ -DarchetypeGroupId=org.jboss.teiid.arche-types \ -DarchetypeArtifactId=translator-archetype \ -DarchetypeVersion=8.7.0 \ -DgroupId=org.jboss.teiid.connector \ -DartifactId=translator-myType \ -Dpackage=org.teiid.translator.myType \ -Dversion=0.0.1-SNAPSHOT \ -Dtranslator-name=MyType \ -Dteiid-version=8.7.0.Final
- After you execute it, you will be asked to confirm the properties:
Confirm properties configuration: groupId: org.jboss.teiid.connector artifactId: translator-myType version: 0.0.1-SNAPSHOT package: org.teiid.translator.myType teiid-version: 8.7.0.Final translator-name: MyType Y: :
Type Y (for Yes) and click enter. - Upon creation, a directory based on the artifactId will be created, that will contain the project. Navigate to that directory.
- Execute a test build to confirm the project was created correctly:
mvn clean install
It should build successfully. If so, you are now ready to start adding your custom code.
5.2. Implementing the Framework
ExecutionFactory.getCacheDirective
method, which is called prior to execution. The command passed to getCacheDirective will already have been vetted to ensure that the results are eligible for caching. For example update commands or commands with pushed dependent sets will not be eligible for caching.
Note
ExecutionContext.getCacheDirective()
method. Having ExeuctionFactory.getCacheDirective called prior to execution allows the translator to potentially be selective about which results to even attempt to cache. Since there is a resource overhead with creating and storing the cached results it may not be desirable to attempt to cache all results if it is possible to return large results that have a low usage factor. If you are unsure about whether to cache a particular command result you may return an initial CacheDirective then change the Scope to Scope.NONE at any time prior to the final cache entry being created and the engine will give up creating the entry and release its resources.
Note
Table 5.1. Options
Option | Default |
---|---|
scope |
Session
|
ttl |
rs cache ttl
|
readAll |
true
|
updatable |
true
|
prefersMemory |
false
|
- QueryExpression
- Insert
- Update
- Delete
- BatchedUpdates
- Call
- Expression – base expression interface.
- ColumnReference – represents an column in the data source.
- Literal – represents a literal scalar value.
- Parameter – represents a parameter with multiple values. The command should be an instance of BatchedCommand, which provides all values via getParameterValues.
- Function – represents a scalar function with parameters that are also Expressions.
- AggregateFunction – represents an aggregate function which can hold a single expression.
- WindowFunction – represents an window function which holds an AggregateFunction (which is also used to represent analytical functions) and a WindowSpecification.
- ScalarSubquery – represents a subquery that returns a single value.
- SearchedCase, SearchedWhenClause – represents a searched CASE expression. The searched CASE expression evaluates the criteria in WHEN clauses till one evaluates to TRUE, then evaluates the associated THEN clause.
- Array – represents an array of expressions, used by the engine in multi-attribute dependent joins.
- Condition – the base criteria interface
- Not – used to NOT another criteria
- AndOr – used to combine other criteria via AND or OR
- SubuqeryComparison – represents a comparison criteria with a subquery including a quantifier such as SOME or ALL
- Comparison – represents a comparison criteria with =, >, and so on.
- BaseInCondition – base class for an IN criteria
- In – represents an IN criteria that has a set of expressions for values
- SubqueryIn – represents an IN criteria that uses a subquery to produce the value set
- IsNull – represents an IS NULL criteria
- Exists – represents an EXISTS criteria that determines whether a subquery will return any values.
- Like – represents a LIKE/SIMILAR TO/LIKE_REGEX criteria that compares string values.
- NamedTable – represents a single Table
- Join – has a left and right TableReference and information on the join between the items
- DerivedTable – represents a table defined by an inline QueryExpression A list of TableReference are used by default, in the pushdown query when no outer joins are used. If an outer join is used anywhere in the join tree, there will be a tree of joins with a single root. This latter form is the ANSI preferred style. If you wish all pushdown queries containing joins to be in ANSI style have the capability "useAnsiJoin" return true.
- Column - returns Column metadata record
- Table - returns a Table metadata record
- Procedure - returns a Procedure metadata record
- ProcedureParameter - returns a Procedure Parameter metadata record
//getting the Table metadata from an Table is straight-forward Table table = runtimeMetadata.getTable("table-name"); String contextName = table.getNameInSource(); //The props will contain extension properties Map<String, String> props = table.getProperties();
Procedure 5.3. Write a Visitor
- Create a subclass of AbstractLanguageVisitor. Override any visit methods needed for your processing. For instance, if you wanted to count the number of elements in the tree, you need only override the visit(ColumnReference) method. Collect any state in local variables and provide accessor methods for that state.
- Decide whether to use pre-order or post-order iteration. Note that visitation order is based upon syntax ordering of SQL clauses - not processing order.
- Write code to execute your visitor using the utility methods on DelegatingHierarchyVisitor:
// Get object tree LanguageObject objectTree = … // Create your visitor initialize as necessary MyVisitor visitor = new MyVisitor(); // Call the visitor using pre-order visitation DelegatingHierarchyVisitor.preOrderVisit(visitor, objectTree); // Retrieve state collected while visiting int count = visitor.getCount();
Table 5.2. Execution Modes
Execution Interface | Command Interface | Description |
---|---|---|
ResultSetExecution |
QueryExpression
|
A query corresponding to a SQL SELECT or set query statement.
|
UpdateExecution |
Insert, Update, Delete, BatchedUpdates
|
An insert, update, or delete, corresponding to a SQL INSERT, UPDATE, or DELETE command.
|
ProcedureExecution |
Call
|
A procedure execution that may return a result set and/or output values.
|
Important
Important
Important
- Client cancellation via the JDBC API (or other client APIs)
- Administrative cancellation
- Clean-up during session termination
- Clean-up if a query fails during processing
package org.teiid.translator.custom; @Translator(name="custom", description="Connect to My EIS") public class CustomExecutionFactory extends ExecutionFactory<MyConnectionFactory, MyConnection> { public CustomExecutionFactory() { } }
private String foo = "blah"; @TranslatorProperty(display="Foo property", description="description about Foo") public String getFoo() { return foo; } public void setFoo(String value) { return this.foo = value; }
- display: Display name of the property
- description: Description about the property
- required: The property is a required property
- advanced: This is advanced property; A default value must be provided. A property can not be "advanced" and "required" at same time.
- masked: The tools need to mask the property; Do not show in plain text; used for passwords
- createResultSetExecution - Override if you are doing read based operation that is returning a rows of results. For ex: select
- createUpdateExecution - Override if you are doing write based operations. For example, insert, update and delete
- createProcedureExecution- Overide if you are doing procedure based operations. For example; stored procedures. This works well for non-relational sources.
public class MyMetadataProcessor implements MetadataProcessor<Connection> { public void process(MetadataFactory mf, Connection conn) { Object somedata = connection.getSomeMetadata(); Table table = mf.addTable(tableName); Column col1 = mf.addColumn("col1", TypeFacility.RUNTIME_NAMES.STRING, table); column col2 = mf.addColumn("col2", TypeFacility.RUNTIME_NAMES.STRING, table); } }
@TranslatorProperty(display="Column Name Pattern", category=PropertyType.IMPORT, description="Pattern to derive column names") public String getColumnNamePattern() { return columnNamePattern; } public void setColumnNamePattern(String columnNamePattern) { this.columnNamePattern = columnNamePattern; }
vdb.xml
file, like this:
<vdb name="myvdb" version="1"> <model name="legacydata" type="PHYSICAL"> <property name="importer.ColumnNamePattern" value="col*"/> .... <source name = .../> </model> </vdb>
public class MyMetadataProcessor implements MetadataProcessor<Connection> { public static final String NAMESPACE = "{http://my.company.corp}"; @ExtensionMetadataProperty(applicable={Table.class}, datatype=String.class, display="File name", description="File Name", required=true) public static final String FILE_PROP = NAMESAPCE+"FILE"; public void process(MetadataFactory mf, Connection conn) { Object somedata = connection.getSomeMetadata(); Table table = mf.addTable(tableName); table.setProperty(FILE_PROP, somedata.getFileName()); Column col1 = mf.addColumn("col1", TypeFacility.RUNTIME_NAMES.STRING, table); column col2 = mf.addColumn("col2", TypeFacility.RUNTIME_NAMES.STRING, table); } }
- applicable: Metadata object this is applicable on. This is array of metadata classes like Table.class, Column.class.
- datatype: The java class indicating the data type
- display: Display name of the property
- description: Description about the property
- required: Indicates if the property is a required property
for (TableReference tr:query.getFrom()) { NamedTable t = (NameTable) tr; Table table = t.getMetadataObject(); String file = table.getProperty(FILE_PROP); .. }
- Reduces memory usage when returning the result set to the user.
- Improves performance by passing less data in the result set.
- Allows access to large objects when needed rather than assuming that users will always use the large object data.
- Allows the passing of arbitrarily large data values.
executionContext.keepExecutionAlive(true);
Chapter 6. Extending the Execution Factory Class
6.1. Extending the ExecutionFactory Class
org.teiid.translator.ExecutionFactory
class to connect and query a data source. This extended class must provide a constructor with no arguments that can be constructed using Java reflection libraries.
package org.teiid.translator.custom; @Translator(name="custom", description="Connect to My EIS") public class CustomExecutionFactory extends ExecutionFactory<MyConnectionFactory, MyConnection> { public CustomExecutionFactory() { } }
@Translator
on the extended "ExecutionFactory" class. This annotation defines the name and description of your translator, and is also used as an identifier during deployment. This is the name you would be using in the VDB and elsewhere in the configuration to refer to this translator.
MyConnectionFactory
specifies the type of ConnectionFactory interface that is expected from the associated resource adapter. This is required as part of the class definition when extending the ExecutionFactory
class.
MyConnection
specifies the type of Connection interface that is expected from the associated resource adapter. This is required as part of class definition when extending the ExecutionFactory
class.
6.2. Configuration Properties
- define a variable for every property as an attribute in the extended
ExecutionFactory
class, - define "get" and "set" methods for each attribute,
- and annotate each "get" method with
@TranslatorProperty
annotation and provide the metadata about the property.
foo
, by providing the annotation on these properties, JBoss Data Virtualization will automatically interrogate and provide a graphical way to configure your Translator while designing your VDB.
private String foo = "blah"; @TranslatorProperty(display="Foo property", description="description about Foo") public String getFoo() { return foo; } public void setFoo(String value) { return this.foo = value; }
int
, boolean
), primitive object wrapper (java.lang.Integer
), or Enum
types are supported as Translator properties. The default value will be derived from calling the getter, if available, on a newly constructed instance. All properties should have a default value. If there is no applicable default, then the property should be marked in the annotation as required. Initialization will fail if a required property value is not provided.
@TranslatorProperty
defines the following metadata that you can define about your property.
- display - the display name of the property.
- description - a description about the property.
- required - specifies that the property is required.
- advanced - an advanced property (a default value must be provided).
- masked - tools need to mask the property, that is, do not show it in plain text. Used for passwords.
Note
6.3. Initializing the Translator
start()
method if your translator needs to do any initialization before it is used by the JBoss Data Virtualization engine. This method must also call super.start()
to perform any initialization required by the superclass. This method is called by JBoss Data Virtualization once all the configuration properties are injected into the class.
6.4. Extended Translator Capabilities
supports
, that specify translator capabilities. These methods need to be overridden to describe the execution capabilities of the Translator. See Section 10.1, “Translator Capabilities” for more information about these methods.
6.5. Execution (and sub-interfaces)
createResultSetExecution
- Override if you are doing read based operation that is returning rows of results. For example, select.createUpdateExecution
- Override if you are doing write based operations. For example, insert, update, delete.createProcedureExecution
- Override if you are doing procedure based operations. For example, stored procedures. This works well for non-relational sources.
6.6. Metadata
public class MyMetadataProcessor implements MetadataProcessor<Connection> { public void process(MetadataFactory mf, Connection conn) { Object somedata = connection.getSomeMetadata(); Table table = mf.addTable(tableName); Column col1 = mf.addColumn("col1", TypeFacility.RUNTIME_NAMES.STRING, table); column col2 = mf.addColumn("col2", TypeFacility.RUNTIME_NAMES.STRING, table); //add a pushdown function that can also be evaluated in the engine Method method = ... Function f = mf.addFunction("func", method); //add a pushdown aggregate function that can also be evaluated in the engine Method aggMethod = ... Function af = mf.addFunction("agg", aggMethod); af.setAggregateAttributes(new AggregateAttributes()); ... } }
@TranslatorProperty(display="Column Name Pattern", category=PropertyType.IMPORT, description="Pattern to derive column names") public String getColumnNamePattern() { return columnNamePattern; } public void setColumnNamePattern(String columnNamePattern) { this.columnNamePattern = columnNamePattern; }
<vdb name="myvdb" version="1"> <model name="legacydata" type="PHYSICAL"> <property name="importer.ColumnNamePattern" value="col*"/> .... <source name = .../> </model> </vdb>
public class MyMetadataProcessor implements MetadataProcessor<Connection> { public static final String NAMESPACE = "{http://my.company.corp}"; @ExtensionMetadataProperty(applicable={Table.class}, datatype=String.class, display="File name", description="File Name", required=true) public static final String FILE_PROP = NAMESAPCE+"FILE"; public void process(MetadataFactory mf, Connection conn) { Object somedata = connection.getSomeMetadata(); Table table = mf.addTable(tableName); table.setProperty(FILE_PROP, somedata.getFileName()); Column col1 = mf.addColumn("col1", TypeFacility.RUNTIME_NAMES.STRING, table); column col2 = mf.addColumn("col2", TypeFacility.RUNTIME_NAMES.STRING, table); } }
- applicable: Metadata object this is applicable on. This is array of metadata classes like Table.class, Column.class.
- datatype: The java class indicating the data type
- display: Display name of the property
- description: Description about the property
- required: Indicates if the property is a required property
for (TableReference tr:query.getFrom()) { NamedTable t = (NameTable) tr; Table table = t.getMetadataObject(); String file = table.getProperty(FILE_PROP); .. }
6.7. Logging
org.teiid.logging.LogManager
class for logging purposes, based on the Apache Log4j logging services.
6.8. Exceptions
org.teiid.translator.TranslatorException
class.
6.9. Default Name
@Translator
on the ExecutionFactory
. After deployment, a default instance of this Translator can be used by any VDB by referencing it by this name in its vdb.xml
configuration file.
Note
6.10. Obtaining Connections
ExecutionFactory
must implement the getConnection()
method to allow the Connector Manager to obtain a connection.
6.11. Releasing Connections
closeConnection()
method is called on the ExecutionFactory
. You must override this method to close the connection properly.
Note
Chapter 7. Extending the JDBC Translator
7.1. Extensions
org.teiid.translator.jdbc.JDBCExecutionFactory
class in the translator-jdbc
module. There are three types of methods that you can override from the base class to define the behavior of the Translator.
Table 7.1. Extensions
Extension
|
Purpose
|
---|---|
Capabilities
|
Specify the SQL syntax and functions the source supports.
|
SQL Translation
|
Customize what SQL syntax is used, how source-specific functions are supported, how procedures are executed.
|
Results Translation
|
Customize how results are retrieved from JDBC and translated.
|
7.2. Capabilities Extension
7.3. SQL Translation Extension
- Change basic SQL syntax options. See the useXXX methods, e.g. useSelectLimit returns true for SQLServer to indicate that limits are applied in the SELECT clause.
- Register one or more FunctionModifiers that define how a scalar function is to be modified or transformed.
- Modify a LanguageObject (see the
translate
,translateXXX
, andFunctionModifiers.translate
methods). Modify the passed in object and return null to indicate that the standard syntax output will be used. - Change the way SQL strings are formed for a LanguageObject (see the
translate
,translateXXX
, andFunctionModifiers.translate
methods). Return a list of parts, which can contain strings and LanguageObjects, that will be appended in order to the SQL string. If the in coming LanguageObject appears in the returned list it will not be translated again.
7.4. Results Translation Extension
- Overriding the createXXXExecution to subclass the corresponding JDBCXXXExecution. The JDBCBaseExecution has protected methods to get the appropriate statement (getStatement, getPreparedStatement, getCallableStatement) and to bind prepared statement values bindPreparedStatementValues.
- Retrieve values from the JDBC ResultSet or CallableStatement - see the retrieveValue methods.
7.5. Adding Function Support
- Override the capabilities method to declare support for the function (REQUIRED)
- Implement a FunctionModifier to change how a function is translated and register it for use (OPTIONAL)
package my.connector; import java.util.ArrayList; import java.util.List; public class ExtendedJDBCExecutionFactory extends JDBCExecutionFactory { @Override public List getSupportedFunctions() { List supportedFunctions = new ArrayList(); supportedFunctions.addAll(super.getSupportedFunctions()); supportedFunctions.add("ABS"); return supportedFunctions; } }
7.6. Using Function Modifiers
FunctionModifier
for this purpose.
JDBCExecutionFactory.registerFunctionModifier
.
translate
. Use the translate method to change the way the function is represented.
public class ModFunctionModifier implements FunctionModifier { public List translate(Function function) { List parts = new ArrayList(); parts.add("("); Expression[] args = function.getParameters(); parts.add(args[0]); parts.add(" % "); parts.add(args[1]); parts.add(")"); return parts; } }
Table 7.2. Common Modifiers
Modifier
|
Description
|
---|---|
AliasModifier
|
Handles renaming a function ("ucase" to "upper" for example)
|
EscapeSyntaxModifier
|
Wraps a function in the standard JDBC escape syntax for functions: {fn xxxx()}
|
ExecutionFactory.registerFunctionModifier(String name, FunctionModifier modifier)
method.
public class ExtendedJDBCExecutionFactory extends JDBCExecutionFactory { @Override public void start() { super.start(); // register functions. registerFunctionModifier("abs", new MyAbsModifier()); registerFunctionModifier("concat", new AliasModifier("concat2")); } }
7.7. Installing Extensions
Chapter 8. Translator Development and Large Objects
8.1. Data Types
8.2. Why Use Large Object Support?
- Reduces memory usage when returning the result set to the user.
- Improves performance by passing less data in the result set.
- Allows access to large objects when needed rather than assuming that users will always use the large object data.
- Allows the passing of arbitrarily large data values.However, these benefits can only truly be gained if the Translator itself does not materialize an entire large object all at once. For example, the Java JDBC API supports a streaming interface for BLOB and CLOB data.
8.3. Handling Large Objects
ExecutionContext.keepAlive()
method.
executionContext.keepExecutionAlive(true);
8.4. Inserting or Updating Large Objects
Chapter 9. Other Considerations for Translator Development
9.1. Caching API
CacheDirective
object. Translators wishing to participate in caching should return a CacheDirective
from the ExecutionFactory.getCacheDirective
method, which is called prior to execution. The commands passed to getCacheDirective
will have already been vetted to ensure that the results are eligible for caching. For example update commands or commands with pushed dependent sets will not be eligible for caching.
CacheDirective
, which is the default implementation, the engine will not cache the translator results beyond the current command. It is up to your custom translator or custom delegating translator to implement your desired caching policy.
Note
Scope
to Scope.NONE
.
CacheDirective
will be set on the ExecutionContext
and is available via the ExecutionContext.getCacheDirective()
method. Having ExeuctionFactory.getCacheDirective
called prior to execution allows the translator to potentially be selective about which results to even attempt to cache. Since there is a resource overhead with creating and storing the cached results it may not be desirable to attempt to cache all results if it is possible to return large results that have a low usage factor. If you are unsure about whether to cache a particular command result you may return an initial CacheDirective
then change the Scope
to Scope.NONE
at any time prior to the final cache entry being created and the engine will give up creating the entry and release its resources.
Note
CacheDirective
during execution, return a new instance from the ExecutionFactory.getCacheDirective
call, rather than returning a shared instance.
CacheDirective
readAll Boolean field is used to control whether the entire result should be read if not all of the results were consumed by the engine. If readAll is false then any partial usage of the result will not result in it being added as a cache entry. Partial use is determined after any implicit or explicit limit has been applied. The other fields on the CacheDirective
object map to the cache hint options . See the table below for the default values for all options.
option
|
default
|
---|---|
scope
|
Session
|
ttl
|
rs cache ttl
|
readAll
|
true
|
updatable
|
true
|
prefersMemory
|
false
|
9.2. Dependent Join Pushdown
Comparison
with a Parameter
, may be ignored in part or in total. Pushdown dependent join queries will be instances of Select
with the relevant dependent sets available via Select.getDependentSets()
. The dependent set is associated to Parameters by id via the Parameter.getDepenentValueId()
identifier. The dependent set tuple iterators provide rows that are referenced by the column positions (available via Parameter.getValueIndex()
) on the dependent join Comparison criteria right expression. Care should be taken with the tuple values as they may guaranteed to be unique or ordered.
Note
9.3. Delegating Translator
BaseDelegatingExecutionFactory
. Within this subclass, delegation methods can be overridden to perform the common functionality.
@Translator(name="custom-delegator") public class MyTranslator extends BaseDelegatingExecutionFactory<Object, Object> { @Override public Execution createExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, Object connection) throws TranslatorException { if (command instanceof Select) { //modify the command or return a different execution ... } //the super call will be to the delegate instance return super.createExecution(command, executionContext, metadata, connection); } ... }
<translator type="custom-delegator" name="my-translator"> <property value="delegateName" name="name of the delegate instance"/> <!-- any custom properties you may have on your custom translator --> </translator>
Note
BaseDelegatingExecutionFactory
by default means that standard override translator property settings on your instance will have no effect, since the underlying delegate is called instead.
DelegatingExecutionFactory
instead.
9.4. Adding Dependent Modules
Dependencies: org.jboss.teiid.common-core,org.jboss.teiid.api,javax.api
Chapter 10. Translator Capabilities
10.1. Translator Capabilities
ExecutionFactory
class defines all the methods that describe the capabilities of a Translator. These are used by the Connector Manager to determine what kinds of commands the translator is capable of executing. A base ExecutionFactory
class implements all the basic capabilities methods, which says your translator does not support any capabilities. Your extended ExecutionFactory
class must override the necessary methods to specify which capabilities your translator supports. You should consult the debug log of query planning (set showplan debug) to see if desired pushdown requires additional capabilities.
Note
10.2. Translator Capabilities
@TranslatorProperty(display="Copy LOBs",description="If true, returned LOBs will be copied, rather than streamed from the source",advanced=true) public boolean isCopyLobs() { return copyLobs; } public void setCopyLobs(boolean copyLobs) { this.copyLobs = copyLobs; }
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <vdb name="vdb" version="1"> <model name="PM1"> <source name="connector" translator-name="my-translator-override" /> </model> <translator name="my-translator-override" type="my-translator"> <property name="CopyLobs" value="true" /> </translator> </vdb>
@Translator(name = "my-translator", description = "My Translator") public class MyExecutionFactory extends ExecutionFactory<ConnectionFactory, MyConnection> { ... public MetadataProcessor<C> getMetadataProcessor() { return MyMetadataProcessor(); } } public MyMetadataProcessor implements MetadataProcessor<MyConnection> { public void process(MetadataFactory metadataFactory, MyConnection connection) throws TranslatorException{ // schema generation code here } @TranslatorProperty(display="Header Row Number", category=PropertyType.IMPORT, description="Row number that contains the header information") public int getHeaderRowNumber() { return headerRowNumber; } public void setHeaderRowNumber(int headerRowNumber) { this.headerRowNumber = headerRowNumber; } }
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <vdb name="vdb" version="1"> <model name="PM1"> <property name="importer.HeaderRowNumber" value="12"/> <source name="connector" translator-name="my-translator" /> </model> </vdb>
Note
public class MyMetadataProcessor implements MetadataProcessor<MyConnection> { public static final String URI = "{http://www.teiid.org/translator/mytranslator/2014}"; @ExtensionMetadataProperty(applicable=Table.class, datatype=String.class, display="Encoding", description="Encoding", required=true) public static final String ENCODING = URI+"encode"; public void process(MetadataFactory mf, FileConnection conn) throws TranslatorException { .. Table t = mf.addTable(tableName); t.setProperty(ENCODING, "UTF-16"); // add columns etc. .. } }
Select select = (Select)command; NamedTable tableReferece = select.getFrom().get(0); Table t = tableReference.getMetadataObject(); String encoding = t.getProperty(MyMetadataProcessor.ENCODING, false); // use the encoding value as needed to marshal or unmarshal data
Note
10.3. Available Capabilities
ExecutionFactory
class.
Table 10.1. Available Capabilities
Capability
|
Requires
|
Description
|
---|---|---|
SelectDistinct
| |
Translator can support SELECT DISTINCT in queries.
|
SelectExpression
| |
Translator can support SELECT of more than column references.
|
AliasedTable
| |
Translator can support Tables in the FROM clause that have an alias.
|
InnerJoins
| |
Translator can support inner and cross joins
|
SelfJoins
|
AliasedGroups and at least on of the join type supports.
|
Translator can support a self join between two aliased versions of the same Table.
|
OuterJoins
| |
Translator can support LEFT and RIGHT OUTER JOIN.
|
FullOuterJoins
| |
Translator can support FULL OUTER JOIN.
|
DependentJoins
|
Base join and criteria support
|
Translator supports key set dependent join pushdown (see Section 9.2, “Dependent Join Pushdown”). When set, the MaxDependentInPredicates and MaxInCriteriaSize values are not used by the engine, rather all independent values are made available to the pushdown command.
|
SubqueryInOn
|
Join and base subquery support, such as ExistsCriteria
|
Translator can support subqueries in the ON clause. Defaults to true.
|
InlineViews
|
AliasedTable
|
Translator can support a named subquery in the FROM clause.
|
BetweenCriteria
| |
Not currently used - between criteria is rewritten as compound comparisons.
|
CompareCriteriaEquals
| |
Translator can support comparison criteria with the operator "=".
|
CompareCriteriaOrdered
| |
Translator can support comparison criteria with the operator ">" or "<".
|
LikeCriteria
| |
Translator can support LIKE criteria.
|
LikeCriteriaEscapeCharacter
|
LikeCriteria
|
Translator can support LIKE criteria with an ESCAPE character clause.
|
SimilarTo
| |
Translator can support SIMILAR TO criteria.
|
LikeRegexCriteria
| |
Translator can support LIKE_REGEX criteria.
|
InCriteria
|
MaxInCriteria
|
Translator can support IN predicate criteria.
|
InCriteriaSubquery
| |
Translator can support IN predicate criteria where values are supplied by a subquery.
|
IsNullCriteria
| |
Translator can support IS NULL predicate criteria.
|
OrCriteria
| |
Translator can support the OR logical criteria.
|
NotCriteria
| |
Translator can support the NOT logical criteria. IMPORTANT: This capability also applies to negation of predicates, such as specifying IS NOT NULL, "<=" (not ">"), ">=" (not "<"), etc.
|
ExistsCriteria
| |
Translator can support EXISTS predicate criteria.
|
QuantifiedCompareCriteriaAll
| |
Translator can support a quantified comparison criteria using the ALL quantifier.
|
QuantifiedCompareCriteriaSome
| |
Translator can support a quantified comparison criteria using the SOME or ANY quantifier.
|
OnlyLiteralComparison
| |
Translator if only Literal comparisons (equality, ordered, like, etc.) are supported for non-join conditions.
|
Convert(int fromType, int toType)
| |
Used for fine grained control of convert/cast pushdown. The
ExecutionFactory.getSupportedFunctions() should contain SourceSystemFunctions.CONVERT . This method can then return false to indicate a lack of specific support. See TypeFacility.RUNTIME_CODES for the possible type codes. The engine will does not care about an unnecessary conversion where fromType == toType. By default lob conversion is disabled.
|
OrderBy
| |
Translator can support the ORDER BY clause in queries.
|
OrderByUnrelated
|
OrderBy
|
Translator can support ORDER BY items that are not directly specified in the select clause.
|
OrderByNullOrdering
|
OrderBy
|
Translator can support ORDER BY items with NULLS FIRST/LAST.
|
GroupBy
| |
Translator can support an explicit GROUP BY clause.
|
Having
|
GroupBy
|
Translator can support the HAVING clause.
|
AggregatesAvg
| |
Translator can support the AVG aggregate function.
|
AggregatesCount
| |
Translator can support the COUNT aggregate function.
|
AggregatesCountStar
| |
Translator can support the COUNT(*) aggregate function.
|
AggregatesDistinct
|
At least one of the aggregate functions.
|
Translator can support the keyword DISTINCT inside an aggregate function. This keyword indicates that duplicate values within a group of rows will be ignored.
|
AggregatesMax
| |
Translator can support the MAX aggregate function.
|
AggregatesMin
| |
Translator can support the MIN aggregate function.
|
AggregatesSum
| |
Translator can support the SUM aggregate function.
|
AggregatesEnhancedNumeric
| |
Translator can support the VAR_SAMP, VAR_POP, STDDEV_SAMP, STDDEV_POP aggregate functions.
|
ScalarSubqueries
| |
Translator can support the use of a subquery in a scalar context (wherever an expression is valid).
|
CorrelatedSubqueries
|
At least one of the subquery pushdown capabilities.
|
Translator can support a correlated subquery that refers to an element in the outer query.
|
CaseExpressions
| |
Not currently used - simple case is rewritten as searched case.
|
SearchedCaseExpressions
| |
Translator can support "searched" CASE expressions anywhere that expressions are accepted.
|
Unions
| |
Translator support UNION and UNION ALL
|
Intersect
| |
Translator supports INTERSECT
|
Except
| |
Translator supports Except
|
SetQueryOrderBy
|
Unions, Intersect, or Except
|
Translator supports set queries with an ORDER BY
|
RowLimit
| |
Translator can support the limit portion of the limit clause
|
RowOffset
| |
Translator can support the offset portion of the limit clause
|
FunctionsInGroupBy
|
GroupBy
|
Translator can support non-column reference grouping expressions.
|
InsertWithQueryExpression
| |
Translator supports INSERT statements with values specified by a QueryExpression.
|
BatchedUpdates
| |
Translator supports a batch of INSERT, UPDATE and DELETE commands to be executed together.
|
BulkUpdate
| |
Translator supports updates with multiple value sets
|
CommonTableExpressions
| |
Translator supports the WITH clause.
|
ElementaryOlapOperations
| |
Translator supports window functions and analytic functions RANK, DENSE_RANK, and ROW_NUMBER.
|
WindowOrderByWithAggregates
|
ElementaryOlapOperations
|
Translator supports windowed aggregates with a window order by clause.
|
WindowDistinctAggregates
|
ElementaryOlapOperations, AggregatesDistinct
|
Translator supports windowed distinct aggregates.
|
AdvancedOlapOperations
|
ElementaryOlapOperations
|
Translator supports aggregate conditions.
|
OnlyFormatLiterals
|
function support for a parse/format function and an implementation of the supportsFormatLiteral method.
|
Translator supports only literal format patterns that must be validated by the supportsFormatLiteral method
|
FormatLiteral(String literal, Format type)
|
OnlyFormatLiterals
|
Translator supports the given literal format string.
|
ArrayType
| |
Translator supports the push down of array values.
|
OnlyCorrelatedSubqueries
|
CorrelatedSubqueries
|
Translator ONLY supports correlated subqueries. Uncorrelated scalar and exists subqueries will be pre-evaluated prior to push-down.
|
SelectWithoutFrom
|
SelectExpressions
|
Translator supports selecting values without a FROM clause, such as SELECT 1.
|
Note
10.4. Command Form
ExecutionFactory.useAnsiJoin()
should return true if the Translator prefers the use of ANSI style join structure for join trees that contain only INNER and CROSS joins.
ExecutionFactory.requiresCriteria()
should return true if the Translator requires criteria for any Query, Update, or Delete. This is a replacement for the model support property "Where All".
10.5. Scalar Functions
ExecutionFactory.getSupportedFunctions()
can be used to specify which scalar and aggregate functions the Translator supports. The set of possible functions is based on the set of functions supported by JBoss Data Virtualization. This set can be found in the JBoss Data Virtualization Reference Guide. If the Translator states that it supports a function, it must support all type combinations and overloaded forms of that function.
ExecutionFactory.getPushDownFunctions()
list as FunctionMethod
metadata objects. The FuncitonMethod
representation allow the translator to control all of the metadata related to the function, including type signature, determinism, varargs, etc. The simplest way to add a pushdown function is with a call to ExecutionFactory.addPushDownFunction
:
FunctionMethod addPushDownFunction(String qualifier, String name, String returnType, String...paramTypes)
FunctionMethod
object may be further manipulated depending upon the needs of the source. An example of adding a custom concat vararg function in an ExecutionFactory
subclass:
public void start() throws TranslatorException { super.start(); FunctionMethod func = addPushDownFunciton("oracle", "concat", "string", "string", "string"); func.setVarArgs(true); ... }
10.6. Physical Limits
ExecutionFactory.getMaxInCriteriaSize()
can be used to specify the maximum number of values that can be passed in an IN criteria. This is an important constraint as an IN criteria is frequently used to pass criteria between one source and another using a dependent join.
ExecutionFactory.getMaxDependentInPredicates()
is used to specify the maximum number of IN predicates (of at most MaxInCriteriaSize) that can be passed as part of a dependent join. For example if there are 10000 values to pass as part of the dependent join and a MaxInCriteriaSize of 1000 and a MaxDependentInPredicates setting of 5, then the dependent join logic will form two source queries each with 5 IN predicates of 1000 values each combined by OR.
ExecutionFactory.getMaxFromGroups()
can be used to specify the maximum number of FROM Clause groups that can used in a join. -1 indicates there is no limit.
10.7. Update Execution Modes
ExecutionFactory.supportsBatchedUpdates()
can be used to indicate that the Translator supports executing the BatchedUpdates
command.
ExecutionFactory.supportsBulkUpdate()
can be used to indicate that the Translator accepts update commands containg multi valued Literals.
Note
10.8. Null Ordering
ExecutionFactory.getDefaultNullOrder()
specifies the default null order. It can be one of UNKNOWN, LOW, HIGH, FIRST, LAST. This is only used if ORDER BY is supported, but null ordering is not.
ExecutionFactory.getCollation()
specifies the default collation. If you set it to a value that does not match the collation locale defined by org.teiid.collationLocale, then some ordering may not be pushed down.
Chapter 11. Packaging and Deploying the Translator
11.1. Packaging
org.teiid.translator.custom.CustomExecutionFactory
11.2. Translator Deployment Overview
11.3. Module Deployment
standalone.xml
file or domain.xml
file and restart the server. The dependent JBoss Data Virtualization or any other Java class libraries must be defined in module.xml file of the module. For production profiles this is recommended.
Example 11.1. Example module.xml
file
module.xml
file provided for the Salesforce translator. This file is located in the EAP_HOME/docs/teiid/datasources/salesforce/modules/org/springframework/spring/main
directory.
<module xmlns="urn:jboss:module:1.0" name="org.springframework.spring"> <resources> <resource-root path="spring-beans.jar"/> <resource-root path="spring-context.jar"/> <resource-root path="spring-core.jar"/> </resources> <dependencies> <module name="javax.api"/> </dependencies> </module>
11.4. JAR Deployment
Example 11.2. Example MANIFEST.mf
file
/META-INF/MANIFEST.mf
file provided in the Salesforce translator JAR file, EAP_HOME/modules/system/layers/dv/org/jboss/teiid/translator/salesforce/main/translator-salesforce[VERSION].jar
.
Manifest-Version: 1.0 Build-Timestamp: Wed, 30 Oct 2013 07:24:14 -0400 Implementation-Title: Salesforce Translator Implementation-Version: 8.4.1-redhat-4 Os-Version: 2.6.32-358.18.1.el6.x86_64 Built-By: mockbuild Specification-Vendor: JBoss by Red Hat Created-By: Apache Maven Os-Name: Linux Implementation-URL: http://www.jboss.org/ip-parent/teiid-parent/connec tors/translator-salesforce Java-Vendor: Sun Microsystems Inc. Implementation-Vendor: JBoss by Red Hat Scm-Revision: d19b010480ee51efe9f82956d8775e1a604657fd Implementation-Vendor-Id: org.jboss.teiid.connectors Scm-Url: http://github.com/jboss/jboss-parent-pom/ip-parent/teiid-pare nt/connectors/translator-salesforce Build-Jdk: 1.6.0_24 Java-Version: 1.6.0_24 Scm-Connection: scm:git:git@github.com:jboss/jboss-parent-pom.git/ip-p arent/teiid-parent/connectors/translator-salesforce Os-Arch: i386 Specification-Title: Salesforce Translator Specification-Version: 8.4.1-redhat-4 Archiver-Version: Plexus Archiver
Chapter 12. User Defined Functions
12.1. User Defined Functions
- Function Name - When you create the function name, keep these requirements in mind:
- You cannot overload existing JBoss Data Virtualization functions.
- The function name must be unique among user-defined functions in its model for the number of arguments. You can use the same function name for different numbers of types of arguments. Hence, you can overload your user-defined functions.
- The function name cannot contain the '.' character.
- The function name cannot exceed 255 characters.
- Input Parameters - defines a type specific signature list. All arguments are considered required.
- Return Type - the expected type of the returned scalar value.
- Pushdown - can be one of REQUIRED, NEVER, ALLOWED. Indicates the expected pushdown behavior. If NEVER or ALLOWED are specified then a Java implementation of the function should be supplied. If REQUIRED is used, then user must extend the Translator for the source and add this function to its pushdown function library.
- invocationClass/invocationMethod - optional properties indicating the static method to invoke when the UDF is not pushed down.
- Deterministic - if the method will always return the same result for the same input parameters. Defaults to false. It is important to mark the function as deterministic if it returns the same value for the same inputs as this will lead to better performance. See also the Relational extension boolean metadata property "deterministic" and the DDL OPTION property "determinism".
Note
12.2. Support for Non-Pushdown User Defined Functions
12.2.1. Non-Pushdown UDF Metadata in Teiid Designer
12.2.2. Non-Pushdown UDF Metadata for Dynamic VDBs
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="VIRTUAL"> <metadata type="DDL"><![CDATA[ CREATE VIRTUAL FUNCTION celsiusToFahrenheit(celsius decimal) RETURNS decimal OPTIONS (JAVA_CLASS 'org.something.TempConv', JAVA_METHOD 'celsiusToFahrenheit'); CREATE VIRTUAL FUNCTION sumAll(arg integer) RETURNS integer OPTIONS (JAVA_CLASS 'org.something.SumAll', JAVA_METHOD 'addInput', AGGREGATE 'true', VARARGS 'true', "NULL-ON-NULL" 'true');]]> </metadata> </model> </vdb>
12.2.3. Coding Non-Pushdown Functions
12.2.3.1. UDF Coding
- The Java class containing the function method must be defined public.
Note
You can declare multiple user defined functions for a given class. - The function method must be public and static.
Example 12.1. Sample UDF Code
package org.something; public class TempConv { /** * Converts the given Celsius temperature to Fahrenheit, and returns the * value. * @param doubleCelsiusTemp * @return Fahrenheit */ public static Double celsiusToFahrenheit(Double doubleCelsiusTemp) { if (doubleCelsiusTemp == null) { return null; } return (doubleCelsiusTemp)*9/5 + 32; } }
12.2.3.2. UDAF Coding
- The Java class containing the function method must be defined public and extend
org.teiid.UserDefinedAggregate
. - The function method must be public.
Example 12.2. Sample UDAF Code
package org.something; public static class SumAll implements UserDefinedAggregate<Integer> { private boolean isNull = true; private int result; public void addInput(Integer... vals) { isNull = false; for (int i : vals) { result += i; } } @Override public Integer getResult(org.teiid.CommandContext commandContext) { if (isNull) { return null; } return result; } @Override public void reset() { isNull = true; result = 0; } }
12.2.3.3. Coding: Other Considerations
- Number of input arguments and types must match the function metadata defined in Section 12.1, “User Defined Functions”.
- Any exception can be thrown, but JBoss Data Virtualization will throw the exception as a
FunctionExecutionException
. - You may optionally add an additional
org.teiid.CommandContext
argument as the first parameter. TheCommandContext
interface provides access to information about the current command, such as the executing user, subject, the VDB, the session id, etc. ThisCommandContext
parameter should not be declared in the function metadata.
Example 12.3. Sample CommandContext
Usage
package org.something; public class SessionInfo { /** * @param context * @return the created Timestamp */ public static Timestamp sessionCreated(CommandContext context) { return new Timestamp(context.getSession().getCreatedTime()); } }
Timestamp sessionCreated()
.
12.2.3.4. Post Coding Activities
- After coding the functions, compile the Java code into a Java Archive (JAR) file.
- Create a JBoss EAP module (
module.xml
) accompanying the JAR file in theEAP_HOME/modules/
directory. - Add the module dependency to the
DATABASE-vdb.xml
file as shown in the example below.<vdb name="{vdb-name}" version="1"> <property name ="lib" value ="{module-name}"></property> ... </vdb>
Thelib
property value may contain a space delimited list of module names if more than one dependency is needed.Note
Alternatively, when using a VDB created with Teiid Designer (DATABASE.vdb
), the JAR file may be placed in your VDB under the/lib
directory. It will be added automatically to the VDB classloader.
12.3. Source Supported Functions
SELECT score(1), ID, FREEDATA FROM Docs WHERE contains(freedata, 'nick', 1) > 0
score
and contains
functions are not part of built-in scalar function library. While you could write your own custom scalar function to mimic their behavior, it is more likely that you would want to use the actual Oracle functions that are provided by Oracle when using the Oracle Free Text functionality.
12.3.1. Defining a Source Supported Function by Extending the Translator
- Required - extend the OracleExecutionFactory and add SCORE and CONTAINS as supported pushdown functions by either overriding or adding additional functions in "getPushDownFunctions" method. For this example, we'll call the class MyOracleExecutionFactory. Add the
org.teiid.translator.Translator
annotation to the class, e.g.@Translator(name="myoracle")
- Optionally register new FunctionModifiers on the start of the ExecutionFactory to handle translation of these functions. Given that the syntax of these functions is same as other typical functions, this probably is not needed - the default translation should work.
- Create a new translator JAR containing your custom ExecutionFactory. Refer to Section 11.1, “Packaging” and Section 11.2, “Translator Deployment Overview” for instructions on using the JAR file. Once this extended translator is deployed in JBoss Data Virtualization, use "myoracle" as translator name instead of the "oracle" in your VDB's Oracle source configuration.
12.3.2. Defining a Source Supported Function via Teiid Designer
Note
12.3.3. Defining a Source Supported Function Using Dynamic VDBs
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="PHYSICAL"> <source name="AccountsDB" translator-name="oracle" connection-jndi-name="java:/oracleDS"/> <metadata type="DDL"><![CDATA[ CREATE FOREIGN FUNCTION SCORE (val integer) RETURNS integer; .... (other tables, procedures etc) ]]> </metadata> </model> </vdb>
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="PHYSICAL"> <source name="AccountsDB" translator-name="oracle" connection-jndi-name="java:/oracleDS"/> <metadata type="NATIVE,DDL"><![CDATA[ CREATE FOREIGN FUNCTION SCORE (val integer) RETURNS integer; ]]> </metadata> </model> </vdb>
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="PHYSICAL"> <source name="AccountsDB" translator-name="oracle" connection-jndi-name="java:/oracleDS"/> <metadata type="{metadata-repo-module}"></metadata> </model> </vdb>
Chapter 13. Admin API
13.1. Admin API
org.teiid.adminapi
package.
13.2. Connecting
org.teiid.adminapi.Admin
interface, is obtained through the org.teiid.adminapi.AdminFactory.createAdmin
methods. AdminFactory
is a singleton, see AdminFactory.getInstance()
. The Admin
instance automatically tests its connection and reconnects to a server in the event of a failure. The close
method should be called to terminate the connection.
13.3. Administration Methods
Chapter 14. Custom Logging
14.1. Customized Logging
standalone.xml
or domain.xml
configuration file and the "logging" subsystem. Refer to the Red Hat JBoss Data Virtualization Administration and Configuration Guide for more details about the different contexts available.
14.2. Command Logging API
java.util.logging.LogRecord
s to the "COMMAND_LOG" context, the handler will receive a message that is an instance of LogRecord
. This object will contain a parameter of type org.teiid.logging.CommandLogMessage
. The relevant JBoss Data Virtualization classes are defined in the teiid-api-[versionNumber].jar
. The CommandLogMessage includes information about VDB, session, command SQL, etc. CommandLogMessages are logged at the DEBUG level. An example follows.
package org.something; import java.util.logging.Handler; import java.util.logging.LogRecord; public class CommandHandler extends Handler { @Override public void publish(LogRecord record) { CommandLogMessage msg = (CommandLogMessage)record.getParameters()[0]; //log to a database, trigger an email, etc. } @Override public void flush() { } @Override public void close() throws SecurityException { } }
14.3. Audit Logging API
java.util.logging.LogRecord
s to the "AUDIT_LOG" context, the handler will receive a message that is an instance of LogRecord
. This object will contain a parameter of type org.teiid.logging.AuditMessage
. The relevant JBoss Data Virtualization classes are defined in the teiid-api-[versionNumber].jar
. AuditMessages are logged at the DEBUG level. An example follows.
package org.something; import java.util.logging.Handler; import java.util.logging.LogRecord; public class AuditHandler extends Handler { @Override public void publish(LogRecord record) { AuditMessage msg = (AuditMessage)record.getParameters()[0]; //log to a database, trigger an email, etc. } @Override public void flush() { } @Override public void close() throws SecurityException { } }
14.4. Configuration
module.xml
file in the same directory and add
<resource-root path="{your-jar-name}.jar" />
standalone.xml
or domain.xml
file, locate the "logging" subsystem and add the following entries.
<custom-handler name="COMMAND" class="org.teiid.logging.CommandHandler" module="org.jboss.teiid"> </custom-handler> ..other entries <logger category="org.teiid.COMMAND_LOG"> <level name="DEBUG"/> <handlers> <handler name="COMMAND"/> </handlers> </logger>
Chapter 15. Runtime Updates
15.1. Data Updates
org.teiid.events.EventDistributorFactory
and org.teiid.events.EventDistributor
can be used to distribute change events. The EventDistributorFactory
can be looked up by its name "teiid/event-distributor-factory". See the example below.
InitialContext ctx = new InitialContext(); EventDistributorFactory edf = (EventDistributorFactory)ctx.lookup("teiid/event-distributor-factory"); EventDistributor ed = edf.getEventDistributor(); ed.dataModification(vdbName, vdbVersion, schema, tableName);
EventDistributor
methods to manually distribute other events is not always necessary. See System Procedures in Red Hat JBoss Development Guide: Reference Material for SQL based updates.
Note
org.teiid.events.EventDistributor
interface you can also update runtime metadata. Refer to the API.
15.2. Runtime Metadata Updates
org.teiid.metadata.MetadataRepository
.
MetadataRepository
can be installed via the VDB file.
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="VIRTUAL"> <metadata type="{jboss-as-module-name}"></metadata> </model> </vdb>
org.teiid.metadata.MetadataRepository
interface and defines file "META-INF/services/org.teiid.metadata.MetadataRepository" with name of the implementation file.
MetadataRepository
repository instance may fully implement as many of the methods as needed and return null from any unneeded getter.
Note
org.teiid.metadata.AbstractMetadataRecord
instances. System procedures and DDL statements should be used instead since the effects will be distributed through the cluster and will not introduce inconsistencies.
org.teiid.metadata.AbstractMetadataRecord
objects passed to the MetadataRepository
have not yet been modified. If the MetadataRepository
cannot persist the update, then a RuntimeException
should be thrown to prevent the update from being applied by the runtime engine.
Note
15.3. Costing Updates
SYSADMIN.setColumnStats
and SYSADMIN.setTableStats
. To make costing updates persistent MetadataRepository
implementations should be provided for the following methods:
TableStats getTableStats(String vdbName, int vdbVersion, Table table); void setTableStats(String vdbName, int vdbVersion, Table table, TableStats tableStats); ColumnStats getColumnStats(String vdbName, int vdbVersion, Column column); void setColumnStats(String vdbName, int vdbVersion, Column column, ColumnStats columnStats);
15.4. Schema Updates
String getViewDefinition(String vdbName, int vdbVersion, Table table); void setViewDefinition(String vdbName, int vdbVersion, Table table, String viewDefinition); String getInsteadOfTriggerDefinition(String vdbName, int vdbVersion, Table table, Table.TriggerEvent triggerOperation); void setInsteadOfTriggerDefinition(String vdbName, int vdbVersion, Table table, Table.TriggerEvent triggerOperation, String triggerDefinition); boolean isInsteadOfTriggerEnabled(String vdbName, int vdbVersion, Table table, Table.TriggerEvent triggerOperation); void setInsteadOfTriggerEnabled(String vdbName, int vdbVersion, Table table, Table.TriggerEvent triggerOperation, boolean enabled); String getProcedureDefinition(String vdbName, int vdbVersion, Procedure procedure); void setProcedureDefinition(String vdbName, int vdbVersion, Procedure procedure, String procedureDefinition); LinkedHashMap<String, String> getProperties(String vdbName, int vdbVersion, AbstractMetadataRecord record); void setProperty(String vdbName, int vdbVersion, AbstractMetadataRecord record, String name, String value);
Chapter 16. Custom Metadata Repository
16.1. Custom Metadata Repository
16.2. NATIVE
Example 16.1. Sample vdb.xml file
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="PHYSICAL"> <source name="AccountsDB" translator-name="oracle" connection-jndi-name="java:/oracleDS"/> <metadata type="NATIVE"></metadata> </model> </vdb>
Note
getMetadata
method on the ExecutionFactory
class, NATIVE uses this method to retrieve the metadata from source.
16.3. DDL
Example 16.2. Sample vdb.xml file
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="PHYSICAL"> <source name="AccountsDB" translator-name="oracle" connection-jndi-name="java:/oracleDS"/> <metadata type="DDL"> **DDL Here** </metadata> </model> </vdb>
16.4. FILE
Example 16.3. Sample vdb.xml file
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="PHYSICAL"> <source name="AccountsDB" translator-name="oracle" connection-jndi-name="java:/oracleDS"/> <metadata type="DDL-FILE">/accounts.ddl</metadata> </model> </vdb>
16.5. Custom
- Users can write metadata facility that is based on reading data from database or a JCR repository or so forth. Here is an example:
package com.something; import org.teiid.metadata.MetadataRepository; ... public class CustomMetadataRepository extends MetadataRepository { @Override public void loadMetadata(MetadataFactory factory, ExecutionFactory executionFactory, Object connectionFactory) throws TranslatorException { /* Provide implementation and fill the details in factory */ ... } }
- Build a JAR archive with above implementation class and create file named org.teiid.metadata.MetadataRepository in the META-INF/services directory with these contents:
com.something.CustomMetadataRepository
- Deploy the JAR to Red Hat JBoss EAP as a module under the modules directory. Follow the below steps to create a module.
- Create a directory called modules/com/something/main.
- Under this directory create a "module.xml" file that looks like:
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="com.something"> <resources> <resource-root path="something.jar" /> </resources> <dependencies> <module name="javax.api"/> <module name="javax.resource.api"/> <module name="org.jboss.teiid.common-core"/> <module name="org.jboss.teiid.teiid-api" /> </dependencies> </module>
- Copy the jar file under this same directory. Make sure you add any additional dependencies if required by your implementation class under dependencies.
- Restart the server.
Example 16.4. Sample vdb.xml file
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="PHYSICAL"> <source name="AccountsDB" translator-name="oracle" connection-jndi-name="java:/oracleDS"/> <metadata type="{metadata-repo-module}"></metadata> </model> </vdb>
Important
16.6. Using Multiple Importers
<vdb name="{vdb-name}" version="1"> <model name="{model-name}" type="PHYSICAL"> <source name="AccountsDB" translator-name="oracle" connection-jndi-name="java:/oracleDS"/> <metadata type="NATIVE,DDL"> **DDL Here** </metadata> </model> </vdb>
16.7. Development Considerations
MetadataRepository
instances are created on a per VDB basis and may be called concurrently for the load of multiple models.
- See the
MetadataFactory
and theorg.teiid.metadata
package javadocs for metadata construction methods and objects. For example if you use your own DDL, then call theMetadataFactory.parse(Reader)
method. If you need access to files in a VDB zip deployment, then use theMetadataFactory.getVDBResources
method.
- Use the
MetadataFactory.addPermission
and addMetadataFactory.addColumnPermission
method to grant permissions on the given metadata objects to the named roles. The roles should be declared in your vdb.xml, which is also where they are typically tied to container roles.
16.8. Preparser
import org.teiid.PreParser; ... package com.something; public class CustomPreParser implements PreParser { @Override public String preParse(String command, CommandContext context) { //manipulate the command } }
com.something.CustomPreParser
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="com.something"> <resources> <resource-root path="something.jar" /> </resources> <dependencies> <module name="javax.api"/> <module name="javax.resource.api"/> <module name="org.jboss.teiid.common-core"/> <module name="org.jboss.teiid.teiid-api" /> </dependencies> </module>
Important
Appendix A. Executing Commands
A.1. Execution Modes
ExecutionFactory
class to obtain the Execution
interface for the command it is executing. The query is sent to the translator as a set of objects. Refer to Section B.1, “Language” for more information.
Table A.1. Types of Execution Modes
Execution Interface | Command interface(s) | Description |
---|---|---|
ResultSetExecution | QueryExpression | A query corresponding to a SQL SELECT or set query statement. |
UpdateExecution | Insert, Update, Delete, BatchedUpdates | An insert, update, or delete, corresponding to a SQL INSERT, UPDATE, or DELETE command |
ProcedureExecution | Call | A procedure execution that may return a result set and/or output values. |
Execution
interface that defines how executions are canceled and closed. ProcedureExecution also extends ResultSetExecution, since procedures may also return resultsets.
A.2. ExecutionContext
org.teiid.translator.ExecutionContext
class provides information related to the current execution. An instance of ExecutionContext
is available for each Execution
. Various 'get' methods are provided; for example, ExecutionContext.getRequestIdentifier()
and ExecutionContext.getSession()
are provided for logging purposes. Specific usage is highlighted in this guide where applicable.
A.3. Generated Keys
CommandContext.isReturnAutoGeneratedKeys()
method. If you wish to return generated keys, you must first create a GeneratedKeys
instance to hold the keys with the returnGeneratedKeys
method passing the column names and types of the key columns. Only one GeneratedKeys
may be associated with the CommandContext
at any given time.
A.4. Source Hints
getGeneralHint
and getSourceHint
. See the source for the OracleExecutionFactory
for an example of how this source hint information can be utilized.
A.5. ResultSetExecution
ResultSetExecution.next()
method. This method returns null to indicate the end of results. Note: the expected batch size can be obtained using the ExecutionContext.getBatchSize()
method and used as a hint in fetching results from the EIS.
A.6. Update Execution
ExecutionContext.isTransactional()
method can be used to determine if the execution is already under a transaction.
A.7. Procedure Execution
getOutputParameterValues()
method.
A.8. Asynchronous Executions
DataNotAvailableException
is thrown during a retrieval method, rather than explicitly waiting or sleeping for the results.
Note
DataNotAvailableException
should not be thrown by the execute method, as that can result in the execute method being called multiple times. The DataNotAvailableException
may take a delay parameter or a Date
in its constructor to indicate when to poll next for results. Any non-negative delay value indicates the time in milliseconds until the next polling should be performed.
DataNotAvailableException.NO_POLLING
exception (or any DataNotAvailableException with a negative delay) can be thrown so that processing will resume (via ExecutionContext.dataAvailable()
).
DataNotAvailableException
is consumed while the engine thinks more work can be performed or there are other shorter delays issued from other translators, then the plan may be queued again earlier than expected. You should throw a DataNotAvailableException
again if your execution is not yet ready. Alternatively the DataNotAvailableException
may be marked as strict, which does provide a guarantee that the Execution
will not be called until the delay has expired or the given Date
has been reached. Using the Date
constructor makes the DataNotAvailableException
automatically strict. Due to engine thread pool contention, platform time resolution, etc. a strict DataNotAvailableException
is not a real-time guarantee of when the next poll for results will occur, only that it will not occur before then.
Note
ExecutionFactory
returns only asynch executions that perform minimal work, then consider having ExecutionFactory.isForkable
return false so that the engine knows not to spawn a separate thread for accessing your Execution
.
A.9. Reusable Executions
ReusableExecutions
for the expected Execution objects. There can be one ReusableExecution
per query executing node in the processing plan. The lifecycle of a ReusableExecution
is different that a normal Execution
. After a normal creation/execute/close cycle the ReusableExecution.reset
is called for the next execution cycle. This may occur indefinitely depending on how many times a processing node executes its query. The behavior of the close
method is no different from a regular Execution
, it may not be called until the end of the statement if lobs are detected and any connection associated with the Execution
will also be closed. When the user command is finished, the ReusableExecution.dispose()
method will be called.
ReusableExecutions
are most useful for continuous query execution and will also make use of the ExecutionCotext.dataAvailable()
method for Asynchronous Executions. See Red Hat JBoss Development Guide: Client Development for more information about executing continuous statements. In continuous mode the user query will be continuously re-executed. A ReusableExecution
allows the same Execution
object to be associated with the processing plan for a given processing node for the lifetime of the user query. This can simplify asynch resource management, such as establishing queue listeners. Returning a null result from the next()
method ReusableExecution
as with normal Executions
indicates that the current pushdown command results have ended. Once the reset()
method has been called, the next set of results should be returned again terminated with a null result.
A.10. Bulk Execution
Insert, Update, Delete
commands may have multi-valued Parameter
objects if the capabilities shows support for BulkUpdate. Commands with multi-valued Parameters represent multiple executions of the same command with different values. As with BatchedUpdates, bulk operations should be executed atomically if possible.
A.11. Command Completion
close()
on the Execution object. Your implementation of this method should do the appropriate clean-up work for all state created in the Execution object.
A.12. Command Cancellation
- Client cancellation via the JDBC API (or other client APIs)
- Administrative cancellation
- Clean-up during session termination
- Clean-up if a query fails during processing
Appendix B. Command Language
B.1. Language
ExecutionFactory
class. Refer to the section on translator capabilities for more information.
LanguageObject
interface. Language objects should be thought of as a tree where each node is a language object that has zero or more child language objects of types that are dependent on the current node.
Command
. Command has several sub-interfaces, namely:
QueryExpression
Insert
Update
Delete
BatchedUpdates
Call
B.2. Expressions
Expression
- base expression interfaceColumnReference
- represents an column in the data sourceLiteral
- represents a literal scalar value, but may also be multi-valued in the case of bulk updates.Function
- represents a scalar function with parameters that are also ExpressionsAggregateFunction
- represents an aggregate function which holds a single expressionWindowFunction
- represents a window function which holds an AggregateFunction (which is also used to represent analytical functions) and a WindowSpecificationScalarSubquery
- represents a subquery that returns a single valueSearchedCase, SearchedWhenClause
- represents a searched CASE expression. The searched CASE expression evaluates the criteria in WHEN clauses until one of them evaluates to TRUE, then evaluates the associated THEN clause.Array
- represents an array of expressions, currently only used by the engine in multi-attribute dependent joins - see the supportsArrayType capability.
B.3. Condition
Condition
- the base criteria interfaceNot
- used to NOT another criteriaAndOr
- used to combine other criteria via AND or ORSubqueryComparison
- represents a comparison criteria with a subquery including a quantifier such as SOME or ALLComparison
- represents a comparison criteria with =, >, <, etc.BaseInCondition
- base class for an IN criteriaIn
- represents an IN criteria that has a set of expressions for valuesSubqueryIn
- represents an IN criteria that uses a subquery to produce the value setIsNull
- represents an IS NULL criteriaExists
represents an EXISTS criteria that determines whether a subquery will return any valuesLike
- represents a LIKE/SIMILAR TO/LIKE_REGEX criteria that compares string values
B.4. The FROM Clause
TableReference
's.
NamedTable
- represents a single TableJoin
- has a left and rightTableReference
and information on the join between the itemsDerivedTable
- represents a table defined by an inlineQueryExpression
TableReference
are used by default, in the pushdown query when no outer joins are used. If an outer join is used anywhere in the join tree, there will be a tree of Join
s with a single root. This latter form is the ANSI perfered style. If you wish all pushdown queries containing joins to be in ANSI style have the capability "useAnsiJoin" return true. Refer to the section on command form for more information.
B.5. QueryExpression Structure
QueryExpression
is the base for both SELECT queries and set queries. It may optionally take an OrderBy
(representing a SQL ORDER BY clause) and a Limit
(represent a SQL LIMIT clause) or a With
(represents a SQL WITH clause).
B.6. Select Structure
QueryExpression
can be a Select
describing the expressions (typically elements) being selected and a TableReference
specifying the table or tables being selected from, along with any join information. The Select
may optionally also supply a Condition
(representing a SQL WHERE clause), a GroupBy
(representing a SQL GROUP BY clause), a Condition
(representing a SQL HAVING clause).
B.7. SetQuery Structure
QueryExpression
can also be a SetQuery
that represents the SQL set operations (UNION, INTERSECT, EXCEPT) on two QueryExpression
s. The all flag may be set to indicate UNION ALL (currently INTERSECT and EXCEPT ALL are not supported).
B.8. With Structure
With
clause contains named QueryExpressions
held by WithItem
s that can be referenced as tables in the main QueryExpression
.
B.9. Insert Structure
Insert
will have a single NamedTable
specifying the table being inserted into. It will also has a list of ColumnReference
specifying the columns of the NamedTable
that are being inserted into. It also has InsertValueSource
, which will be a list of Expressions (ExpressionValueSource
), or a QueryExpression
.
B.10. Update Structure
Update
will have a single NamedTable
specifying the table being updated and list of SetClause
entries that specify ColumnReference
and Expression
pairs for the update. The Update may optionally provide a criteria Condition
specifying which rows should be updated.
B.11. Delete Structure
Delete
will have a single NamedTable
specifying the table being deleted from. It may also optionally have a criteria specifying which rows should be deleted.
B.12. Call Structure
Call
has zero or more Argument
objects. The Argument
objects describe the input parameters, the output result set, and the output parameters.
B.13. BatchedUpdates Structure
BatchedUpdates
has a list of Command
objects (which must be either Insert
, Update
or Delete
) that compose the batch.
B.14. The Type Facility
TypeFacility
that defines data types and provides value translation facilities. This interface can be obtained from calling the ExecutionFactory.getTypeFacility()
method.
Expression
instances define a data type based on this set of types. These constants are often needed in understanding or creating language interfaces.
B.15. Language Manipulation
getLanguageFactory()
method on the ExecutionFactory
to get a reference to the LanguageFactory
instance for your translator. This interface is a factory that can be used to create new instances of all the concrete language interface objects.
Condition
objects are provided in the LanguageUtil
class. This class has methods to combine Condition
with AND
or to break a Condition
apart based on AND
operators. These utilities are helpful for breaking apart a criteria into individual filters that your translator can implement.
B.16. Runtime Metadata
RuntimeMetadata
interface at the time of Excecution
creation. Translators can access runtime metadata by using the interfaces defined in org.teiid.metadata
package. This package defines API representing a Schema, Table, Columns and Procedures, and ways to navigate these objects.
B.17. Metadata Objects
AbstractMetadataRecord
class
- Column - returns Column metadata record
- Table - returns a Table metadata record
- Procedure - returns a Procedure metadata record
- ProcedureParameter - returns a Procedure Parameter metadata record
B.18. Access to Runtime Metadata
Example B.1. Obtaining Metadata Properties
//getting the Table metadata from an Table is straight-forward Table table = runtimeMetadata.getTable("table-name"); String contextName = table.getNameInSource(); //The props will contain extension properties Map<String, String> props = table.getProperties();
B.19. Visitor Framework
org.teiid.language.visitor
package. The framework provides utilities useful in navigating and extracting information from trees of language objects.
AbstractLanguageVisitor
class defines the visit methods for all leaf language interfaces that can exist in the tree. The LanguageObject interface defines an acceptVisitor() method. This method will call back on the visit method of the visitor to complete the contract. A base class with empty visit methods is provided as AbstractLanguageVisitor. The AbstractLanguageVisitor is a visitor shell - it performs no actions when visiting nodes and does not provide any iteration.
HierarchyVisitor
provides the basic code for walking a language object tree. The HierarchyVisitor
performs no action as it walks the tree - it encapsulates the knowledge of how to walk it. If your translator wants to provide a custom iteration that walks the objects in a special order (to exclude nodes, include nodes multiple times, conditionally include nodes, and so forth) then you must either extend HierarchyVisitor or build your own iteration visitor. In general, that is not necessary.
DelegatingHierarchyVisitor
is a special subclass of the HierarchyVisitor that provides the ability to perform a different visitor's processing before and after iteration. This allows users of this class to implement either pre- or post-order processing based on the HierarchyVisitor. Two helper methods are provided on DelegatingHierarchyVisitor
to aid in executing pre- and post-order visitors.
B.20. Provided Visitors
SQLStringVisitor
is a special visitor that can traverse a tree of language interfaces and output the equivalent JBoss Data Virtualization SQL. This visitor can be used to print language objects for debugging and logging. The SQLStringVisitor
does not use the HierarchyVisitor
described in the last section; it provides both iteration and processing type functionality in a single custom visitor.
CollectorVisitor
is a handy utility to collect all language objects of a certain type in a tree. Some additional helper methods exist to do common tasks such as retrieving all elements in a tree, retrieving all groups in a tree, and so on.
B.21. Writing a Visitor
visit(ColumnReference)
method. Collect any state in local variables and provide accessor methods for that state.
// Get object tree LanguageObject objectTree = ... // Create your visitor initialize as necessary MyVisitor visitor = new MyVisitor(); // Call the visitor using pre-order visitation DelegatingHierarchyVisitor.preOrderVisit(visitor, objectTree); // Retrieve state collected while visiting int count = visitor.getCount();
Appendix C. Appendix
C.1. Template for ra.xml
<?xml version="1.0" encoding="UTF-8"?> <connector xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd" version="1.5"> <vendor-name>${comapany-name}</vendor-name> <eis-type>${type-of-connector}</eis-type> <resourceadapter-version>1.0</resourceadapter-version> <license> <description>${license text}</description> <license-required>true</license-required> </license> <resourceadapter> <resourceadapter-class>org.teiid.resource.spi.BasicResourceAdapter</resourceadapter-class> <outbound-resourceadapter> <connection-definition> <managedconnectionfactory-class>${connection-factory}</managedconnectionfactory-class> <!-- repeat for every configuration property --> <config-property> <description> {$display:"${short-name}",$description:"${description}",$allowed:[${value-list}], $required:"${required-boolean}", $defaultValue:"${default-value}"} </description> <config-property-name>${property-name}</config-property-name> <config-property-type>${property-type}</config-property-type> <config-property-value>${optional-property-value}</config-property-value> </config-property> <!-- use the below as is if you used the Connection Factory interface --> <connectionfactory-interface> javax.resource.cci.ConnectionFactory </connectionfactory-interface> <connectionfactory-impl-class> org.teiid.resource.spi.WrappedConnectionFactory </connectionfactory-impl-class> <connection-interface> javax.resource.cci.Connection </connection-interface> <connection-impl-class> org.teiid.resource.spi.WrappedConnection </connection-impl-class> </connection-definition> <transaction-support>NoTransaction</transaction-support> <authentication-mechanism> <authentication-mechanism-type>BasicPassword</authentication-mechanism-type> <credential-interface> javax.resource.spi.security.PasswordCredential </credential-interface> </authentication-mechanism> <reauthentication-support>false</reauthentication-support> </outbound-resourceadapter> </resourceadapter> </connector>
C.2. Download API Documentation
Procedure C.1. Download API Documentation
- Open a web browser and navigate to https://access.redhat.com/jbossnetwork.
- From the Software Downloads page, when prompted for a Product, select Data Virtualization. This will present a table of files to download for the latest version of the product.
- Change the Version to the current release if required.
- Look for JBoss Data Virtualization VERSION Javadocs in the table and select Download.
C.3. JBoss Data Virtualization Functions and Order of Precedence
- System functions (effectively scoped to SYS) and are known at design time.
- Pushdown functions (also effectively scoped to SYS) and are supplied by translators.
- UDFs which are schema scoped (except for legacy function models) and are defined via metadata.
Note
Appendix D. Revision History
Revision History | |||
---|---|---|---|
Revision 6.2.0-54444 | Thu Dec 10 2015 | David Le Sage | |
|