teiid SVN: r2244 - in trunk/documentation/quick-start-example/src/main/docbook/en-US: content and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-06-17 22:57:39 -0400 (Thu, 17 Jun 2010)
New Revision: 2244
Removed:
trunk/documentation/quick-start-example/src/main/docbook/en-US/content/learn.xml
Modified:
trunk/documentation/quick-start-example/src/main/docbook/en-US/content/buildvdb.xml
trunk/documentation/quick-start-example/src/main/docbook/en-US/content/connect-vdb.xml
trunk/documentation/quick-start-example/src/main/docbook/en-US/content/deployment.xml
trunk/documentation/quick-start-example/src/main/docbook/en-US/content/download.xml
trunk/documentation/quick-start-example/src/main/docbook/en-US/content/example-explained.xml
trunk/documentation/quick-start-example/src/main/docbook/en-US/content/preface.xml
trunk/documentation/quick-start-example/src/main/docbook/en-US/quick_start_example.xml
Log:
TEIID-922 updated the links/text of the quick start guide. also made it less designer centric. we'll still need to update the portfolio vdb with a new designer build
Modified: trunk/documentation/quick-start-example/src/main/docbook/en-US/content/buildvdb.xml
===================================================================
--- trunk/documentation/quick-start-example/src/main/docbook/en-US/content/buildvdb.xml 2010-06-18 01:43:01 UTC (rev 2243)
+++ trunk/documentation/quick-start-example/src/main/docbook/en-US/content/buildvdb.xml 2010-06-18 02:57:39 UTC (rev 2244)
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="designer">
+<chapter id="step-3">
+ <title>Building a VDB</title>
+ <para>A VDB can be built with either the <link linkend="designer">Designer</link> tool or through a simple XML file called a dynamic VDB. See the dyanmicvdb-portolio for an example dynamic VDB. You can skip the next section if you choose to use a dynamic VDB.</para>
+ <sect1 id="designer">
<title>Using Teiid Designer to build a VDB</title>
- <sect1>
+ <sect2>
<title>Download Teiid Designer</title>
<note>
@@ -16,16 +19,14 @@
<para>
The Teiid Designer project provides a Eclipse based designer tool for this purpose of building a VDB. You can
download Teiid Designer
- <ulink url="http://teiid.org/teiiddesigner.html">here</ulink>
+ <ulink url="http://www.jboss.org/teiiddesigner/downloads.html">here</ulink>
Once downloaded, please follow the installation instructions. Start the Teiid Designer and return here to continue
building the VDB.
</para>
- </sect1>
- <sect1 id="step-3">
- <title>Building a VDB</title>
+ </sect2>
+
<para>Once you start the Designer, there are several steps you must perform to create a VDB. These steps are
- summarized in the following table. This is a <ulink url="../images/EmbeddedDesignerExampleVideo.swf">video</ulink>
- will take you though all the steps involved. (please note this video is based on old version of Designer, a updated one coming soon..)</para>
+ summarized in the following table.</para>
<orderedlist>
<listitem>
<para>Switch to the Designer Perspective, by opening the "Window->Open Perspective.."</para>
@@ -39,9 +40,6 @@
<listitem>
<para>Manually create the view model for the "Text File". Create a Table called "Price" with
"stock" and "price" as column names. In the transformation window add the following SQL</para>
- <programlisting><![CDATA[
- SQL text here..
- ]]> </programlisting>
</listitem>
<listitem>
<para>Create a view model called "AccountView"</para>
@@ -64,5 +62,5 @@
<para>Export or copy the VDB for use in your application.</para>
</listitem>
</orderedlist>
- </sect1>
+ </sect1>
</chapter>
\ No newline at end of file
Modified: trunk/documentation/quick-start-example/src/main/docbook/en-US/content/connect-vdb.xml
===================================================================
--- trunk/documentation/quick-start-example/src/main/docbook/en-US/content/connect-vdb.xml 2010-06-18 01:43:01 UTC (rev 2243)
+++ trunk/documentation/quick-start-example/src/main/docbook/en-US/content/connect-vdb.xml 2010-06-18 02:57:39 UTC (rev 2244)
@@ -9,77 +9,69 @@
<title>Stand-alone Java Application Deployment</title>
<para>Before you can make a JDBC connection to the Teiid VDB, add the Teiid's driver jar file to your application's classpath</para>
- <programlisting><![CDATA[
- ${jboss-install}/server/${profile}/lib/teiid-${version}-client.jar
- ]]> </programlisting>
+ <programlisting><![CDATA[${jboss-install}/server/${profile}/lib/teiid-${version}-client.jar]]> </programlisting>
<para>
For a Java application to connect to a JDBC source, it needs a URL, user-id, and password. To
connect to your VDB all you need is a URL and any additional optional properties that you would like to set.
Teiid defaults to allowing the "admin" as user with password as "teiid". Additional user accounts can be added.
A JDBC connection can be obtained through the Teiid driver
- <emphasis>"org.teiid.jdbc.TeiidDriver"</emphasis>
+ <code>"org.teiid.jdbc.TeiidDriver"</code>
with the URL syntax of
</para>
<para>
- <emphasis>jdbc:teiid:<VDB-Name>@(mm|mms)://<host name>:<port></emphasis>
+ <emphasis>jdbc:teiid:<VDB-Name>@mm(s)://<host name>:<port></emphasis>
</para>
<para>
You can add optional properties at the end of the URL using a semi-colon(;) name=value
format. For example</para>
<para />
<para>
- <emphasis>jdbc:teiid:<VDB-Name>@(mm|mms)://<host name>:<port>;autoCommitTxn=DETECT</emphasis>
+ <emphasis>jdbc:teiid:<VDB-Name>@mm(s)://<host name>:<port>;autoCommitTxn=DETECT</emphasis>
</para>
- <para />
<para>
You can use any of these <ulink url="https://www.jboss.org/community/docs/DOC-13157"> optional connection properties </ulink>
in your URL. Here is sample code showing how to make JDBC connection.
</para>
- <programlisting><![CDATA[
- public void execute() throws SQLException {
- String url = "jdbc:metamatrix:Portfolio@mm://localhost:31000";
- String sql = "select firstname, lastname from customer";
-
- Class.forName("org.teiid.jdbc.TeiidDriver");
-
- Connection connection;
- try{
- connection = DriverManager.getConnection(url, "admin", "teiid");
- Statement statement = connection.createStatement();
- ResultSet results = statement.executeQuery(sql);
- while(results.next()) {
- System.out.println(results.getString(1));
- System.out.println(results.getString(2));
- ...
- }
- results.close();
- statement.close();
- } catch (SQLException e){
- e.printStackTrace();
- throw e;
- } finally {
- try{
- connection.close();
- }catch(SQLException e1){
- // ignore
- }
- }
- }
- ]]></programlisting>
- <para>You can also use <emphasis>org.teiid.jdbc.TeiidDataSource</emphasis>
+ <programlisting><![CDATA[public void execute() throws SQLException {
+ String url = "jdbc:teiid:Portfolio@mm://localhost:31000";
+ String sql = "select firstname, lastname from customer";
+
+ Class.forName("org.teiid.jdbc.TeiidDriver");
+
+ Connection connection;
+ try{
+ connection = DriverManager.getConnection(url, "admin", "teiid");
+ Statement statement = connection.createStatement();
+ ResultSet results = statement.executeQuery(sql);
+ while(results.next()) {
+ System.out.println(results.getString(1));
+ System.out.println(results.getString(2));
+ ...
+ }
+ results.close();
+ statement.close();
+ } catch (SQLException e){
+ e.printStackTrace();
+ throw e;
+ } finally {
+ try{
+ connection.close();
+ }catch(SQLException e1){
+ // ignore
+ }
+ }
+}]]></programlisting>
+ <para>You can also use <code>org.teiid.jdbc.TeiidDataSource</code>
to make connection in your Java application. For example, you can use following code fragment to make a
connection to the VDB and issuing the query exactly same as in the above example</para>
- <programlisting><![CDATA[
- TeiidDataSource ds = new TeiidDataSource();
- ds.setDatabaseName("Portfolio");
- ds.setEmbeddedBootstrapFile("<teiid home>/deploy.properties");
- ds.setUser("admin");
- ds.setPassword("teiid");
-
- Connection connection = ds.getConnection();
- ...
- ]]></programlisting>
+ <programlisting><![CDATA[TeiidDataSource ds = new TeiidDataSource();
+ds.setDatabaseName("Portfolio");
+ds.setUser("admin");
+ds.setPassword("teiid");
+
+Connection connection = ds.getConnection();
+...]]></programlisting>
<para>TeiidDataSource source also provides an option to set optional parameters using the "set" methods on the
data source look. For all the allowable properties at the
<ulink url="https://www.jboss.org/community/docs/DOC-13158">data source properties</ulink>.</para>
@@ -93,16 +85,13 @@
<listitem><para>Change to the ${jboss-install}/server/profile/teiid-examples/portfolio directory</para></listitem>
<listitem><para>Execute the run script (either for Linux or Windows)</para></listitem>
</orderedlist>
- <para>The sample query, "select * from CustomerAccount", queries the view model and, from that, queries the two underlying
- data sources: one relational, one file-based. All the sample Java class does is connect to the VDB, issue the query,
- and print the results. Teiid does the "heavy lifting" of integrating the results.
- (For the complete code used in this example, look in the "examples/portfolio" directory.)</para>
- <para>
- You are encouraged to experiment with queries that go beyond the simple "select * from CustomerAccount".
+ <para>Depending on the VDB you deployed, see the relevant README file for example queries. If you are using a graphical client, such
+ as <ulink url="http://www.squirrelsql.org/">SQuirreL</ulink>, have a look at the metadata tree to see not only what is exposed by your
+ VDB, but also the SYS schema tables.
</para>
<para>If your application is Web based, you can create data source for your VDB using the above and treat it as any other JDBC source using
- <emphasis>org.teiid.jdbc.TeiidDataSource</emphasis> and assigning it a JNDI name.
+ <code>org.teiid.jdbc.TeiidDataSource</code> and assigning it a JNDI name.
Refer to <ulink url="https://community.jboss.org/docs/DOC-13888">deployment to application server</ulink> for more information.
</para>
<note><para>"embedded" mode is only available in versions of Teiid up to 6.2</para></note>
Modified: trunk/documentation/quick-start-example/src/main/docbook/en-US/content/deployment.xml
===================================================================
--- trunk/documentation/quick-start-example/src/main/docbook/en-US/content/deployment.xml 2010-06-18 01:43:01 UTC (rev 2243)
+++ trunk/documentation/quick-start-example/src/main/docbook/en-US/content/deployment.xml 2010-06-18 02:57:39 UTC (rev 2244)
@@ -21,16 +21,14 @@
<para>For this example we need to create three (2) different data sources. You would first need to create a data source to Derby,
then to File source. See or copy the following</para>
- <programlisting><![CDATA[
- ${teiid-examples}/portfolio/PortfolioModel/portfolio-ds.xml
- ${teiid-examples}/portfolio/PortfolioModel/marketdata-file-ds.xml
- ]]> </programlisting>
+ <programlisting><![CDATA[${teiid-examples}/portfolio/portfolio-ds.xml
+${teiid-examples}/portfolio/marketdata-file-ds.xml]]> </programlisting>
<para>files into "${jboss-install}/server/{profile}/deploy" directory.</para>
</listitem>
<listitem>
- <para>The above data sources provide the data to your VDB. Now to deploy your VDB, place your VDB in a the "${jboss-install}/server/{profile}/deploy" directory.
+ <para>The above data sources provide the data to your VDB. Now to deploy your VDBl place your VDB file (either the dynamicvdb-portfolio/portfolio-vdb.xml file or the full .vdb file) in a the "${jboss-install}/server/{profile}/deploy" directory.
If the JBoss AS is not already started, start by running the "${jboss-install}/bin/run.sh" or "${jboss-install}/bin/run.bat" scripts.
- Make sure there were no errors during the deply of the VDB
+ Check the logs or the console to make sure there were no errors during the deployment of the VDB.
</para>
</listitem>
<listitem>
Modified: trunk/documentation/quick-start-example/src/main/docbook/en-US/content/download.xml
===================================================================
--- trunk/documentation/quick-start-example/src/main/docbook/en-US/content/download.xml 2010-06-18 01:43:01 UTC (rev 2243)
+++ trunk/documentation/quick-start-example/src/main/docbook/en-US/content/download.xml 2010-06-18 02:57:39 UTC (rev 2244)
@@ -4,31 +4,31 @@
<title>Download</title>
<para>
You need to download the binaries for
- <ulink url="http://teiid.org/Download.html">Teiid</ulink>
+ <ulink url="http://www.jboss.org/teiid/downloads.html">Teiid</ulink>
. Note that there are three different artifacts are available for download.
</para>
<orderedlist>
<listitem>
- <para>Teiid Source - contains all the source code for all modules</para>
+ <para>Teiid Source - contains all of the source code</para>
</listitem>
<listitem>
- <para>Teiid Adminshell - contains the admin client binary code</para>
+ <para>Teiid Adminshell - contains the admin client</para>
</listitem>
<listitem>
- <para>Teiid Kit - contains only required modules and their required 3rd party
+ <para>Teiid Runtime - contains the Teiid engine and required 3rd party
dependencies</para>
</listitem>
</orderedlist>
<para>
For this Quick Start, download and install <ulink url="http://www.jboss.org/jbossas/downloads.html">JBoss AS 5.1.0</ulink>.
- Then download <emphasis>Teiid</emphasis> runtime and unzip the contents of the Teiid under any of one of the JBoss AS profiles
- like "default" or "all". For example in "<jboss-install>/server/default". The Teiid runtime directory structure matches that
- of the JBoss profile directly, so you can just overlay the needed classes.
+ Then download Teiid runtime and unzip the contents of the Teiid under any of one of the JBoss AS profiles
+ like "default" or "all". The default profile is the typical installation location, for example "<jboss-install>/server/default". The Teiid runtime directory structure matches that
+ of the JBoss profile directly.
</para>
<para>In the "<jboss-install>/server/<profile>/lib" directory, you will find "teiid-${version}-client.jar", which
is the main client binary jar file for Teiid. This jar file contains the Teiid's JDBC driver and data source classes. </para>
<note>
- <para>JBoss AS requires <ulink url="http://java.sun.com/javase/downloads">Java 6</ulink> to run.
+ <para>JBoss AS 5.1 requires <ulink url="http://java.sun.com/javase/downloads">Java 6</ulink> to run.
</para>
<para>
Access to physical data sources such as Oracle, MS-SQL Server, DB2, and Sybase through Teiid relies upon
Modified: trunk/documentation/quick-start-example/src/main/docbook/en-US/content/example-explained.xml
===================================================================
--- trunk/documentation/quick-start-example/src/main/docbook/en-US/content/example-explained.xml 2010-06-18 01:43:01 UTC (rev 2243)
+++ trunk/documentation/quick-start-example/src/main/docbook/en-US/content/example-explained.xml 2010-06-18 02:57:39 UTC (rev 2244)
@@ -5,23 +5,10 @@
<sect1>
<title>Portfolio Application Explained</title>
<para>
- To demonstrate how Teiid Designer and Teiid work together, follow these steps to build a simple
- portfolio valuation virtual database. The investor's portfolio information is stored in a Derby database and
- "current" stock prices are stored in a delimited text file. When completed, a single query will cause
+ The investor's portfolio information is stored in a Derby database and
+ "current" stock prices are stored in a delimited text file. When the VDB is completed, a single query will cause
Teiid to access the relational and non-relational sources, calculate the portfolio values, and
- return the results. Here are some of key points to consider as you build this example:
- <itemizedlist>
- <listitem>
- <para>It's pretty simple to do</para>
- </listitem>
- <listitem>
- <para>You're querying a text file as though it was a relational database</para>
- </listitem>
- <listitem>
- <para>Imagine how much more complete this would be if you replaced the text file with a connection
- to a financial Web site. (Hint: You can with Teiid and a custom connector.)</para>
- </listitem>
- </itemizedlist>
+ return the results.
</para>
<figure id="steps">
<title>Various Steps involved in creating the example</title>
@@ -45,12 +32,12 @@
</listitem>
<listitem>
<para>
- <link linkend="step-4">Step-4: Deploy the VDB in Teiid</link>
+ <link linkend="deployment">Step-4: Deploy the VDB in Teiid</link>
</para>
</listitem>
<listitem>
<para>
- <link linkend="step-5">Step-5: Access the VDB using JDBC API</link>
+ <link linkend="OpenConnection">Step-5: Access the VDB using the JDBC API</link>
</para>
</listitem>
</itemizedlist>
@@ -58,63 +45,51 @@
<note>
<para>
<ulink url="http://db.apache.org/derby/">Derby</ulink>
- is suggested as it is Open Source, easily obtained, and light-weight. You can substitute any other relational
+ is used here since it is Open Source, easily obtained, and light-weight. You can substitute any other relational
database, as long as you have a suitable JDBC driver. The schema file provided, and described below, is
specific to Derby, but can be easily converted for use with other databases.
</para>
</note>
<sect1 id="step-1">
- <title>Step-1: Create the Relational Database's schema and load the sample data</title>
+ <title>Create the Relational Database's schema and load the sample data</title>
<para>
This example is written using
<ulink url="http://db.apache.org/derby/">"Derby"</ulink>
as the relational database.
<ulink url="http://db.apache.org/derby/derby_downloads.html">Download</ulink>
- and install Derby on your machine, or if you have access to an installed instance use that. It is
- expected that you create a database called "accounts" in this Derby instance that is used by this example
- application.
+ and install Derby on your machine. An existing local or remote instance can be used if it exists.
</para>
- <para>
- Below find the corresponding schema. For the complete schema, please refer to
- <emphasis>"examples/portfolio/customer-schema.sql"</emphasis>
- file of the downloaded kit.
- </para>
- <programlisting><![CDATA[
- - -Contains the name and address of a Customer who owns portfolio account
- CREATE TABLE CUSTOMER
- ...
-
- --Contains Customer's account number and its current status
- CREATE TABLE ACCOUNT
- ...
-
- --Contains information about stock symbol, company name etc.
- CREATE TABLE PRODUCT
- ...
-
- --Contains each Account's holdings of Stocks
- CREATE TABLE HOLDINGS
- ...
- ]]>
- </programlisting>
<para>We need to start the Derby RDBMS and create the "accounts" database with the below schema. These
commands are intended for a Linux environment. For starting the Derby instance on another platform, you will need to use
commands appropriate to that platform.</para>
<para>Start a terminal session, and change directory to where
Derby is installed and execute following commands</para>
- <programlisting><![CDATA[
- export DERBY_HOME=`pwd`
- ./bin/startNetworkServer
- ]]>
+ <programlisting><![CDATA[export DERBY_HOME=`pwd`
+./bin/startNetworkServer]]>
</programlisting>
- <para>The above starts the Derby in network mode. Now, start another terminal and we will use Derby''s 'ij' tool
+ <para>This starts the Derby in network mode. Now, start another terminal and we will use Derby''s 'ij' tool
(like SQL*PLus for Oracle) to create the schema, using the "customer-schema.sql" file in
"examples/portfolio" directory</para>
- <programlisting><![CDATA[
- export DERBY_HOME=`pwd`
- ./bin/ij /path/to/customer-schema.sql
- ]]>
+ <programlisting><![CDATA[export DERBY_HOME=`pwd`
+./bin/ij /path/to/customer-schema.sql]]>
</programlisting>
+ <para>This will create the accounts schema. It's abbreviated ddl is shown below. </para>
+ <programlisting><![CDATA[--Contains the name and address of a Customer who owns portfolio account
+CREATE TABLE CUSTOMER
+...
+
+--Contains Customer's account number and its current status
+CREATE TABLE ACCOUNT
+...
+
+--Contains information about stock symbol, company name etc.
+CREATE TABLE PRODUCT
+...
+
+--Contains each Account's holdings of Stocks
+CREATE TABLE HOLDINGS
+...]]></programlisting>
+
<para>
Make sure you did not have any issues when creating the schema as it is needed for going forward in this example.
You can use 'ij' tool to verify the tables were created. As an alternative, you may use other tools like
@@ -125,7 +100,7 @@
</para>
</sect1>
<sect1 id="step-2">
- <title>Step-2: Describe the CSV file and its contents</title>
+ <title>Describe the CSV file and its contents</title>
<para>In order to use a Text file as the source, we need a data file defines data inside a table</para>
<orderedlist>
<listitem>
@@ -143,8 +118,6 @@
</programlisting>
</listitem>
</orderedlist>
- <para>Just locate the sample data files provided or create your own data files. Make sure that the
- descriptor file contains the full path to the data file. Now, both our sources are ready to be
- used to build a VDB</para>
+ <para>Just locate the sample data files provided or create your own data files. Now, both our sources are ready.</para>
</sect1>
</chapter>
\ No newline at end of file
Deleted: trunk/documentation/quick-start-example/src/main/docbook/en-US/content/learn.xml
===================================================================
--- trunk/documentation/quick-start-example/src/main/docbook/en-US/content/learn.xml 2010-06-18 01:43:01 UTC (rev 2243)
+++ trunk/documentation/quick-start-example/src/main/docbook/en-US/content/learn.xml 2010-06-18 02:57:39 UTC (rev 2244)
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="learn">
- <title>Learning about Virtual Databases (VDB)</title>
- <sect1>
- <title>What is a Virtual Database?</title>
- <para> A Virtual Database (VDB) is an artifact that defines the logical schema model combining one or more
- physical data sources to provide easy data integration. This is accomplished by use of virtual tables,
- virtual views and virtual procedures, transformed by queries to their underlying
- physical data sources. The physical sources can be JDBC sources, delimited text files, spreadsheets
- or even Web services.</para>
- <para>Your JDBC application references the virtual (logical) schema defined in this VDB. When tables, or
- other objects, in the VDB's models are queried, the Teiid query engine interprets the virtual schema,
- makes the appropriate calls to the actual physical sources, combines and translates them as requested, and
- returns the top level results to the application.</para>
- </sect1>
- <sect1>
- <title>What is Teiid?</title>
- <para> Teiid is runtime for executing queries against a VDB. Before you can access your data in a federated
- manner, use the Teiid Designer to build a VDB. This picture shows the relationship between the tools
- involved.</para>
- <figure id="lifecycle">
- <title>Lifecycle of Events</title>
- <graphic align="center" scale="100" fileref="../images/steps.png" />
- </figure>
- <para>The Teiid Designer tool lets you define physical data sources by importing the required metadata
- (schema) from these sources. Once the metadata is imported, use the Designer to build a virtual data model.
- The collection of physical and logical models form a virtual schema. Once the user has completed the models,
- the Designer is used to package them in a Virtual Database, or VDB. So, a VDB can be further defined as a
- collection of logical (virtual) data models.</para>
- </sect1>
-</chapter>
\ No newline at end of file
Modified: trunk/documentation/quick-start-example/src/main/docbook/en-US/content/preface.xml
===================================================================
--- trunk/documentation/quick-start-example/src/main/docbook/en-US/content/preface.xml 2010-06-18 01:43:01 UTC (rev 2243)
+++ trunk/documentation/quick-start-example/src/main/docbook/en-US/content/preface.xml 2010-06-18 02:57:39 UTC (rev 2244)
@@ -2,37 +2,46 @@
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<preface>
<title>Preface</title>
- <para> Teiid offers the power of a federated relational query engine for use with any Java
- application - without the need for a separate server process. Accessing your federated data is as easy as
- making a JDBC connection to any relational data source. This guide will take you through</para>
- <itemizedlist>
- <listitem>
- <para>Deployment of Teiid in your environment</para>
- </listitem>
- <listitem>
- <para>Building and deploying a Virtual Database(VDB)</para>
- </listitem>
- <listitem>
- <para>Connecting to your VDB and issuing federated queries against your VDB and getting results
- back</para>
- </listitem>
- </itemizedlist>
- <para> Commercial development support, production support, and training for Teiid is available through JBoss.
- Teiid is a Professional Open Source project and a critical component of the JBoss Enterprise Data Services
- Platform.</para>
+ <sect1>
+ <title>What is Teiid?</title>
+ <para>Teiid is runtime for executing queries against a Virtual Database or VDB. Before you can access your data in a federated
+ manner, use can use Teiid Designer or the Dynamic VDB feature to build a VDB. This picture shows the relationship between the tools
+ involved.</para>
+ <figure id="lifecycle">
+ <title>Lifecycle of Events</title>
+ <graphic align="center" scale="100" fileref="../images/steps.png" />
+ </figure>
+ <sect2>
+ <title>What is a Virtual Database?</title>
+ <para> A Virtual Database (VDB) is an artifact that combines one or more
+ physical data sources to provide for easy data integration. Integration is encapsulated through view and procedures that Teiid will process in an optimized way against their respective sources.
+ The physical sources can be JDBC sources, delimited text files, spreadsheets, or even Web services.</para>
+ </sect2>
+
+ <para>The Teiid Designer tool lets you define physical data sources by importing the required metadata
+ (schema) from these sources. Once the metadata is imported, Designer can assist in building additional view layers.
+ The collection of physical and view models will form a VDB.</para>
+ </sect1>
+
<sect1>
<title>What is This Guide About?</title>
<para>This guide takes you through an introduction to the concepts important to Teiid,
- downloading the software, and building and deploying a demonstration virtual database in 60 minutes.
+ downloading the software, and building and deploying a virtual database in 60 minutes.
There is a lot to cover, so let's begin!</para>
</sect1>
+
<note>
<para>
Please read
<ulink url="http://www.jboss.org/teiid/basics.html">Federation Basics</ulink>
- and understand different terminologies used, resources needed and artifacts that need to be generated before
+ to understand different terminologies used, resources needed, and artifacts to be generated before
developing a successful application. This example takes advantage of only a minimal set of features from
- Teiid Embedded for the sake of simplicity and time.
+ Teiid for the sake of simplicity and time.
</para>
</note>
+
+ <para>Commercial development support, production support, and training for Teiid is available through JBoss.
+ Teiid is a Professional Open Source project and a critical component of the JBoss Enterprise Data Services
+ Platform.</para>
+
</preface>
\ No newline at end of file
Modified: trunk/documentation/quick-start-example/src/main/docbook/en-US/quick_start_example.xml
===================================================================
--- trunk/documentation/quick-start-example/src/main/docbook/en-US/quick_start_example.xml 2010-06-18 01:43:01 UTC (rev 2243)
+++ trunk/documentation/quick-start-example/src/main/docbook/en-US/quick_start_example.xml 2010-06-18 02:57:39 UTC (rev 2244)
@@ -48,7 +48,6 @@
<toc />
<xi:include href="content/preface.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/download.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="content/learn.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/example-explained.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/buildvdb.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/deployment.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
14 years, 7 months
teiid SVN: r2243 - in trunk: common-core/src/main/java/org/teiid/core/types and 11 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-06-17 21:43:01 -0400 (Thu, 17 Jun 2010)
New Revision: 2243
Added:
trunk/common-core/src/main/java/org/teiid/core/util/InputStreamReader.java
trunk/engine/src/main/java/org/teiid/query/function/CharsetUtils.java
Removed:
trunk/documentation/quick-start-example/src/main/docbook/en-US/images/EmbeddedDesignerExampleVideo.swf
Modified:
trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java
trunk/common-core/src/main/java/org/teiid/core/types/BaseLob.java
trunk/common-core/src/main/java/org/teiid/core/types/SQLXMLImpl.java
trunk/common-core/src/main/java/org/teiid/core/types/Streamable.java
trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java
trunk/common-core/src/main/java/org/teiid/core/util/ReaderInputStream.java
trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java
trunk/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
trunk/engine/src/test/java/org/teiid/query/function/source/TestXMLSystemFunctions.java
trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
Log:
TEIID-1021 refining support for clob<->blob conversions. changes encode/decode to to_bytes/to_chars to cover both binary and character encodings.
Modified: trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -40,8 +40,6 @@
public static final String ASCII = "ascii"; //$NON-NLS-1$
public static final String CHAR = "char"; //$NON-NLS-1$
public static final String CONCAT = "concat"; //$NON-NLS-1$
- public static final String DECODE = "decode"; //$NON-NLS-1$
- public static final String ENCODE = "encode"; //$NON-NLS-1$
//public static final String DIFFERENCE = "difference";
public static final String INITCAP = "initcap"; //$NON-NLS-1$
public static final String INSERT = "insert"; //$NON-NLS-1$
@@ -58,6 +56,8 @@
public static final String RTRIM = "rtrim"; //$NON-NLS-1$
//public static final String SOUNDEX = "soundex";
public static final String SUBSTRING = "substring"; //$NON-NLS-1$
+ public static final String TO_BYTES = "to_bytes"; //$NON-NLS-1$
+ public static final String TO_CHARS = "to_chars"; //$NON-NLS-1$
public static final String UCASE = "ucase"; //$NON-NLS-1$
//numeric
Modified: trunk/common-core/src/main/java/org/teiid/core/types/BaseLob.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/BaseLob.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/common-core/src/main/java/org/teiid/core/types/BaseLob.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -1,3 +1,25 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
package org.teiid.core.types;
import java.io.Externalizable;
@@ -3,5 +25,4 @@
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.ObjectInput;
import java.io.ObjectOutput;
@@ -11,13 +32,13 @@
import java.sql.SQLException;
import org.teiid.core.types.InputStreamFactory.StreamFactoryReference;
+import org.teiid.core.util.InputStreamReader;
-
public class BaseLob implements Externalizable, StreamFactoryReference {
private static final long serialVersionUID = -1586959324208959519L;
private InputStreamFactory streamFactory;
- private String encoding;
+ private Charset charset;
public BaseLob() {
@@ -38,14 +59,22 @@
return streamFactory;
}
- public String getEncoding() {
- return encoding;
+ public void setEncoding(String encoding) {
+ if (encoding != null) {
+ this.charset = Charset.forName(encoding);
+ } else {
+ this.charset = null;
+ }
}
- public void setEncoding(String encoding) {
- this.encoding = encoding;
+ public Charset getCharset() {
+ return charset;
}
+ public void setCharset(Charset charset) {
+ this.charset = charset;
+ }
+
public void free() throws SQLException {
if (this.streamFactory != null) {
try {
@@ -70,11 +99,11 @@
ex.initCause(e);
throw ex;
}
- String enc = getEncoding();
- if (enc == null) {
- enc = Streamable.ENCODING;
+ Charset cs = getCharset();
+ if (cs == null) {
+ cs = Streamable.CHARSET;
}
- return new InputStreamReader(getBinaryStream(), Charset.forName(enc));
+ return new InputStreamReader(getBinaryStream(), cs.newDecoder());
}
public InputStream getBinaryStream() throws SQLException {
Modified: trunk/common-core/src/main/java/org/teiid/core/types/SQLXMLImpl.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/SQLXMLImpl.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/common-core/src/main/java/org/teiid/core/types/SQLXMLImpl.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -84,19 +84,19 @@
}
@Override
- public String getEncoding() {
- String enc = super.getEncoding();
- if (enc != null) {
- return enc;
+ public Charset getCharset() {
+ Charset cs = super.getCharset();
+ if (cs != null) {
+ return cs;
}
try {
- enc = XMLType.getEncoding(this.getBinaryStream());
+ String enc = XMLType.getEncoding(this.getBinaryStream());
if (enc != null) {
setEncoding(enc);
}
} catch (SQLException e) {
}
- return Streamable.ENCODING;
+ return Streamable.CHARSET;
}
@SuppressWarnings("unchecked")
Modified: trunk/common-core/src/main/java/org/teiid/core/types/Streamable.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/Streamable.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/common-core/src/main/java/org/teiid/core/types/Streamable.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -26,6 +26,7 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.nio.charset.Charset;
import org.teiid.core.CorePlugin;
@@ -43,6 +44,7 @@
private static final long serialVersionUID = -8252488562134729374L;
public static final String ENCODING = "UTF-8"; //$NON-NLS-1$
+ public static final Charset CHARSET = Charset.forName(ENCODING);
public static final String FORCE_STREAMING = "FORCE_STREAMING"; //$NON-NLS-1$
public static final int STREAMING_BATCH_SIZE_IN_BYTES = 102400; // 100K
Modified: trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -29,6 +29,7 @@
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
+import java.nio.charset.Charset;
import java.sql.SQLException;
import java.sql.SQLXML;
@@ -147,7 +148,10 @@
xml = type.reference;
}
if (xml instanceof SQLXMLImpl) {
- return ((SQLXMLImpl)xml).getEncoding();
+ Charset cs = ((SQLXMLImpl)xml).getCharset();
+ if (cs != null) {
+ return cs.displayName();
+ }
}
return getEncoding(xml.getBinaryStream());
} catch (SQLException e) {
Added: trunk/common-core/src/main/java/org/teiid/core/util/InputStreamReader.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/util/InputStreamReader.java (rev 0)
+++ trunk/common-core/src/main/java/org/teiid/core/util/InputStreamReader.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -0,0 +1,104 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.core.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+
+import org.teiid.core.types.DataTypeManager;
+
+/**
+ * Replacement for the standard {@link java.io.InputStreamReader},
+ * which suffers from a <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4744247">bug</a> in sun.nio.cs.StreamDecoder
+ */
+public class InputStreamReader extends Reader {
+
+ private CharsetDecoder cd;
+ private ReadableByteChannel rbc;
+ private ByteBuffer bb;
+ private CharBuffer cb;
+ private boolean done;
+
+ public InputStreamReader(InputStream in, CharsetDecoder cd) {
+ this(in, cd, DataTypeManager.MAX_LOB_MEMORY_BYTES);
+ }
+
+ public InputStreamReader(InputStream in, CharsetDecoder cd, int bufferSize) {
+ this.cd = cd;
+ this.rbc = Channels.newChannel(in);
+ this.bb = ByteBuffer.allocate(bufferSize);
+ this.cb = CharBuffer.allocate((int)(bufferSize * (double)cd.maxCharsPerByte()));
+ this.cb.limit(0);
+ }
+
+ @Override
+ public void close() throws IOException {
+ rbc.close();
+ cd.reset();
+ }
+
+ @Override
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ if ((off < 0) || (off > cbuf.length) || (len < 0) ||
+ ((off + len) > cbuf.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+ while (!done && !cb.hasRemaining()) {
+ int read = 0;
+ while ((read = rbc.read(bb)) == 0) {
+ //blocking read
+ }
+ bb.flip();
+ cb.clear();
+ CoderResult cr = cd.decode(bb, cb, read == -1);
+ if (!cr.isUnderflow()) {
+ cr.throwException();
+ }
+ if (read == -1) {
+ cr = cd.flush(cb);
+ if (!cr.isUnderflow()) {
+ cr.throwException();
+ }
+ done = true;
+ }
+ bb.clear();
+ cb.flip();
+ }
+ len = Math.min(len, cb.remaining());
+ if (len == 0 && done) {
+ return -1;
+ }
+ cb.get(cbuf, off, len);
+ return len;
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/common-core/src/main/java/org/teiid/core/util/InputStreamReader.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/common-core/src/main/java/org/teiid/core/util/ReaderInputStream.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/util/ReaderInputStream.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/common-core/src/main/java/org/teiid/core/util/ReaderInputStream.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -47,15 +47,15 @@
private char[] charBuffer;
private AccessibleByteArrayOutputStream out = new AccessibleByteArrayOutputStream();
private boolean hasMore = true;
- private int pos = 0;
+ private int pos;
- public ReaderInputStream(Reader reader, Charset charSet) {
- this(reader, charSet, DEFAULT_BUFFER_SIZE);
+ public ReaderInputStream(Reader reader, Charset charset) {
+ this(reader, charset, DEFAULT_BUFFER_SIZE);
}
- public ReaderInputStream(Reader reader, Charset charSet, int bufferSize) {
+ public ReaderInputStream(Reader reader, Charset charset, int bufferSize) {
this.reader = reader;
- this.writer = new OutputStreamWriter(out, charSet);
+ this.writer = new OutputStreamWriter(out, charset);
this.charBuffer = new char[bufferSize];
}
Deleted: trunk/documentation/quick-start-example/src/main/docbook/en-US/images/EmbeddedDesignerExampleVideo.swf
===================================================================
(Binary files differ)
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml 2010-06-18 01:43:01 UTC (rev 2243)
@@ -801,27 +801,6 @@
</row>
<row>
<entry>
- <para>ENCODE(x, encoding)</para>
- </entry>
- <entry>
- <para>Return a clob from the blob with the given encoding. The builtin Java Charset<footnote id="charset"><para>See the <ulink url="http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/Charset.html">Charset JavaDoc</ulink></para></footnote> names are valid values for encoding.</para>
- </entry>
- <entry>
- <para>x is a blob, encoding is a string, and returns a clob</para>
- </entry>
- </row><row>
- <entry>
- <para>DECODE(x, encoding)</para>
- </entry>
- <entry>
- <para>Return a blob from the clob with the given encoding. The builtin Java Charset<footnoteref linkend="charset"/> names are valid values for encoding.</para>
- </entry>
- <entry>
- <para>x in a clob, encoding is a string, and returns a blob</para>
- </entry>
- </row>
- <row>
- <entry>
<para>INITCAP(x)</para>
</entry>
<entry>
@@ -1046,6 +1025,27 @@
</row>
<row>
<entry>
+ <para>TO_CHARS(x, encoding)</para>
+ </entry>
+ <entry>
+ <para>Return a clob from the blob with the given encoding. BASE64, HEX, and the builtin Java Charset<footnote id="charset"><para>See the <ulink url="http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/Charset.html">Charset JavaDoc</ulink></para></footnote> names are valid values for the encoding.</para>
+ </entry>
+ <entry>
+ <para>x is a blob, encoding is a string, and returns a clob</para>
+ </entry>
+ </row><row>
+ <entry>
+ <para>TO_BYTES(x, encoding)</para>
+ </entry>
+ <entry>
+ <para>Return a blob from the clob with the given encoding. BASE64, HEX, and the builtin Java Charset<footnoteref linkend="charset"/> names are valid values for the encoding.</para>
+ </entry>
+ <entry>
+ <para>x in a clob, encoding is a string, and returns a blob</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
<para>TRANSLATE(x, y, z)</para>
</entry>
<entry>
Added: trunk/engine/src/main/java/org/teiid/query/function/CharsetUtils.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/CharsetUtils.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/function/CharsetUtils.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -0,0 +1,205 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.function;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.util.Arrays;
+
+import org.teiid.core.util.Base64;
+
+public final class CharsetUtils {
+
+ public static final String HEX_NAME = "HEX"; //$NON-NLS-1$
+ static final char[] hex_alphabet = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ public static Charset HEX = new Charset(HEX_NAME, new String[0]) {
+
+ @Override
+ public CharsetEncoder newEncoder() {
+ return new FixedEncoder(this, 2, .5f, 1) {
+ char[] chars = new char[2];
+
+ @Override
+ protected void encode(ByteBuffer out) {
+ this.cb.get(chars);
+ out.put((byte)(Integer.parseInt(new String(chars), 16) & 0xff));
+ }
+
+ };
+ }
+
+ @Override
+ public CharsetDecoder newDecoder() {
+ return new FixedDecoder(this, 1, 2, 2) {
+
+ @Override
+ public void decode(CharBuffer out) {
+ byte b = this.bb.get();
+ toHex(out, b);
+ }
+
+ };
+ }
+
+ @Override
+ public boolean contains(Charset cs) {
+ return false;
+ }
+ };
+
+ public static void toHex(CharBuffer out, byte b) {
+ out.put(hex_alphabet[(b & 0xf0) >> 4]);
+ out.put(hex_alphabet[b & 0x0f]);
+ }
+
+ public static final String BASE64_NAME = "BASE64"; //$NON-NLS-1$
+ public static Charset BASE64 = new Charset(BASE64_NAME, new String[0]) {
+ @Override
+ public CharsetEncoder newEncoder() {
+ return new FixedEncoder(this, 4, .75f, 1) {
+
+ @Override
+ protected void encode(ByteBuffer out) {
+ out.put(Base64.decode(cb));
+ }
+
+ };
+ }
+
+ @Override
+ public CharsetDecoder newDecoder() {
+ return new FixedDecoder(this, 3, 1.25f, 3) {
+
+ @Override
+ public void decode(CharBuffer out) {
+ if (bb.limit() == bb.array().length) {
+ out.put(Base64.encodeBytes(bb.array()));
+ } else {
+ out.put(Base64.encodeBytes(Arrays.copyOf(bb.array(), bb.limit())));
+ }
+ }
+ };
+ }
+
+ @Override
+ public boolean contains(Charset cs) {
+ return false;
+ }
+ };
+
+ public static abstract class FixedEncoder extends CharsetEncoder {
+
+ protected CharBuffer cb;
+
+ protected FixedEncoder(Charset cs, int encodeChars, float averageBytesPerChar, float maxBytesPerChar) {
+ super(cs, averageBytesPerChar, maxBytesPerChar);
+ cb = CharBuffer.wrap(new char[encodeChars]);
+ }
+
+ @Override
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ while (in.hasRemaining()) {
+ cb.put(in.get());
+ if (!cb.hasRemaining()) {
+ if (!out.hasRemaining()) {
+ return CoderResult.OVERFLOW;
+ }
+ cb.flip();
+ encode(out);
+ cb.clear();
+ }
+ }
+ return CoderResult.UNDERFLOW;
+ }
+
+ abstract protected void encode(ByteBuffer out);
+
+ @Override
+ protected CoderResult implFlush(ByteBuffer out) {
+ if (cb.position() != 0) {
+ return CoderResult.unmappableForLength(cb.position());
+ }
+ return super.implFlush(out);
+ }
+
+ @Override
+ protected void implReset() {
+ cb.clear();
+ }
+
+ }
+
+ public static abstract class FixedDecoder extends CharsetDecoder {
+
+ protected ByteBuffer bb;
+
+ protected FixedDecoder(Charset cs, int decodeBytes,
+ float averageCharsPerByte,
+ float maxCharsPerByte) {
+ super(cs, averageCharsPerByte, maxCharsPerByte);
+ this.bb = ByteBuffer.wrap(new byte[decodeBytes]);
+ }
+
+ @Override
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ while (in.hasRemaining()) {
+ bb.put(in.get());
+ if (!bb.hasRemaining()) {
+ if (!out.hasRemaining()) {
+ return CoderResult.OVERFLOW;
+ }
+ bb.flip();
+ decode(out);
+ bb.clear();
+ }
+ }
+ return CoderResult.UNDERFLOW;
+ }
+
+ protected abstract void decode(CharBuffer out);
+
+ @Override
+ protected CoderResult implFlush(CharBuffer out) {
+ if (bb.position() != 0) {
+ if (!out.hasRemaining()) {
+ return CoderResult.OVERFLOW;
+ }
+ bb.flip();
+ decode(out);
+ bb.clear();
+ }
+ return super.implFlush(out);
+ }
+
+ @Override
+ protected void implReset() {
+ bb.clear();
+ }
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/engine/src/main/java/org/teiid/query/function/CharsetUtils.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -25,11 +25,7 @@
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Time;
@@ -53,14 +49,15 @@
import org.teiid.core.types.TransformationException;
import org.teiid.core.types.InputStreamFactory.BlobInputStreamFactory;
import org.teiid.core.types.InputStreamFactory.ClobInputStreamFactory;
-import org.teiid.core.util.Base64;
import org.teiid.core.util.TimestampWithTimezone;
import org.teiid.language.SQLConstants.NonReserved;
import org.teiid.query.QueryPlugin;
import org.teiid.query.util.CommandContext;
import org.teiid.query.util.ErrorMessageKeys;
-
+/**
+ * Static method hooks for most of the function library.
+ */
public final class FunctionMethods {
// ================== Function = plus =====================
@@ -1260,102 +1257,29 @@
return TimestampWithTimezone.createTimestamp(value, context.getServerTimeZone(), cal);
}
- public static Blob decode(ClobType value, String encoding) {
- /*if ("HEX".equalsIgnoreCase(encoding)) {
-
- }
- if ("BASE64".equalsIgnoreCase(encoding)) {
-
- }*/
- ClobInputStreamFactory cisf = new ClobInputStreamFactory(value.getReference());
- cisf.setCharset(Charset.forName(encoding));
- return new BlobType(new BlobImpl(cisf));
- }
-
- public static Clob encode(BlobType value, String encoding) {
- /*if ("HEX".equalsIgnoreCase(encoding)) {
-
- }
- if ("BASE64".equalsIgnoreCase(encoding)) {
-
- }*/
- BlobInputStreamFactory bisf = new BlobInputStreamFactory(value.getReference());
+ public static Clob toChars(BlobType value, String encoding) {
+ Charset cs = getCharset(encoding);
+ BlobInputStreamFactory bisf = new BlobInputStreamFactory(value.getReference());
ClobImpl clob = new ClobImpl(bisf, -1);
- clob.setEncoding(encoding);
+ clob.setCharset(cs);
return new ClobType(clob);
}
- public static class Base64Encoder extends CharsetEncoder {
-
- private CharBuffer cb = CharBuffer.wrap(new char[4]);
-
- protected Base64Encoder() {
- super(Charset.forName("US-ASCII"), .75f, 1); //$NON-NLS-1$
- }
-
- @Override
- protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
- while (in.hasRemaining()) {
- cb.put(in.get());
- if (!cb.hasRemaining()) {
- if (!out.hasRemaining()) {
- return CoderResult.OVERFLOW;
- }
- cb.position(0);
- out.put(Base64.decode(cb));
- cb.clear();
- }
- }
- return CoderResult.UNDERFLOW;
+ public static Blob toBytes(ClobType value, String encoding) {
+ Charset cs = getCharset(encoding);
+ ClobInputStreamFactory cisf = new ClobInputStreamFactory(value.getReference());
+ cisf.setCharset(cs);
+ return new BlobType(new BlobImpl(cisf));
+ }
+
+ public static Charset getCharset(String encoding) {
+ if (CharsetUtils.BASE64_NAME.equalsIgnoreCase(encoding)) {
+ return CharsetUtils.BASE64;
}
-
- @Override
- protected CoderResult implFlush(ByteBuffer out) {
- if (cb.position() != 0) {
- return CoderResult.unmappableForLength(cb.position());
- }
- return super.implFlush(out);
- }
- }
+ if (CharsetUtils.HEX_NAME.equalsIgnoreCase(encoding)) {
+ return CharsetUtils.HEX;
+ }
+ return Charset.forName(encoding);
+ }
-/* This does not seem to work, since the flush is never called
- public static class Base64Decoder extends CharsetDecoder {
-
- private ByteBuffer bb = ByteBuffer.wrap(new byte[3]);
-
- protected Base64Decoder() {
- super(Charset.forName("US-ASCII"), 1.25f, 3); //$NON-NLS-1$
- }
-
- @Override
- protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
- while (in.hasRemaining()) {
- bb.put(in.get());
- if (!bb.hasRemaining()) {
- if (!out.hasRemaining()) {
- return CoderResult.OVERFLOW;
- }
- bb.position(0);
- out.put(Base64.encodeBytes(bb.array()));
- bb.clear();
- }
- }
- return CoderResult.UNDERFLOW;
- }
-
- @Override
- protected CoderResult implFlush(CharBuffer out) {
- if (bb.position() != 0) {
- if (!out.hasRemaining()) {
- return CoderResult.OVERFLOW;
- }
- byte[] bytes = Arrays.copyOf(bb.array(), bb.position());
- out.put(Base64.encodeBytes(bytes));
- bb.clear();
- }
- return super.implFlush(out);
- }
- }
-*/
-
}
Modified: trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -144,8 +144,8 @@
addClobFunction("lower", QueryPlugin.Util.getString("SystemSource.LowerClob_result"), "lowerCase", DataTypeManager.DefaultDataTypes.CLOB); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
addClobFunction("upper", QueryPlugin.Util.getString("SystemSource.UpperClob_result"), "upperCase", DataTypeManager.DefaultDataTypes.CLOB); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- addEncodeFunction();
- addDecodeFunction();
+ addToCharsFunction();
+ addToBytesFunction();
// conversion
addConversionFunctions();
@@ -580,18 +580,18 @@
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Insert_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
- private void addEncodeFunction() {
+ private void addToCharsFunction() {
functions.add(
- new FunctionMethod("encode", QueryPlugin.Util.getString("SystemSource.encode_desc"), CONVERSION, FUNCTION_CLASS, "encode", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionMethod("to_chars", QueryPlugin.Util.getString("SystemSource.encode_desc"), CONVERSION, FUNCTION_CLASS, "toChars", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {
new FunctionParameter("value", DataTypeManager.DefaultDataTypes.BLOB, QueryPlugin.Util.getString("SystemSource.encode_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("encoding", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.encode_arg2"))}, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.CLOB, QueryPlugin.Util.getString("SystemSource.encode_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
- private void addDecodeFunction() {
+ private void addToBytesFunction() {
functions.add(
- new FunctionMethod("decode", QueryPlugin.Util.getString("SystemSource.decode_desc"), CONVERSION, FUNCTION_CLASS, "decode", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionMethod("to_bytes", QueryPlugin.Util.getString("SystemSource.decode_desc"), CONVERSION, FUNCTION_CLASS, "toBytes", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {
new FunctionParameter("value", DataTypeManager.DefaultDataTypes.CLOB, QueryPlugin.Util.getString("SystemSource.decode_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("encoding", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.decode_arg2"))}, //$NON-NLS-1$ //$NON-NLS-2$
Modified: trunk/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -74,6 +74,7 @@
import org.teiid.core.types.XMLType;
import org.teiid.core.types.XMLType.Type;
import org.teiid.query.eval.Evaluator;
+import org.teiid.query.function.CharsetUtils;
import org.teiid.query.function.FunctionMethods;
import org.teiid.query.processor.xml.XMLUtil;
import org.teiid.query.util.CommandContext;
@@ -522,7 +523,11 @@
}
private static String escapeChar(char chr) {
- return "_u00" + Integer.toHexString(chr).toUpperCase() + "_"; //$NON-NLS-1$ //$NON-NLS-2$
+ CharBuffer cb = CharBuffer.allocate(7);
+ cb.append("_u"); //$NON-NLS-1$
+ CharsetUtils.toHex(cb, (byte)(chr >> 8));
+ CharsetUtils.toHex(cb, (byte)chr);
+ return cb.append("_").flip().toString(); //$NON-NLS-1$
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -22,7 +22,6 @@
package org.teiid.query.validator;
-import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -46,6 +45,7 @@
import org.teiid.query.QueryPlugin;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.function.FunctionLibrary;
+import org.teiid.query.function.FunctionMethods;
import org.teiid.query.function.source.XMLSystemFunctions;
import org.teiid.query.metadata.SupportConstants;
import org.teiid.query.resolver.util.ResolverUtil;
@@ -348,9 +348,9 @@
handleValidationError(QueryPlugin.Util.getString("QueryResolver.invalid_xpath", e.getMessage()), obj); //$NON-NLS-1$
}
}
- } else if(obj.getFunctionDescriptor().getName().equalsIgnoreCase(SourceSystemFunctions.ENCODE) || obj.getFunctionDescriptor().getName().equalsIgnoreCase(SourceSystemFunctions.DECODE)) {
+ } else if(obj.getFunctionDescriptor().getName().equalsIgnoreCase(SourceSystemFunctions.TO_BYTES) || obj.getFunctionDescriptor().getName().equalsIgnoreCase(SourceSystemFunctions.TO_CHARS)) {
try {
- Charset.forName((String)((Constant)obj.getArg(1)).getValue());
+ FunctionMethods.getCharset((String)((Constant)obj.getArg(1)).getValue());
} catch (IllegalArgumentException e) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.invalid_encoding", obj.getArg(1)), obj); //$NON-NLS-1$
}
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-06-18 01:43:01 UTC (rev 2243)
@@ -3229,8 +3229,8 @@
<RPAREN>
)
|
- LOOKAHEAD(<ID>, {matchesAny(getToken(1).image, "encode", "decode") != null}) (
- funcName = nonReserved("ENCODE", "DECODE")
+ LOOKAHEAD(<ID>, {matchesAny(getToken(1).image, "to_chars", "to_bytes") != null}) (
+ funcName = nonReserved("TO_CHARS", "TO_BYTES")
<LPAREN>
expression = expression(info)
{
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-06-18 01:43:01 UTC (rev 2243)
@@ -811,14 +811,14 @@
SystemSource.coalesce_description=Returns the first non-null parameter
SystemSource.coalesce_param1=parameter
SystemSource.coalesce_result=The first non-null parameter
-SystemSource.encode_desc=Encodes the given Blob to a Clob
+SystemSource.encode_desc=Converts a Blob to the appropriate chars
SystemSource.encode_arg1=Blob
-SystemSource.encode_arg2=The encoding
-SystemSource.encode_result=The Clob
-SystemSource.decode_desc=Decodes a Clob to a Blob
+SystemSource.encode_arg2=char representation Clob
+SystemSource.encode_result=Clob char rep
+SystemSource.decode_desc=Converts a Clob to the appropriate bytes
SystemSource.decode_arg1=Clob
SystemSource.decode_arg2=The encoding
-SystemSource.decode_result=The Blob
+SystemSource.decode_result=byte representation Blob
TempMetadataAdapter.Element_____{0}_____not_found._1=Element ''{0}'' not found.
TempMetadataAdapter.Group_____{0}_____not_found._1=Group ''{0}'' not found.
ExpressionEvaluator.Must_push=Function {0} is marked in the function metadata as a function that must be evaluated at the source.
Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -52,6 +52,7 @@
import org.teiid.core.types.NullType;
import org.teiid.core.types.XMLType;
import org.teiid.core.types.DataTypeManager.DefaultDataClasses;
+import org.teiid.core.util.Base64;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.TimestampWithTimezone;
import org.teiid.language.SQLConstants.NonReserved;
@@ -1369,14 +1370,31 @@
}
@Test public void testEncode() throws Exception {
- Clob result = (Clob)helpInvokeMethod("encode", new Class[] {DefaultDataClasses.BLOB, DefaultDataClasses.STRING}, new Object[] { new BlobType(new SerialBlob("hello world".getBytes("ASCII"))), "ASCII" }, null); //$NON-NLS-1$
+ Clob result = (Clob)helpInvokeMethod("to_chars", new Class[] {DefaultDataClasses.BLOB, DefaultDataClasses.STRING}, new Object[] { new BlobType(new SerialBlob("hello world".getBytes("ASCII"))), "ASCII" }, null); //$NON-NLS-1$
String string = result.getSubString(1, (int)result.length());
assertEquals("hello world", string);
}
@Test public void testDecode() throws Exception {
- Blob result = (Blob)helpInvokeMethod("decode", new Class[] {DefaultDataClasses.CLOB, DefaultDataClasses.STRING}, new Object[] { new ClobType(new SerialClob("hello world".toCharArray())), "UTF32" }, null); //$NON-NLS-1$
+ Blob result = (Blob)helpInvokeMethod("to_bytes", new Class[] {DefaultDataClasses.CLOB, DefaultDataClasses.STRING}, new Object[] { new ClobType(new SerialClob("hello world".toCharArray())), "UTF32" }, null); //$NON-NLS-1$
assertEquals(44, result.length()); //4 bytes / char
}
+ @Test public void testEncode1() throws Exception {
+ Clob result = (Clob)helpInvokeMethod("to_chars", new Class[] {DefaultDataClasses.BLOB, DefaultDataClasses.STRING}, new Object[] { new BlobType(new SerialBlob("hello world".getBytes("ASCII"))), "BASE64" }, null); //$NON-NLS-1$
+ String string = result.getSubString(1, (int)result.length());
+ assertEquals("hello world", new String(Base64.decode(string), "ASCII"));
+ }
+
+ @Test public void testEncode2() throws Exception {
+ Clob result = (Clob)helpInvokeMethod("to_chars", new Class[] {DefaultDataClasses.BLOB, DefaultDataClasses.STRING}, new Object[] { new BlobType(new SerialBlob("hello world".getBytes("ASCII"))), "HEX" }, null); //$NON-NLS-1$
+ String string = result.getSubString(1, (int)result.length());
+ assertEquals("68656C6C6F20776F726C64", string);
+ }
+
+ @Test public void testDecode2() throws Exception {
+ Blob result = (Blob)helpInvokeMethod("to_bytes", new Class[] {DefaultDataClasses.CLOB, DefaultDataClasses.STRING}, new Object[] { new ClobType(new SerialClob("68656C6C6F20776F726C64".toCharArray())), "HEX" }, null); //$NON-NLS-1$
+ assertEquals("hello world", new String(ObjectConverterUtil.convertToCharArray(result.getBinaryStream(), -1, "ASCII")));
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/function/source/TestXMLSystemFunctions.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/source/TestXMLSystemFunctions.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/test/java/org/teiid/query/function/source/TestXMLSystemFunctions.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -209,6 +209,10 @@
assertEquals("a_u005F_x", XMLSystemFunctions.escapeName("a_x", true));
}
+ @Test public void testNameEscaping2() throws Exception {
+ assertEquals("_u000A_", XMLSystemFunctions.escapeName(new String(new char[] {10}), true));
+ }
+
@BeforeClass static public void setUpOnce() {
TimeZone.setDefault(TimeZone.getTimeZone("GMT-6:00"));
}
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2010-06-17 20:14:18 UTC (rev 2242)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2010-06-18 01:43:01 UTC (rev 2243)
@@ -2036,7 +2036,7 @@
}
@Test public void testDecode() throws Exception {
- helpValidate("select decode(e1, '?') from pm1.g1", new String[] {"decode(e1, '?')"}, FakeMetadataFactory.example1Cached());
+ helpValidate("select to_bytes(e1, '?') from pm1.g1", new String[] {"to_bytes(e1, '?')"}, FakeMetadataFactory.example1Cached());
}
}
14 years, 7 months
teiid SVN: r2242 - trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/impl.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-06-17 16:14:18 -0400 (Thu, 17 Jun 2010)
New Revision: 2242
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/impl/ConnectorManager.java
Log:
TEIID-1124: when the connection name does not start with the "java:" prefix automatically add it then do the look up. If in case that is not found, fall back and lookup with original name supplied.
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/impl/ConnectorManager.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/impl/ConnectorManager.java 2010-06-17 18:51:53 UTC (rev 2241)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/impl/ConnectorManager.java 2010-06-17 20:14:18 UTC (rev 2242)
@@ -67,6 +67,8 @@
*/
public class ConnectorManager {
+ private static final String JAVA_CONTEXT = "java:"; //$NON-NLS-1$
+
public static final int DEFAULT_MAX_THREADS = 20;
private static AtomicInteger ID_SEQUENCE = new AtomicInteger();
@@ -276,9 +278,20 @@
*/
protected Object getConnectionFactory() {
if (this.connectionName != null) {
- try {
- InitialContext ic = new InitialContext();
- return ic.lookup(this.connectionName);
+ String jndiName = this.connectionName;
+ if (!this.connectionName.startsWith(JAVA_CONTEXT)) {
+ jndiName = JAVA_CONTEXT + jndiName;
+ }
+
+ try {
+ InitialContext ic = new InitialContext();
+ try {
+ return ic.lookup(jndiName);
+ } catch (NamingException e) {
+ if (!jndiName.equals(this.connectionName)) {
+ return ic.lookup(this.connectionName);
+ }
+ }
} catch (NamingException e) {
}
}
14 years, 7 months
teiid SVN: r2241 - in trunk/documentation: admin-guide/src/main/docbook/en-US/content and 1 other directories.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-06-17 14:51:53 -0400 (Thu, 17 Jun 2010)
New Revision: 2241
Added:
trunk/documentation/admin-guide/src/main/docbook/en-US/content/logging.xml
trunk/documentation/admin-guide/src/main/docbook/en-US/content/security.xml
Modified:
trunk/documentation/admin-guide/src/main/docbook/en-US/admin_guide.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/logging.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/security.xml
Log:
TEIID-315: adding the parts of the logging and security to the admin guide and leaving the customizing parts in the developer's guide.
Modified: trunk/documentation/admin-guide/src/main/docbook/en-US/admin_guide.xml
===================================================================
--- trunk/documentation/admin-guide/src/main/docbook/en-US/admin_guide.xml 2010-06-17 18:35:22 UTC (rev 2240)
+++ trunk/documentation/admin-guide/src/main/docbook/en-US/admin_guide.xml 2010-06-17 18:51:53 UTC (rev 2241)
@@ -29,7 +29,7 @@
]>
<book>
-
+
<bookinfo>
<title>Teiid - Scalable Information Integration</title>
<subtitle>Teiid Administrator's Guide</subtitle>
@@ -47,6 +47,8 @@
<xi:include href="content/installation.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/vdb-deployment.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="content/security.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="content/logging.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/admin-console.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/adminshell-introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/getting-started.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
Added: trunk/documentation/admin-guide/src/main/docbook/en-US/content/logging.xml
===================================================================
--- trunk/documentation/admin-guide/src/main/docbook/en-US/content/logging.xml (rev 0)
+++ trunk/documentation/admin-guide/src/main/docbook/en-US/content/logging.xml 2010-06-17 18:51:53 UTC (rev 2241)
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../../../../../../docbook/custom.dtd">
+%CustomDTD;
+]>
+<chapter id="logging">
+ <title>Logging</title>
+ <sect1 id="general_logging">
+ <title>General Logging</title>
+ <para>
+ The Teiid system provides a wealth of information via logging. To
+ control logging level, contexts, and log locations, you should be
+ familiar with
+ <ulink url="http://logging.apache.org/log4j/">log4j</ulink>
+ and the container's jboss-log4j.xml configuration file.
+ Teiid also provides a <profile>/conf/jboss-teiid-log4j.xml containing much of information from chapter.
+ </para>
+ <para>
+ All the logs
+ produced by Teiid are prefixed by "org.teiid". This makes it extremely
+ easy to control of of Teiid logging from a single context. Note however that changes to the log configuration file
+ require a restart to take affect
+ </para>
+ <sect2>
+ <title>Logging Contexts</title>
+ <para>While all of Teiid's logs are prefixed with "org.teiid", there
+ are more specific contexts depending on the functional area of the
+ system. Note that logs originating from third-party code, including
+ integrated org.jboss components, will be logged through their
+ respective contexts and not through org.teiid. See the table below for information on contexts
+ relevant to Teiid. See the container's jboss-log4j.xml for a more
+ complete listing of logging contexts used in the container.
+ </para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>
+ <para>Context</para>
+ </entry>
+ <entry>
+ <para>Description</para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>com.arjuna</para>
+ </entry>
+ <entry>
+ <para>Third-party transaction manager. This will include
+ information about all transactions, not just those for Teiid.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid</para>
+ </entry>
+ <entry>
+ <para>Root context for all Teiid logs. Note: there are
+ potentially other contexts used under org.teiid than are shown
+ in this table.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.PROCESSOR</para>
+ </entry>
+ <entry>
+ <para>Query processing logs. See also org.teiid.PLANNER for
+ query planning logs.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.PLANNER</para>
+ </entry>
+ <entry>
+ <para>Query planning logs.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.SECURITY</para>
+ </entry>
+ <entry>
+ <para>Session/Authentication events - see also AUDIT logging</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.TRANSPORT</para>
+ </entry>
+ <entry>
+ <para>Events related to the socket transport.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.RUNTIME</para>
+ </entry>
+ <entry>
+ <para>Events related to work management and system start/stop.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.CONNECTOR</para>
+ </entry>
+ <entry>
+ <para>Connector logs.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.BUFFER_MGR</para>
+ </entry>
+ <entry>
+ <para>Buffer and storage management logs.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.TXN_LOG</para>
+ </entry>
+ <entry>
+ <para>Detail log of all transaction operations.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.COMMAND_LOG</para>
+ </entry>
+ <entry>
+ <para>
+ See
+ <link linkend="command_logigng">command logging</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.AUDIT_LOG</para>
+ </entry>
+ <entry>
+ <para>
+ See
+ <link linkend="audit_logigng">audit logging</link>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>org.teiid.ADMIN_API</para>
+ </entry>
+ <entry>
+ <para>Admin API logs.</para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect2>
+ </sect1>
+ <sect1 id="command_logging">
+ <title>Command Logging</title>
+ <para>Command logging captures executing commands in the Teiid System.
+ Both user commands (that have been submitted to Teiid) and data source
+ commands (that are being executed by the connectors) are tracked
+ through command logging.</para>
+ <para>To enable command logging to the default log location, simply
+ enable the DETAIL level of logging for the org.teiid.COMMAND_LOG
+ context.</para>
+ <para>
+ To enable command logging to an alternative file location,
+ configure a separate file appender for the DETAIL logging of the
+ org.teiid.COMMAND_LOG context. An example of this is shown below and
+ can also be found in the jboss-log4j.xml distributed with Teiid.
+ <programlisting><![CDATA[
+ <appender name="COMMAND" class="org.apache.log4j.RollingFileAppender">
+ <param name="File" value="log/command.log"/>
+ <param name="MaxFileSize" value="1000KB"/>
+ <param name="MaxBackupIndex" value="25"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d %p [%t] %c - %m%n"/>
+ </layout>
+ </appender>
+
+ <category name="org.teiid.COMMAND_LOG">
+ <priority value="INFO"/>
+ <appender-ref ref="COMMAND"/>
+ </category>
+ ]]>
+ </programlisting>
+
+ See Developer's Guide if the file based logging is not sufficient and would need a custom logging solution.
+ </para>
+ </sect1>
+ <sect1 id="audit_logging">
+ <title>Audit Logging</title>
+ <para>Audit logging captures important security events. This includes
+ the enforcement of permissions, authentication success/failures, etc.
+ </para>
+ <para>To enable audit logging to the default log location, simply
+ enable the DETAIL level of logging for the org.teiid.AUDIT_LOG
+ context.</para>
+ <para>To enable audit logging to an alternative file location,
+ configure a separate file appender for the DETAIL logging of the
+ org.teiid.AUDIT_LOG context. An example of this is already in
+ the log4j.xml distributed with Teiid. See Developer's Guide if the
+ file based logging is not sufficient and would need a custom logging solution.</para>
+ </sect1>
+</chapter>
\ No newline at end of file
Property changes on: trunk/documentation/admin-guide/src/main/docbook/en-US/content/logging.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/documentation/admin-guide/src/main/docbook/en-US/content/security.xml
===================================================================
--- trunk/documentation/admin-guide/src/main/docbook/en-US/content/security.xml (rev 0)
+++ trunk/documentation/admin-guide/src/main/docbook/en-US/content/security.xml 2010-06-17 18:51:53 UTC (rev 2241)
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="custom_security">
+ <title>Teiid Security</title>
+ <para>The Teiid system provides a range of built-in and extensible security features to enable the
+ secure access of data. </para>
+ <sect1>
+ <title>Authentication</title>
+ <para>JDBC clients may use simple passwords to authenticate a user.</para>
+ <para>Typically a user name is required, however user names may be considered optional if the
+ identity of the user can be discerned by the password credential alone. In
+ any case it is up to the configured security domain to determine whether a user can be
+ authenticated.</para>
+ </sect1>
+ <sect1>
+ <title>Authorization</title>
+ <para>Authorization covers both administrative activities and data
+ roles. A data role is a collection of permissions (also referred to as entitlements) and a
+ collection of entitled principals or groups. With the deployment of a VDB
+ the deployer can choose which principals and groups have which data roles.</para>
+ </sect1>
+ <sect1>
+ <title>Encryption</title>
+ <para>At a transport level Teiid provides built-in support for JDBC
+ over SSL or just sensitive message encryption when SSL is not in use.
+ </para>
+ <para>
+ Passwords in configuration files however are by default stored in
+ plain text. If you need these values to be encrypted, please see
+ <ulink
+ url="http://community.jboss.org/wiki/maskingpasswordsinjbossasxmlconfiguration">encrypting passwords</ulink>
+ for instructions on encryption facilities provided by the container.
+ </para>
+ </sect1>
+ <sect1>
+ <title>LoginModules</title>
+ <para>
+ LoginModules are an essential part of the JAAS security
+ framework and provide Teiid customizable user authentication and the
+ ability to reuse existing LoginModules defined for JBossAS. See
+ <ulink
+ url="http://docs.jboss.org/jbossas/admindevel326/html/ch8.chapter.html">JBossAS Security</ulink>
+ for general information on configuring security in JBossAS.</para>
+ <para>
+ Teiid can be configured with multiple named application policies
+ that group together relevant LoginModules. Each of these application
+ policy (or domains) names can be used to fully
+ qualify user names to
+ authenticate only against that domain. The format for a qualified
+ name is username@domainname.
+ </para>
+ <para>If a user name is not fully qualified, then the installed
+ domains will be consulted in order until a domain
+ successfully or unsuccessfully authenticates the
+ user.
+ </para>
+ <para>If no domain can authenticate the user, the logon
+ attempt will fail.
+ Details of the failed attempt including invalid users, which
+ domains were consulted, etc. will be in the server log with appropriate
+ levels of severity.</para>
+ <sect2>
+ <title>Built-in LoginModules</title>
+ <para>JBossAS provides several LoginModules for common authentication needs, such as authenticating from text files or LDAP.</para>
+ <para>The UsersRolesLoginModule, which utilizes simple text files
+ to authenticate users and to define
+ their groups. The teiid-jboss-beans.xml configuration file contains an example of how to use UsersRolesLoginModule.
+ Note that this is typically not for production use.
+ </para>
+ <para>See <ulink url="http://community.jboss.org/docs/DOC-11253">LDAP LoginModule configuration</ulink> for utilizing LDAP based authentication.
+ If you want use a your own Custom Login module, check out the Developer's Guide for instructions.
+ </para>
+ </sect2>
+ </sect1>
+ <note>
+ <para>The security-domain defined for the JDBC connection and Admin connections are separate.
+ The default name of JDBC connection's security-domain is "teiid-security". The default name for Admin connection
+ is "jmx-console". For the Admin connection's security domain, the user is allowed
+ to change which LoginModule that "jmx-console" pointing to, however should not change the name of the domain, as this name is
+ shared between the "admin-console" application.</para>
+ </note>
+</chapter>
\ No newline at end of file
Property changes on: trunk/documentation/admin-guide/src/main/docbook/en-US/content/security.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/logging.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/logging.xml 2010-06-17 18:35:22 UTC (rev 2240)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/logging.xml 2010-06-17 18:51:53 UTC (rev 2241)
@@ -5,8 +5,8 @@
]>
<chapter id="logging">
<title>Logging</title>
- <sect1 id="general_logging">
- <title>General Logging</title>
+ <sect1 id="custom_logging">
+ <title>Customized Logging</title>
<para>
The Teiid system provides a wealth of information via logging. To
control logging level, contexts, and log locations, you should be
@@ -14,265 +14,38 @@
<ulink url="http://logging.apache.org/log4j/">log4j</ulink>
and the container's jboss-log4j.xml configuration file.
Teiid also provides a <profile>/conf/jboss-teiid-log4j.xml containing much of information from chapter.
+ Check out Admin Guide for more details about different Teiid contexts available.
</para>
- <para>
- All the logs
- produced by Teiid are prefixed by org.teiid. This
- makes it extremely
- easy to control of of Teiid logging from a single
- context. Note however that changes to the log configuration file
- require a restart to take affect
+
+ <para>
+ If the default log4j logging mechanisms are not sufficient for your
+ logging needs you may need a different appender - see
+ <ulink url="http://logging.apache.org/log4j/1.2/apidocs/index.html">the log4j javadocs</ulink>.
+ Note that log4j already provides quite a few appenders including JMS, RDBMS, and SMTP.
</para>
- <sect2>
- <title>Logging Contexts</title>
- <para>While all of Teiid's logs are prefixed with org.teiid, there
- are more specific contexts depending on the functional area of the
- system. Note that logs originating from third-party code, including
- integrated org.jboss components, will be logged through their
- respective contexts and not through org.teiid. See the table below for information on contexts
- relevant to Teiid. See the container's jboss-log4j.xml for a more
- complete listing of logging contexts used in the container.
- </para>
- <informaltable frame="all">
- <tgroup cols="2">
- <thead>
- <row>
- <entry>
- <para>Context</para>
- </entry>
- <entry>
- <para>Description</para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>com.arjuna</para>
- </entry>
- <entry>
- <para>Third-party transaction manager. This will include
- information about all transactions, not just those for Teiid.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid</para>
- </entry>
- <entry>
- <para>Root context for all Teiid logs. Note: there are
- potentially other contexts used under org.teiid than are shown
- in this table.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.PROCESSOR</para>
- </entry>
- <entry>
- <para>Query processing logs. See also org.teiid.PLANNER for
- query planning logs.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.PLANNER</para>
- </entry>
- <entry>
- <para>Query planning logs.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.SECURITY</para>
- </entry>
- <entry>
- <para>Session/Authentication events - see also AUDIT logging</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.TRANSPORT</para>
- </entry>
- <entry>
- <para>Events related to the socket transport.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.RUNTIME</para>
- </entry>
- <entry>
- <para>Events related to work management and system start/stop.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.CONNECTOR</para>
- </entry>
- <entry>
- <para>Connector logs.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.BUFFER_MGR</para>
- </entry>
- <entry>
- <para>Buffer and storage management logs.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.TXN_LOG</para>
- </entry>
- <entry>
- <para>Detail log of all transaction operations.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.COMMAND_LOG</para>
- </entry>
- <entry>
- <para>
- See
- <link linkend="command_logigng">command logging</link>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.AUDIT_LOG</para>
- </entry>
- <entry>
- <para>
- See
- <link linkend="audit_logigng">audit logging</link>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>org.teiid.ADMIN_API</para>
- </entry>
- <entry>
- <para>Admin API logs.</para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect2>
- <sect2>
- <title>Command Logging API</title>
- <para>
- If the default log4j logging mechanisms are not sufficient for your
- logging needs you may need a appender - see
- <ulink url="http://logging.apache.org/log4j/1.2/apidocs/index.html">the log4j javadocs</ulink>
- . Note that log4j already provides quite a few appenders including
- JMS, RDBMS, and SMTP.
- </para>
- <para>If you develop a custom logging solution, the implementation
- jar should be placed in the lib directory of the server profile
- Teiid is installed in.
- </para>
- </sect2>
+ <para>If you want a custom appender, follow the Log4J directions to write a custom appender. See instructions
+ <ulink url="http://logging.apache.org/log4net/release/faq.html">here</ulink>. If you develop a custom
+ logging solution, the implementation jar should be placed in the "lib" directory of the JBoss AS server profile
+ Teiid is installed in.
+ </para>
+
+ <sect2>
+ <title>Command Logging API</title>
+ <para>
+ If you want to build a custom appender for command logging that will have access to
+ log4j "LoggingEvents" to the "COMMAND_LOG" context, it will have a message that is an instance of
+ <code>org.teiid.logging.CommandLogMessage</code> defined in the <code>teiid-api-&versionNumber;.jar</code>
+ use these class in your development. The CommmdLogMessage include information about vdb, session, command-sql etc.
+ </para>
+ </sect2>
+
+ <sect2 id="audit_logging">
+ <title>Audit Logging API</title>
+ <para>If you want to build a custom appender for command logging that will have access to
+ log4j "LoggingEvents" to the "AUDIT_LOG" context, it will have a message that is an instance of
+ <code>org.teiid.logging.AuditMessage</code> defined in the <code>teiid-api-&versionNumber;.jar</code>
+ use this class in your development. AuditMessage include information about user, the action, and the
+ target(s) of the action.</para>
+ </sect2>
</sect1>
- <sect1 id="command_logging">
- <title>Command Logging</title>
- <para>Command logging captures executing commands in the
- Teiid System.
- Both user commands (that have been submitted
- to Teiid)
- and data source
- commands (that are being executed by the
- connectors)
- are tracked
- through command logging.</para>
- <para>To enable command logging to the default log location, simply
- enable the DETAIL level of logging for the org.teiid.COMMAND_LOG
- context.</para>
- <para>
- To enable command logging to an alternative file location,
- configure a
- separate file appender for the DETAIL logging of the
- org.teiid.COMMAND_LOG context. An example of this is shown below and
- can also be found in the jboss-log4j.xml distributed with Teiid.
- <programlisting><![CDATA[
- <appender name="COMMAND" class="org.apache.log4j.RollingFileAppender">
- <param name="File" value="log/command.log"/>
- <param name="MaxFileSize" value="1000KB"/>
- <param name="MaxBackupIndex" value="25"/>
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%d %p [%t] %c - %m%n"/>
- </layout>
- </appender>
-
- <category name="org.teiid.COMMAND_LOG">
- <priority value="INFO"/>
- <appender-ref ref="COMMAND"/>
- </category>
- ]]>
- </programlisting>
- </para>
- <sect2>
- <title>Command Logging API</title>
- <para>
- If the default log4j logging mechanisms are not sufficient for
- your
- command logging needs, you may need a custom log4j appender.
- The
- custom appender will have access to log4j LoggingEvents to the
- COMMAND_LOG context, which have a
- message that is an instance of
- org.teiid.logging.api.CommandLogMessage defined in the
- teiid-connector-api-&versionNumber;.jar.
- </para>
- <para>
- See
- <link linkend="general_logging">General Logging</link>
- for more information on utilizing log4j.
- </para>
- </sect2>
- </sect1>
- <sect1 id="audit_logging">
- <title>Audit Logging</title>
- <para>Audit logging captures important security events. This includes
- the enforcement of permissions, authentication success/failures, etc.
- </para>
- <para>To enable audit logging to the default log location, simply
- enable the DETAIL level of logging for the org.teiid.AUDIT_LOG
- context.</para>
- <para>To enable audit logging to an alternative file location,
- configure a separate file appender for the DETAIL logging of the
- org.teiid.AUDIT_LOG context. An example of this is already in
- the
- log4j.xml distributed with Teiid.</para>
- <sect2>
- <title>Audit Logging API</title>
- <para>
- If the default log4j logging mechanisms are not sufficient for
- your
- audit logging needs, you may need a custom log4j appender.
- The
- custom
- appender will have access to log4j LoggingEvents to the
- AUDIT_LOG
- context, which have a
- message that is an instance of
- org.teiid.logging.api.AuditMessage defined in the
- teiid-connector-api-&versionNumber;.jar.
- AuditMessages include
- information about user, the action, and the
- target(s) of the action.
- </para>
- <para>
- See
- <link linkend="general_logging">General Logging</link>
- for more information on utilizing log4j.
- </para>
- </sect2>
- </sect1>
</chapter>
\ No newline at end of file
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/security.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/security.xml 2010-06-17 18:35:22 UTC (rev 2240)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/security.xml 2010-06-17 18:51:53 UTC (rev 2241)
@@ -1,93 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="custom_security">
- <title>Teiid Security</title>
- <para>The Teiid system provides a range of built-in and extensible
- security features to enable the
- secure access of data. </para>
- <sect1>
- <title>Authentication</title>
- <para>JDBC clients may use simple passwords to authenticate a user.
- </para>
- <para>Typically a user name is required, however user names may be
- considered optional if the
- identity of the user can be discerned by
- the password credential alone. In
- any case it is up
- to the configured
- security domain to determine whether a user can be
- authenticated.
- </para>
- </sect1>
- <sect1>
- <title>Authorization</title>
- <para>Authorization covers both administrative activities and
- data
- roles. A data role is a collection of permissions (also referred to
- as entitlements) and a
- collection of entitled principals or groups.
- With the deployment of a VDB
- the deployer can choose which principals
- and groups have which data roles.</para>
- </sect1>
- <sect1>
- <title>Encryption</title>
- <para>At a transport level Teiid provides built-in support for JDBC
- over SSL or just sensitive message encryption when SSL is not in use.
- </para>
- <para>
- Passwords in configuration files however are by default stored in
- plain text. If you need these values to be encrypted, please see
- <ulink
- url="http://community.jboss.org/wiki/maskingpasswordsinjbossasxmlconfiguration">encrypting passwords</ulink>
- for instructions on encryption facilities provided by the container.
- </para>
- </sect1>
- <sect1>
- <title>LoginModules</title>
- <para>
- LoginModules are an essential part of the JAAS security
- framework and provide Teiid customizable user authentication and the
- ability to reuse existing LoginModules defined for JBossAS. See
- <ulink
- url="http://docs.jboss.org/jbossas/admindevel326/html/ch8.chapter.html">JBossAS Security</ulink>
- for general information on configuring security in JBossAS.</para>
- <para>
- Teiid can be configured with multiple named application policies
- that group together relevant LoginModules. Each of these application
- policy (or domains) names can be used to fully
- qualify user names to
- authenticate only against that domain. The format for a qualified
- name is username@domainname.
- </para>
- <para>If a user name is not fully qualified, then the installed
- domains will be consulted in order until a domain
- successfully or unsuccessfully authenticates the
- user.
- </para>
- <para>If no domain can authenticate the user, the logon
- attempt will fail.
- Details of the failed attempt including invalid users, which
- domains were consulted, etc. will be in the server log with appropriate
- levels of severity.</para>
- <sect2>
+<chapter id="custom_login_modules">
+ <title>Login Modules</title>
+ <para>The Teiid system provides a range of built-in and extensible security features to enable the
+ secure access of data. For details about how to configure the available security features check out
+ Admin Guide.</para>
+ <para>
+ LoginModules are an essential part of the JAAS security
+ framework and provide Teiid customizable user authentication and the
+ ability to reuse existing LoginModules defined for JBossAS. See
+ <ulink
+ url="http://docs.jboss.org/jbossas/admindevel326/html/ch8.chapter.html">JBossAS Security</ulink>
+ for general information on configuring security in JBossAS.</para>
+
+ <sect1>
<title>Built-in LoginModules</title>
- <para>JBossAS provides several LoginModules for common authentication needs, such as authenticating from text files or LDAP.</para>
- <para>The UsersRolesLoginModule, which utilizes simple text files
- to authenticate users and to define
- their groups. The teiid-jboss-beans.xml configuration file contains an example of how to use UsersRolesLoginModule.
- Note that this is typically not for production use.
- </para>
- <para>See <ulink url="http://community.jboss.org/docs/DOC-11253">LDAP LoginModule configuration</ulink> for utilizing LDAP based authentication.
- </para>
- </sect2>
- <sect2>
+ <para>JBossAS provides several LoginModules for common authentication needs, such as authenticating from text files or LDAP.
+ The below are are some of the available in JBoss AS </para>
+
+ <para>See for all the available <ulink url="http://community.jboss.org/docs/DOC-11287"> login modules.</ulink></para>
+
+ <para>See <ulink url="http://community.jboss.org/docs/DOC-12510">UserRoles LoginModule configuration</ulink>
+ for utilizing simple file based authentication.</para>
+ <para>See <ulink url="http://community.jboss.org/docs/DOC-11253">LDAP LoginModule configuration</ulink> for
+ utilizing LDAP based authentication. </para>
+ <para>See <ulink url="http://community.jboss.org/docs/DOC-9511">Database LoginModule configuration</ulink> for
+ utilizing Database based authentication. </para>
+
+ <para>See <ulink url="http://community.jboss.org/docs/DOC-9160">Cert LoginModule configuration</ulink> for
+ utilizing X509 certificate based authentication. </para>
+ </sect1>
+ <sect1>
<title>Custom LoginModules</title>
<para>
If your authentication needs go beyond the provided LoginModules, please consult the
<ulink url="http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/JAASLMDevGuide.html">JAAS development guide</ulink>.
There are also numerous guides available.
</para>
- </sect2>
- </sect1>
+
+ <para>If you are extending one of the built-in LoginModules, please see
+ <ulink url="http://community.jboss.org/docs/DOC-9466">this</ulink>.</para>
+ </sect1>
</chapter>
\ No newline at end of file
14 years, 7 months
teiid SVN: r2240 - in trunk: build/kits/jboss-container/teiid-examples/portfolio/data and 5 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-06-17 14:35:22 -0400 (Thu, 17 Jun 2010)
New Revision: 2240
Added:
trunk/client/src/test/java/org/teiid/jdbc/TestCallableStatement.java
trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java
trunk/client/src/test/java/org/teiid/jdbc/TestJDBCURL.java
trunk/client/src/test/java/org/teiid/jdbc/TestPreparedStatement.java
trunk/client/src/test/java/org/teiid/jdbc/TestResultSet.java
trunk/client/src/test/java/org/teiid/jdbc/TestSQLException.java
trunk/client/src/test/java/org/teiid/jdbc/TestStatement.java
trunk/client/src/test/java/org/teiid/jdbc/TestXAConnection.java
Removed:
trunk/client/src/test/java/org/teiid/jdbc/TestMMCallableStatement.java
trunk/client/src/test/java/org/teiid/jdbc/TestMMConnection.java
trunk/client/src/test/java/org/teiid/jdbc/TestMMJDBCURL.java
trunk/client/src/test/java/org/teiid/jdbc/TestMMPreparedStatement.java
trunk/client/src/test/java/org/teiid/jdbc/TestMMResultSet.java
trunk/client/src/test/java/org/teiid/jdbc/TestMMSQLException.java
trunk/client/src/test/java/org/teiid/jdbc/TestMMStatement.java
trunk/client/src/test/java/org/teiid/jdbc/TestMMXAConnection.java
trunk/common-core/src/test/java/org/teiid/api/
trunk/common-core/src/test/java/org/teiid/common/
Modified:
trunk/build/kits/jboss-container/teiid-examples/portfolio/customer-schema.sql
trunk/build/kits/jboss-container/teiid-examples/portfolio/data/marketdata-price.txt
trunk/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java
trunk/client/src/test/java/org/teiid/jdbc/TestAllResultsImpl.java
trunk/common-core/src/main/java/org/teiid/core/types/BlobImpl.java
trunk/common-core/src/main/java/org/teiid/core/types/ClobImpl.java
trunk/common-core/src/test/java/org/teiid/core/types/TestBlobValue.java
trunk/common-core/src/test/java/org/teiid/core/types/TestClobValue.java
Log:
TEIID-1021 fix for resultsetimpl regression with the xmltype. fixing an issue with substream reading with blobs/clobs. Also updating the text example.
Modified: trunk/build/kits/jboss-container/teiid-examples/portfolio/customer-schema.sql
===================================================================
--- trunk/build/kits/jboss-container/teiid-examples/portfolio/customer-schema.sql 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/build/kits/jboss-container/teiid-examples/portfolio/customer-schema.sql 2010-06-17 18:35:22 UTC (rev 2240)
@@ -88,9 +88,9 @@
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1002,'BA','The Boeing Company');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1003,'MON','Monsanto Company');
-INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1004,'ORCL','Oracle Corporation');
+INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1004,'PNRA','Panera Bread Company');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1005,'SY','Sybase Incorporated');
-INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1006,'MSFT','Microsoft Corporation');
+INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1006,'BTU','Peabody Energy');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1007,'IBM','International Business Machines Corporation');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1008,'DELL','Dell Computer Corporation');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1010,'HPQ','Hewlett-Packard Company');
@@ -101,7 +101,6 @@
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1015,'MCD','McDonalds Corporation');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1016,'DOW','Dow Chemical Company');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1018,'GM','General Motors Corporation');
-INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1022,'JAVA','Sun Microsystems Incorporated');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1024,'SBGI','Sinclair Broadcast Group Incorporated');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1025,'COLM','Columbia Sportsware Company');
INSERT INTO PRODUCT (ID,SYMBOL,COMPANY_NAME) VALUES(1026,'COLB','Columbia Banking System Incorporated');
Modified: trunk/build/kits/jboss-container/teiid-examples/portfolio/data/marketdata-price.txt
===================================================================
--- trunk/build/kits/jboss-container/teiid-examples/portfolio/data/marketdata-price.txt 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/build/kits/jboss-container/teiid-examples/portfolio/data/marketdata-price.txt 2010-06-17 18:35:22 UTC (rev 2240)
@@ -2,9 +2,9 @@
RHT,30.00
BA,42.75
MON,78.75
-ORCL,16.54
+PNRA,84.97
SY,24.30
-MSFT,20.60
+BTU,41.25
IBM,80.89
DELL,10.75
HPQ,31.52
Modified: trunk/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -286,9 +286,9 @@
// defect 13539 - set the currentValue (defined in MMResultSet) so that wasNull() accurately returns whether this value was null
currentValue = cursorRow.get(column-1);
- if (currentValue instanceof Streamable) {
+ if (currentValue instanceof Streamable<?>) {
if (Boolean.getBoolean(Streamable.FORCE_STREAMING)) {
- Object reference = ((Streamable)currentValue).getReference();
+ Object reference = ((Streamable<?>)currentValue).getReference();
if (reference != null) {
currentValue = reference;
return currentValue;
@@ -303,8 +303,9 @@
currentValue = new BlobImpl(isf);
}
else if (currentValue instanceof XMLType) {
- currentValue = new SQLXMLImpl(createInputStreamFactory((XMLType)currentValue));
- ((SQLXMLImpl)currentValue).setEncoding(((XMLType)currentValue).getEncoding());
+ XMLType val = (XMLType)currentValue;
+ currentValue = new SQLXMLImpl(createInputStreamFactory(val));
+ ((SQLXMLImpl)currentValue).setEncoding(val.getEncoding());
}
}
else if (currentValue instanceof java.util.Date) {
Modified: trunk/client/src/test/java/org/teiid/jdbc/TestAllResultsImpl.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestAllResultsImpl.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestAllResultsImpl.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -62,7 +62,7 @@
private StatementImpl statement;
@Before public void setUp() throws Exception {
- statement = TestMMResultSet.createMockStatement(TYPE_SCROLL_SENSITIVE);
+ statement = TestResultSet.createMockStatement(TYPE_SCROLL_SENSITIVE);
}
/** test hasNext(), actual result set should return FALSE. */
@@ -766,14 +766,14 @@
private ResultSetImpl helpGetResultSetImpl(int type)
throws SQLException {
ResultsMessage rsMsg = exampleResultsMsg2();
- statement = TestMMResultSet.createMockStatement(type);
+ statement = TestResultSet.createMockStatement(type);
ResultSetImpl rs = new ResultSetImpl(rsMsg, statement);
return rs;
}
private ResultSetImpl helpGetNoResults(int type) throws SQLException {
ResultsMessage rsMsg = exampleResultsMsg3();
- statement = TestMMResultSet.createMockStatement(type);
+ statement = TestResultSet.createMockStatement(type);
ResultSetImpl rs = new ResultSetImpl(rsMsg, statement);
return rs;
}
Copied: trunk/client/src/test/java/org/teiid/jdbc/TestCallableStatement.java (from rev 2238, trunk/client/src/test/java/org/teiid/jdbc/TestMMCallableStatement.java)
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestCallableStatement.java (rev 0)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestCallableStatement.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -0,0 +1,109 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Licensed to Red Hat, Inc. under one or more contributor
+ * license agreements. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.mockito.Mockito;
+import org.teiid.client.RequestMessage;
+import org.teiid.client.ResultsMessage;
+import org.teiid.client.metadata.ParameterInfo;
+import org.teiid.client.security.LogonResult;
+import org.teiid.core.types.JDBCSQLTypeInfo;
+import org.teiid.jdbc.CallableStatementImpl;
+import org.teiid.jdbc.ConnectionImpl;
+import org.teiid.jdbc.ResultSetImpl;
+import org.teiid.net.ServerConnection;
+
+
+public class TestCallableStatement extends TestCase {
+
+ public void testWasNull() throws Exception {
+ CallableStatementImpl mmcs = getCallableStatement();
+
+ Map<Integer, Integer> params = new HashMap<Integer, Integer>();
+ mmcs.outParamIndexMap = params;
+ params.put(Integer.valueOf(1), Integer.valueOf(1));
+ params.put(Integer.valueOf(2), Integer.valueOf(2));
+ ResultSetImpl rs = Mockito.mock(ResultSetImpl.class);
+ mmcs.resultSet = rs;
+ Mockito.stub(rs.getOutputParamValue(1)).toReturn(null);
+ Mockito.stub(rs.getOutputParamValue(2)).toReturn(Boolean.TRUE);
+ mmcs.getBoolean(1);
+ assertTrue(mmcs.wasNull());
+ assertTrue(mmcs.getBoolean(2));
+ assertFalse(mmcs.wasNull());
+ }
+
+ public void testGetOutputParameter() throws Exception {
+ CallableStatementImpl mmcs = getCallableStatement();
+
+ RequestMessage request = new RequestMessage();
+ request.setExecutionId(1);
+ ResultsMessage resultsMsg = new ResultsMessage(request);
+ List[] results = new List[] {Arrays.asList(null, null, null), Arrays.asList(null, 1, 2)};
+ resultsMsg.setResults(results);
+ resultsMsg.setColumnNames(new String[] { "IntNum", "Out1", "Out2" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ resultsMsg.setDataTypes(new String[] { JDBCSQLTypeInfo.INTEGER, JDBCSQLTypeInfo.INTEGER, JDBCSQLTypeInfo.INTEGER });
+ resultsMsg.setFinalRow(results.length);
+ resultsMsg.setLastRow(results.length);
+ resultsMsg.setFirstRow(1);
+ resultsMsg.setParameters(Arrays.asList(new ParameterInfo(ParameterInfo.RESULT_SET, 1), new ParameterInfo(ParameterInfo.OUT, 1), new ParameterInfo(ParameterInfo.OUT, 1)));
+ mmcs.createResultSet(resultsMsg);
+ assertEquals(1, mmcs.getInt(1));
+ assertEquals(2, mmcs.getInt(2));
+ }
+
+ public void testUnknownIndex() throws Exception {
+ CallableStatementImpl mmcs = getCallableStatement();
+
+ mmcs.outParamIndexMap = new HashMap<Integer, Integer>();
+
+ try {
+ mmcs.getBoolean(0);
+ fail("expected exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ assertEquals("Parameter is not found at index 0.", e.getMessage());
+ }
+ }
+
+ private CallableStatementImpl getCallableStatement() throws SQLException {
+ ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
+ ServerConnection sc = Mockito.mock(ServerConnection.class);
+
+ Mockito.stub(sc.getLogonResult()).toReturn(new LogonResult());
+ Mockito.stub(conn.getServerConnection()).toReturn(sc);
+
+ CallableStatementImpl mmcs = new CallableStatementImpl(conn, "{?=call x(?)}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+ return mmcs;
+ }
+
+}
Property changes on: trunk/client/src/test/java/org/teiid/jdbc/TestCallableStatement.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java (from rev 2238, trunk/client/src/test/java/org/teiid/jdbc/TestMMConnection.java)
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java (rev 0)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import static org.mockito.Mockito.*;
+
+import java.sql.SQLException;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.teiid.client.DQP;
+import org.teiid.client.security.LogonResult;
+import org.teiid.client.security.SessionToken;
+import org.teiid.client.util.ResultsFuture;
+import org.teiid.client.xa.XATransactionException;
+import org.teiid.client.xa.XidImpl;
+import org.teiid.jdbc.BaseDataSource;
+import org.teiid.jdbc.ConnectionImpl;
+import org.teiid.net.ServerConnection;
+
+
+public class TestConnection extends TestCase {
+
+ protected static final String STD_DATABASE_NAME = "QT_Ora9DS"; //$NON-NLS-1$
+ protected static final int STD_DATABASE_VERSION = 1;
+
+ static String serverUrl = "jdbc:metamatrix:QT_Ora9DS@mm://localhost:7001;version=1;user=metamatrixadmin;password=mm"; //$NON-NLS-1$
+
+ public TestConnection(String name) {
+ super(name);
+ }
+
+ public static ConnectionImpl getMMConnection() {
+ ServerConnection mock = mock(ServerConnection.class);
+ DQP dqp = mock(DQP.class);
+ try {
+ stub(dqp.start((XidImpl)Mockito.anyObject(), Mockito.anyInt(), Mockito.anyInt())).toAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return ResultsFuture.NULL_FUTURE;
+ }
+ });
+ stub(dqp.rollback((XidImpl)Mockito.anyObject())).toAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return ResultsFuture.NULL_FUTURE;
+ }
+ });
+ stub(dqp.rollback()).toAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return ResultsFuture.NULL_FUTURE;
+ }
+ });
+ } catch (XATransactionException e) {
+ throw new RuntimeException(e);
+ }
+ stub(mock.getService(DQP.class)).toReturn(dqp);
+ Properties props = new Properties();
+ props.setProperty(BaseDataSource.VDB_NAME, STD_DATABASE_NAME);
+ props.setProperty(BaseDataSource.VDB_VERSION, String.valueOf(STD_DATABASE_VERSION));
+ props.setProperty(BaseDataSource.USER_NAME, "metamatrixadmin"); //$NON-NLS-1$
+ stub(mock.getLogonResult()).toReturn(new LogonResult(new SessionToken(1, "metamatrixadmin"), STD_DATABASE_NAME,STD_DATABASE_VERSION , "fake")); //$NON-NLS-1$
+ return new ConnectionImpl(mock, props, serverUrl);
+ }
+
+ public void testGetMetaData() throws Exception {
+ assertNotNull(getMMConnection().getMetaData());
+ }
+
+ public void testGetSchema() throws Exception {
+ assertEquals("Actual schema is not equql to the expected one. ", STD_DATABASE_NAME, getMMConnection().getVDBName()); //$NON-NLS-1$
+ }
+
+ public void testNativeSql() throws Exception {
+ String sql = "SELECT * FROM BQT1.SmallA"; //$NON-NLS-1$
+ assertEquals("Actual schema is not equql to the expected one. ", sql, getMMConnection().nativeSQL(sql)); //$NON-NLS-1$
+ }
+
+ /** test getUserName() through DriverManager */
+ public void testGetUserName2() throws Exception {
+ assertEquals("Actual userName is not equal to the expected one. ", "metamatrixadmin", getMMConnection().getUserName()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /** test isReadOnly default value on Connection */
+ public void testIsReadOnly() throws Exception {
+ assertEquals(false, getMMConnection().isReadOnly());
+ }
+
+ /** test setReadOnly on Connection */
+ public void testSetReadOnly1() throws Exception {
+ ConnectionImpl conn = getMMConnection();
+ conn.setReadOnly(true);
+ assertEquals(true, conn.isReadOnly());
+ }
+
+ /** test setReadOnly on Connection during a transaction */
+ public void testSetReadOnly2() throws Exception {
+ ConnectionImpl conn = getMMConnection();
+ conn.setAutoCommit(false);
+ try {
+ conn.setReadOnly(true);
+ fail("Error Expected"); //$NON-NLS-1$
+ } catch (SQLException e) {
+ // error expected
+ }
+ }
+}
Copied: trunk/client/src/test/java/org/teiid/jdbc/TestJDBCURL.java (from rev 2238, trunk/client/src/test/java/org/teiid/jdbc/TestMMJDBCURL.java)
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestJDBCURL.java (rev 0)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestJDBCURL.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -0,0 +1,342 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import java.net.URLEncoder;
+import java.util.Properties;
+
+import org.teiid.jdbc.BaseDataSource;
+import org.teiid.jdbc.ExecutionProperties;
+import org.teiid.jdbc.JDBCURL;
+import org.teiid.net.TeiidURL;
+
+import junit.framework.TestCase;
+
+
+
+/**
+ * @since 4.3
+ */
+public class TestJDBCURL extends TestCase {
+
+ // Need to allow embedded spaces and ='s within optional properties
+ public final void testCredentials() throws Exception {
+ String credentials = URLEncoder.encode("defaultToLogon,(system=BQT1 SQL Server 2000 Simple Cap,user=xyz,password=xyz)", "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+ JDBCURL url = new JDBCURL("jdbc:metamatrix:QT_sqls2kds@mm://slwxp136:43100;credentials="+credentials); //$NON-NLS-1$
+ Properties p = url.getProperties();
+ assertEquals("defaultToLogon,(system=BQT1 SQL Server 2000 Simple Cap,user=xyz,password=xyz)", p.getProperty("credentials")); //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ public void testJDBCURLWithProperties() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1;configFile=testdata/bqt/dqp_stmt_e2e.xmi;disableLocalTxn=true;autoFailover=false"; //$NON-NLS-1$
+
+ Properties expectedProperties = new Properties();
+ expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("logLevel", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("configFile", "testdata/bqt/dqp_stmt_e2e.xmi"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty(ExecutionProperties.DISABLE_LOCAL_TRANSACTIONS, "true"); //$NON-NLS-1$
+ expectedProperties.setProperty(TeiidURL.CONNECTION.AUTO_FAILOVER, "false"); //$NON-NLS-1$
+ JDBCURL url = new JDBCURL(URL);
+ assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
+ assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
+ assertEquals(expectedProperties, url.getProperties());
+ }
+
+ public void testJDBCURLWithoutProperties() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345"; //$NON-NLS-1$
+
+ JDBCURL url = new JDBCURL(URL);
+ assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
+ assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
+ assertEquals(new Properties(), url.getProperties());
+ }
+
+ public void testCaseConversion() {
+ // Different case ------------------------------------HERE -v ----------------and HERE -v
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;VERSION=1;user=xyz;password=***;configFile=testdata/bqt/dqp_stmt_e2e.xmi"; //$NON-NLS-1$
+
+ Properties expectedProperties = new Properties();
+ expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("configFile", "testdata/bqt/dqp_stmt_e2e.xmi"); //$NON-NLS-1$ //$NON-NLS-2$
+ JDBCURL url = new JDBCURL(URL);
+ assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
+ assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
+ assertEquals(expectedProperties, url.getProperties());
+ }
+
+ public void testWithExtraSemicolons() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1;;;configFile=testdata/bqt/dqp_stmt_e2e.xmi;;"; //$NON-NLS-1$
+
+ Properties expectedProperties = new Properties();
+ expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("logLevel", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("configFile", "testdata/bqt/dqp_stmt_e2e.xmi"); //$NON-NLS-1$ //$NON-NLS-2$
+ JDBCURL url = new JDBCURL(URL);
+ assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
+ assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
+ assertEquals(expectedProperties, url.getProperties());
+ }
+
+ public void testWithWhitespace() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345; version =1;user= xyz ;password=***; logLevel = 1 ; configFile=testdata/bqt/dqp_stmt_e2e.xmi ;"; //$NON-NLS-1$
+
+ Properties expectedProperties = new Properties();
+ expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("logLevel", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("configFile", "testdata/bqt/dqp_stmt_e2e.xmi"); //$NON-NLS-1$ //$NON-NLS-2$
+ JDBCURL url = new JDBCURL(URL);
+ assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
+ assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
+ assertEquals(expectedProperties, url.getProperties());
+ }
+
+ public void testNoPropertyValue() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=;configFile="; //$NON-NLS-1$
+
+ Properties expectedProperties = new Properties();
+ expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("logLevel", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ expectedProperties.setProperty("configFile", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ JDBCURL url = new JDBCURL(URL);
+ assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
+ assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
+ assertEquals(expectedProperties, url.getProperties());
+ }
+
+ public void testInvalidProtocol() {
+ String URL = "jdbc:monkeymatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1"; //$NON-NLS-1$
+ try {
+ new JDBCURL(URL);
+ fail("Illegal argument should have failed."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testNoVDBName() {
+ String URL = "jdbc:metamatrix:@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1"; //$NON-NLS-1$
+ try {
+ new JDBCURL(URL);
+ fail("Illegal argument should have failed."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testNoAtSignInURL() {
+ String URL = "jdbc:metamatrix:bqt!mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1"; //$NON-NLS-1$
+ try {
+ new JDBCURL(URL);
+ // No @ sign is llowed as part of embedded driver now,
+ // but this form of URL rejected in the acceptURL
+ //fail("Illegal argument should have failed.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testMoreThanOneAtSign() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xy@;password=***;logLevel=1"; //$NON-NLS-1$
+ try {
+ // this allowed as customer properties can have @ in their properties
+ new JDBCURL(URL);
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testNoEqualsInProperty() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password***;logLevel=1"; //$NON-NLS-1$
+ try {
+ new JDBCURL(URL);
+ fail("Illegal argument should have failed."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testMoreThanOneEqualsInProperty() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password==***;logLevel=1"; //$NON-NLS-1$
+ try {
+ new JDBCURL(URL);
+ fail("Illegal argument should have failed."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***=;logLevel=1"; //$NON-NLS-1$
+ try {
+ new JDBCURL(URL);
+ fail("Illegal argument should have failed."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;=password=***;logLevel=1"; //$NON-NLS-1$
+ try {
+ new JDBCURL(URL);
+ fail("Illegal argument should have failed."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testNoKeyInProperty() {
+ String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;=***;logLevel=1"; //$NON-NLS-1$
+ try {
+ new JDBCURL(URL);
+ fail("Illegal argument should have failed."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testConstructor() {
+ JDBCURL url = new JDBCURL("myVDB", "mm://myhost:12345",null); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals("jdbc:teiid:myVDB@mm://myhost:12345", url.getJDBCURL()); //$NON-NLS-1$
+
+ Properties props = new Properties();
+ props.setProperty(BaseDataSource.USER_NAME, "myuser"); //$NON-NLS-1$
+ props.setProperty(BaseDataSource.PASSWORD, "mypassword"); //$NON-NLS-1$
+ props.put("ClieNTtOKeN", new Integer(1)); //$NON-NLS-1$
+ url = new JDBCURL("myVDB", "mm://myhost:12345", props); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals("jdbc:teiid:myVDB@mm://myhost:12345;user=myuser;password=mypassword", url.getJDBCURL()); //$NON-NLS-1$
+ }
+
+ public void testConstructor_Exception() {
+ try {
+ new JDBCURL(null, "myhost", null); //$NON-NLS-1$
+ fail("Should have failed."); //$NON-NLS-1$
+ } catch (Exception e) {
+
+ }
+ try {
+ new JDBCURL(" ", "myhost", null); //$NON-NLS-1$ //$NON-NLS-2$
+ fail("Should have failed."); //$NON-NLS-1$
+ } catch (Exception e) {
+
+ }
+
+ try {
+ // in embedded situation there is no connection url
+ new JDBCURL("myVDB", " ", null); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (Exception e) {
+
+ }
+ }
+
+ public void testNormalize() {
+ Properties props = new Properties();
+ props.setProperty("UsEr", "myuser"); //$NON-NLS-1$ //$NON-NLS-2$
+ props.setProperty("pAssWOrD", "mypassword"); //$NON-NLS-1$ //$NON-NLS-2$
+ props.put("ClieNTtOKeN", new Integer(1)); //$NON-NLS-1$
+ JDBCURL.normalizeProperties(props);
+ assertEquals("myuser", props.getProperty(BaseDataSource.USER_NAME)); //$NON-NLS-1$
+ assertEquals("mypassword", props.getProperty(BaseDataSource.PASSWORD)); //$NON-NLS-1$
+ }
+
+ public final void testEncodedPropertyProperties() throws Exception {
+ String password = "=@#^&*()+!%$^%@#_-)_~{}||\\`':;,./<>?password has = & %"; //$NON-NLS-1$
+ Properties props = new Properties();
+ props.setProperty("UsEr", "foo"); //$NON-NLS-1$ //$NON-NLS-2$
+ props.setProperty("PASswoRd", password); //$NON-NLS-1$
+ JDBCURL.normalizeProperties(props);
+
+ assertEquals(password, props.getProperty("password")); //$NON-NLS-1$
+ assertEquals("foo", props.getProperty("user")); //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ public final void testEncodedPropertyInURL() throws Exception {
+ String password = "=@#^&*()+!%$^%@#_-)_~{}||\\`':;,./<>?password has = & %"; //$NON-NLS-1$
+ String encPassword = URLEncoder.encode(password, "UTF-8"); //$NON-NLS-1$
+ JDBCURL url = new JDBCURL("jdbc:metamatrix:QT_sqls2kds@mm://slwxp136:43100;PASswoRd="+encPassword); //$NON-NLS-1$
+ Properties p = url.getProperties();
+ assertEquals(password, p.getProperty("password")); //$NON-NLS-1$
+ }
+
+
+ public void testGetServerURL_NoProperties() {
+ String result = new JDBCURL("jdbc:metamatrix:designtimecatalog@mm://slwxp172:44401;user=ddifranco;password=mm").getConnectionURL(); //$NON-NLS-1$
+ assertEquals("mm://slwxp172:44401", result); //$NON-NLS-1$
+ }
+
+ public void testGetServerURL_Properties() {
+ String result = new JDBCURL("jdbc:metamatrix:designtimecatalog@mm://slwxp172:44401;user=ddifranco;password=mm").getConnectionURL(); //$NON-NLS-1$
+ assertEquals("mm://slwxp172:44401", result); //$NON-NLS-1$
+ }
+
+ /**
+ * Test getServerURL with a valid URL and password that contains at least
+ * one ASCII character in the range of 32 to 126 excluding the ; and = sign.
+ *
+ * @since 5.0.2
+ */
+ public void testGetServerURL_PasswordProperties() throws Exception {
+ String result = null;
+ String srcURL = "jdbc:metamatrix:designtimecatalog@mm://slwxp172:44401;user=ddifranco;password="; //$NON-NLS-1$
+ String password = null;
+ String tgtURL = "mm://slwxp172:44401"; //$NON-NLS-1$
+
+
+ for ( char ch = 32; ch <= 126; ch++ ) {
+ //exclude URL reserved characters
+ if ( ch != ';' && ch != '=' && ch != '%') {
+ password = ch+"mm"; //$NON-NLS-1$
+ result = new JDBCURL(srcURL+URLEncoder.encode(password, "UTF-8")).getConnectionURL(); //$NON-NLS-1$
+ assertEquals("Failed to obtain correct ServerURL when using password "+password,tgtURL, result); //$NON-NLS-1$
+ }
+ }
+
+ }
+
+ public void testGetServerURL_2Servers() {
+ String result = new JDBCURL("jdbc:metamatrix:designtimecatalog@mm://slwxp172:44401,slabc123:12345;user=ddifranco;password=mm").getConnectionURL(); //$NON-NLS-1$
+ assertEquals("mm://slwxp172:44401,slabc123:12345", result); //$NON-NLS-1$
+ }
+
+ public void testBuildEmbeedURL() {
+ JDBCURL url = new JDBCURL("vdb", "/home/foo/deploy.properties", new Properties()); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals("jdbc:teiid:vdb@/home/foo/deploy.properties", url.getJDBCURL()); //$NON-NLS-1$
+
+ Properties p = new Properties();
+ p.setProperty("user", "test"); //$NON-NLS-1$ //$NON-NLS-2$
+ p.setProperty("password", "pass"); //$NON-NLS-1$ //$NON-NLS-2$
+ p.setProperty("autoFailover", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ p.setProperty("any", "thing"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ url = new JDBCURL("vdb", "/home/foo/deploy.properties", p); //$NON-NLS-1$ //$NON-NLS-2$
+ assertTrue(url.getJDBCURL().startsWith("jdbc:teiid:vdb@/home/foo/deploy.properties;user=test;")); //$NON-NLS-1$
+ assertTrue(url.getJDBCURL().indexOf("any=thing")!=-1); //$NON-NLS-1$
+ assertTrue(url.getJDBCURL().indexOf("password=pass")!=-1); //$NON-NLS-1$
+ assertTrue(url.getJDBCURL().indexOf("autoFailover=true")!=-1); //$NON-NLS-1$
+
+ }
+}
Deleted: trunk/client/src/test/java/org/teiid/jdbc/TestMMCallableStatement.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestMMCallableStatement.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestMMCallableStatement.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -1,109 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright (C) 2008 Red Hat, Inc.
- * Licensed to Red Hat, Inc. under one or more contributor
- * license agreements. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.jdbc;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import junit.framework.TestCase;
-
-import org.mockito.Mockito;
-import org.teiid.client.RequestMessage;
-import org.teiid.client.ResultsMessage;
-import org.teiid.client.metadata.ParameterInfo;
-import org.teiid.client.security.LogonResult;
-import org.teiid.core.types.JDBCSQLTypeInfo;
-import org.teiid.jdbc.CallableStatementImpl;
-import org.teiid.jdbc.ConnectionImpl;
-import org.teiid.jdbc.ResultSetImpl;
-import org.teiid.net.ServerConnection;
-
-
-public class TestMMCallableStatement extends TestCase {
-
- public void testWasNull() throws Exception {
- CallableStatementImpl mmcs = getCallableStatement();
-
- Map<Integer, Integer> params = new HashMap<Integer, Integer>();
- mmcs.outParamIndexMap = params;
- params.put(Integer.valueOf(1), Integer.valueOf(1));
- params.put(Integer.valueOf(2), Integer.valueOf(2));
- ResultSetImpl rs = Mockito.mock(ResultSetImpl.class);
- mmcs.resultSet = rs;
- Mockito.stub(rs.getOutputParamValue(1)).toReturn(null);
- Mockito.stub(rs.getOutputParamValue(2)).toReturn(Boolean.TRUE);
- mmcs.getBoolean(1);
- assertTrue(mmcs.wasNull());
- assertTrue(mmcs.getBoolean(2));
- assertFalse(mmcs.wasNull());
- }
-
- public void testGetOutputParameter() throws Exception {
- CallableStatementImpl mmcs = getCallableStatement();
-
- RequestMessage request = new RequestMessage();
- request.setExecutionId(1);
- ResultsMessage resultsMsg = new ResultsMessage(request);
- List[] results = new List[] {Arrays.asList(null, null, null), Arrays.asList(null, 1, 2)};
- resultsMsg.setResults(results);
- resultsMsg.setColumnNames(new String[] { "IntNum", "Out1", "Out2" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- resultsMsg.setDataTypes(new String[] { JDBCSQLTypeInfo.INTEGER, JDBCSQLTypeInfo.INTEGER, JDBCSQLTypeInfo.INTEGER });
- resultsMsg.setFinalRow(results.length);
- resultsMsg.setLastRow(results.length);
- resultsMsg.setFirstRow(1);
- resultsMsg.setParameters(Arrays.asList(new ParameterInfo(ParameterInfo.RESULT_SET, 1), new ParameterInfo(ParameterInfo.OUT, 1), new ParameterInfo(ParameterInfo.OUT, 1)));
- mmcs.createResultSet(resultsMsg);
- assertEquals(1, mmcs.getInt(1));
- assertEquals(2, mmcs.getInt(2));
- }
-
- public void testUnknownIndex() throws Exception {
- CallableStatementImpl mmcs = getCallableStatement();
-
- mmcs.outParamIndexMap = new HashMap<Integer, Integer>();
-
- try {
- mmcs.getBoolean(0);
- fail("expected exception"); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- assertEquals("Parameter is not found at index 0.", e.getMessage());
- }
- }
-
- private CallableStatementImpl getCallableStatement() throws SQLException {
- ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
- ServerConnection sc = Mockito.mock(ServerConnection.class);
-
- Mockito.stub(sc.getLogonResult()).toReturn(new LogonResult());
- Mockito.stub(conn.getServerConnection()).toReturn(sc);
-
- CallableStatementImpl mmcs = new CallableStatementImpl(conn, "{?=call x(?)}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
- return mmcs;
- }
-
-}
Deleted: trunk/client/src/test/java/org/teiid/jdbc/TestMMConnection.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestMMConnection.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestMMConnection.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -1,132 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.jdbc;
-
-import static org.mockito.Mockito.*;
-
-import java.sql.SQLException;
-import java.util.Properties;
-
-import junit.framework.TestCase;
-
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.teiid.client.DQP;
-import org.teiid.client.security.LogonResult;
-import org.teiid.client.security.SessionToken;
-import org.teiid.client.util.ResultsFuture;
-import org.teiid.client.xa.XATransactionException;
-import org.teiid.client.xa.XidImpl;
-import org.teiid.jdbc.BaseDataSource;
-import org.teiid.jdbc.ConnectionImpl;
-import org.teiid.net.ServerConnection;
-
-
-public class TestMMConnection extends TestCase {
-
- protected static final String STD_DATABASE_NAME = "QT_Ora9DS"; //$NON-NLS-1$
- protected static final int STD_DATABASE_VERSION = 1;
-
- static String serverUrl = "jdbc:metamatrix:QT_Ora9DS@mm://localhost:7001;version=1;user=metamatrixadmin;password=mm"; //$NON-NLS-1$
-
- public TestMMConnection(String name) {
- super(name);
- }
-
- public static ConnectionImpl getMMConnection() {
- ServerConnection mock = mock(ServerConnection.class);
- DQP dqp = mock(DQP.class);
- try {
- stub(dqp.start((XidImpl)Mockito.anyObject(), Mockito.anyInt(), Mockito.anyInt())).toAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- return ResultsFuture.NULL_FUTURE;
- }
- });
- stub(dqp.rollback((XidImpl)Mockito.anyObject())).toAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- return ResultsFuture.NULL_FUTURE;
- }
- });
- stub(dqp.rollback()).toAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- return ResultsFuture.NULL_FUTURE;
- }
- });
- } catch (XATransactionException e) {
- throw new RuntimeException(e);
- }
- stub(mock.getService(DQP.class)).toReturn(dqp);
- Properties props = new Properties();
- props.setProperty(BaseDataSource.VDB_NAME, STD_DATABASE_NAME);
- props.setProperty(BaseDataSource.VDB_VERSION, String.valueOf(STD_DATABASE_VERSION));
- props.setProperty(BaseDataSource.USER_NAME, "metamatrixadmin"); //$NON-NLS-1$
- stub(mock.getLogonResult()).toReturn(new LogonResult(new SessionToken(1, "metamatrixadmin"), STD_DATABASE_NAME,STD_DATABASE_VERSION , "fake")); //$NON-NLS-1$
- return new ConnectionImpl(mock, props, serverUrl);
- }
-
- public void testGetMetaData() throws Exception {
- assertNotNull(getMMConnection().getMetaData());
- }
-
- public void testGetSchema() throws Exception {
- assertEquals("Actual schema is not equql to the expected one. ", STD_DATABASE_NAME, getMMConnection().getVDBName()); //$NON-NLS-1$
- }
-
- public void testNativeSql() throws Exception {
- String sql = "SELECT * FROM BQT1.SmallA"; //$NON-NLS-1$
- assertEquals("Actual schema is not equql to the expected one. ", sql, getMMConnection().nativeSQL(sql)); //$NON-NLS-1$
- }
-
- /** test getUserName() through DriverManager */
- public void testGetUserName2() throws Exception {
- assertEquals("Actual userName is not equal to the expected one. ", "metamatrixadmin", getMMConnection().getUserName()); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- /** test isReadOnly default value on Connection */
- public void testIsReadOnly() throws Exception {
- assertEquals(false, getMMConnection().isReadOnly());
- }
-
- /** test setReadOnly on Connection */
- public void testSetReadOnly1() throws Exception {
- ConnectionImpl conn = getMMConnection();
- conn.setReadOnly(true);
- assertEquals(true, conn.isReadOnly());
- }
-
- /** test setReadOnly on Connection during a transaction */
- public void testSetReadOnly2() throws Exception {
- ConnectionImpl conn = getMMConnection();
- conn.setAutoCommit(false);
- try {
- conn.setReadOnly(true);
- fail("Error Expected"); //$NON-NLS-1$
- } catch (SQLException e) {
- // error expected
- }
- }
-}
Deleted: trunk/client/src/test/java/org/teiid/jdbc/TestMMJDBCURL.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestMMJDBCURL.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestMMJDBCURL.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -1,342 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.jdbc;
-
-import java.net.URLEncoder;
-import java.util.Properties;
-
-import org.teiid.jdbc.BaseDataSource;
-import org.teiid.jdbc.ExecutionProperties;
-import org.teiid.jdbc.JDBCURL;
-import org.teiid.net.TeiidURL;
-
-import junit.framework.TestCase;
-
-
-
-/**
- * @since 4.3
- */
-public class TestMMJDBCURL extends TestCase {
-
- // Need to allow embedded spaces and ='s within optional properties
- public final void testCredentials() throws Exception {
- String credentials = URLEncoder.encode("defaultToLogon,(system=BQT1 SQL Server 2000 Simple Cap,user=xyz,password=xyz)", "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
- JDBCURL url = new JDBCURL("jdbc:metamatrix:QT_sqls2kds@mm://slwxp136:43100;credentials="+credentials); //$NON-NLS-1$
- Properties p = url.getProperties();
- assertEquals("defaultToLogon,(system=BQT1 SQL Server 2000 Simple Cap,user=xyz,password=xyz)", p.getProperty("credentials")); //$NON-NLS-1$//$NON-NLS-2$
- }
-
- public void testJDBCURLWithProperties() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1;configFile=testdata/bqt/dqp_stmt_e2e.xmi;disableLocalTxn=true;autoFailover=false"; //$NON-NLS-1$
-
- Properties expectedProperties = new Properties();
- expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("logLevel", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("configFile", "testdata/bqt/dqp_stmt_e2e.xmi"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty(ExecutionProperties.DISABLE_LOCAL_TRANSACTIONS, "true"); //$NON-NLS-1$
- expectedProperties.setProperty(TeiidURL.CONNECTION.AUTO_FAILOVER, "false"); //$NON-NLS-1$
- JDBCURL url = new JDBCURL(URL);
- assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
- assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
- assertEquals(expectedProperties, url.getProperties());
- }
-
- public void testJDBCURLWithoutProperties() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345"; //$NON-NLS-1$
-
- JDBCURL url = new JDBCURL(URL);
- assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
- assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
- assertEquals(new Properties(), url.getProperties());
- }
-
- public void testCaseConversion() {
- // Different case ------------------------------------HERE -v ----------------and HERE -v
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;VERSION=1;user=xyz;password=***;configFile=testdata/bqt/dqp_stmt_e2e.xmi"; //$NON-NLS-1$
-
- Properties expectedProperties = new Properties();
- expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("configFile", "testdata/bqt/dqp_stmt_e2e.xmi"); //$NON-NLS-1$ //$NON-NLS-2$
- JDBCURL url = new JDBCURL(URL);
- assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
- assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
- assertEquals(expectedProperties, url.getProperties());
- }
-
- public void testWithExtraSemicolons() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1;;;configFile=testdata/bqt/dqp_stmt_e2e.xmi;;"; //$NON-NLS-1$
-
- Properties expectedProperties = new Properties();
- expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("logLevel", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("configFile", "testdata/bqt/dqp_stmt_e2e.xmi"); //$NON-NLS-1$ //$NON-NLS-2$
- JDBCURL url = new JDBCURL(URL);
- assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
- assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
- assertEquals(expectedProperties, url.getProperties());
- }
-
- public void testWithWhitespace() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345; version =1;user= xyz ;password=***; logLevel = 1 ; configFile=testdata/bqt/dqp_stmt_e2e.xmi ;"; //$NON-NLS-1$
-
- Properties expectedProperties = new Properties();
- expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("logLevel", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("configFile", "testdata/bqt/dqp_stmt_e2e.xmi"); //$NON-NLS-1$ //$NON-NLS-2$
- JDBCURL url = new JDBCURL(URL);
- assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
- assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
- assertEquals(expectedProperties, url.getProperties());
- }
-
- public void testNoPropertyValue() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=;configFile="; //$NON-NLS-1$
-
- Properties expectedProperties = new Properties();
- expectedProperties.setProperty("version", "1"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("user", "xyz"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("password", "***"); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("logLevel", ""); //$NON-NLS-1$ //$NON-NLS-2$
- expectedProperties.setProperty("configFile", ""); //$NON-NLS-1$ //$NON-NLS-2$
- JDBCURL url = new JDBCURL(URL);
- assertEquals("bqt", url.getVDBName()); //$NON-NLS-1$
- assertEquals("mm://localhost:12345", url.getConnectionURL()); //$NON-NLS-1$
- assertEquals(expectedProperties, url.getProperties());
- }
-
- public void testInvalidProtocol() {
- String URL = "jdbc:monkeymatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1"; //$NON-NLS-1$
- try {
- new JDBCURL(URL);
- fail("Illegal argument should have failed."); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testNoVDBName() {
- String URL = "jdbc:metamatrix:@mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1"; //$NON-NLS-1$
- try {
- new JDBCURL(URL);
- fail("Illegal argument should have failed."); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testNoAtSignInURL() {
- String URL = "jdbc:metamatrix:bqt!mm://localhost:12345;version=1;user=xyz;password=***;logLevel=1"; //$NON-NLS-1$
- try {
- new JDBCURL(URL);
- // No @ sign is llowed as part of embedded driver now,
- // but this form of URL rejected in the acceptURL
- //fail("Illegal argument should have failed.");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testMoreThanOneAtSign() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xy@;password=***;logLevel=1"; //$NON-NLS-1$
- try {
- // this allowed as customer properties can have @ in their properties
- new JDBCURL(URL);
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testNoEqualsInProperty() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password***;logLevel=1"; //$NON-NLS-1$
- try {
- new JDBCURL(URL);
- fail("Illegal argument should have failed."); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testMoreThanOneEqualsInProperty() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password==***;logLevel=1"; //$NON-NLS-1$
- try {
- new JDBCURL(URL);
- fail("Illegal argument should have failed."); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- // expected
- }
- URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;password=***=;logLevel=1"; //$NON-NLS-1$
- try {
- new JDBCURL(URL);
- fail("Illegal argument should have failed."); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- // expected
- }
- URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;=password=***;logLevel=1"; //$NON-NLS-1$
- try {
- new JDBCURL(URL);
- fail("Illegal argument should have failed."); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testNoKeyInProperty() {
- String URL = "jdbc:metamatrix:bqt@mm://localhost:12345;version=1;user=xyz;=***;logLevel=1"; //$NON-NLS-1$
- try {
- new JDBCURL(URL);
- fail("Illegal argument should have failed."); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testConstructor() {
- JDBCURL url = new JDBCURL("myVDB", "mm://myhost:12345",null); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals("jdbc:teiid:myVDB@mm://myhost:12345", url.getJDBCURL()); //$NON-NLS-1$
-
- Properties props = new Properties();
- props.setProperty(BaseDataSource.USER_NAME, "myuser"); //$NON-NLS-1$
- props.setProperty(BaseDataSource.PASSWORD, "mypassword"); //$NON-NLS-1$
- props.put("ClieNTtOKeN", new Integer(1)); //$NON-NLS-1$
- url = new JDBCURL("myVDB", "mm://myhost:12345", props); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals("jdbc:teiid:myVDB@mm://myhost:12345;user=myuser;password=mypassword", url.getJDBCURL()); //$NON-NLS-1$
- }
-
- public void testConstructor_Exception() {
- try {
- new JDBCURL(null, "myhost", null); //$NON-NLS-1$
- fail("Should have failed."); //$NON-NLS-1$
- } catch (Exception e) {
-
- }
- try {
- new JDBCURL(" ", "myhost", null); //$NON-NLS-1$ //$NON-NLS-2$
- fail("Should have failed."); //$NON-NLS-1$
- } catch (Exception e) {
-
- }
-
- try {
- // in embedded situation there is no connection url
- new JDBCURL("myVDB", " ", null); //$NON-NLS-1$ //$NON-NLS-2$
- } catch (Exception e) {
-
- }
- }
-
- public void testNormalize() {
- Properties props = new Properties();
- props.setProperty("UsEr", "myuser"); //$NON-NLS-1$ //$NON-NLS-2$
- props.setProperty("pAssWOrD", "mypassword"); //$NON-NLS-1$ //$NON-NLS-2$
- props.put("ClieNTtOKeN", new Integer(1)); //$NON-NLS-1$
- JDBCURL.normalizeProperties(props);
- assertEquals("myuser", props.getProperty(BaseDataSource.USER_NAME)); //$NON-NLS-1$
- assertEquals("mypassword", props.getProperty(BaseDataSource.PASSWORD)); //$NON-NLS-1$
- }
-
- public final void testEncodedPropertyProperties() throws Exception {
- String password = "=@#^&*()+!%$^%@#_-)_~{}||\\`':;,./<>?password has = & %"; //$NON-NLS-1$
- Properties props = new Properties();
- props.setProperty("UsEr", "foo"); //$NON-NLS-1$ //$NON-NLS-2$
- props.setProperty("PASswoRd", password); //$NON-NLS-1$
- JDBCURL.normalizeProperties(props);
-
- assertEquals(password, props.getProperty("password")); //$NON-NLS-1$
- assertEquals("foo", props.getProperty("user")); //$NON-NLS-1$//$NON-NLS-2$
- }
-
- public final void testEncodedPropertyInURL() throws Exception {
- String password = "=@#^&*()+!%$^%@#_-)_~{}||\\`':;,./<>?password has = & %"; //$NON-NLS-1$
- String encPassword = URLEncoder.encode(password, "UTF-8"); //$NON-NLS-1$
- JDBCURL url = new JDBCURL("jdbc:metamatrix:QT_sqls2kds@mm://slwxp136:43100;PASswoRd="+encPassword); //$NON-NLS-1$
- Properties p = url.getProperties();
- assertEquals(password, p.getProperty("password")); //$NON-NLS-1$
- }
-
-
- public void testGetServerURL_NoProperties() {
- String result = new JDBCURL("jdbc:metamatrix:designtimecatalog@mm://slwxp172:44401;user=ddifranco;password=mm").getConnectionURL(); //$NON-NLS-1$
- assertEquals("mm://slwxp172:44401", result); //$NON-NLS-1$
- }
-
- public void testGetServerURL_Properties() {
- String result = new JDBCURL("jdbc:metamatrix:designtimecatalog@mm://slwxp172:44401;user=ddifranco;password=mm").getConnectionURL(); //$NON-NLS-1$
- assertEquals("mm://slwxp172:44401", result); //$NON-NLS-1$
- }
-
- /**
- * Test getServerURL with a valid URL and password that contains at least
- * one ASCII character in the range of 32 to 126 excluding the ; and = sign.
- *
- * @since 5.0.2
- */
- public void testGetServerURL_PasswordProperties() throws Exception {
- String result = null;
- String srcURL = "jdbc:metamatrix:designtimecatalog@mm://slwxp172:44401;user=ddifranco;password="; //$NON-NLS-1$
- String password = null;
- String tgtURL = "mm://slwxp172:44401"; //$NON-NLS-1$
-
-
- for ( char ch = 32; ch <= 126; ch++ ) {
- //exclude URL reserved characters
- if ( ch != ';' && ch != '=' && ch != '%') {
- password = ch+"mm"; //$NON-NLS-1$
- result = new JDBCURL(srcURL+URLEncoder.encode(password, "UTF-8")).getConnectionURL(); //$NON-NLS-1$
- assertEquals("Failed to obtain correct ServerURL when using password "+password,tgtURL, result); //$NON-NLS-1$
- }
- }
-
- }
-
- public void testGetServerURL_2Servers() {
- String result = new JDBCURL("jdbc:metamatrix:designtimecatalog@mm://slwxp172:44401,slabc123:12345;user=ddifranco;password=mm").getConnectionURL(); //$NON-NLS-1$
- assertEquals("mm://slwxp172:44401,slabc123:12345", result); //$NON-NLS-1$
- }
-
- public void testBuildEmbeedURL() {
- JDBCURL url = new JDBCURL("vdb", "/home/foo/deploy.properties", new Properties()); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals("jdbc:teiid:vdb@/home/foo/deploy.properties", url.getJDBCURL()); //$NON-NLS-1$
-
- Properties p = new Properties();
- p.setProperty("user", "test"); //$NON-NLS-1$ //$NON-NLS-2$
- p.setProperty("password", "pass"); //$NON-NLS-1$ //$NON-NLS-2$
- p.setProperty("autoFailover", "true"); //$NON-NLS-1$ //$NON-NLS-2$
- p.setProperty("any", "thing"); //$NON-NLS-1$ //$NON-NLS-2$
-
- url = new JDBCURL("vdb", "/home/foo/deploy.properties", p); //$NON-NLS-1$ //$NON-NLS-2$
- assertTrue(url.getJDBCURL().startsWith("jdbc:teiid:vdb@/home/foo/deploy.properties;user=test;")); //$NON-NLS-1$
- assertTrue(url.getJDBCURL().indexOf("any=thing")!=-1); //$NON-NLS-1$
- assertTrue(url.getJDBCURL().indexOf("password=pass")!=-1); //$NON-NLS-1$
- assertTrue(url.getJDBCURL().indexOf("autoFailover=true")!=-1); //$NON-NLS-1$
-
- }
-}
Deleted: trunk/client/src/test/java/org/teiid/jdbc/TestMMPreparedStatement.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestMMPreparedStatement.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestMMPreparedStatement.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -1,343 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.jdbc;
-
-import static org.junit.Assert.*;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.TimeZone;
-
-import org.junit.Test;
-import org.mockito.Matchers;
-import org.mockito.Mockito;
-import org.teiid.client.DQP;
-import org.teiid.client.RequestMessage;
-import org.teiid.client.ResultsMessage;
-import org.teiid.client.RequestMessage.ResultsMode;
-import org.teiid.client.security.LogonResult;
-import org.teiid.client.util.ResultsFuture;
-import org.teiid.jdbc.ConnectionImpl;
-import org.teiid.jdbc.PreparedStatementImpl;
-import org.teiid.jdbc.TeiidSQLException;
-import org.teiid.net.ServerConnection;
-
-
-/**
- * Test case to validate general operations on an <code>MMPreparedStatement
- * </code>
- */
-public class TestMMPreparedStatement {
-
- /**
- * Test that <code>MMPreparedStatement</code>'s <code>execute()</code> method
- * will throw a <code>MMSQLException</code> if a connection does not exist.
- *
- * @throws Exception
- */
- @Test(expected=TeiidSQLException.class) public void testUpdateException() throws Exception {
- PreparedStatementImpl statement = getMMPreparedStatement("delete from table"); //$NON-NLS-1$
- statement.execute();
- }
-
- /**
- * Verify that the <code>executeBatch()</code> method of <code>
- * MMPreparedStatement</code> is resulting in the correct command,
- * parameter values for each command of the batch, and the request type
- * are being set in the request message that would normally be sent to the
- * server.
- *
- * @throws Exception
- */
- @Test public void testBatchedUpdateExecution() throws Exception {
- // Build up a fake connection instance for use with the prepared statement
- ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
- DQP dqp = Mockito.mock(DQP.class);
- ServerConnection serverConn = Mockito.mock(ServerConnection.class);
- LogonResult logonResult = Mockito.mock(LogonResult.class);
-
- // stub methods
- Mockito.stub(conn.getServerConnection()).toReturn(serverConn);
- Mockito.stub(serverConn.getLogonResult()).toReturn(logonResult);
- Mockito.stub(logonResult.getTimeZone()).toReturn(TimeZone.getDefault());
-
- // a dummy result message that is specific to this test case
- ResultsFuture<ResultsMessage> results = new ResultsFuture<ResultsMessage>();
- Mockito.stub(dqp.executeRequest(Matchers.anyLong(), (RequestMessage)Matchers.anyObject())).toReturn(results);
- ResultsMessage rm = new ResultsMessage();
- rm.setResults(new List<?>[] {Arrays.asList(0), Arrays.asList(0), Arrays.asList(0)});
- rm.setUpdateResult(true);
- results.getResultsReceiver().receiveResults(rm);
- Mockito.stub(conn.getDQP()).toReturn(dqp);
-
- // some update SQL
- String sqlCommand = "delete from table where col=?"; //$NON-NLS-1$
- TestableMMPreparedStatement statement = (TestableMMPreparedStatement) getMMPreparedStatement(conn, sqlCommand);
-
- ArrayList<ArrayList<Object>> expectedParameterValues = new ArrayList<ArrayList<Object>>(3);
- // Add some batches and their parameter values
- expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(1) } ) ) );
- statement.setInt(1, new Integer(1));
- statement.addBatch();
- expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(2) } ) ) );
- statement.setInt(1, new Integer(2));
- statement.addBatch();
- expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(3) } ) ) );
- statement.setInt(1, new Integer(3));
- statement.addBatch();
-
- // execute the batch and verify that it matches our dummy results
- // message set earlier
- assertTrue(Arrays.equals(new int[] {0, 0, 0}, statement.executeBatch()));
-
- // Now verify the statement's RequestMessage is what we expect
- assertEquals("Command does not match", sqlCommand, statement.requestMessage.getCommandString()); //$NON-NLS-1$
- assertEquals("Parameter values do not match", expectedParameterValues, statement.requestMessage.getParameterValues()); //$NON-NLS-1$
- assertTrue("RequestMessage.isBatchedUpdate should be true", statement.requestMessage.isBatchedUpdate()); //$NON-NLS-1$
- assertFalse("RequestMessage.isCallableStatement should be false", statement.requestMessage.isCallableStatement()); //$NON-NLS-1$
- assertTrue("RequestMessage.isPreparedStatement should be true", statement.requestMessage.isPreparedStatement()); //$NON-NLS-1$
- }
-
- /**
- * Verify that the <code>clearBatch()</code> method of
- * <code>MMPreparedStatement</code> is clearing the list of batched
- * commands.
- * <p>
- * This is done by first adding command parameter values to the batch and
- * then invoking the <code>clearBatch()</code> method.
- *
- * @throws Exception
- */
- @Test public void testClearBatch() throws Exception {
- PreparedStatementImpl statement = getMMPreparedStatement("delete from table where col=?"); //$NON-NLS-1$
- // Add some stuff
- statement.setInt(1, new Integer(1));
- statement.addBatch();
- statement.setInt(1, new Integer(2));
- statement.addBatch();
- // Make sure something is really there
- assertTrue("MMPreparedStatement.ParameterValuesList should not be empty", statement.getParameterValuesList().size() > 0); //$NON-NLS-1$
- // Now clear it
- statement.clearBatch();
- assertTrue("MMPreparedStatement.ParameterValuesList should be empty", statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
- }
-
- /**
- * Adds additional batches of command parameter values to a prepared
- * statement after a previous list has been cleared.
- * <p>
- * This is done by first adding command parameter values to the batch and
- * then invoking the <code>clearBatch()</code> method. Then a different
- * set of command parameter values are added to the existing batch command.
- * <p>
- * The expected result is the command parameter list for the batches will
- * only reflect what was added after <code>clearBatch()</code> was invoked.
- *
- * @throws Exception
- */
- @Test public void testClearBatchAddBatch() throws Exception {
- PreparedStatementImpl statement = getMMPreparedStatement("delete from table where col=?"); //$NON-NLS-1$
-
- statement.setInt(1, new Integer(1));
- statement.addBatch();
- statement.setInt(1, new Integer(2));
- statement.addBatch();
- // Make sure something is really there
- assertTrue("MMPreparedStatement.ParameterValuesList should not be empty", statement.getParameterValuesList().size() > 0); //$NON-NLS-1$
- // Now clear it
- statement.clearBatch();
- // Make sure it is empty now
- assertTrue("MMPreparedStatement.ParameterValuesList should be empty", statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
-
- ArrayList<ArrayList<Object>> expectedParameterValues = new ArrayList<ArrayList<Object>>(1);
-
- // Now add something for validation
- expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(5) } ) ) );
- statement.setInt(1, new Integer(5));
- statement.addBatch();
- assertEquals("MMPreparedStatement.ParameterValuesList does not match", expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
- }
-
- /**
- * Test the <code>addBatch()</code> method of <code>MMPreparedStatement</code>
- * to verify that the command parameter values of the batch are added to the
- * command parameter values list.
- *
- * @throws Exception
- */
- @Test public void testAddBatch() throws Exception {
- PreparedStatementImpl statement = getMMPreparedStatement("delete from table where col=?"); //$NON-NLS-1$
-
- ArrayList<ArrayList<Object>> expectedParameterValues = new ArrayList<ArrayList<Object>>(1);
-
- // First we add a single batch
- expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(1) } ) ) );
- statement.setInt(1, new Integer(1));
- statement.addBatch();
- assertEquals("MMPreparedStatement.ParameterValuesList does not match", expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
-
- // Now add some more batches just for sanity sake
- expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(3) } ) ) );
- expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(5) } ) ) );
- statement.setInt(1, new Integer(3));
- statement.addBatch();
- statement.setInt(1, new Integer(5));
- statement.addBatch();
- assertEquals("MMPreparedStatement.ParameterValuesList does not match", expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
- }
-
- /**
- * Test the <code>addBatch()</code> method of <code>MMPreparedStatement</code>
- * using a batch with an empty parameter value list. The test will verify
- * no failures occur when there are no command parameter values defined
- * when the <code>addBatch()</code> method is invoked.
- * <p>
- * It is valid to add an empty parameter value list to a batch list.
- * <p>
- * For example:
- * <p>
- * <code>PreparedStatement stmt = conn.prepareStatement(sql);<br \>
- * stmt.addBatch();<br \>
- * stmt.addBatch();<br \>
- * stmt.executeBatch();</code>
- *
- * @throws Exception
- */
- @Test public void testAddBatchNoParameterValues() throws Exception {
- PreparedStatementImpl statement = getMMPreparedStatement("delete from table where col=?"); //$NON-NLS-1$
-
- // This will hold our expected values list
- ArrayList<ArrayList<Object>> expectedParameterValues = new ArrayList<ArrayList<Object>>(1);
-
- // First batch has an empty parameter value list
- expectedParameterValues.add( new ArrayList<Object>(Collections.emptyList()) );
-
- // No values have been set so we are adding a batch with an empty
- // parameter value list
- statement.addBatch();
-
- // Second batch contains a parameter value list
- expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(1) } ) ) );
-
- // We now are adding a batch that does have parameter values
- statement.setInt(1, new Integer(1));
- statement.addBatch();
-
- // Check to see if our statement contains our expected parameter value list
- assertEquals("MMPreparedStatement.ParameterValuesList does not match", expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
- }
-
- /**
- * A helper method to get an <code>MMPreparedStatement</code> that can be
- * used for simple test cases.
- * <p>
- * The returned value is an instance of <code>TestableMMPreparedStatement</code>
- * <p>
- * This method invokes <code>getMMPreparedStatement(final MMConnection conn,
- * final String sql)</code> with a fake connection object constructed by
- * <code>Mockito</code>.
- *
- * @param sql the query for the prepared statement
- * @return an instance of TestableMMPreparedStatement
- * @throws SQLException
- */
- protected PreparedStatementImpl getMMPreparedStatement(final String sql) throws SQLException {
- ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
- ServerConnection serverConn = Mockito.mock(ServerConnection.class);
- LogonResult logonResult = Mockito.mock(LogonResult.class);
-
- Mockito.stub(conn.getServerConnection()).toReturn(serverConn);
- Mockito.stub(serverConn.getLogonResult()).toReturn(logonResult);
- Mockito.stub(logonResult.getTimeZone()).toReturn(TimeZone.getDefault());
-
- return getMMPreparedStatement(conn, sql);
- }
-
- /**
- * A helper method to get an <code>MMPreparedStatement</code> that can be
- * used for simple test cases.
- * <p>
- * The returned value is an instance of <code>TestableMMPreparedStatement</code>
- * <p>
- * <code>conn</code> should be a valid instance of <code>MMConnection</code>
- * or this method will fail.
- *
- * @param conn an instance of <code>MMConnection</code>
- * @param sql the query for the prepared statement
- * @return an instance of TestableMMPreparedStatement
- * @throws SQLException
- */
- protected PreparedStatementImpl getMMPreparedStatement(final ConnectionImpl conn, final String sql) throws SQLException {
- TestableMMPreparedStatement statement = new TestableMMPreparedStatement(conn, sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
-
- // Make sure everything is empty on start
- assertTrue("MMPreparedStatement.ParameterValuesList should be empty", statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
- assertTrue("MMPreparedStatement.ParameterValues should be empty", statement.getParameterValues().size() == 0); //$NON-NLS-1$
-
- return statement;
- }
-
- /**
- * Represents an extension to <code>MMPreparedStatement</code> that
- * gives access to the <code>RequestMessage</code> that is passed
- * around inside <code>MMPreparedStatement</code>.
- * <p>
- * This extension simply adds a field named <code>requestMessage</code>
- * which is <code>public</code>. This field gets set when the <code>protected</code>
- * method <code>createRequestMessage()</code> is called.
- * <p>
- * This extension also overrides <code>RequestMessage createRequestMessage(String[] commands,
- * boolean isBatchedCommand, Boolean requiresResultSet)</code> so that
- * reference to the created <code>RequestMessage</code> can be retained in
- * the field <code>requestMessage</code>.
- */
- class TestableMMPreparedStatement extends PreparedStatementImpl {
- /**
- * Contains a reference to the <code>RequestMessage</code> created by
- * a call to <code>createRequestMessage(String[] commands,
- * boolean isBatchedCommand, Boolean requiresResultSet)</code>. This
- * will allow easy access to the prepared statement's request message
- * generated by a call to one of the statement's execute methods.
- */
- public RequestMessage requestMessage;
- @Override
- protected RequestMessage createRequestMessage(String[] commands,
- boolean isBatchedCommand, ResultsMode resultsMode) {
- this.requestMessage = super
- .createRequestMessage(commands, isBatchedCommand, resultsMode);
- return this.requestMessage;
- }
-
- public TestableMMPreparedStatement(ConnectionImpl connection,
- String sql, int resultSetType, int resultSetConcurrency)
- throws SQLException {
- super(connection, sql, resultSetType, resultSetConcurrency);
- }
-
- }
-
-}
Deleted: trunk/client/src/test/java/org/teiid/jdbc/TestMMResultSet.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestMMResultSet.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestMMResultSet.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -1,753 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.jdbc;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.List;
-import java.util.TimeZone;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-import org.junit.Test;
-import org.teiid.client.DQP;
-import org.teiid.client.ResultsMessage;
-import org.teiid.core.TeiidProcessingException;
-
-
-public class TestMMResultSet {
-
- /** test next() without walking through */
- @Test public void testNext1() throws SQLException {
- ResultSet cs = helpExecuteQuery();
- assertEquals(" Actual doesn't match with expected. ", new Integer(0), new Integer(cs.getRow())); //$NON-NLS-1$
- cs.close();
- }
-
- /** test next() with walking through all the rows and compare records */
- @Test public void testNext2() throws SQLException {
- List[] expected = TestAllResultsImpl.exampleResults1(1000);
- ResultSetImpl cs = helpExecuteQuery();
-
- int i=0;
- while(cs.next()) {
- assertEquals(" Actual doesn't match with expected. ", expected[i], cs.getCurrentRecord()); //$NON-NLS-1$
- i++;
- }
-
- cs.close();
- }
-
- /** test with LargeA -- only work with real model rather than fake metadata*/
-
- // Note for all the following: processor batch size is 100,
- // so some of these tests check what happens when the client
- // fetch size is above, the same, or below it
- public static final int PROC_BATCH_SIZE = 100;
-
- /** Test stability when next() is called beyond the rowcount. */
- @Test public void testNextBeyondEnd_fetchEqualsCount() throws Exception {
- helpTestNextBeyondResultSet(1000, 1000);
- }
-
- /** Test stability when next() is called beyond the rowcount. */
- @Test public void testNextBeyondEnd_fetchLessThanCount() throws Exception {
- helpTestNextBeyondResultSet(100, 1000);
- }
-
- /** Test stability when next() is called beyond the rowcount with one more row. */
- @Test public void testNextBeyondEnd_fetchLessThanCount1() throws Exception {
- helpTestNextBeyondResultSet(100, 101);
- }
-
- /** Test stability when next() is called beyond the rowcount. */
- @Test public void testNextBeyondEnd_fetchLessThanCountNonMultiple() throws Exception {
- helpTestNextBeyondResultSet(120, 1000);
- }
-
- /** Test stability when next() is called beyond the rowcount. */
- @Test public void testNextBeyondEnd_fetchGreaterThanCount() throws Exception {
- helpTestNextBeyondResultSet(300, PROC_BATCH_SIZE);
- }
-
- /** Test stability when next() is called beyond the rowcount. */
- @Test public void testNextBeyondEnd_fetchGreaterThanCountNonMultiple() throws Exception {
- helpTestNextBeyondResultSet(310, PROC_BATCH_SIZE-50);
- }
-
- /** Test stability when next() is called beyond the rowcount. */
- @Test public void testNextBeyondEnd_fetchGreaterThanCountNonMultiple2() throws Exception {
- helpTestNextBeyondResultSet(300, PROC_BATCH_SIZE+10);
- }
-
- /** Test that the returned results walks through all results if
- * fetchSize < rows < proc batch size.
- * Test for defect 11356
- */
- @Test public void testNextBeyondEnd_fetchLessThanCount_ResultsBetweenFetchAndProcBatch() throws Exception {
- helpTestNextBeyondResultSet(30, PROC_BATCH_SIZE-25);
- }
-
- public void helpTestNextBeyondResultSet(int fetchSize, int numRows) throws Exception {
- ResultSet cs = helpExecuteQuery(fetchSize, numRows, ResultSet.TYPE_SCROLL_INSENSITIVE);
- try {
- Object lastRowValue = null;
- for (int rowNum = 1; rowNum <= numRows; rowNum++) {
- assertEquals("Should return true before end cs.next()", true, cs.next()); //$NON-NLS-1$
- }
-
- lastRowValue = cs.getObject(1);
-
- // Should just return false and leave cursor where it is
- for(int i=numRows+1; i<numRows+4; i++) {
- assertEquals("Should return false when going past the end: " + i, false, cs.next()); //$NON-NLS-1$
- assertEquals("Is after last should be true: " + i, true, cs.isAfterLast()); //$NON-NLS-1$
- }
-
- // Should still be just after last row
- cs.previous();
- assertEquals("Is last should be true", true, cs.isLast()); //$NON-NLS-1$
- assertEquals("Not on last row", lastRowValue, cs.getObject(1)); //$NON-NLS-1$
-
- } finally {
- cs.close();
- }
- }
-
- /** test both next() and previous() -- when result set scroll in bidirection */
- @Test public void testBidirection() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- assertNotNull(cs);
- cs.absolute(290);
- assertEquals(" Actual value doesn't match with expected one.", new Integer(290), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
- cs.next();
- assertEquals(" Actual value doesn't match with expected one.", new Integer(291), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
- cs.next();
- assertEquals(" Actual value doesn't match with expected one.", new Integer(292), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
- cs.previous();
- assertEquals(" Actual value doesn't match with expected one.", new Integer(291), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
- cs.next();
- assertEquals(" Actual value doesn't match with expected one.", new Integer(292), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
- cs.close();
- }
-
- /** test hasNext() without walking through any row */
- @Test public void testHasNext1() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- assertEquals(" hasNext() doesn't match expected value. ", true, cs.hasNext()); //$NON-NLS-1$
- cs.close();
- }
-
- /** test hasNext() with blocking for the Next batch -- triggering point */
- @Test public void testHasNext2() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.absolute(100);
- assertEquals(" hasNext() doesn't match expected value. ", true, cs.hasNext()); //$NON-NLS-1$
- cs.close();
- }
-
- /** test hasNext() with nextBatch!=null -- short response */
- @Test public void testHasNext3() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- int i = 0;
- while (cs.next()) {
- if (i == 289) {
- break;
- }
- i++;
- }
- assertEquals(" hasNext() doesn't match expected value. ", true, cs.hasNext()); //$NON-NLS-1$
- cs.close();
- }
-
- /** at the end of all batches */
- @Test public void testHasNext4() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.absolute(1000);
- assertTrue(!cs.hasNext());
- cs.close();
- }
-
- /** walk all way through from the end back to first row */
- @Test public void testPrevious1() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- List[] expected = TestAllResultsImpl.exampleResults1(1000);
- while(cs.next()) {
- //System.out.println(" rs.next == " + cs.getCurrentRecord());
- }
- // cursor is after the last row. getRow() should return 0 when not on a valid row
- assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
-
- int i= 1000;
- while (cs.previous()) {
- //System.out.println(" rs.previous == " + cs.getCurrentRecord());
- assertEquals(" Actual doesn't match with expected. ", expected[i-1], cs.getCurrentRecord()); //$NON-NLS-1$
- i--;
- }
- assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** test the previous in the middle of a batch */
- @Test public void testPrevious2() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.absolute(290);
-
- // cursor is at the row of 289 now
- assertTrue(cs.previous());
- assertEquals(" current row doesn't match expected value. ", 289, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** walk all way through from the end back to first row */
- @Test public void testPrevious3() throws Exception {
- //large batch size
- ResultSetImpl cs = helpExecuteQuery(600, 10000, ResultSet.TYPE_SCROLL_INSENSITIVE);
- List[] expected = TestAllResultsImpl.exampleResults1(10000);
- while(cs.next()) {
- }
- // cursor is after the last row. getRow() should return 0 when not on a valid row
- assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
-
- int i= 10000;
- while (cs.previous()) {
- //System.out.println(" rs.previous == " + cs.getCurrentRecord());
- assertEquals(" Actual doesn't match with expected. ", expected[i-1], cs.getCurrentRecord()); //$NON-NLS-1$
- i--;
- }
- assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** walk all way through from the end back to first row */
- @Test public void testPrevious4() throws Exception {
- //small batch size
- ResultSetImpl cs = helpExecuteQuery(50, 1000, ResultSet.TYPE_SCROLL_INSENSITIVE);
- List[] expected = TestAllResultsImpl.exampleResults1(1000);
- while(cs.next()) {
- //System.out.println(" rs.next == " + cs.getCurrentRecord());
- }
- // cursor is after the last row. getRow() should return 0 when not on a valid row
- assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
-
- int i= 1000;
- while (cs.previous()) {
- //System.out.println(" rs.previous == " + cs.getCurrentRecord());
- assertEquals(" Actual doesn't match with expected. ", expected[i-1], cs.getCurrentRecord()); //$NON-NLS-1$
- i--;
- }
- assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** test rare case that cursor change direction */
- @Test public void testChangeDirection() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.absolute(291);
- cs.previous();
-
- assertEquals(" current row doesn't match expected value. ", 290, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- @Test public void testIsFirst() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.next();
- assertTrue(cs.isFirst());
- cs.close();
- }
-
- /** test cursor is in the middle of all batches */
- @Test public void testIsLast1() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.next();
- assertTrue(!cs.isLast());
- cs.close();
- }
-
- /** test cursor at the triggering point -- blocking case*/
- @Test public void testIsLast2() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- int i = 0;
- while (cs.next()) {
- if (i == 99) {
- break;
- }
- i++;
- }
-
- assertTrue(!cs.isLast());
- cs.close();
- }
-
- /** test cursor at the last row of all batches */
- @Test public void testIsLast3() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.absolute(1000);
- assertTrue(cs.isLast());
- cs.close();
- }
-
- @Test public void testIsBeforeFirst() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- assertTrue(cs.isBeforeFirst());
- cs.close();
- }
-
- @Test public void testBeforeFirst() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to row 1
- cs.next();
- assertEquals(" Current row number doesn't match with expected one.", 1, cs.getRow()); //$NON-NLS-1$
-
- // move back to before first row
- cs.beforeFirst();
- assertTrue(cs.isBeforeFirst());
- cs.close();
- }
-
- @Test public void testFirst() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to row #2
- cs.next();
- cs.next();
- assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
-
- // move back to the 1st row
- cs.first();
- assertEquals(" Current row number doesn't match with expected one.", 1, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- @Test public void testAfterLast() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.afterLast();
- assertTrue(cs.isAfterLast());
- cs.close();
- }
-
- /** right after the last row */
- @Test public void testIsAfterLast1() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.absolute(1000);
- cs.next();
- assertTrue(cs.isAfterLast());
- cs.close();
- }
-
- /** right before the first */
- @Test public void testIsAfterLast2() throws Exception {
- ResultSetImpl cs = helpExecuteQuery();
- assertTrue(!cs.isAfterLast());
- cs.close();
- }
-
- /** absolute with cursor movement backward in the same batch -- absolute(positive) */
- @Test public void testAbsolute1() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to row #2
- cs.next();
- cs.next();
- assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
-
- // move back to the 1st row
- cs.absolute(1);
- assertEquals(" Current row number doesn't match with expected one.", 1, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** absolute with cursor movement forward in the same batch -- absolute(positive) */
- @Test public void testAbsolute2() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to row #2
- cs.next();
- cs.next();
- assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
-
- // move back to the 1st row
- cs.absolute(3);
- assertEquals(" Current row number doesn't match with expected one.", 3, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** absolute with cursor movement forward -- absolute(positive) -- blocking */
- @Test public void testAbsolute3() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to row #2
- cs.next();
- cs.next();
- assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
-
- // move to row #100 -- blocking
- cs.absolute(100);
- assertEquals(" Current row number doesn't match with expected one.", 100, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** absolute with cursor movement forward -- absolute(positive) -- triggering point */
- @Test public void testAbsolute4() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to row #2
- cs.next();
- cs.next();
- assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
-
- // move to row #200 -- new batch
- cs.absolute(200);
- assertEquals(" Current row number doesn't match with expected one.", 200, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** absolute with cursor movement back in the same batch -- absolute(negative) */
- @Test public void testAbsolute5() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to row #2
- cs.next();
- cs.next();
- assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
-
- // move back to the 1st row
- cs.absolute(-1);
- assertEquals(" Current row number doesn't match with expected one.", 1000, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** absolute after last row */
- @Test public void testAbsolute6() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.absolute(1005);
- // Cursor should be after last row. getRow() should return 0 because
- // cursor is not on a valid row
- assertEquals(" Current row number doesn't match with expected one.", 0, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** relative(positive) -- forward to another batch */
- @Test public void testRelative1() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to the row #3
- cs.absolute(3);
- assertEquals(" Current row number doesn't match with expected one.", 3, cs.getRow()); //$NON-NLS-1$
-
- // move to the row #140
- cs.relative(137);
- assertEquals(" Current row number doesn't match with expected one.", 140, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** relative(negative) -- backward to another batch */
- @Test public void testRelative2() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to the row #137
- cs.absolute(137);
- assertEquals(" Current row number doesn't match with expected one.", 137, cs.getRow()); //$NON-NLS-1$
-
- // move to the row #4
- cs.relative(-133);
- assertEquals(" Current row number doesn't match with expected one.", 4, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** relative(negative) -- backward to triggering point or blocking batch */
- @Test public void testRelative3() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to the row #137
- cs.absolute(137);
- assertEquals(" Current row number doesn't match with expected one.", 137, cs.getRow()); //$NON-NLS-1$
-
- // move to the row #100
- cs.relative(-37);
- assertEquals(" Current row number doesn't match with expected one.", 100, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** relative(negative) -- backward to triggering point or blocking batch */
- @Test public void testRelative4() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // move to the row #237 in the third batch, so that the fourth batch has been requested when we switch direction
- cs.absolute(237);
- assertEquals(" Current row number doesn't match with expected one.", 237, cs.getRow()); //$NON-NLS-1$
-
- // move to the row #37
- cs.relative(-200);
- assertEquals(" Current row number doesn't match with expected one.", 37, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** in the first fetched batch */
- @Test public void testGetRow1() throws SQLException {
- ResultSet cs = helpExecuteQuery();
-
- int i = 0;
- while (cs.next()) {
- if (i == 102) {
- break;
- }
- i++;
- }
-
- assertEquals(" Current row number doesn't match with expected one.", i+1, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** in the first batch */
- @Test public void testGetRow2() throws SQLException {
- ResultSet cs = helpExecuteQuery();
-
- cs.next();
- assertEquals(" Current row number doesn't match with expected one.", 1, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- /** in the triggering point -- blocking */
- @Test public void testGetRow3() throws SQLException {
- ResultSet cs = helpExecuteQuery();
- int i = 0;
- while (cs.next()) {
- if (i == 99) {
- break;
- }
- i++;
- }
- assertEquals(" Current row number doesn't match with expected one.", 100, cs.getRow()); //$NON-NLS-1$
- cs.close();
- }
-
- @Test public void testGetCurrentRecord() throws SQLException {
- ResultSet cs = helpExecuteQuery();
- cs.absolute(103);
- assertEquals(" Current record doesn't match with expected one.", new Integer(103), ((ResultSetImpl)cs).getCurrentRecord().get(0)); //$NON-NLS-1$
- cs.close();
- }
-
- /** test close() without walking through any of the record*/
- @Test public void testClose() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- assertEquals(" Actual doesn't match with expected. ", new Integer(0), new Integer(cs.getRow())); //$NON-NLS-1$
- cs.close();
- }
-
- /** test basic results-related metadata */
- @Test public void testGetMetaData() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
-
- // check result set metadata
- // expected column info.
- List columnName = getBQTRSMetaData1a();
- List columnType = getBQTRSMetaData1b();
- List columnTypeName = getBQTRSMetaData1c();
-
- ResultSetMetaData rm = cs.getMetaData();
- assertNotNull(rm);
-
- for (int j = 1; j <= rm.getColumnCount(); j++) {
- assertEquals(" Actual doesn't match with expected. ", columnName.get(j-1), rm.getColumnName(j)); //$NON-NLS-1$
- assertEquals(" Actual doesn't match with expected. ", columnType.get(j-1), new Integer(rm.getColumnType(j))); //$NON-NLS-1$
- assertEquals(" Actual doesn't match with expected. ", columnTypeName.get(j-1), rm.getColumnTypeName(j)); //$NON-NLS-1$
- }
-
- cs.close();
- }
-
- @Test public void testFindColumn() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- ResultSetMetaData rm = cs.getMetaData();
- assertNotNull(rm);
- //assertEquals(" Actual columnName doesn't match with expected. ", 1, cs.findColumn("BQT1.MediumA.IntKey"));
- assertEquals(" Actual columnName doesn't match with expected. ", 1, cs.findColumn("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
- cs.close();
- }
-
- @Test public void testFindNonExistentColumn() throws SQLException {
- ResultSet rs = helpExecuteQuery();
- rs.next();
- try {
- rs.findColumn("BOGUS"); //$NON-NLS-1$
- } catch(SQLException e) {
- }
-
- try {
- rs.getObject("BOGUS"); //$NON-NLS-1$
- } catch(SQLException e) {
- }
- rs.close();
- }
-
- @Test public void testGetStatement() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- assertNotNull(cs.getStatement());
- cs.close();
- }
-
- @Test public void testGetPlanDescription() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- assertNotNull(cs);
-
- assertNull((cs.getStatement()).getPlanDescription());
- cs.close();
- }
-
- /** getObject(String) */
- @Test public void testGetObject2() throws SQLException {
- ResultSet cs = helpExecuteQuery();
-
- // move to the 1st row
- cs.next();
- assertEquals(" Actual value doesn't match with expected. ", new Integer(1), cs.getObject("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
- cs.close();
- }
-
- @Test public void testGetWarnings() throws SQLException {
- ResultSet cs = helpExecuteQuery();
- assertNull(cs.getWarnings());
- cs.close();
- }
-
- @Test public void testGetCursorName() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- assertNull(cs.getCursorName());
- cs.close();
- }
-
- @Test public void testAllGetters() throws SQLException {
- ResultSetImpl cs = helpExecuteQuery();
- cs.next();
- assertEquals(" Actual value of getInt() doesn't match with expected one. ", 1, cs.getInt("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(" Actual value of getString() doesn't match with expected one. ", "1", cs.getString("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
- // Add these back when the MediumA has all those columns
- assertEquals(" Actual value of getFloat() doesn't match with expected one. ", new Float(1), new Float(cs.getFloat("IntKey"))); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(" Actual value of getLong() doesn't match with expected one. ", 1, cs.getLong("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(" Actual value of getDouble() doesn't match with expected one. ", new Double(1), new Double(cs.getDouble("IntKey"))); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(" Actual value of getByte() doesn't match with expected one. ", (byte)1, cs.getByte("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- /** test wasNull() for ResultSet, this result actually is not a cursor result, but AllResults here. */
- @Test public void testWasNull() throws SQLException {
- ResultSet cs = helpExecuteQuery();
- cs.next();
- assertNotNull(cs.getObject("IntKey")); //$NON-NLS-1$
- assertFalse(cs.wasNull());
- }
-
- @Test public void testForwardOnly() throws Exception {
- ResultSetImpl cs = helpExecuteQuery(400, 1000, ResultSet.TYPE_FORWARD_ONLY);
-
- while (cs.next()) {
- cs.getObject(1);
- }
-
- assertTrue(cs.isAfterLast());
- cs.close();
- }
-
- @Test public void testOutputParameter() throws Exception {
- StatementImpl statement = createMockStatement(ResultSet.TYPE_FORWARD_ONLY);
- ResultsMessage resultsMsg = new ResultsMessage();
- resultsMsg.setResults(new List<?>[] {Arrays.asList(1, null, null), Arrays.asList(null, 2, 3)});
- resultsMsg.setLastRow(2);
- resultsMsg.setFirstRow(1);
- resultsMsg.setFinalRow(2);
- resultsMsg.setColumnNames(new String[] {"x", "out1", "out2"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- resultsMsg.setDataTypes(new String[] {"integer", "integer", "integer"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- ResultSetImpl cs = new ResultSetImpl(resultsMsg, statement, null, 2);
-
- int count = 0;
- while (cs.next()) {
- cs.getObject(1);
- count++;
- }
- assertEquals(1, count);
- assertTrue(cs.isAfterLast());
- assertEquals(2, cs.getOutputParamValue(2));
- assertEquals(3, cs.getOutputParamValue(3));
- }
-
- /////////////////////// Helper Method ///////////////////
-
- private ResultSetImpl helpExecuteQuery() {
- try {
- return helpExecuteQuery(400, 1000, ResultSet.TYPE_SCROLL_INSENSITIVE);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private ResultSetImpl helpExecuteQuery(int fetchSize, int totalResults, int cursorType) throws SQLException, TeiidProcessingException, InterruptedException, ExecutionException, TimeoutException {
- StatementImpl statement = createMockStatement(cursorType);
- return TestAllResultsImpl.helpTestBatching(statement, fetchSize, Math.min(fetchSize, totalResults), totalResults);
- }
-
- static StatementImpl createMockStatement(int cursorType) throws SQLException {
- StatementImpl statement = mock(StatementImpl.class);
- stub(statement.getDQP()).toReturn(mock(DQP.class));
- stub(statement.getResultSetType()).toReturn(cursorType);
- TimeZone tz = TimeZone.getTimeZone("GMT-06:00"); //$NON-NLS-1$
- TimeZone serverTz = TimeZone.getTimeZone("GMT-05:00"); //$NON-NLS-1$
- stub(statement.getDefaultCalendar()).toReturn(Calendar.getInstance(tz));
- stub(statement.getServerTimeZone()).toReturn(serverTz);
- return statement;
- }
-
- ////////////////////////Expected Results////////////////
- /** column name */
- private List getBQTRSMetaData1a() {
- List results = new ArrayList();
- results.add("IntKey"); //$NON-NLS-1$
- return results;
- }
-
- /** column type */
- private List getBQTRSMetaData1b() {
- List results = new ArrayList();
- results.add(new Integer(Types.INTEGER));
- return results;
- }
-
- /** column type name*/
- private List getBQTRSMetaData1c() {
- List results = new ArrayList();
- results.add("integer"); //$NON-NLS-1$
- return results;
- }
-}
Deleted: trunk/client/src/test/java/org/teiid/jdbc/TestMMSQLException.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestMMSQLException.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestMMSQLException.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -1,234 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.jdbc;
-
-import java.io.IOException;
-import java.net.ConnectException;
-import java.net.MalformedURLException;
-import java.net.NoRouteToHostException;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-import java.sql.SQLException;
-
-import junit.framework.TestCase;
-
-import org.teiid.client.ProcedureErrorInstructionException;
-import org.teiid.core.TeiidProcessingException;
-import org.teiid.core.TeiidException;
-import org.teiid.core.TeiidException;
-import org.teiid.core.TeiidRuntimeException;
-import org.teiid.net.CommunicationException;
-import org.teiid.net.ConnectionException;
-
-
-public class TestMMSQLException extends TestCase {
-
- /*
- * Test method for 'com.metamatrix.jdbc.MMSQLException.MMSQLException()'
- */
- public void testMMSQLException() {
- TeiidSQLException e = new TeiidSQLException();
- String sqlState = e.getSQLState();
- Throwable cause = e.getCause();
- int errorCode = e.getErrorCode();
- Throwable nestedException = e.getCause();
- SQLException nextException = e.getNextException();
-
- assertTrue(
- "Expected MMSQLException.getSQLState() to return <null> but got \"" //$NON-NLS-1$
- + sqlState + "\" instead.", sqlState == null); //$NON-NLS-1$
- assertTrue(
- "Expected MMSQLException.getCause() to return <null> but got [" //$NON-NLS-1$
- + (cause != null ? cause.getClass().getName()
- : "<unknown>") + "] instead.", cause == null); //$NON-NLS-1$ //$NON-NLS-2$
- assertTrue(
- "Expected MMSQLException.getErrorCode() to return [0] but got [" //$NON-NLS-1$
- + errorCode + "] instead.", errorCode == 0); //$NON-NLS-1$
- assertTrue(
- "Expected MMSQLException.getNestedException() to return <null> but got [" //$NON-NLS-1$
- + (nestedException != null ? nestedException.getClass()
- .getName() : "<unknown>") + "] instead.", //$NON-NLS-1$ //$NON-NLS-2$
- nestedException == null);
- assertTrue(
- "Expected MMSQLException.getNextException() to return <null> but got a SQLException with message \"" //$NON-NLS-1$
- + (nextException != null ? nextException.getMessage()
- : "") + "\" instead.", nextException == null); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- /*
- * Test method for 'com.metamatrix.jdbc.MMSQLException.create(Throwable)'
- *
- * Tests various simple exceptions to see if the expected SQLState is
- * returend.
- */
- public void testCreateThrowable_01() {
- testCreateThrowable(new CommunicationException(
- "A test MM Communication Exception"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
- testCreateThrowable(
- new ConnectException("A test connection attempt exception"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
- testCreateThrowable(
- new ConnectionException("A test MM Connection Exception"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
- testCreateThrowable(new IOException(
- "A test Generic java.io.IOException"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
- testCreateThrowable(
- new MalformedURLException(
- "A test java.net.MalformedURLException"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
- testCreateThrowable(new TeiidException(
- "A test Generic MM Core Exception"), SQLStates.DEFAULT); //$NON-NLS-1$
- testCreateThrowable(new TeiidException("A test MM Exception"), //$NON-NLS-1$
- SQLStates.DEFAULT);
- testCreateThrowable(new TeiidProcessingException(
- "A test Generic MM Query Processing Exception"), //$NON-NLS-1$
- SQLStates.USAGE_ERROR);
- testCreateThrowable(new TeiidRuntimeException(
- "A test MM Runtime Exception"), SQLStates.DEFAULT); //$NON-NLS-1$
- testCreateThrowable(new TeiidSQLException(
- "A test Generic MM SQL Exception"), SQLStates.DEFAULT); //$NON-NLS-1$
- testCreateThrowable(
- new NoRouteToHostException(
- "A test java.net.NoRouteToHostException"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
- testCreateThrowable(new NullPointerException("A test NPE"), //$NON-NLS-1$
- SQLStates.DEFAULT);
- testCreateThrowable(new ProcedureErrorInstructionException(
- "A test SQL Procedure Error exception"), //$NON-NLS-1$
- SQLStates.VIRTUAL_PROCEDURE_ERROR);
- testCreateThrowable(new SocketTimeoutException(
- "A test socket timeout exception"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
- testCreateThrowable(
- new UnknownHostException("A test connection attempt exception"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
- }
-
- /*
- * Test method for 'com.metamatrix.jdbc.MMSQLException.create(Throwable)'
- *
- * Tests various nested exceptions to see if the expected SQLState is
- * returend.
- */
- public void testCreateThrowable_02() {
- testCreateThrowable(
- new CommunicationException(new ConnectException(
- "A test java.net.ConnectException"), //$NON-NLS-1$
- "Test Communication Exception with a ConnectException in it"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
- testCreateThrowable(new CommunicationException(new SocketException(
- "A test java.net.SocketException"), //$NON-NLS-1$
- "Test Communication Exception with a SocketException in it"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
- testCreateThrowable(
- new TeiidException(new SocketTimeoutException(
- "A test java.net.SocketTimeoutException"), //$NON-NLS-1$
- "Test MetaMatrixException with a SocketTimeoutException in it"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
- }
-
- public void testCreateThrowable3() {
- TeiidSQLException e = testCreateThrowable(
- new TeiidException(
- new TeiidRuntimeException(
- new SocketTimeoutException(
- "A test MM Invalid Session Exception"), //$NON-NLS-1$
- "Test MetaMatrixRuntimeException with a InvalidSessionException in it"), //$NON-NLS-1$
- "Test MM Core Exception with an MM Runtime Exception in it and an InvalidSessionException nested within"), //$NON-NLS-1$
- SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
-
- //test to ensure that wrapping mmsqlexceptions works
- TeiidSQLException e1 = TeiidSQLException.create(e, "new message"); //$NON-NLS-1$
- assertEquals("new message", e1.getMessage()); //$NON-NLS-1$
- testCreateThrowable(((TeiidSQLException)e1.getCause()).getCause(), SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
- }
-
- /*
- * Helper method to test SQLState and general MMSQLException validation
- */
- private TeiidSQLException testCreateThrowable(Throwable ecause, String esqlState) {
- TeiidSQLException e = TeiidSQLException.create(ecause);
- if (ecause.getClass() == TeiidSQLException.class) {
- ecause = null;
- }
- String sqlState = e.getSQLState();
- Throwable cause = e.getCause();
- int errorCode = e.getErrorCode();
- Throwable nestedException = e.getCause();
- SQLException nextException = e.getNextException();
-
- assertTrue("Expected MMSQLException.getSQLState() to return \"" //$NON-NLS-1$
- + esqlState + "\" but got \"" + sqlState + "\" instead.", //$NON-NLS-1$ //$NON-NLS-2$
- sqlState.compareTo(esqlState) == 0);
- assertTrue("Expected MMSQLException.getCause() to return [" //$NON-NLS-1$
- + (ecause != null ? ecause.getClass().getName() : "<null>") //$NON-NLS-1$
- + "] but got [" //$NON-NLS-1$
- + (cause != null ? cause.getClass().getName() : "<unknown>") //$NON-NLS-1$
- + "] instead.", cause == ecause); //$NON-NLS-1$
- assertTrue(
- "Expected MMSQLException.getErrorCode() to return [0] but got [" //$NON-NLS-1$
- + errorCode + "] instead.", errorCode == 0); //$NON-NLS-1$
- assertTrue("Expected MMSQLException.getNestedException() to return [" //$NON-NLS-1$
- + (ecause != null ? ecause.getClass().getName() : "<null>") //$NON-NLS-1$
- + "] but got [" //$NON-NLS-1$
- + (nestedException != null ? nestedException.getClass()
- .getName() : "<unknown>") + "] instead.", //$NON-NLS-1$ //$NON-NLS-2$
- nestedException == ecause);
- assertTrue(
- "Expected MMSQLException.getNextException() to return <null> but got a SQLException with message \"" //$NON-NLS-1$
- + (nextException != null ? nextException.getMessage()
- : "") + "\" instead.", nextException == null); //$NON-NLS-1$ //$NON-NLS-2$
- return e;
- }
-
- public void testCreate() {
- TeiidSQLException exception = TeiidSQLException.create(new Exception());
-
- assertEquals(exception.getMessage(), Exception.class.getName());
- assertNotNull(exception.getSQLState());
- assertEquals(exception.getSQLState(), "38000"); //$NON-NLS-1$
-
- assertEquals(exception, TeiidSQLException.create(exception));
- }
-
- public void testCreateFromSQLException() {
- SQLException sqlexception = new SQLException("foo", "21"); //$NON-NLS-1$ //$NON-NLS-2$
-
- SQLException nested = new SQLException("bar"); //$NON-NLS-1$
-
- sqlexception.setNextException(nested);
-
- String message = "top level message"; //$NON-NLS-1$
-
- TeiidSQLException exception = TeiidSQLException.create(sqlexception, message);
-
- assertEquals(exception.getMessage(), message);
- assertEquals(exception.getSQLState(), sqlexception.getSQLState());
- assertEquals(exception.getNextException().getMessage(), sqlexception.getMessage());
- assertEquals(exception.getNextException().getNextException().getMessage(), nested.getMessage());
- }
-
-}
Deleted: trunk/client/src/test/java/org/teiid/jdbc/TestMMStatement.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestMMStatement.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestMMStatement.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -1,88 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.jdbc;
-
-import static org.junit.Assert.*;
-
-import java.sql.ResultSet;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Properties;
-
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.teiid.client.DQP;
-import org.teiid.client.RequestMessage;
-import org.teiid.client.ResultsMessage;
-import org.teiid.client.util.ResultsFuture;
-import org.teiid.jdbc.ConnectionImpl;
-import org.teiid.jdbc.TeiidSQLException;
-import org.teiid.jdbc.StatementImpl;
-
-
-public class TestMMStatement {
-
- @Test(expected=TeiidSQLException.class) public void testUpdateException() throws Exception {
- StatementImpl statement = new StatementImpl(Mockito.mock(ConnectionImpl.class), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
- statement.executeQuery("delete from table"); //$NON-NLS-1$
- }
-
- @Test public void testBatchExecution() throws Exception {
- ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
- DQP dqp = Mockito.mock(DQP.class);
- ResultsFuture<ResultsMessage> results = new ResultsFuture<ResultsMessage>();
- Mockito.stub(dqp.executeRequest(Mockito.anyLong(), (RequestMessage)Mockito.anyObject())).toReturn(results);
- ResultsMessage rm = new ResultsMessage();
- rm.setResults(new List<?>[] {Arrays.asList(1), Arrays.asList(2)});
- rm.setUpdateResult(true);
- results.getResultsReceiver().receiveResults(rm);
- Mockito.stub(conn.getDQP()).toReturn(dqp);
- StatementImpl statement = new StatementImpl(conn, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
- statement.addBatch("delete from table"); //$NON-NLS-1$
- statement.addBatch("delete from table1"); //$NON-NLS-1$
- assertTrue(Arrays.equals(new int[] {1, 2}, statement.executeBatch()));
- }
-
- @Test public void testSetStatement() throws Exception {
- ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
- Properties p = new Properties();
- Mockito.stub(conn.getConnectionProperties()).toReturn(p);
- StatementImpl statement = new StatementImpl(conn, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
- assertFalse(statement.execute("set foo bar")); //$NON-NLS-1$
- assertEquals("bar", p.get("foo")); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- @Test public void testPropertiesOverride() throws Exception {
- ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
- Properties p = new Properties();
- p.setProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS, Boolean.TRUE.toString());
- Mockito.stub(conn.getConnectionProperties()).toReturn(p);
- StatementImpl statement = new StatementImpl(conn, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
- assertEquals(Boolean.TRUE.toString(), statement.getExecutionProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS));
- statement.setExecutionProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS, Boolean.FALSE.toString());
- assertEquals(Boolean.FALSE.toString(), statement.getExecutionProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS));
- assertEquals(Boolean.TRUE.toString(), p.getProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS));
- }
-
-
-}
Deleted: trunk/client/src/test/java/org/teiid/jdbc/TestMMXAConnection.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestMMXAConnection.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestMMXAConnection.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -1,72 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.jdbc;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-
-import javax.transaction.xa.XAResource;
-
-import org.teiid.client.xa.XidImpl;
-import org.teiid.jdbc.ConnectionImpl;
-import org.teiid.jdbc.StatementImpl;
-import org.teiid.jdbc.XAConnectionImpl;
-
-import junit.framework.TestCase;
-
-
-
-public class TestMMXAConnection extends TestCase {
-
- public void testConnectionClose() throws Exception {
-
- final ConnectionImpl mmConn = TestMMConnection.getMMConnection();
-
- XAConnectionImpl xaConn = new XAConnectionImpl(new XAConnectionImpl.ConnectionSource() {
- //## JDBC4.0-begin ##
- @Override
- //## JDBC4.0-end ##
- public ConnectionImpl createConnection() throws SQLException {
- return mmConn;
- }
- });
-
- Connection conn = xaConn.getConnection();
- StatementImpl stmt = (StatementImpl)conn.createStatement();
- conn.setAutoCommit(false);
- conn.close();
-
- assertTrue(stmt.isClosed());
- assertTrue(conn.getAutoCommit());
-
- conn = xaConn.getConnection();
- stmt = (StatementImpl)conn.createStatement();
- XAResource resource = xaConn.getXAResource();
- resource.start(new XidImpl(1, new byte[0], new byte[0]), XAResource.TMNOFLAGS);
- conn.close();
-
- assertTrue(stmt.isClosed());
- assertTrue(conn.getAutoCommit());
- }
-
-}
Copied: trunk/client/src/test/java/org/teiid/jdbc/TestPreparedStatement.java (from rev 2238, trunk/client/src/test/java/org/teiid/jdbc/TestMMPreparedStatement.java)
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestPreparedStatement.java (rev 0)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestPreparedStatement.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -0,0 +1,343 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import static org.junit.Assert.*;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.teiid.client.DQP;
+import org.teiid.client.RequestMessage;
+import org.teiid.client.ResultsMessage;
+import org.teiid.client.RequestMessage.ResultsMode;
+import org.teiid.client.security.LogonResult;
+import org.teiid.client.util.ResultsFuture;
+import org.teiid.jdbc.ConnectionImpl;
+import org.teiid.jdbc.PreparedStatementImpl;
+import org.teiid.jdbc.TeiidSQLException;
+import org.teiid.net.ServerConnection;
+
+
+/**
+ * Test case to validate general operations on an <code>MMPreparedStatement
+ * </code>
+ */
+public class TestPreparedStatement {
+
+ /**
+ * Test that <code>MMPreparedStatement</code>'s <code>execute()</code> method
+ * will throw a <code>MMSQLException</code> if a connection does not exist.
+ *
+ * @throws Exception
+ */
+ @Test(expected=TeiidSQLException.class) public void testUpdateException() throws Exception {
+ PreparedStatementImpl statement = getMMPreparedStatement("delete from table"); //$NON-NLS-1$
+ statement.execute();
+ }
+
+ /**
+ * Verify that the <code>executeBatch()</code> method of <code>
+ * MMPreparedStatement</code> is resulting in the correct command,
+ * parameter values for each command of the batch, and the request type
+ * are being set in the request message that would normally be sent to the
+ * server.
+ *
+ * @throws Exception
+ */
+ @Test public void testBatchedUpdateExecution() throws Exception {
+ // Build up a fake connection instance for use with the prepared statement
+ ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
+ DQP dqp = Mockito.mock(DQP.class);
+ ServerConnection serverConn = Mockito.mock(ServerConnection.class);
+ LogonResult logonResult = Mockito.mock(LogonResult.class);
+
+ // stub methods
+ Mockito.stub(conn.getServerConnection()).toReturn(serverConn);
+ Mockito.stub(serverConn.getLogonResult()).toReturn(logonResult);
+ Mockito.stub(logonResult.getTimeZone()).toReturn(TimeZone.getDefault());
+
+ // a dummy result message that is specific to this test case
+ ResultsFuture<ResultsMessage> results = new ResultsFuture<ResultsMessage>();
+ Mockito.stub(dqp.executeRequest(Matchers.anyLong(), (RequestMessage)Matchers.anyObject())).toReturn(results);
+ ResultsMessage rm = new ResultsMessage();
+ rm.setResults(new List<?>[] {Arrays.asList(0), Arrays.asList(0), Arrays.asList(0)});
+ rm.setUpdateResult(true);
+ results.getResultsReceiver().receiveResults(rm);
+ Mockito.stub(conn.getDQP()).toReturn(dqp);
+
+ // some update SQL
+ String sqlCommand = "delete from table where col=?"; //$NON-NLS-1$
+ TestableMMPreparedStatement statement = (TestableMMPreparedStatement) getMMPreparedStatement(conn, sqlCommand);
+
+ ArrayList<ArrayList<Object>> expectedParameterValues = new ArrayList<ArrayList<Object>>(3);
+ // Add some batches and their parameter values
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(1) } ) ) );
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(2) } ) ) );
+ statement.setInt(1, new Integer(2));
+ statement.addBatch();
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(3) } ) ) );
+ statement.setInt(1, new Integer(3));
+ statement.addBatch();
+
+ // execute the batch and verify that it matches our dummy results
+ // message set earlier
+ assertTrue(Arrays.equals(new int[] {0, 0, 0}, statement.executeBatch()));
+
+ // Now verify the statement's RequestMessage is what we expect
+ assertEquals("Command does not match", sqlCommand, statement.requestMessage.getCommandString()); //$NON-NLS-1$
+ assertEquals("Parameter values do not match", expectedParameterValues, statement.requestMessage.getParameterValues()); //$NON-NLS-1$
+ assertTrue("RequestMessage.isBatchedUpdate should be true", statement.requestMessage.isBatchedUpdate()); //$NON-NLS-1$
+ assertFalse("RequestMessage.isCallableStatement should be false", statement.requestMessage.isCallableStatement()); //$NON-NLS-1$
+ assertTrue("RequestMessage.isPreparedStatement should be true", statement.requestMessage.isPreparedStatement()); //$NON-NLS-1$
+ }
+
+ /**
+ * Verify that the <code>clearBatch()</code> method of
+ * <code>MMPreparedStatement</code> is clearing the list of batched
+ * commands.
+ * <p>
+ * This is done by first adding command parameter values to the batch and
+ * then invoking the <code>clearBatch()</code> method.
+ *
+ * @throws Exception
+ */
+ @Test public void testClearBatch() throws Exception {
+ PreparedStatementImpl statement = getMMPreparedStatement("delete from table where col=?"); //$NON-NLS-1$
+ // Add some stuff
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+ statement.setInt(1, new Integer(2));
+ statement.addBatch();
+ // Make sure something is really there
+ assertTrue("MMPreparedStatement.ParameterValuesList should not be empty", statement.getParameterValuesList().size() > 0); //$NON-NLS-1$
+ // Now clear it
+ statement.clearBatch();
+ assertTrue("MMPreparedStatement.ParameterValuesList should be empty", statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
+ }
+
+ /**
+ * Adds additional batches of command parameter values to a prepared
+ * statement after a previous list has been cleared.
+ * <p>
+ * This is done by first adding command parameter values to the batch and
+ * then invoking the <code>clearBatch()</code> method. Then a different
+ * set of command parameter values are added to the existing batch command.
+ * <p>
+ * The expected result is the command parameter list for the batches will
+ * only reflect what was added after <code>clearBatch()</code> was invoked.
+ *
+ * @throws Exception
+ */
+ @Test public void testClearBatchAddBatch() throws Exception {
+ PreparedStatementImpl statement = getMMPreparedStatement("delete from table where col=?"); //$NON-NLS-1$
+
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+ statement.setInt(1, new Integer(2));
+ statement.addBatch();
+ // Make sure something is really there
+ assertTrue("MMPreparedStatement.ParameterValuesList should not be empty", statement.getParameterValuesList().size() > 0); //$NON-NLS-1$
+ // Now clear it
+ statement.clearBatch();
+ // Make sure it is empty now
+ assertTrue("MMPreparedStatement.ParameterValuesList should be empty", statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
+
+ ArrayList<ArrayList<Object>> expectedParameterValues = new ArrayList<ArrayList<Object>>(1);
+
+ // Now add something for validation
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(5) } ) ) );
+ statement.setInt(1, new Integer(5));
+ statement.addBatch();
+ assertEquals("MMPreparedStatement.ParameterValuesList does not match", expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
+ }
+
+ /**
+ * Test the <code>addBatch()</code> method of <code>MMPreparedStatement</code>
+ * to verify that the command parameter values of the batch are added to the
+ * command parameter values list.
+ *
+ * @throws Exception
+ */
+ @Test public void testAddBatch() throws Exception {
+ PreparedStatementImpl statement = getMMPreparedStatement("delete from table where col=?"); //$NON-NLS-1$
+
+ ArrayList<ArrayList<Object>> expectedParameterValues = new ArrayList<ArrayList<Object>>(1);
+
+ // First we add a single batch
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(1) } ) ) );
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+ assertEquals("MMPreparedStatement.ParameterValuesList does not match", expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
+
+ // Now add some more batches just for sanity sake
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(3) } ) ) );
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(5) } ) ) );
+ statement.setInt(1, new Integer(3));
+ statement.addBatch();
+ statement.setInt(1, new Integer(5));
+ statement.addBatch();
+ assertEquals("MMPreparedStatement.ParameterValuesList does not match", expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
+ }
+
+ /**
+ * Test the <code>addBatch()</code> method of <code>MMPreparedStatement</code>
+ * using a batch with an empty parameter value list. The test will verify
+ * no failures occur when there are no command parameter values defined
+ * when the <code>addBatch()</code> method is invoked.
+ * <p>
+ * It is valid to add an empty parameter value list to a batch list.
+ * <p>
+ * For example:
+ * <p>
+ * <code>PreparedStatement stmt = conn.prepareStatement(sql);<br \>
+ * stmt.addBatch();<br \>
+ * stmt.addBatch();<br \>
+ * stmt.executeBatch();</code>
+ *
+ * @throws Exception
+ */
+ @Test public void testAddBatchNoParameterValues() throws Exception {
+ PreparedStatementImpl statement = getMMPreparedStatement("delete from table where col=?"); //$NON-NLS-1$
+
+ // This will hold our expected values list
+ ArrayList<ArrayList<Object>> expectedParameterValues = new ArrayList<ArrayList<Object>>(1);
+
+ // First batch has an empty parameter value list
+ expectedParameterValues.add( new ArrayList<Object>(Collections.emptyList()) );
+
+ // No values have been set so we are adding a batch with an empty
+ // parameter value list
+ statement.addBatch();
+
+ // Second batch contains a parameter value list
+ expectedParameterValues.add( new ArrayList<Object>( Arrays.asList( new Object[] { new Integer(1) } ) ) );
+
+ // We now are adding a batch that does have parameter values
+ statement.setInt(1, new Integer(1));
+ statement.addBatch();
+
+ // Check to see if our statement contains our expected parameter value list
+ assertEquals("MMPreparedStatement.ParameterValuesList does not match", expectedParameterValues, statement.getParameterValuesList()); //$NON-NLS-1$
+ }
+
+ /**
+ * A helper method to get an <code>MMPreparedStatement</code> that can be
+ * used for simple test cases.
+ * <p>
+ * The returned value is an instance of <code>TestableMMPreparedStatement</code>
+ * <p>
+ * This method invokes <code>getMMPreparedStatement(final MMConnection conn,
+ * final String sql)</code> with a fake connection object constructed by
+ * <code>Mockito</code>.
+ *
+ * @param sql the query for the prepared statement
+ * @return an instance of TestableMMPreparedStatement
+ * @throws SQLException
+ */
+ protected PreparedStatementImpl getMMPreparedStatement(final String sql) throws SQLException {
+ ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
+ ServerConnection serverConn = Mockito.mock(ServerConnection.class);
+ LogonResult logonResult = Mockito.mock(LogonResult.class);
+
+ Mockito.stub(conn.getServerConnection()).toReturn(serverConn);
+ Mockito.stub(serverConn.getLogonResult()).toReturn(logonResult);
+ Mockito.stub(logonResult.getTimeZone()).toReturn(TimeZone.getDefault());
+
+ return getMMPreparedStatement(conn, sql);
+ }
+
+ /**
+ * A helper method to get an <code>MMPreparedStatement</code> that can be
+ * used for simple test cases.
+ * <p>
+ * The returned value is an instance of <code>TestableMMPreparedStatement</code>
+ * <p>
+ * <code>conn</code> should be a valid instance of <code>MMConnection</code>
+ * or this method will fail.
+ *
+ * @param conn an instance of <code>MMConnection</code>
+ * @param sql the query for the prepared statement
+ * @return an instance of TestableMMPreparedStatement
+ * @throws SQLException
+ */
+ protected PreparedStatementImpl getMMPreparedStatement(final ConnectionImpl conn, final String sql) throws SQLException {
+ TestableMMPreparedStatement statement = new TestableMMPreparedStatement(conn, sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+
+ // Make sure everything is empty on start
+ assertTrue("MMPreparedStatement.ParameterValuesList should be empty", statement.getParameterValuesList().size() == 0); //$NON-NLS-1$
+ assertTrue("MMPreparedStatement.ParameterValues should be empty", statement.getParameterValues().size() == 0); //$NON-NLS-1$
+
+ return statement;
+ }
+
+ /**
+ * Represents an extension to <code>MMPreparedStatement</code> that
+ * gives access to the <code>RequestMessage</code> that is passed
+ * around inside <code>MMPreparedStatement</code>.
+ * <p>
+ * This extension simply adds a field named <code>requestMessage</code>
+ * which is <code>public</code>. This field gets set when the <code>protected</code>
+ * method <code>createRequestMessage()</code> is called.
+ * <p>
+ * This extension also overrides <code>RequestMessage createRequestMessage(String[] commands,
+ * boolean isBatchedCommand, Boolean requiresResultSet)</code> so that
+ * reference to the created <code>RequestMessage</code> can be retained in
+ * the field <code>requestMessage</code>.
+ */
+ class TestableMMPreparedStatement extends PreparedStatementImpl {
+ /**
+ * Contains a reference to the <code>RequestMessage</code> created by
+ * a call to <code>createRequestMessage(String[] commands,
+ * boolean isBatchedCommand, Boolean requiresResultSet)</code>. This
+ * will allow easy access to the prepared statement's request message
+ * generated by a call to one of the statement's execute methods.
+ */
+ public RequestMessage requestMessage;
+ @Override
+ protected RequestMessage createRequestMessage(String[] commands,
+ boolean isBatchedCommand, ResultsMode resultsMode) {
+ this.requestMessage = super
+ .createRequestMessage(commands, isBatchedCommand, resultsMode);
+ return this.requestMessage;
+ }
+
+ public TestableMMPreparedStatement(ConnectionImpl connection,
+ String sql, int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ super(connection, sql, resultSetType, resultSetConcurrency);
+ }
+
+ }
+
+}
Property changes on: trunk/client/src/test/java/org/teiid/jdbc/TestPreparedStatement.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/client/src/test/java/org/teiid/jdbc/TestResultSet.java (from rev 2238, trunk/client/src/test/java/org/teiid/jdbc/TestMMResultSet.java)
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestResultSet.java (rev 0)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestResultSet.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -0,0 +1,777 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.nio.charset.Charset;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.teiid.client.DQP;
+import org.teiid.client.ResultsMessage;
+import org.teiid.client.lob.LobChunk;
+import org.teiid.client.util.ResultsFuture;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.types.XMLType;
+
+@SuppressWarnings("nls")
+public class TestResultSet {
+
+ /** test next() without walking through */
+ @Test public void testNext1() throws SQLException {
+ ResultSet cs = helpExecuteQuery();
+ assertEquals(" Actual doesn't match with expected. ", new Integer(0), new Integer(cs.getRow())); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** test next() with walking through all the rows and compare records */
+ @Test public void testNext2() throws SQLException {
+ List[] expected = TestAllResultsImpl.exampleResults1(1000);
+ ResultSetImpl cs = helpExecuteQuery();
+
+ int i=0;
+ while(cs.next()) {
+ assertEquals(" Actual doesn't match with expected. ", expected[i], cs.getCurrentRecord()); //$NON-NLS-1$
+ i++;
+ }
+
+ cs.close();
+ }
+
+ /** test with LargeA -- only work with real model rather than fake metadata*/
+
+ // Note for all the following: processor batch size is 100,
+ // so some of these tests check what happens when the client
+ // fetch size is above, the same, or below it
+ public static final int PROC_BATCH_SIZE = 100;
+
+ /** Test stability when next() is called beyond the rowcount. */
+ @Test public void testNextBeyondEnd_fetchEqualsCount() throws Exception {
+ helpTestNextBeyondResultSet(1000, 1000);
+ }
+
+ /** Test stability when next() is called beyond the rowcount. */
+ @Test public void testNextBeyondEnd_fetchLessThanCount() throws Exception {
+ helpTestNextBeyondResultSet(100, 1000);
+ }
+
+ /** Test stability when next() is called beyond the rowcount with one more row. */
+ @Test public void testNextBeyondEnd_fetchLessThanCount1() throws Exception {
+ helpTestNextBeyondResultSet(100, 101);
+ }
+
+ /** Test stability when next() is called beyond the rowcount. */
+ @Test public void testNextBeyondEnd_fetchLessThanCountNonMultiple() throws Exception {
+ helpTestNextBeyondResultSet(120, 1000);
+ }
+
+ /** Test stability when next() is called beyond the rowcount. */
+ @Test public void testNextBeyondEnd_fetchGreaterThanCount() throws Exception {
+ helpTestNextBeyondResultSet(300, PROC_BATCH_SIZE);
+ }
+
+ /** Test stability when next() is called beyond the rowcount. */
+ @Test public void testNextBeyondEnd_fetchGreaterThanCountNonMultiple() throws Exception {
+ helpTestNextBeyondResultSet(310, PROC_BATCH_SIZE-50);
+ }
+
+ /** Test stability when next() is called beyond the rowcount. */
+ @Test public void testNextBeyondEnd_fetchGreaterThanCountNonMultiple2() throws Exception {
+ helpTestNextBeyondResultSet(300, PROC_BATCH_SIZE+10);
+ }
+
+ /** Test that the returned results walks through all results if
+ * fetchSize < rows < proc batch size.
+ * Test for defect 11356
+ */
+ @Test public void testNextBeyondEnd_fetchLessThanCount_ResultsBetweenFetchAndProcBatch() throws Exception {
+ helpTestNextBeyondResultSet(30, PROC_BATCH_SIZE-25);
+ }
+
+ public void helpTestNextBeyondResultSet(int fetchSize, int numRows) throws Exception {
+ ResultSet cs = helpExecuteQuery(fetchSize, numRows, ResultSet.TYPE_SCROLL_INSENSITIVE);
+ try {
+ Object lastRowValue = null;
+ for (int rowNum = 1; rowNum <= numRows; rowNum++) {
+ assertEquals("Should return true before end cs.next()", true, cs.next()); //$NON-NLS-1$
+ }
+
+ lastRowValue = cs.getObject(1);
+
+ // Should just return false and leave cursor where it is
+ for(int i=numRows+1; i<numRows+4; i++) {
+ assertEquals("Should return false when going past the end: " + i, false, cs.next()); //$NON-NLS-1$
+ assertEquals("Is after last should be true: " + i, true, cs.isAfterLast()); //$NON-NLS-1$
+ }
+
+ // Should still be just after last row
+ cs.previous();
+ assertEquals("Is last should be true", true, cs.isLast()); //$NON-NLS-1$
+ assertEquals("Not on last row", lastRowValue, cs.getObject(1)); //$NON-NLS-1$
+
+ } finally {
+ cs.close();
+ }
+ }
+
+ /** test both next() and previous() -- when result set scroll in bidirection */
+ @Test public void testBidirection() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ assertNotNull(cs);
+ cs.absolute(290);
+ assertEquals(" Actual value doesn't match with expected one.", new Integer(290), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
+ cs.next();
+ assertEquals(" Actual value doesn't match with expected one.", new Integer(291), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
+ cs.next();
+ assertEquals(" Actual value doesn't match with expected one.", new Integer(292), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
+ cs.previous();
+ assertEquals(" Actual value doesn't match with expected one.", new Integer(291), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
+ cs.next();
+ assertEquals(" Actual value doesn't match with expected one.", new Integer(292), cs.getCurrentRecord().get(0)); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** test hasNext() without walking through any row */
+ @Test public void testHasNext1() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ assertEquals(" hasNext() doesn't match expected value. ", true, cs.hasNext()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** test hasNext() with blocking for the Next batch -- triggering point */
+ @Test public void testHasNext2() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.absolute(100);
+ assertEquals(" hasNext() doesn't match expected value. ", true, cs.hasNext()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** test hasNext() with nextBatch!=null -- short response */
+ @Test public void testHasNext3() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ int i = 0;
+ while (cs.next()) {
+ if (i == 289) {
+ break;
+ }
+ i++;
+ }
+ assertEquals(" hasNext() doesn't match expected value. ", true, cs.hasNext()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** at the end of all batches */
+ @Test public void testHasNext4() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.absolute(1000);
+ assertTrue(!cs.hasNext());
+ cs.close();
+ }
+
+ /** walk all way through from the end back to first row */
+ @Test public void testPrevious1() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ List[] expected = TestAllResultsImpl.exampleResults1(1000);
+ while(cs.next()) {
+ //System.out.println(" rs.next == " + cs.getCurrentRecord());
+ }
+ // cursor is after the last row. getRow() should return 0 when not on a valid row
+ assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
+
+ int i= 1000;
+ while (cs.previous()) {
+ //System.out.println(" rs.previous == " + cs.getCurrentRecord());
+ assertEquals(" Actual doesn't match with expected. ", expected[i-1], cs.getCurrentRecord()); //$NON-NLS-1$
+ i--;
+ }
+ assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** test the previous in the middle of a batch */
+ @Test public void testPrevious2() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.absolute(290);
+
+ // cursor is at the row of 289 now
+ assertTrue(cs.previous());
+ assertEquals(" current row doesn't match expected value. ", 289, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** walk all way through from the end back to first row */
+ @Test public void testPrevious3() throws Exception {
+ //large batch size
+ ResultSetImpl cs = helpExecuteQuery(600, 10000, ResultSet.TYPE_SCROLL_INSENSITIVE);
+ List[] expected = TestAllResultsImpl.exampleResults1(10000);
+ while(cs.next()) {
+ }
+ // cursor is after the last row. getRow() should return 0 when not on a valid row
+ assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
+
+ int i= 10000;
+ while (cs.previous()) {
+ //System.out.println(" rs.previous == " + cs.getCurrentRecord());
+ assertEquals(" Actual doesn't match with expected. ", expected[i-1], cs.getCurrentRecord()); //$NON-NLS-1$
+ i--;
+ }
+ assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** walk all way through from the end back to first row */
+ @Test public void testPrevious4() throws Exception {
+ //small batch size
+ ResultSetImpl cs = helpExecuteQuery(50, 1000, ResultSet.TYPE_SCROLL_INSENSITIVE);
+ List[] expected = TestAllResultsImpl.exampleResults1(1000);
+ while(cs.next()) {
+ //System.out.println(" rs.next == " + cs.getCurrentRecord());
+ }
+ // cursor is after the last row. getRow() should return 0 when not on a valid row
+ assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
+
+ int i= 1000;
+ while (cs.previous()) {
+ //System.out.println(" rs.previous == " + cs.getCurrentRecord());
+ assertEquals(" Actual doesn't match with expected. ", expected[i-1], cs.getCurrentRecord()); //$NON-NLS-1$
+ i--;
+ }
+ assertEquals(" current row doesn't match expected value. ", 0, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** test rare case that cursor change direction */
+ @Test public void testChangeDirection() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.absolute(291);
+ cs.previous();
+
+ assertEquals(" current row doesn't match expected value. ", 290, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ @Test public void testIsFirst() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.next();
+ assertTrue(cs.isFirst());
+ cs.close();
+ }
+
+ /** test cursor is in the middle of all batches */
+ @Test public void testIsLast1() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.next();
+ assertTrue(!cs.isLast());
+ cs.close();
+ }
+
+ /** test cursor at the triggering point -- blocking case*/
+ @Test public void testIsLast2() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ int i = 0;
+ while (cs.next()) {
+ if (i == 99) {
+ break;
+ }
+ i++;
+ }
+
+ assertTrue(!cs.isLast());
+ cs.close();
+ }
+
+ /** test cursor at the last row of all batches */
+ @Test public void testIsLast3() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.absolute(1000);
+ assertTrue(cs.isLast());
+ cs.close();
+ }
+
+ @Test public void testIsBeforeFirst() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ assertTrue(cs.isBeforeFirst());
+ cs.close();
+ }
+
+ @Test public void testBeforeFirst() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to row 1
+ cs.next();
+ assertEquals(" Current row number doesn't match with expected one.", 1, cs.getRow()); //$NON-NLS-1$
+
+ // move back to before first row
+ cs.beforeFirst();
+ assertTrue(cs.isBeforeFirst());
+ cs.close();
+ }
+
+ @Test public void testFirst() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to row #2
+ cs.next();
+ cs.next();
+ assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
+
+ // move back to the 1st row
+ cs.first();
+ assertEquals(" Current row number doesn't match with expected one.", 1, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ @Test public void testAfterLast() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.afterLast();
+ assertTrue(cs.isAfterLast());
+ cs.close();
+ }
+
+ /** right after the last row */
+ @Test public void testIsAfterLast1() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.absolute(1000);
+ cs.next();
+ assertTrue(cs.isAfterLast());
+ cs.close();
+ }
+
+ /** right before the first */
+ @Test public void testIsAfterLast2() throws Exception {
+ ResultSetImpl cs = helpExecuteQuery();
+ assertTrue(!cs.isAfterLast());
+ cs.close();
+ }
+
+ /** absolute with cursor movement backward in the same batch -- absolute(positive) */
+ @Test public void testAbsolute1() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to row #2
+ cs.next();
+ cs.next();
+ assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
+
+ // move back to the 1st row
+ cs.absolute(1);
+ assertEquals(" Current row number doesn't match with expected one.", 1, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** absolute with cursor movement forward in the same batch -- absolute(positive) */
+ @Test public void testAbsolute2() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to row #2
+ cs.next();
+ cs.next();
+ assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
+
+ // move back to the 1st row
+ cs.absolute(3);
+ assertEquals(" Current row number doesn't match with expected one.", 3, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** absolute with cursor movement forward -- absolute(positive) -- blocking */
+ @Test public void testAbsolute3() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to row #2
+ cs.next();
+ cs.next();
+ assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
+
+ // move to row #100 -- blocking
+ cs.absolute(100);
+ assertEquals(" Current row number doesn't match with expected one.", 100, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** absolute with cursor movement forward -- absolute(positive) -- triggering point */
+ @Test public void testAbsolute4() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to row #2
+ cs.next();
+ cs.next();
+ assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
+
+ // move to row #200 -- new batch
+ cs.absolute(200);
+ assertEquals(" Current row number doesn't match with expected one.", 200, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** absolute with cursor movement back in the same batch -- absolute(negative) */
+ @Test public void testAbsolute5() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to row #2
+ cs.next();
+ cs.next();
+ assertEquals(" Current row number doesn't match with expected one.", 2, cs.getRow()); //$NON-NLS-1$
+
+ // move back to the 1st row
+ cs.absolute(-1);
+ assertEquals(" Current row number doesn't match with expected one.", 1000, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** absolute after last row */
+ @Test public void testAbsolute6() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.absolute(1005);
+ // Cursor should be after last row. getRow() should return 0 because
+ // cursor is not on a valid row
+ assertEquals(" Current row number doesn't match with expected one.", 0, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** relative(positive) -- forward to another batch */
+ @Test public void testRelative1() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to the row #3
+ cs.absolute(3);
+ assertEquals(" Current row number doesn't match with expected one.", 3, cs.getRow()); //$NON-NLS-1$
+
+ // move to the row #140
+ cs.relative(137);
+ assertEquals(" Current row number doesn't match with expected one.", 140, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** relative(negative) -- backward to another batch */
+ @Test public void testRelative2() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to the row #137
+ cs.absolute(137);
+ assertEquals(" Current row number doesn't match with expected one.", 137, cs.getRow()); //$NON-NLS-1$
+
+ // move to the row #4
+ cs.relative(-133);
+ assertEquals(" Current row number doesn't match with expected one.", 4, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** relative(negative) -- backward to triggering point or blocking batch */
+ @Test public void testRelative3() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to the row #137
+ cs.absolute(137);
+ assertEquals(" Current row number doesn't match with expected one.", 137, cs.getRow()); //$NON-NLS-1$
+
+ // move to the row #100
+ cs.relative(-37);
+ assertEquals(" Current row number doesn't match with expected one.", 100, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** relative(negative) -- backward to triggering point or blocking batch */
+ @Test public void testRelative4() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // move to the row #237 in the third batch, so that the fourth batch has been requested when we switch direction
+ cs.absolute(237);
+ assertEquals(" Current row number doesn't match with expected one.", 237, cs.getRow()); //$NON-NLS-1$
+
+ // move to the row #37
+ cs.relative(-200);
+ assertEquals(" Current row number doesn't match with expected one.", 37, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** in the first fetched batch */
+ @Test public void testGetRow1() throws SQLException {
+ ResultSet cs = helpExecuteQuery();
+
+ int i = 0;
+ while (cs.next()) {
+ if (i == 102) {
+ break;
+ }
+ i++;
+ }
+
+ assertEquals(" Current row number doesn't match with expected one.", i+1, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** in the first batch */
+ @Test public void testGetRow2() throws SQLException {
+ ResultSet cs = helpExecuteQuery();
+
+ cs.next();
+ assertEquals(" Current row number doesn't match with expected one.", 1, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** in the triggering point -- blocking */
+ @Test public void testGetRow3() throws SQLException {
+ ResultSet cs = helpExecuteQuery();
+ int i = 0;
+ while (cs.next()) {
+ if (i == 99) {
+ break;
+ }
+ i++;
+ }
+ assertEquals(" Current row number doesn't match with expected one.", 100, cs.getRow()); //$NON-NLS-1$
+ cs.close();
+ }
+
+ @Test public void testGetCurrentRecord() throws SQLException {
+ ResultSet cs = helpExecuteQuery();
+ cs.absolute(103);
+ assertEquals(" Current record doesn't match with expected one.", new Integer(103), ((ResultSetImpl)cs).getCurrentRecord().get(0)); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** test close() without walking through any of the record*/
+ @Test public void testClose() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ assertEquals(" Actual doesn't match with expected. ", new Integer(0), new Integer(cs.getRow())); //$NON-NLS-1$
+ cs.close();
+ }
+
+ /** test basic results-related metadata */
+ @Test public void testGetMetaData() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+
+ // check result set metadata
+ // expected column info.
+ List columnName = getBQTRSMetaData1a();
+ List columnType = getBQTRSMetaData1b();
+ List columnTypeName = getBQTRSMetaData1c();
+
+ ResultSetMetaData rm = cs.getMetaData();
+ assertNotNull(rm);
+
+ for (int j = 1; j <= rm.getColumnCount(); j++) {
+ assertEquals(" Actual doesn't match with expected. ", columnName.get(j-1), rm.getColumnName(j)); //$NON-NLS-1$
+ assertEquals(" Actual doesn't match with expected. ", columnType.get(j-1), new Integer(rm.getColumnType(j))); //$NON-NLS-1$
+ assertEquals(" Actual doesn't match with expected. ", columnTypeName.get(j-1), rm.getColumnTypeName(j)); //$NON-NLS-1$
+ }
+
+ cs.close();
+ }
+
+ @Test public void testFindColumn() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ ResultSetMetaData rm = cs.getMetaData();
+ assertNotNull(rm);
+ //assertEquals(" Actual columnName doesn't match with expected. ", 1, cs.findColumn("BQT1.MediumA.IntKey"));
+ assertEquals(" Actual columnName doesn't match with expected. ", 1, cs.findColumn("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
+ cs.close();
+ }
+
+ @Test public void testFindNonExistentColumn() throws SQLException {
+ ResultSet rs = helpExecuteQuery();
+ rs.next();
+ try {
+ rs.findColumn("BOGUS"); //$NON-NLS-1$
+ } catch(SQLException e) {
+ }
+
+ try {
+ rs.getObject("BOGUS"); //$NON-NLS-1$
+ } catch(SQLException e) {
+ }
+ rs.close();
+ }
+
+ @Test public void testGetStatement() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ assertNotNull(cs.getStatement());
+ cs.close();
+ }
+
+ @Test public void testGetPlanDescription() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ assertNotNull(cs);
+
+ assertNull((cs.getStatement()).getPlanDescription());
+ cs.close();
+ }
+
+ /** getObject(String) */
+ @Test public void testGetObject2() throws SQLException {
+ ResultSet cs = helpExecuteQuery();
+
+ // move to the 1st row
+ cs.next();
+ assertEquals(" Actual value doesn't match with expected. ", new Integer(1), cs.getObject("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
+ cs.close();
+ }
+
+ @Test public void testGetWarnings() throws SQLException {
+ ResultSet cs = helpExecuteQuery();
+ assertNull(cs.getWarnings());
+ cs.close();
+ }
+
+ @Test public void testGetCursorName() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ assertNull(cs.getCursorName());
+ cs.close();
+ }
+
+ @Test public void testAllGetters() throws SQLException {
+ ResultSetImpl cs = helpExecuteQuery();
+ cs.next();
+ assertEquals(" Actual value of getInt() doesn't match with expected one. ", 1, cs.getInt("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals(" Actual value of getString() doesn't match with expected one. ", "1", cs.getString("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ // Add these back when the MediumA has all those columns
+ assertEquals(" Actual value of getFloat() doesn't match with expected one. ", new Float(1), new Float(cs.getFloat("IntKey"))); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals(" Actual value of getLong() doesn't match with expected one. ", 1, cs.getLong("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals(" Actual value of getDouble() doesn't match with expected one. ", new Double(1), new Double(cs.getDouble("IntKey"))); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals(" Actual value of getByte() doesn't match with expected one. ", (byte)1, cs.getByte("IntKey")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /** test wasNull() for ResultSet, this result actually is not a cursor result, but AllResults here. */
+ @Test public void testWasNull() throws SQLException {
+ ResultSet cs = helpExecuteQuery();
+ cs.next();
+ assertNotNull(cs.getObject("IntKey")); //$NON-NLS-1$
+ assertFalse(cs.wasNull());
+ }
+
+ @Test public void testForwardOnly() throws Exception {
+ ResultSetImpl cs = helpExecuteQuery(400, 1000, ResultSet.TYPE_FORWARD_ONLY);
+
+ while (cs.next()) {
+ cs.getObject(1);
+ }
+
+ assertTrue(cs.isAfterLast());
+ cs.close();
+ }
+
+ @Test public void testOutputParameter() throws Exception {
+ StatementImpl statement = createMockStatement(ResultSet.TYPE_FORWARD_ONLY);
+ ResultsMessage resultsMsg = new ResultsMessage();
+ resultsMsg.setResults(new List<?>[] {Arrays.asList(1, null, null), Arrays.asList(null, 2, 3)});
+ resultsMsg.setLastRow(2);
+ resultsMsg.setFirstRow(1);
+ resultsMsg.setFinalRow(2);
+ resultsMsg.setColumnNames(new String[] {"x", "out1", "out2"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ resultsMsg.setDataTypes(new String[] {"integer", "integer", "integer"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ResultSetImpl cs = new ResultSetImpl(resultsMsg, statement, null, 2);
+
+ int count = 0;
+ while (cs.next()) {
+ cs.getObject(1);
+ count++;
+ }
+ assertEquals(1, count);
+ assertTrue(cs.isAfterLast());
+ assertEquals(2, cs.getOutputParamValue(2));
+ assertEquals(3, cs.getOutputParamValue(3));
+ }
+
+ @Test public void testXML() throws Exception {
+ StatementImpl statement = createMockStatement(ResultSet.TYPE_FORWARD_ONLY);
+ ResultsFuture<LobChunk> future = new ResultsFuture<LobChunk>();
+ future.getResultsReceiver().receiveResults(new LobChunk("<a/>".getBytes(Charset.forName("UTF-8")), true));
+ Mockito.stub(statement.getDQP().requestNextLobChunk(0, 0, null)).toReturn(future);
+ ResultsMessage resultsMsg = new ResultsMessage();
+ XMLType result = new XMLType();
+ result.setEncoding("UTF-8");
+ resultsMsg.setResults(new List<?>[] {Arrays.asList(result)});
+ resultsMsg.setLastRow(1);
+ resultsMsg.setFirstRow(1);
+ resultsMsg.setFinalRow(1);
+ resultsMsg.setColumnNames(new String[] {"x"}); //$NON-NLS-1$
+ resultsMsg.setDataTypes(new String[] {"xml"}); //$NON-NLS-1$
+ ResultSetImpl cs = new ResultSetImpl(resultsMsg, statement);
+ cs.next();
+ assertEquals("<a/>", cs.getString(1));
+ }
+
+ /////////////////////// Helper Method ///////////////////
+
+ private ResultSetImpl helpExecuteQuery() {
+ try {
+ return helpExecuteQuery(400, 1000, ResultSet.TYPE_SCROLL_INSENSITIVE);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private ResultSetImpl helpExecuteQuery(int fetchSize, int totalResults, int cursorType) throws SQLException, TeiidProcessingException, InterruptedException, ExecutionException, TimeoutException {
+ StatementImpl statement = createMockStatement(cursorType);
+ return TestAllResultsImpl.helpTestBatching(statement, fetchSize, Math.min(fetchSize, totalResults), totalResults);
+ }
+
+ static StatementImpl createMockStatement(int cursorType) throws SQLException {
+ StatementImpl statement = mock(StatementImpl.class);
+ stub(statement.getDQP()).toReturn(mock(DQP.class));
+ stub(statement.getResultSetType()).toReturn(cursorType);
+ TimeZone tz = TimeZone.getTimeZone("GMT-06:00"); //$NON-NLS-1$
+ TimeZone serverTz = TimeZone.getTimeZone("GMT-05:00"); //$NON-NLS-1$
+ stub(statement.getDefaultCalendar()).toReturn(Calendar.getInstance(tz));
+ stub(statement.getServerTimeZone()).toReturn(serverTz);
+ return statement;
+ }
+
+ ////////////////////////Expected Results////////////////
+ /** column name */
+ private List getBQTRSMetaData1a() {
+ List results = new ArrayList();
+ results.add("IntKey"); //$NON-NLS-1$
+ return results;
+ }
+
+ /** column type */
+ private List getBQTRSMetaData1b() {
+ List results = new ArrayList();
+ results.add(new Integer(Types.INTEGER));
+ return results;
+ }
+
+ /** column type name*/
+ private List getBQTRSMetaData1c() {
+ List results = new ArrayList();
+ results.add("integer"); //$NON-NLS-1$
+ return results;
+ }
+}
Copied: trunk/client/src/test/java/org/teiid/jdbc/TestSQLException.java (from rev 2238, trunk/client/src/test/java/org/teiid/jdbc/TestMMSQLException.java)
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestSQLException.java (rev 0)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestSQLException.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -0,0 +1,234 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.MalformedURLException;
+import java.net.NoRouteToHostException;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+
+import org.teiid.client.ProcedureErrorInstructionException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.TeiidException;
+import org.teiid.core.TeiidException;
+import org.teiid.core.TeiidRuntimeException;
+import org.teiid.net.CommunicationException;
+import org.teiid.net.ConnectionException;
+
+
+public class TestSQLException extends TestCase {
+
+ /*
+ * Test method for 'com.metamatrix.jdbc.MMSQLException.MMSQLException()'
+ */
+ public void testMMSQLException() {
+ TeiidSQLException e = new TeiidSQLException();
+ String sqlState = e.getSQLState();
+ Throwable cause = e.getCause();
+ int errorCode = e.getErrorCode();
+ Throwable nestedException = e.getCause();
+ SQLException nextException = e.getNextException();
+
+ assertTrue(
+ "Expected MMSQLException.getSQLState() to return <null> but got \"" //$NON-NLS-1$
+ + sqlState + "\" instead.", sqlState == null); //$NON-NLS-1$
+ assertTrue(
+ "Expected MMSQLException.getCause() to return <null> but got [" //$NON-NLS-1$
+ + (cause != null ? cause.getClass().getName()
+ : "<unknown>") + "] instead.", cause == null); //$NON-NLS-1$ //$NON-NLS-2$
+ assertTrue(
+ "Expected MMSQLException.getErrorCode() to return [0] but got [" //$NON-NLS-1$
+ + errorCode + "] instead.", errorCode == 0); //$NON-NLS-1$
+ assertTrue(
+ "Expected MMSQLException.getNestedException() to return <null> but got [" //$NON-NLS-1$
+ + (nestedException != null ? nestedException.getClass()
+ .getName() : "<unknown>") + "] instead.", //$NON-NLS-1$ //$NON-NLS-2$
+ nestedException == null);
+ assertTrue(
+ "Expected MMSQLException.getNextException() to return <null> but got a SQLException with message \"" //$NON-NLS-1$
+ + (nextException != null ? nextException.getMessage()
+ : "") + "\" instead.", nextException == null); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /*
+ * Test method for 'com.metamatrix.jdbc.MMSQLException.create(Throwable)'
+ *
+ * Tests various simple exceptions to see if the expected SQLState is
+ * returend.
+ */
+ public void testCreateThrowable_01() {
+ testCreateThrowable(new CommunicationException(
+ "A test MM Communication Exception"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
+ testCreateThrowable(
+ new ConnectException("A test connection attempt exception"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
+ testCreateThrowable(
+ new ConnectionException("A test MM Connection Exception"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
+ testCreateThrowable(new IOException(
+ "A test Generic java.io.IOException"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
+ testCreateThrowable(
+ new MalformedURLException(
+ "A test java.net.MalformedURLException"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
+ testCreateThrowable(new TeiidException(
+ "A test Generic MM Core Exception"), SQLStates.DEFAULT); //$NON-NLS-1$
+ testCreateThrowable(new TeiidException("A test MM Exception"), //$NON-NLS-1$
+ SQLStates.DEFAULT);
+ testCreateThrowable(new TeiidProcessingException(
+ "A test Generic MM Query Processing Exception"), //$NON-NLS-1$
+ SQLStates.USAGE_ERROR);
+ testCreateThrowable(new TeiidRuntimeException(
+ "A test MM Runtime Exception"), SQLStates.DEFAULT); //$NON-NLS-1$
+ testCreateThrowable(new TeiidSQLException(
+ "A test Generic MM SQL Exception"), SQLStates.DEFAULT); //$NON-NLS-1$
+ testCreateThrowable(
+ new NoRouteToHostException(
+ "A test java.net.NoRouteToHostException"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
+ testCreateThrowable(new NullPointerException("A test NPE"), //$NON-NLS-1$
+ SQLStates.DEFAULT);
+ testCreateThrowable(new ProcedureErrorInstructionException(
+ "A test SQL Procedure Error exception"), //$NON-NLS-1$
+ SQLStates.VIRTUAL_PROCEDURE_ERROR);
+ testCreateThrowable(new SocketTimeoutException(
+ "A test socket timeout exception"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
+ testCreateThrowable(
+ new UnknownHostException("A test connection attempt exception"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
+ }
+
+ /*
+ * Test method for 'com.metamatrix.jdbc.MMSQLException.create(Throwable)'
+ *
+ * Tests various nested exceptions to see if the expected SQLState is
+ * returend.
+ */
+ public void testCreateThrowable_02() {
+ testCreateThrowable(
+ new CommunicationException(new ConnectException(
+ "A test java.net.ConnectException"), //$NON-NLS-1$
+ "Test Communication Exception with a ConnectException in it"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION);
+ testCreateThrowable(new CommunicationException(new SocketException(
+ "A test java.net.SocketException"), //$NON-NLS-1$
+ "Test Communication Exception with a SocketException in it"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
+ testCreateThrowable(
+ new TeiidException(new SocketTimeoutException(
+ "A test java.net.SocketTimeoutException"), //$NON-NLS-1$
+ "Test MetaMatrixException with a SocketTimeoutException in it"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
+ }
+
+ public void testCreateThrowable3() {
+ TeiidSQLException e = testCreateThrowable(
+ new TeiidException(
+ new TeiidRuntimeException(
+ new SocketTimeoutException(
+ "A test MM Invalid Session Exception"), //$NON-NLS-1$
+ "Test MetaMatrixRuntimeException with a InvalidSessionException in it"), //$NON-NLS-1$
+ "Test MM Core Exception with an MM Runtime Exception in it and an InvalidSessionException nested within"), //$NON-NLS-1$
+ SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
+
+ //test to ensure that wrapping mmsqlexceptions works
+ TeiidSQLException e1 = TeiidSQLException.create(e, "new message"); //$NON-NLS-1$
+ assertEquals("new message", e1.getMessage()); //$NON-NLS-1$
+ testCreateThrowable(((TeiidSQLException)e1.getCause()).getCause(), SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
+ }
+
+ /*
+ * Helper method to test SQLState and general MMSQLException validation
+ */
+ private TeiidSQLException testCreateThrowable(Throwable ecause, String esqlState) {
+ TeiidSQLException e = TeiidSQLException.create(ecause);
+ if (ecause.getClass() == TeiidSQLException.class) {
+ ecause = null;
+ }
+ String sqlState = e.getSQLState();
+ Throwable cause = e.getCause();
+ int errorCode = e.getErrorCode();
+ Throwable nestedException = e.getCause();
+ SQLException nextException = e.getNextException();
+
+ assertTrue("Expected MMSQLException.getSQLState() to return \"" //$NON-NLS-1$
+ + esqlState + "\" but got \"" + sqlState + "\" instead.", //$NON-NLS-1$ //$NON-NLS-2$
+ sqlState.compareTo(esqlState) == 0);
+ assertTrue("Expected MMSQLException.getCause() to return [" //$NON-NLS-1$
+ + (ecause != null ? ecause.getClass().getName() : "<null>") //$NON-NLS-1$
+ + "] but got [" //$NON-NLS-1$
+ + (cause != null ? cause.getClass().getName() : "<unknown>") //$NON-NLS-1$
+ + "] instead.", cause == ecause); //$NON-NLS-1$
+ assertTrue(
+ "Expected MMSQLException.getErrorCode() to return [0] but got [" //$NON-NLS-1$
+ + errorCode + "] instead.", errorCode == 0); //$NON-NLS-1$
+ assertTrue("Expected MMSQLException.getNestedException() to return [" //$NON-NLS-1$
+ + (ecause != null ? ecause.getClass().getName() : "<null>") //$NON-NLS-1$
+ + "] but got [" //$NON-NLS-1$
+ + (nestedException != null ? nestedException.getClass()
+ .getName() : "<unknown>") + "] instead.", //$NON-NLS-1$ //$NON-NLS-2$
+ nestedException == ecause);
+ assertTrue(
+ "Expected MMSQLException.getNextException() to return <null> but got a SQLException with message \"" //$NON-NLS-1$
+ + (nextException != null ? nextException.getMessage()
+ : "") + "\" instead.", nextException == null); //$NON-NLS-1$ //$NON-NLS-2$
+ return e;
+ }
+
+ public void testCreate() {
+ TeiidSQLException exception = TeiidSQLException.create(new Exception());
+
+ assertEquals(exception.getMessage(), Exception.class.getName());
+ assertNotNull(exception.getSQLState());
+ assertEquals(exception.getSQLState(), "38000"); //$NON-NLS-1$
+
+ assertEquals(exception, TeiidSQLException.create(exception));
+ }
+
+ public void testCreateFromSQLException() {
+ SQLException sqlexception = new SQLException("foo", "21"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ SQLException nested = new SQLException("bar"); //$NON-NLS-1$
+
+ sqlexception.setNextException(nested);
+
+ String message = "top level message"; //$NON-NLS-1$
+
+ TeiidSQLException exception = TeiidSQLException.create(sqlexception, message);
+
+ assertEquals(exception.getMessage(), message);
+ assertEquals(exception.getSQLState(), sqlexception.getSQLState());
+ assertEquals(exception.getNextException().getMessage(), sqlexception.getMessage());
+ assertEquals(exception.getNextException().getNextException().getMessage(), nested.getMessage());
+ }
+
+}
Copied: trunk/client/src/test/java/org/teiid/jdbc/TestStatement.java (from rev 2238, trunk/client/src/test/java/org/teiid/jdbc/TestMMStatement.java)
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestStatement.java (rev 0)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestStatement.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import static org.junit.Assert.*;
+
+import java.sql.ResultSet;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.teiid.client.DQP;
+import org.teiid.client.RequestMessage;
+import org.teiid.client.ResultsMessage;
+import org.teiid.client.util.ResultsFuture;
+import org.teiid.jdbc.ConnectionImpl;
+import org.teiid.jdbc.TeiidSQLException;
+import org.teiid.jdbc.StatementImpl;
+
+
+public class TestStatement {
+
+ @Test(expected=TeiidSQLException.class) public void testUpdateException() throws Exception {
+ StatementImpl statement = new StatementImpl(Mockito.mock(ConnectionImpl.class), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+ statement.executeQuery("delete from table"); //$NON-NLS-1$
+ }
+
+ @Test public void testBatchExecution() throws Exception {
+ ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
+ DQP dqp = Mockito.mock(DQP.class);
+ ResultsFuture<ResultsMessage> results = new ResultsFuture<ResultsMessage>();
+ Mockito.stub(dqp.executeRequest(Mockito.anyLong(), (RequestMessage)Mockito.anyObject())).toReturn(results);
+ ResultsMessage rm = new ResultsMessage();
+ rm.setResults(new List<?>[] {Arrays.asList(1), Arrays.asList(2)});
+ rm.setUpdateResult(true);
+ results.getResultsReceiver().receiveResults(rm);
+ Mockito.stub(conn.getDQP()).toReturn(dqp);
+ StatementImpl statement = new StatementImpl(conn, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+ statement.addBatch("delete from table"); //$NON-NLS-1$
+ statement.addBatch("delete from table1"); //$NON-NLS-1$
+ assertTrue(Arrays.equals(new int[] {1, 2}, statement.executeBatch()));
+ }
+
+ @Test public void testSetStatement() throws Exception {
+ ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
+ Properties p = new Properties();
+ Mockito.stub(conn.getConnectionProperties()).toReturn(p);
+ StatementImpl statement = new StatementImpl(conn, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+ assertFalse(statement.execute("set foo bar")); //$NON-NLS-1$
+ assertEquals("bar", p.get("foo")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Test public void testPropertiesOverride() throws Exception {
+ ConnectionImpl conn = Mockito.mock(ConnectionImpl.class);
+ Properties p = new Properties();
+ p.setProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS, Boolean.TRUE.toString());
+ Mockito.stub(conn.getConnectionProperties()).toReturn(p);
+ StatementImpl statement = new StatementImpl(conn, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+ assertEquals(Boolean.TRUE.toString(), statement.getExecutionProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS));
+ statement.setExecutionProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS, Boolean.FALSE.toString());
+ assertEquals(Boolean.FALSE.toString(), statement.getExecutionProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS));
+ assertEquals(Boolean.TRUE.toString(), p.getProperty(ExecutionProperties.ANSI_QUOTED_IDENTIFIERS));
+ }
+
+
+}
Property changes on: trunk/client/src/test/java/org/teiid/jdbc/TestStatement.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/client/src/test/java/org/teiid/jdbc/TestXAConnection.java (from rev 2238, trunk/client/src/test/java/org/teiid/jdbc/TestMMXAConnection.java)
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestXAConnection.java (rev 0)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestXAConnection.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.jdbc;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.transaction.xa.XAResource;
+
+import org.teiid.client.xa.XidImpl;
+import org.teiid.jdbc.ConnectionImpl;
+import org.teiid.jdbc.StatementImpl;
+import org.teiid.jdbc.XAConnectionImpl;
+
+import junit.framework.TestCase;
+
+
+
+public class TestXAConnection extends TestCase {
+
+ public void testConnectionClose() throws Exception {
+
+ final ConnectionImpl mmConn = TestConnection.getMMConnection();
+
+ XAConnectionImpl xaConn = new XAConnectionImpl(new XAConnectionImpl.ConnectionSource() {
+ //## JDBC4.0-begin ##
+ @Override
+ //## JDBC4.0-end ##
+ public ConnectionImpl createConnection() throws SQLException {
+ return mmConn;
+ }
+ });
+
+ Connection conn = xaConn.getConnection();
+ StatementImpl stmt = (StatementImpl)conn.createStatement();
+ conn.setAutoCommit(false);
+ conn.close();
+
+ assertTrue(stmt.isClosed());
+ assertTrue(conn.getAutoCommit());
+
+ conn = xaConn.getConnection();
+ stmt = (StatementImpl)conn.createStatement();
+ XAResource resource = xaConn.getXAResource();
+ resource.start(new XidImpl(1, new byte[0], new byte[0]), XAResource.TMNOFLAGS);
+ conn.close();
+
+ assertTrue(stmt.isClosed());
+ assertTrue(conn.getAutoCommit());
+ }
+
+}
Property changes on: trunk/client/src/test/java/org/teiid/jdbc/TestXAConnection.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/common-core/src/main/java/org/teiid/core/types/BlobImpl.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/BlobImpl.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/common-core/src/main/java/org/teiid/core/types/BlobImpl.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -33,6 +33,7 @@
import org.teiid.core.CorePlugin;
import org.teiid.core.types.LobSearchUtil.StreamProvider;
+import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.SqlUtil;
@@ -89,19 +90,22 @@
else if (pos + length > length()) {
length = (int)(length() - pos);
}
- byte[] dataCopy = new byte[length];
InputStream in = getBinaryStream();
try {
- try {
- in.skip(pos);
- in.read(dataCopy);
- } finally {
- in.close();
- }
+ long skipped = 0;
+ while (pos > 0) {
+ skipped = in.skip(pos);
+ pos -= skipped;
+ }
+ return ObjectConverterUtil.convertToByteArray(in, length);
} catch (IOException e) {
throw new SQLException(e);
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
}
- return dataCopy;
}
/**
Modified: trunk/common-core/src/main/java/org/teiid/core/types/ClobImpl.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/ClobImpl.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/common-core/src/main/java/org/teiid/core/types/ClobImpl.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -35,6 +35,7 @@
import javax.sql.rowset.serial.SerialClob;
import org.teiid.core.CorePlugin;
+import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.ReaderInputStream;
import org.teiid.core.util.SqlUtil;
@@ -122,19 +123,21 @@
} else if ((pos+length) > length()) {
length = (int)(length()-pos);
}
- char[] dataCopy = new char[length];
Reader in = getCharacterStream();
try {
try {
- in.skip(pos);
- in.read(dataCopy);
+ long skipped = 0;
+ while (pos > 0) {
+ skipped = in.skip(pos);
+ pos -= skipped;
+ }
+ return new String(ObjectConverterUtil.convertToCharArray(in, length));
} finally {
in.close();
}
} catch (IOException e) {
throw new SQLException(e);
}
- return new String(dataCopy);
}
/**
Modified: trunk/common-core/src/test/java/org/teiid/core/types/TestBlobValue.java
===================================================================
--- trunk/common-core/src/test/java/org/teiid/core/types/TestBlobValue.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/common-core/src/test/java/org/teiid/core/types/TestBlobValue.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -47,7 +47,6 @@
assertEquals(testString, new String(bv.getBytes(1L, (int)bv.length())));
}
-
public void testBlobValuePersistence() throws Exception {
String testString = "this is test clob"; //$NON-NLS-1$
SerialBlob blob = new SerialBlob(testString.getBytes());
Modified: trunk/common-core/src/test/java/org/teiid/core/types/TestClobValue.java
===================================================================
--- trunk/common-core/src/test/java/org/teiid/core/types/TestClobValue.java 2010-06-17 16:09:26 UTC (rev 2239)
+++ trunk/common-core/src/test/java/org/teiid/core/types/TestClobValue.java 2010-06-17 18:35:22 UTC (rev 2240)
@@ -22,33 +22,32 @@
package org.teiid.core.types;
+import static org.junit.Assert.*;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.Reader;
import javax.sql.rowset.serial.SerialClob;
-import org.teiid.core.types.ClobType;
+import org.junit.Test;
import org.teiid.core.util.UnitTestUtil;
+public class TestClobValue {
-import junit.framework.TestCase;
-
-
-public class TestClobValue extends TestCase {
-
- public void testClobValue() throws Exception {
+ @Test public void testClobValue() throws Exception {
String testString = "this is test clob"; //$NON-NLS-1$
SerialClob clob = new SerialClob(testString.toCharArray());
ClobType cv = new ClobType(clob);
assertEquals(testString, cv.getSubString(1L, (int)cv.length()));
}
-
- public void testClobValuePersistence() throws Exception {
+ @Test public void testClobValuePersistence() throws Exception {
String testString = "this is test clob"; //$NON-NLS-1$
SerialClob clob = new SerialClob(testString.toCharArray());
@@ -77,4 +76,32 @@
saved.delete();
}
+ @Test public void testClobSubstring() throws Exception {
+ ClobImpl clob = new ClobImpl() {
+ public java.io.Reader getCharacterStream() throws java.sql.SQLException {
+ return new Reader() {
+
+ int pos = 0;
+
+ @Override
+ public void close() throws IOException {
+
+ }
+
+ @Override
+ public int read(char[] cbuf, int off, int len)
+ throws IOException {
+ if (pos < 2) {
+ cbuf[off] = 'a';
+ pos++;
+ return 1;
+ }
+ return -1;
+ }
+ };
+ }
+ };
+ assertEquals("aa", clob.getSubString(1, 3));
+ }
+
}
14 years, 7 months
teiid SVN: r2239 - in trunk/documentation: developer-guide/src/main/docbook/en-US and 3 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-06-17 12:09:26 -0400 (Thu, 17 Jun 2010)
New Revision: 2239
Added:
trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/translator-api.xml
Removed:
trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml
Modified:
trunk/documentation/developer-guide/
trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-a.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/develop-adapter.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/introduction.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/main.xml
trunk/documentation/docbook/en-US/legal_notice.xml
trunk/documentation/reference/
Log:
TEIID-315 revisions to the developers guide
Property changes on: trunk/documentation/developer-guide
___________________________________________________________________
Name: svn:ignore
- target
.settings
.classpath
.project
+ target
.settings
.classpath
.project
Legal_Notice.html
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-a.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-a.xml 2010-06-17 13:44:55 UTC (rev 2238)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-a.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -54,5 +54,4 @@
</resourceadapter>
</connector>]]></programlisting>
<para>${...} indicates a value to be supplied by the developer.</para>
- <para>The description entry can utilize a special format in {}, where extended metadata properties can be supplied. This use of the special format and all properties is optional. Property names begin with $ and are separated from the value with :. Double quotes identifies a single value. A pair of square brackets [] containing comma separated double quoted entries denotes a list value.</para>
</appendix>
\ No newline at end of file
Deleted: trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml 2010-06-17 13:44:55 UTC (rev 2238)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -1,1406 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
-<!ENTITY % CustomDTD SYSTEM "../../../../../../docbook/custom.dtd">
-%CustomDTD;
-]>
-<chapter id="translator_api">
- <title>Translator Development</title>
- <sect1>
- <title>Extending the ExecutionFactory Class</title>
- <para>A component called the Connector Manager is controlling access to your translator. This chapter reviews
- the basics of how the Connector Manager interacts with your translator while leaving reference details and
- advanced topics to be covered in later chapters.</para>
- <para>
- A custom translator must extend <code>org.teiid.translator.ExecutionFactory</code>
- to connect and query an enterprise data source. This extended class must provide a no-arg constructor
- that can be constructed using Java reflection libraries. This Execution Factory need define/override following elements.
- </para>
-
- <sect2>
- <title>ConnectionFactory</title>
- <para>Defines the "ConnectionFactory" interface that is expected from resource adapter. This defined as part of
- class definition using generics while extending the "ExecutionFactory" class</para>
- </sect2>
-
- <sect2>
- <title>Connection</title>
- <para>Defines the "Connection" interface that is expected from resource adapter. This defined as part of
- class definition using generics while extending the "ExecutionFactory" class</para>
- </sect2>
-
- <sect2>
- <title>Configuration Properties</title>
- <para>Every software program requires some external configuration, that defines ways user can alter the behavior of a program.
- If this translator needs configurable properties define a variable for every property as an attribute in the extended
- "ExecutionFactory" class. Then define a "get" and "set" methods for each of them. Also, annotate each "get" method with
- <code>@TranslatorProperty</code> annotation and provide the metadata about the property. For example, if you need a
- property called "foo",
- <programlisting><![CDATA[String foo = "balh";
-
-@TranslatorProperty(display="Foo property", description="description about Foo")
-public String getFoo() {
- return foo;
-}
-
-public void setFoo(String value) {
- return this.foo = value;
-}]]> </programlisting>
-
- by providing the annotation on these properties, the Teiid tooling will automatically interrogate and
- provide graphical way to configure your
- Translator. Only java primitive (int), 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 <emphasis>should</emphasis> 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.
- </para>
-
- <para>The <code>@TranslatorProperty</code> defines the following metadata that you can define about your property</para>
- <itemizedlist>
- <listitem>
- <para>display: Display name of the property</para>
- </listitem>
- <listitem>
- <para>description: Description about the property</para>
- </listitem>
- <listitem>
- <para>required: The property is a required property</para>
- </listitem>
- <listitem>
- <para>advanced: This is advanced property; A default should be provided. A property can not be "advanced" and "required" at same time.</para>
- </listitem>
- <listitem>
- <para>masked: The tools need to mask the property; Do not show in plain text; used for passwords</para>
- </listitem>
- </itemizedlist>
- </sect2>
-
- <sect2>
- <title>Initializing the Translator</title>
- <para>Override and implement the <code>start</code> method (be sure to call
- "super.start()") if your translator needs to do any initializing before it is used by the Teiid engine. This method
- will be called by Teiid, once after all the configuration properties set above are injected into the class. </para>
- </sect2>
-
- <sect2>
- <title>TranslatorCapabilities</title>
- <para>These are various methods that typically begin with method
- signature "supports" on the "ExecutionFactory" class. These methods need to be overridden to describe the execution
- capabilities of the Translator. See <link linkend="translator_capabilities">Translator Capabilities</link> for more on these methods.</para>
- </sect2>
-
- <sect2>
- <title>Execution (and sub-interfaces)</title>
- <para>Based on types of executions you are supporting, the following methods need to be overridden
- and need to provide implementations for these methods by extending respective interfaces.</para>
-
- <itemizedlist>
- <listitem>
- <para><code>createResultSetExecution</code> - Define if you are doing read based operation that is
- returning a rows of results.</para>
- </listitem>
- <listitem>
- <para><code>createUpdateExecution</code> - Define if you are doing write based operations.</para>
- </listitem>
- <listitem>
- <para><code>createProcedureExecution</code> - Define if you are doing procedure based operations.</para>
- </listitem>
- </itemizedlist>
- <para>You can choose to implement all the execution modes or just what you need. See more details on this below.</para>
- </sect2>
-
- <sect2>
- <title>Metadata</title>
- <para>Override and implement the method <code>getMetadata()</code>, if you want to expose the
- metadata about the source for use in Dynamic VDBs. This defines the tables, column names, procedures, parameters, etc. for use in the query engine.
- This method is not yet used by Designer tooling. </para>
- </sect2>
-
- <sect2>
- <title>Logging</title>
- <para>Teiid provides <code>org.teiid.logging.LogManager</code> class for logging purposes.
- Create a logging context and use the LogManager to log your messages. These will be automatically
- sent to the main Teiid logs. You can edit the "jboss-log4j.xml" inside "conf" directory of the JBoss AS's profile
- to add the custom context. Teiid uses Log4J as its underlying logging system.</para>
- </sect2>
-
- <sect2>
- <title>Exceptions</title>
- <para>If you need to bubble up any exception use <code>org.teiid.translator.TranslatorException</code>
- class.</para>
- </sect2>
-
- <sect2>
- <title>Default Name</title>
- <para>Finally, you can define a default instance of your Translator by defining the
- annotation <code>@Translator</code> on the "ExecutionFactory". When you define this, and after deployment
- a default instance of this
- Translator is available any VDB that would like to use by just mentioning its name in its "vdb.xml" configuration file.
- VDB can also override the default properties and define another instance of this Translator too. The name you give here is the short
- name used every where else in the Teiid configuration to refer to this translator.</para>
- </sect2>
-
- </sect1>
-
-
- <sect1>
- <title>Connections to Source</title>
- <sect2>
- <title>Obtaining connections</title>
- <para>The extended "ExecutionFactory" must implement the <code>getConnection()</code> method to
- allow the Connector Manager to obtain a connection. </para>
- </sect2>
- <sect2>
- <title>Releasing Connections</title>
- <para>Once the Connector Manager has obtained a connection, it will use that connection only for the
- lifetime of the request. When the request has completed, the closeConnection() method called on the "ExecutionFactory".
- You must also override this method to properly close the connection.</para>
- <para>
- In cases (such as when a connection is stateful and expensive to
- create), connections should be pooled. If the resource adapter is JEE JCA connector based, then pooling is automatically
- provided by the JBoss AS container. If your resource adapter does not implement the JEE JCA, then connection pooling
- semantics are left to the user to define on their own.
- </para>
- </sect2>
- </sect1>
- <sect1>
- <title>Executing Commands</title>
- <sect2>
- <title>Execution Modes</title>
- <para>
- The Teiid query engine uses the "ExecutionFactory" class to obtain the "Execution" interface for the command it is
- executing. The actual queries themselves are sent to translators in the form of a set of objects, which are further
- described in <link linkend="command_language">Command Language</link>.
- translators are allowed to support any subset of the available execution modes.
- </para>
- <table frame='all'>
- <title>Types of Execution Modes</title>
- <tgroup cols='3' align='left' colsep='1' rowsep='1'>
- <colspec colname='c1' colwidth="1*" />
- <colspec colname='c2' colwidth="1*" />
- <colspec colname='c3' colwidth="2*" />
- <thead>
- <row>
- <entry>Execution Interface</entry>
- <entry>Command interface(s)</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <code>ResultSetExecution</code>
- </entry>
- <entry>
- <code>QueryExpression</code>
- </entry>
- <entry>A query corresponding to a SQL SELECT or set query statement.</entry>
- </row>
- <row>
- <entry>
- <code>UpdateExecution</code>
- </entry>
- <entry>
- <code>Insert, Update, Delete, BatchedUpdates</code>
- </entry>
- <entry>An insert, update, or delete, corresponding to a SQL INSERT, UPDATE, or DELETE command
- </entry>
- </row>
- <row>
- <entry>
- <code>ProcedureExecution</code>
- </entry>
- <entry>
- <code>Call</code>
- </entry>
- <entry>A procedure execution that may return a result set and/or output values.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>All of the execution interfaces extend the base <code>Execution</code>
- interface that defines how executions are
- cancelled and closed. ProcedureExecution also extends ResultSetExecution, since procedures may also return resultsets.</para>
- </sect2>
- <sect2>
- <title>ResultSetExecution</title>
- <para>
- Typically most commands executed against translators are QueryExpression.
- While the command is being executed, the translator provides results via the
- ResultSetExecution's "next" method. The "next" method should return null to indicate the end
- of results. Note: the expected batch size can be obtained from the
- ExecutionContext and used as a hint in fetching results from the EIS.
- </para>
- </sect2>
- <sect2>
- <title>Update Execution</title>
- <para>Each execution returns the update count(s) expected by the update command.
- If possible BatchedUpdates should be executed atomically.
- The ExecutionContext can be used to determine if the execution is already under a transaction.</para>
- </sect2>
- <sect2>
- <title>Procedure Execution</title>
- <para>Procedure commands correspond to the execution of a stored procedure or some other functional
- construct. A procedure takes zero or more input values and can return a result
- set and zero or more output values. Examples of procedure execution would be a stored procedure in a
- relational database or a call to a web service.</para>
- <para>If a result set is expected when a procedure is executed, all rows from it will be retrieved via the
- ResultSetExecution interface first. Then, if any output values are expected, they will
- be retrieved via the getOutputParameterValues() method.
- </para>
- </sect2>
-
- <sect2>
- <title>Asynchronous Executions</title>
- <para>In some scenarios, a translator needs to execute
- asynchronously and allow the executing thread to perform other work. To allow this, you should Throw a DataNotAvailableExecption during a retrival method, rather than explicitly waiting or sleeping for the results. The
- DataNotAvailableException may take a delay parameter in its
- constructor to indicate how long the system should wait befor polling
- for results. Any non-negative value is allowed.
- </para>
- <para>Since the exection and the associated connection are not closed until the work has completed, care should be taken if using asynchronous executions that hold a lot of state.</para>
- </sect2>
-
- <sect2>
- <title>Bulk Execution</title>
- <para> Non batched <code>Insert, Update, Delete</code>
- commands may have <code>Literal</code> values marked as multiValued if the
- capabilities shows support for BulkUpdate. Commands with
- multiValued <code>Literal</code>s represent multiple executions of the same
- command with different values. As with BatchedUpdates, bulk operations should be executed atomically if possible.
- </para>
- </sect2>
- <sect2>
- <title>Command Completion</title>
- <para>All normal command executions end with the calling of <code>close()</code> on the Execution object. Your
- implementation of this method should do the appropriate clean-up work for all state created in the Execution object.</para>
- </sect2>
- <sect2>
- <title>Command Cancellation</title>
- <para>Commands submitted to Teiid may be aborted in several scenarios:</para>
- <itemizedlist>
- <listitem>
- <para>Client cancellation via the JDBC API (or other client APIs)
- </para>
- </listitem>
- <listitem>
- <para>Administrative cancellation</para>
- </listitem>
- <listitem>
- <para>Clean-up during session termination</para>
- </listitem>
- <listitem>
- <para>Clean-up if a query fails during processing</para>
- </listitem>
- </itemizedlist>
- <para>Unlike the other execution methods, which are handled in a single-threaded manner,
- calls to cancel happen asynchronously with respect to the execution thread.</para>
- <para>Your connector implementation may choose to do nothing in response to this cancellation message. In
- this instance, Teiid will call close() on the execution object after
- current processing has completed. Implementing the cancel() method allows for faster
- termination of queries being processed and may allow the underlying data source to terminate its operations
- faster as well.</para>
- </sect2>
- </sect1>
-
- <sect1 id="command_language">
- <title>Command Language</title>
-
- <sect2>
- <title>Language </title>
- <para>
- Teiid sends commands to your Translator in object form. These classes are all defined in the "org.teiid.language"
- package. These objects can be combined to represent any possible
- command that Teiid may send to the Translator. However, it is possible
- to notify Teiid that your Translator can only accept certain kinds of
- constructs via the capabilities defined on the "ExecutionFactory" class. See the section on using
- <link linkend="translator_capabilities">Translator Capabilities</link>
- for more information.
- </para>
- <para>The language objects all extend from the <code>LanguageObject</code> 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.</para>
- <para>All commands sent to your Translator are in the form of these
- language trees, where the root of the tree is a subclass of <code>Command</code>.
- Command has several sub-interfaces, namely:
-
- <itemizedlist>
- <listitem><para><code>QueryExpression</code></para></listitem>
- <listitem><para><code>Insert</code></para></listitem>
- <listitem><para><code>Update</code></para></listitem>
- <listitem><para><code>Delete</code></para></listitem>
- <listitem><para><code>BatchedUpdates</code></para></listitem>
- <listitem><para><code>Call</code></para></listitem>
- </itemizedlist>
-
- Important components of these commands are expressions, criteria, and joins, which are examined
- in closer detail below. Also see the <ulink url="&javaDocUrl;">Teiid JavaDocs</ulink>
- for more on the classes and interfaces described here.
- </para>
- <sect3>
- <title>Expressions</title>
- <para>An expression represents a single value in context, although in
- some cases that value may change as the query is evaluated. For
- example, a literal value, such as 5 represents an integer value. An
- column reference such as "table.EmployeeName" represents a column in a data source
- and may take on many values while the command is being
- evaluated.</para>
- <itemizedlist>
- <listitem>
- <para>
- <code>Expression</code>
- – base expression interface
- </para>
- </listitem>
- <listitem>
- <para>
- <code>ColumnReference</code>
- – represents an column in the data source
- </para>
- </listitem>
- <listitem>
- <para>
- <code>Literal</code>
- – represents a literal scalar value, but may also be multi-valued in
- the case of bulk updates.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>Function</code>
- – represents a scalar function with parameters that are also Expressions
- </para>
- </listitem>
- <listitem>
- <para>
- <code>Aggregate</code>
- – represents an aggregate function which holds a single expression
- </para>
- </listitem>
- <listitem>
- <para>
- <code>ScalarSubquery</code>
- – represents a subquery that returns a single value
- </para>
- </listitem>
- <listitem>
- <para>
- <code>SearchedCase, SearchedWhenClause</code>
- – 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.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3>
- <title>Condition</title>
- <para>A criteria is a combination of expressions and operators that
- evaluates to true, false, or unknown. Criteria are most commonly used in the
- WHERE or HAVING clauses.</para>
-
- <itemizedlist>
- <listitem><para><code>Condition</code> – the base criteria interface</para></listitem>
- <listitem><para><code>Not</code> – used to NOT another criteria</para></listitem>
- <listitem><para><code>AndOr</code> – used to combine other criteria via AND or OR</para></listitem>
- <listitem><para><code>SubuqeryComparison</code> – represents a comparison criteria with a subquery including a quantifier such as SOME or ALL</para></listitem>
- <listitem><para><code>Comparison</code> – represents a comparison criteria with =, >, <, etc.</para></listitem>
- <listitem><para><code>BaseInCondition</code> – base class for an IN criteria</para></listitem>
- <listitem><para><code>In</code> – represents an IN criteria that has a set of expressions for values</para></listitem>
- <listitem><para><code>SubqueryIn</code> – represents an IN criteria that uses a subquery to produce the value set</para></listitem>
- <listitem><para><code>IsNull</code> – represents an IS NULL criteria</para></listitem>
- <listitem><para><code>Exists</code> – represents an EXISTS criteria that determines whether a subquery will return any values</para></listitem>
- <listitem><para><code>Like</code> – represents a LIKE criteria that compares string values</para></listitem>
- </itemizedlist>
- </sect3>
-
- <sect3>
- <title>The FROM Clause</title>
- <para>The FROM clause contains a list of <code>TableReference</code>'s. </para>
-
- <itemizedlist>
- <listitem><para><code>NamedTable</code> – represents a single Table</para></listitem>
- <listitem><para><code>Join</code> – has a left and right <code>TableReference</code> and information on the join between the items</para></listitem>
- <listitem><para><code>DerivedTable</code> – represents a table defined by an inline <code>QueryExpression</code></para></listitem>
- </itemizedlist>
- <para>
- A list of <code>TableReference</code>
- 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
- <code>Join</code>
- 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. See
- <link linkend="command_form_capabilities">Command Form Capabilities</link>
- for more information.
- </para>
- </sect3>
- <sect3>
- <title>QueryExpression Structure</title>
- <para><code>QueryExpression</code> is the base for both SELECT queries and set queries. It may optionally take an
- <code>OrderBy</code> (representing a SQL ORDER BY clause) and a <code>Limit</code> (represent a SQL LIMIT clause)</para>
- </sect3>
-
- <sect3>
- <title>Select Structure</title>
-
- <para>Each <code>QueryExpression</code> can be a <code>Select</code> describing the expressions
- (typically elements) being selected and an <code>TableReference</code> specifying the table
- or tables being selected from, along with any join information. The
- <code>Select</code> may optionally also supply an <code>Condition</code> (representing a SQL
- WHERE clause), a <code>GroupBy</code> (representing a SQL GROUP BY clause), an
- an <code>Condition</code> (representing a SQL HAVING clause).</para>
- </sect3>
-
- <sect3>
- <title>SetQuery Structure</title>
-
- <para>A <code>QueryExpression</code> can also be a <code>SetQuery</code> that represents on of the SQL set operations (UNION,
- INTERSECT, EXCEPT) on two <code>QueryExpression</code>. The all flag may be set to
- indicate UNION ALL (currently INTERSECT and EXCEPT ALL are not allowed in Teiid)</para>
- </sect3>
-
- <sect3>
- <title>Insert Structure</title>
-
- <para>Each <code>Insert</code> will have a single <code>NamedTable</code> specifying the table being
- inserted into. It will also has a list of <code>ColumnReference</code> specifying the columns
- of the <code>NamedTable</code> that are being inserted into. It also has
- <code>InsertValueSource</code>, which will either be a list of
- <code>Expression(ExpressionValueSource)</code> or <code>QueryExpression</code></para>
- </sect3>
-
- <sect3>
- <title>Update Structure</title>
-
- <para>Each <code>Update</code> will have a single <code>NamedTable</code> specifying the table being
- updated and list of <code>SetClause</code> entries that specify <code>ColumnReference</code>
- and <code>Expression</code> pairs for the update. The Update may optionally provide a criteria
- <code>Condition</code> specifying which rows should be updated.</para>
- </sect3>
-
- <sect3>
- <title>Delete Structure</title>
-
- <para>Each <code>Delete</code> will have a single <code>NamedTable</code> specifying the table being
- deleted from. It may also optionally have a criteria specifying which rows should be deleted. </para>
- </sect3>
-
- <sect3>
- <title>Call Structure</title>
-
- <para>Each <code>Call</code> has zero or more <code>Argument</code> objects. The
- <code>Argument</code> objects describe the input parameters, the output result
- set, and the output parameters. </para>
- </sect3>
-
- <sect3>
- <title>BatchedUpdates Structure </title>
- <para>Each <code>BatchedUpdates</code> has a list of <code>Command</code> objects (which must be either
- <code>Insert</code>, <code>Update</code> or <code>Delete</code>) that compose the batch. </para>
- </sect3>
- </sect2>
-
- <sect2>
- <title>Language Utilities</title>
- <para>This section covers utilities available when using, creating, and manipulating the language interfaces.</para>
-
- <sect3>
- <title>Data Types</title>
- <para>The Translator API contains an interface <code>TypeFacility</code> that defines
- data types and provides value translation facilities. This interface can be obtained from calling "getTypeFacility()"
- method on the "ExecutionFactory" class.</para>
-
- <para>
- The TypeFacitlity interface has methods that support data type
- transformation and detection of appropriate runtime or JDBC types.
- The TypeFacility.RUNTIME_TYPES and TypeFacility.RUNTIME_NAMES
- interfaces defines constants for all Teiid runtime data types. All
- <code>Expression</code> instances define a data type based on this set of types.
- These constants are often needed in understanding or creating language interfaces.</para>
- </sect3>
-
- <sect3>
- <title>Language Manipulation</title>
- <para>In Translators that support a fuller set of capabilities (those
- that generally are translating to a language of comparable to SQL),
- there is often a need to manipulate or create language interfaces to
- move closer to the syntax of choice. Some utilities are provided for
- this purpose:</para>
- <para>Similar to the TypeFacility, you can call "getLanguageFactory()" method on
- the "ExecutionFactory"
- to get a reference to the <code>LanguageFactory</code> instance for your
- translator. This interface is a factory that can be used to create new
- instances of all the concrete language interface objects. </para>
- <para>Some helpful utilities for working with <code>Condition</code> objects are
- provided in the <code>LanguageUtil</code> class. This class has methods to combine
- <code>Condition</code> with AND or to break an <code>Condition</code> apart based on AND
- operators. These utilities are helpful for breaking apart a criteria
- into individual filters that your translator can implement.</para>
- </sect3>
- </sect2>
-
- <sect2>
- <title>Runtime Metadata</title>
- <para>Teiid uses a library of metadata, known as "runtime metadata” for
- each virtual database that is deployed in Teiid. The runtime metadata
- is a subset of metadata as defined by models in the Teiid models that
- compose the virtual database. While builing your VDB in the Designer, you can define what
- called "Extension Model", that defines any number of arbitary properties on a model and its objects.
- At runtime, using this runtime metadata interface, you get access to those set properties defined during the
- design time, to define/hint any execution behavior.</para>
-
- <para>Translator gets access to the <code>RuntimeMetadata</code> interface at the time of <code>Excecution</code> creation.
- Translators can access runtime metadata by using the interfaces
- defined in <code>org.teiid.metadata</code> package. This package defines
- API representing a Schema, Table, Columns and Procedures, and ways to navigate these objects.</para>
-
- <sect3>
- <title>Metadata Objects</title>
- <para>All the language objects extend <code>AbstractMetadataRecord</code> class</para>
- <itemizedlist>
- <listitem><para>Column - returns Column metadata record</para></listitem>
- <listitem><para>Table - returns a Table metadata record</para></listitem>
- <listitem><para>Procedure - returns a Procedure metadata record</para></listitem>
- <listitem><para>ProcedureParameter - returns a Procedure Parameter metadata record</para></listitem>
- </itemizedlist>
-
- <para>Once a metadata record has been obtained, it is possible to use its metadata about that object or to find other related metadata.</para>
- </sect3>
- <sect3>
- <title>Access to Runtime Metadata</title>
-
- <para>The RuntimeMetadata interface is passed in for the creation of an "Execution". See "createExecution"
- method on the "ExecutionFactory" class. It provides the ability to look up
- metadata records based on their fully qualified names in the VDB.</para>
-
- <example>
- <title>Obtaining Metadata Properties</title>
- <para>The process of getting a Table's properties is sometimes needed for translator development. For example
- to get the "NameInSource" property or all extension properties:</para>
- <programlisting><![CDATA[
-//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();
- ]]></programlisting>
- </example>
-
- </sect3>
- </sect2>
-
- <sect2>
- <title>Language Visitors</title>
-
- <sect3>
- <title>Framework</title>
- <para>The API provides a language visitor framework in the
- <code>org.teiid.language.visitor</code> package. The framework
- provides utilities useful in navigating and extracting information
- from trees of language objects.</para>
-
- <para>The visitor framework is a variant of the Visitor design pattern,
- which is documented in several popular design pattern references. The
- visitor pattern encompasses two primary operations: traversing the
- nodes of a graph (also known as iteration) and performing some action
- at each node of the graph. In this case, the nodes are language
- interface objects and the graph is really a tree rooted at some node.
- The provided framework allows for customization of both aspects of
- visiting.</para>
- <para>The base <code>AbstractLanguageVisitor</code> 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 just a
- visitor shell – it performs no actions when visiting nodes and does
- not provide any iteration.</para>
- <para>The <code>HierarchyVisitor</code> provides the basic code for walking a
- language object tree. <code>The HierarchyVisitor</code> performs no action as it
- walks the tree – it just 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, etc) then you must either extend
- HierarchyVisitor or build your own iteration visitor. In general,
- that is not necessary.</para>
- <para>The <code>DelegatingHierarchyVisitor</code> 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
- <code>DelegatingHierarchyVisitor</code> to aid in executing pre- and post-order
- visitors. </para>
- </sect3>
- <sect3>
- <title>Provided Visitors</title>
- <para>The <code>SQLStringVisitor</code> is a special visitor that can traverse a
- tree of language interfaces and output the equivalent Teiid SQL. This
- visitor can be used to print language objects for debugging and
- logging. The <code>SQLStringVisitor</code> does not use the <code>HierarchyVisitor</code>
- described in the last section; it provides both iteration and
- processing type functionality in a single custom visitor. </para>
- <para>The <code>CollectorVisitor</code> 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. </para>
- </sect3>
- <sect3>
- <title>Writing a Visitor</title>
- <para>Writing your own visitor can be quite easy if you use the
- provided facilities. If the normal method of iterating the language
- tree is sufficient, then just follow these steps:</para>
- <para>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
- <code>visit(ColumnReference)</code> method. Collect any state in local variables and
- provide accessor methods for that state.</para>
- <para>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.</para>
- <para>Write code to execute your visitor using the utility methods on
- DelegatingHierarchyVisitor:</para>
- <programlisting><![CDATA[
-// 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();
- ]]></programlisting>
- </sect3>
- </sect2>
- <sect2 id="translator_capabilities">
- <title>Translator Capabilities</title>
- <para>The <code>ExecutionFactory</code> 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 <code>ExecutionFactory</code> class implements all the basic capabilities, which says
- your translator does not support any cpabilities. Your extended
- <code>ExecutionFactory</code> class must override the the necessary methods to specify which
- capabilities your translator supports. </para>
- <sect3>
- <title>Capability Scope</title>
- <para>
- Note that if your capabilities will remain unchanged for the lifetime
- of the translator, since the engine will cache them for reuse by all instances of that
- translator. Capabilities based on connection/user are not supported.
- </para>
- </sect3>
- <sect3>
- <title>Capabilities</title>
- <para>The following table lists the capabilities that can be specified in the <code>ExecutionFactory</code> class.</para>
- <table frame='all'>
- <title>Available Capabilities</title>
- <tgroup cols='3' align='left' colsep='1' rowsep='1'>
- <colspec colname='c1' colwidth="1.5*" />
- <colspec colname='c2' colwidth="1*" />
- <colspec colname='c3' colwidth="2*" />
- <thead>
- <row>
- <entry>
- <para>Capability</para>
- </entry>
- <entry>
- <para>Requires</para>
- </entry>
- <entry>
- <para>Description</para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>SelectDistinct</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support SELECT DISTINCT in queries.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>SelectExpression</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support SELECT of more than just column references.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AliasedTable</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support Tables in the FROM clause that have an alias.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InnerJoins</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support inner and cross joins</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>SelfJoins</para>
- </entry>
- <entry>
- <para>AliasedGroups and at least on of the join type supports.</para>
- </entry>
- <entry>
- <para>Translator can support a self join between two aliased versions of the
- same Table.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>OuterJoins</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support LEFT and RIGHT OUTER JOIN.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>FullOuterJoins</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support FULL OUTER JOIN.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InlineViews</para>
- </entry>
- <entry>
- <para>AliasedTable</para>
- </entry>
- <entry>
- <para>Translator can support a named subquery in the FROM clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>BetweenCriteria</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Not currently used - between criteria is rewriten as compound comparisions.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>CompareCriteriaEquals</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support comparison criteria with the operator "=”.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>CompareCriteriaOrdered</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support comparison criteria with the operator ">” or "<".</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>LikeCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support LIKE criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>LikeCriteriaEscapeCharacter</para>
- </entry>
- <entry>
- <para>LikeCriteria</para>
- </entry>
- <entry>
- <para>Translator can support LIKE criteria with an ESCAPE character clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InCriteria</para>
- </entry>
- <entry>
- <para>MaxInCriteria</para>
- </entry>
- <entry>
- <para>Translator can support IN predicate criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InCriteriaSubquery</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support IN predicate criteria where values are supplied by a
- subquery.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>IsNullCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support IS NULL predicate criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>OrCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the OR logical criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>NotCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>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.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>ExistsCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support EXISTS predicate criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>QuantifiedCompareCriteriaAll</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support a quantified comparison criteria using the ALL
- quantifier.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>QuantifiedCompareCriteriaSome</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support a quantified comparison criteria using the SOME or ANY
- quantifier.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>OrderBy</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support the ORDER BY clause in queries.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>OrderByUnrelated</para>
- </entry>
- <entry>
- <para>OrderBy</para>
- </entry>
- <entry>
- <para>Translator can support the ORDER BY items that are not directly specified in the select clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>GroupBy</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support an explict GROUP BY clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>Having</para>
- </entry>
- <entry>
- <para>GroupBy</para>
- </entry>
- <entry>
- <para>Translator can support the HAVING clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesAvg</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the AVG aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesCount</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the COUNT aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesCountStar</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the COUNT(*) aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesDistinct</para>
- </entry>
- <entry>
- <para>At least one of the aggregate functions.</para>
- </entry>
- <entry>
- <para>Translator can support the keyword DISTINCT inside an aggregate function. This
- keyword indicates that duplicate values within a group of rows will be ignored.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesMax</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the MAX aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesMin</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the MIN aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesSum</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the SUM aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>ScalarSubqueries</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support the use of a subquery in a scalar context (wherever an
- expression is valid).</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>CorrelatedSubqueries</para>
- </entry>
- <entry>
- <para>At least one of the subquery pushdown capabilities.</para>
- </entry>
- <entry>
- <para>Translator can support a correlated subquery that refers to an element in
- the outer query.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>CaseExpressions</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Not currently used - simple case is rewriten as searched case.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>SearchedCaseExpressions</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support "searched” CASE expressions anywhere that expressions are
- accepted.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>Unions</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator support UNION and UNION ALL</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>Intersect</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports INTERSECT</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>Except</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports Except</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>SetQueryOrderBy</para>
- </entry>
- <entry>
- <para>Unions, Intersect, or Except</para>
- </entry>
- <entry>
- <para>Translator supports set queries with an ORDER BY</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>RowLimit</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the limit portion of the limit clause</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>RowOffset</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the offset portion of the limit clause</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>FunctionsInGroupBy</para>
- </entry>
- <entry>
- <para>GroupBy</para>
- </entry>
- <entry>
- <para>Not currently used - non-element expressions in the group by create an inline view.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InsertWithQueryExpression</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports INSERT statements with values specified by an QueryExpression.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>supportsBatchedUpdates</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports a batch of INSERT, UPDATE and DELETE commands to be executed together.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>supportsBulkUpdate</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports updates with multiple value sets</para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Note that any pushdown subquery must itself be compliant with the Translator capabilities.</para>
- </sect3>
-
- <sect3 id="command_form_capabilities">
- <title>Command Form</title>
- <para>The method <code>ExecutionFactory.useAnsiJoin()</code> should return true
- if the Translator prefers the use of ANSI style join structure for
- join trees that contain only INNER and CROSS joins.</para>
- <para>The method <code>ExecutionFactory.requiresCriteria()</code> 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".</para>
- </sect3>
-
- <sect3>
- <title>Scalar Functions</title>
- <para>The method <code>ExecutionFactory.getSupportedFunctions()</code> can be
- used to specify which scalar functions the Translator supports. The
- set of possible functions is based on the set of functions supported
- by Teiid. This set can be found in the <ulink url="&docUrl;">Reference</ulink>
- documentation. If the Translator states that it supports a function,
- it must support all type combinations and overloaded forms of that
- function.</para>
- <para>There are also five standard operators that can also be specified in the
- supported function list: +, -, *, /, and ||.</para>
- <para>The constants interface SourceSystemFunctions contains the string
- names of all possible built-in pushdown functions. Note that not all
- system functions appear in this list. This is because some system
- functions will always be evaluted in Teiid, are simple aliases to
- other functions, or are rewriten to a more standard expression.</para>
- </sect3>
-
- <sect3>
- <title>Physical Limits</title>
- <para>The method <code>ExecutionFactory.getMaxInCriteriaSize()</code> 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.</para>
- <para>The method <code>ExecutionFactory.getMaxFromGroups()</code> can be used
- to specify the maximum number of FROM Clause groups that can used in a
- join. -1 indicates there is no limit.</para>
- </sect3>
-
- <sect3>
- <title>Update Execution Modes</title>
- <para>The method <code>ExecutionFactory.supportsBatchedUpdates()</code> can be
- used to indicate that the Translator supports executing the <code>BatchedUpdates</code> command.
- </para>
- <para>The method <code>ExecutionFactory.supportsBulkUpdate()</code> can be used
- to indicate that the Translator accepts update commands containg multi valued Literals.</para>
- <para>Note that if the translator does not support either of these
- update modes, the query engine will compensate by issuing the updates individually.</para>
- </sect3>
-
- </sect2>
-
-</sect1>
- <sect1>
- <title>Large Objects</title>
- <para>This section examines how to use facilities provided by the Teiid
- API to use large objects such as blobs, clobs, and xml in
- your Translator.</para>
- <sect2>
- <title>Data Types</title>
- <para>Teiid supports three large object runtime data types: blob,
- clob, and xml. A blob is a “binary large object”, a clob is a
- “character large object”, and “xml” is a “xml
- document”. Columns modeled as a blob, clob, or xml are treated similarly by
- the translator framework to support memory-safe streaming. </para>
- </sect2>
- <sect2>
- <title>Why Use Large Object Support?</title>
- <para>Teiid allows a Translator to return a large object through the
- Teiid translator API by just returning a reference to the actual
- large object. Access to that LOB will be streamed as appropriate rather
- than retrieved all at once. This is useful for several reasons:</para>
- <orderedlist>
- <listitem>
- <para>Reduces memory usage when returning the result set to the user.</para>
- </listitem>
- <listitem>
- <para>Improves performance by passing less data in the result set.</para>
- </listitem>
- <listitem>
- <para>Allows access to large objects when needed rather than assuming that users will
- always use the large object data.</para>
- </listitem>
- <listitem>
- <para>Allows the passing of arbitrarily large data values.</para>
- </listitem>
- </orderedlist>
- <para>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.</para>
- </sect2>
-
- <sect2>
- <title>Handling Large Objects</title>
- <para>The Translator API automatically handles large objects (Blob/Clob/SQLXML) through
- the creation of special purpose wrapper objects when it retrieves results.
- </para>
-
- <para>Once the wrapped object is returned, the streaming of LOB is
- automatically supported. These LOB objects then can for example appear
- in client results, in user defined functions, or sent to other translators.</para>
-
- <para>A Execution is usually closed and the underlying
- connection is either closed/released as soon as all rows for that
- execution have been retrieved. However, LOB objects may need to be
- read after their initial retrieval of results. When LOBs are detected
- the default closing behavior is prevented by setting a flag on the
- ExecutionContext. See ExecutionContext.keepAlive() method. </para>
-
- <para>When the "keepAlive" alive flag is set, then the execution object is only closed when user's Statement is closed.</para>
-
- <programlisting><![CDATA[executionContext.keepExecutionAlive(true);]]></programlisting>
-
- </sect2>
-
- <sect2>
- <title>Inserting or Updating Large Objects</title>
- <para>LOBs will be passed to the Translator in the
- language objects as Literal containing a java.sql.Blob, java.sql.Clob, or
- java.sql.SQLXML. You can use these interfaces to retrieve the data in
- the large object and use it for insert or update.</para>
- </sect2>
-
- </sect1>
-
- <sect1 id="translator_package">
- <title>Packaging</title>
- <para>Once the "ExecutionFactory" class is implemented, package it in a JAR file. The only
- additional requirement is provide a file called "jboss-beans.xml" in the "META-INF" directory of the JAR file, with
- following contents.
- <programlisting><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
-<deployment xmlns="urn:jboss:bean-deployer:2.0">
-
- <bean name="translator-${name}-template" class="org.teiid.templates.TranslatorDeploymentTemplate">
- <property name="info"><inject bean="translator-${name}"/></property>
- <property name="managedObjectFactory"><inject bean="ManagedObjectFactory"/></property>
- </bean>
-
- <bean name="translator-${name}" class="org.teiid.templates.TranslatorTemplateInfo">
- <constructor factoryMethod="createTemplateInfo">
- <factory bean="TranslatorDeploymentTemplateInfoFactory"/>
- <parameter class="java.lang.Class">org.teiid.templates.TranslatorTemplateInfo</parameter>
- <parameter class="java.lang.Class">${execution-factory-class}</parameter>
- <parameter class="java.lang.String">translator-${name}</parameter>
- <parameter class="java.lang.String">${name}</parameter>
- </constructor>
- </bean>
-
-</deployment>]]></programlisting>
-
- replace ${name} with name of your translator, and replace ${execution-factory-class} with your
- overridden ExecutionFactory class name. This will register the Translator for use with tooling and Admin API.</para>
- </sect1>
-
- <sect1 id="translator_deploy">
- <title>Deployment</title>
- <para>Copy the JAR file that defines the Translator into "deploy" directory of the JBoss AS's chosen profile, and
- the Translator will be deployed automatically. There is no restriction that, JBoss AS need to be restarted. However, if your Translator
- has external dependencies to other JAR libraries, they need to be placed inside the "lib" directory of the JBoss AS's profile.
- This will require a restart of the JBoss Server. Another option to avoid the restart is to bundle all the required JAR files into
- the same JAR file as the Translator. It is user's responsibility to make sure they are not running into any conflicts with their
- dependent libraries with those already exist in the JBoss environment.</para>
- </sect1>
-</chapter>
\ No newline at end of file
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/develop-adapter.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/develop-adapter.xml 2010-06-17 13:44:55 UTC (rev 2238)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/develop-adapter.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -5,9 +5,9 @@
<chapter id="develop_adapter">
<title>Developing JEE Connectors</title>
<para>This chapter examines how to use facilities provided by the Teiid
- API to develop a JEE JCA Connector that can be used with the Teiid Translator. Please note that these are
+ API to develop a JEE JCA Connector. Please note that these are
standard JEE JCA connectors, nothing special needs to be done for Teiid. As an aid to our Translator
- developers, we provided some base implementation framework to ease the development of these Connectors.
+ developers, we provided a base implementation framework.
If you already have a JCA Connector or some other mechanism to get data from your source system, you can skip this chapter.</para>
<para>If you are not familiar with JCA API, please read the <ulink url="http://java.sun.com/j2ee/connector/">JCA 1.5 Specification</ulink>.
@@ -19,8 +19,7 @@
<sect1>
<title>Using the Teiid Framework</title>
<para>If you are going to use the Teiid framework for developing a JCA connector, follow these steps. The required classes are in
- <code>org.teiid.resource.api</code> package. Please note that Teiid framework does not make use JCA's CCI framework. It
- only uses the JCA's SPI interfaces. </para>
+ <code>org.teiid.resource.api</code> package. Please note that Teiid framework does not make use JCA's CCI framework, only the JCA's SPI interfaces. </para>
<itemizedlist>
<listitem>
@@ -145,11 +144,9 @@
<config-property-value>${optioal-property-value}</config-property-value>
</config-property>]]></programlisting>
- <para>The format and contents of "<description>" element is a Teiid extension to provide the extended metadata for tooling purpose. The
- JCA specification does not define enough metadata on these properties so Teiid fills in the gap with its own extension.
- For every property define the following properties
-
+ <para>The format and contents of "<description>" element may be used as extended metadata for tooling. The special format must begin and end with curly braces e.g. {...}. This use of the special format and all properties is optional. Property names begin with '$' and are separated from the value with ':'. Double quotes identifies a single value. A pair of square brackets, e.g. [...], containing comma separated double quoted entries denotes a list value.
<itemizedlist>
+ <para>Extended metadata properties</para>
<listitem>
<para>$display: Display name of the property</para>
</listitem>
@@ -173,13 +170,13 @@
</listitem>
</itemizedlist>
- Note that all these are optional properties; however in the absence of this metadata, tooling will not work as expected.
+ Note that all these are optional properties; however in the absence of this metadata, Teiid tooling may not work as expected.
</para>
</sect2>
</sect1>
- <sect1>
+ <sect1 id="ra_package">
<title>Packaging the Adapter</title>
<para>Once all the required code is developed, it is time to package them into a RAR artifact, that can be deployed
into a Conainer. A RAR artifact is lot more similar to a WAR. To put together a RAR file it really depends upon
@@ -230,7 +227,7 @@
you can embed the JAR file containing your connector code and any dependent library JAR files. </para>
</sect1>
- <sect1>
+ <sect1 id="ra_deploy">
<title>Deploying the Adapter</title>
<para>Once the RAR file is built, deploy it by copying the RAR file into "deploy" directory of JBoss AS's choosen profile.
Typically the server does not need to be restarted when a new RAR file is being added. Alternatively, you can also use
Deleted: trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml 2010-06-17 13:44:55 UTC (rev 2238)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -1,201 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="extendingjdbc">
- <title>Extending The JDBC Translator</title>
- <para>The JDBC Translator can be extended to handle new JDBC drivers and database versions. This is one of the most common needs of custom Translator development. This chapter
- outlines the process by which a user can modify the behavior of the JDBC Translator for a new source, rather than starting from scratch.</para>
-
- <para>To design a JDBC Translator for any RDMS that is not already provided by the Teiid, extend the
- <code>org.teiid.translator.jdbc.JDBCExecutionFactory</code> 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.</para>
-
- <table frame='all'>
- <title>Extensions</title>
- <tgroup cols='2' align='left' colsep='1' rowsep='1'>
- <colspec colname='c1' colwidth="1*"/>
- <colspec colname='c2' colwidth="2*"/>
- <thead>
- <row>
- <entry><para>Extension</para></entry>
- <entry><para>Purpose</para></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><para>Capabilities</para></entry>
- <entry><para>Specify the SQL syntax and functions the source supports.</para></entry>
- </row>
- <row>
- <entry><para>SQL Translation</para></entry>
- <entry><para>Customize what SQL syntax is used, how source-specific functions are supported, how procedures are executed.</para></entry>
- </row>
- <row>
- <entry><para>Results Translation</para></entry>
- <entry><para>Customize how results are retrieved from JDBC and translated.</para></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <sect1>
- <title>Capabilities Extension</title>
- <para>This extension must override the methods that begin with "supports" that describe translator capabilities.
- For all the available translator capabilities please see <link linkend="translator_capabilities">this</link>.</para>
-
- <para>The most common example is adding
- support for a scalar function – this requires both declaring that the translator has the capability
- to execute the function and often modifying the SQL Translator to translate the function appropriately for the source.</para>
- <para>Another common example is turning off unsupported SQL capabilities (such as outer joins or subqueries)
- for less sophisticated JDBC sources. </para>
- </sect1>
-
- <sect1>
- <title>SQL Translation Extension</title>
- <para>The JDBCExcecutionFactory provides several methods to modify the command and the string form of the resulting syntax before it is sent to the
- JDBC driver, including:</para>
-
- <itemizedlist>
- <listitem>
- <para>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.</para>
- </listitem>
- <listitem>
- <para>Register one or more <link linkend="function_modifiers">FunctionModifiers</link> that define how a scalar function should be modified or transformed.</para>
- </listitem>
- <listitem>
- <para>Modify a LanguageObject. - see the translate, translateXXX, and <link linkend="function_modifiers">FunctionModifiers</link>.translate methods. Modify the passed in object and return null to indicate that the standard syntax output should be used.</para>
- </listitem>
- <listitem>
- <para>Change the way SQL strings are formed for a LanguageObject. - - see the translate, translateXXX, and <link linkend="function_modifiers">FunctionModifiers</link>.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.</para>
- </listitem>
- </itemizedlist>
- </sect1>
-
- <sect1>
- <title>Results Translation Extension</title>
- <para>The JDBCExecutionFactory provides several methods to modify the java.sql.Statement and java.sql.ResultSet interactions, including:</para>
- <orderedlist>
- <listitem>
- <para>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.</para>
- </listitem>
- <listitem>
- <para>Retrieve values from the JDBC ResultSet or CallableStatement - see the retrieveValue methods.</para>
- </listitem>
- </orderedlist>
-
- </sect1>
-
- <sect1>
- <title>Adding Function Support</title>
- <para>See <link linkend="udfs">User Defined Functions</link> for adding new functions to Teiid. This example will show you how to declare support for the function
- and modify how the function is passed to the data source.</para>
- <para>Following is a summary of all coding steps in supporting a new scalar function:</para>
- <orderedlist>
- <listitem>
- <para>Override the capabilities method to declare support for the function (REQUIRED)</para>
- </listitem>
- <listitem>
- <para>Implement a FunctionModifier to change how a function is translated and register it for use (OPTIONAL)</para>
- </listitem>
- </orderedlist>
- <para>There is a capabilities method getSupportedFunctions() that declares all supported scalar functions.</para>
- <informalexample>
- <para>An example of an extended capabilities class to add support for the “abs” absolute value function:</para>
- <programlisting><![CDATA[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;
- }
-}]]></programlisting></informalexample>
- <para>In general, it is a good idea to call super.getSupportedFunctions() to ensure that you retain any function
- support provided by the translator you are extending.</para>
- <para>This may be all that is needed to support a Teiid function if the JDBC data source supports the
- same syntax as Teiid. The built-in SQL translation will translate most functions as: “function(arg1, arg2, …)”.</para>
- <sect2 id="function_modifiers">
- <title>Using FunctionModifiers</title>
- <para>In some cases you may need to translate the function differently or even insert
- additional function calls above or below the function being translated. The JDBC translator provides
- an abstract class <code>FunctionModifier</code> for this purpose.</para>
- <para>During the start method a modifier instance can be registered against a given function name via a call to <code>JDBCExecutionFactory.registerFunctionModifier</code>.</para>
- <para>The FunctionModifier has a method called <code>translate</code>. Use the translate method to change the way the function is represented.</para>
-
-<informalexample>
- <para>An example of overriding the translate method to change the MOD(a, b) function into an infix operator for Sybase (a % b). The translate method returns a list of strings and language objects that will be assembled by the translator into a final string. The strings will be used as is and the language objects will be further processed by the translator.</para>
-
- <programlisting><![CDATA[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;
- }
-}]]></programlisting>
-</informalexample>
-
- <para>In addition to building your own FunctionModifiers, there are a number of pre-built generic
- function modifiers that are provided with the translator. </para>
-
- <table frame='all'>
- <title>Common Modifiers</title>
- <tgroup cols='2' align='left' colsep='1' rowsep='1'>
- <colspec colname='c1' colwidth=".4*"/>
- <colspec colname='c2' colwidth="1*"/>
- <thead>
- <row>
- <entry><para>Modifier</para></entry>
- <entry><para>Description</para></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><para>AliasModifier</para></entry>
- <entry><para>Handles simply renaming a function (“ucase” to “upper” for example)</para></entry>
- </row>
- <row>
- <entry><para>EscapeSyntaxModifier</para></entry>
- <entry><para>Wraps a function in the standard JDBC escape syntax for functions: {fn xxxx()}</para></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>To register the function modifiers for your supported functions,
- you must call the <code>ExecutionFactory.registerFunctionModifier(String name, FunctionModifier modifier)</code> method.
- <programlisting><![CDATA[public class ExtendedJDBCExecutionFactory extends JDBCExecutionFactory
-
- @Override
- public void start() {
- super.start();
-
- // register functions.
- registerFunctionModifier("abs", new MyAbsModifier());
- registerFunctionModifier("concat", new AliasModifier(“concat2”));
- }
-}]]></programlisting></para>
- <para>Support for the two functions being registered (“abs” and “concat”) must be declared
- in the capabilities as well. Functions that do not have modifiers registered will be translated as usual.
- </para>
- </sect2>
- </sect1>
-
- <sect1>
- <title>Installing Extensions</title>
- <para>Once you have developed an extension to the JDBC translator, you must install it into the Teiid Server.
- The process of <link linkend="translator_package">packaging</link> or <link linkend="translator_deploy">deploying</link> the
- extended JDBC translators is exactly as any other other translator. Since the RDMS is accessible already through its JDBC
- driver, there is no need to develop a resource adapter for this source as JBoss AS provides a wrapper JCA connector (DataSource)
- for any JDBC driver.
- </para>
- </sect1>
-</chapter>
Copied: trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc.xml (from rev 2238, trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml)
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc.xml (rev 0)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="extendingjdbc">
+ <title>Extending The JDBC Translator</title>
+ <para>The JDBC Translator can be extended to handle new JDBC drivers and database versions. This is one of the most common needs of custom Translator development. This chapter
+ outlines the process by which a user can modify the behavior of the JDBC Translator for a new source, rather than starting from scratch.</para>
+
+ <para>To design a JDBC Translator for any RDMS that is not already provided by the Teiid, extend the
+ <code>org.teiid.translator.jdbc.JDBCExecutionFactory</code> 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.</para>
+
+ <table frame='all'>
+ <title>Extensions</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="2*"/>
+ <thead>
+ <row>
+ <entry><para>Extension</para></entry>
+ <entry><para>Purpose</para></entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><para>Capabilities</para></entry>
+ <entry><para>Specify the SQL syntax and functions the source supports.</para></entry>
+ </row>
+ <row>
+ <entry><para>SQL Translation</para></entry>
+ <entry><para>Customize what SQL syntax is used, how source-specific functions are supported, how procedures are executed.</para></entry>
+ </row>
+ <row>
+ <entry><para>Results Translation</para></entry>
+ <entry><para>Customize how results are retrieved from JDBC and translated.</para></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <sect1>
+ <title>Capabilities Extension</title>
+ <para>This extension must override the methods that begin with "supports" that describe translator capabilities.
+ For all the available translator capabilities please see <link linkend="translator_capabilities">this</link>.</para>
+
+ <para>The most common example is adding
+ support for a scalar function – this requires both declaring that the translator has the capability
+ to execute the function and often modifying the SQL Translator to translate the function appropriately for the source.</para>
+ <para>Another common example is turning off unsupported SQL capabilities (such as outer joins or subqueries)
+ for less sophisticated JDBC sources. </para>
+ </sect1>
+
+ <sect1>
+ <title>SQL Translation Extension</title>
+ <para>The JDBCExcecutionFactory provides several methods to modify the command and the string form of the resulting syntax before it is sent to the
+ JDBC driver, including:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>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.</para>
+ </listitem>
+ <listitem>
+ <para>Register one or more <link linkend="function_modifiers">FunctionModifiers</link> that define how a scalar function should be modified or transformed.</para>
+ </listitem>
+ <listitem>
+ <para>Modify a LanguageObject. - see the translate, translateXXX, and <link linkend="function_modifiers">FunctionModifiers</link>.translate methods. Modify the passed in object and return null to indicate that the standard syntax output should be used.</para>
+ </listitem>
+ <listitem>
+ <para>Change the way SQL strings are formed for a LanguageObject. - - see the translate, translateXXX, and <link linkend="function_modifiers">FunctionModifiers</link>.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.</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1>
+ <title>Results Translation Extension</title>
+ <para>The JDBCExecutionFactory provides several methods to modify the java.sql.Statement and java.sql.ResultSet interactions, including:</para>
+ <orderedlist>
+ <listitem>
+ <para>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.</para>
+ </listitem>
+ <listitem>
+ <para>Retrieve values from the JDBC ResultSet or CallableStatement - see the retrieveValue methods.</para>
+ </listitem>
+ </orderedlist>
+
+ </sect1>
+
+ <sect1>
+ <title>Adding Function Support</title>
+ <para>See <link linkend="udfs">User Defined Functions</link> for adding new functions to Teiid. This example will show you how to declare support for the function
+ and modify how the function is passed to the data source.</para>
+ <para>Following is a summary of all coding steps in supporting a new scalar function:</para>
+ <orderedlist>
+ <listitem>
+ <para>Override the capabilities method to declare support for the function (REQUIRED)</para>
+ </listitem>
+ <listitem>
+ <para>Implement a FunctionModifier to change how a function is translated and register it for use (OPTIONAL)</para>
+ </listitem>
+ </orderedlist>
+ <para>There is a capabilities method getSupportedFunctions() that declares all supported scalar functions.</para>
+ <informalexample>
+ <para>An example of an extended capabilities class to add support for the “abs” absolute value function:</para>
+ <programlisting><![CDATA[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;
+ }
+}]]></programlisting></informalexample>
+ <para>In general, it is a good idea to call super.getSupportedFunctions() to ensure that you retain any function
+ support provided by the translator you are extending.</para>
+ <para>This may be all that is needed to support a Teiid function if the JDBC data source supports the
+ same syntax as Teiid. The built-in SQL translation will translate most functions as: “function(arg1, arg2, …)”.</para>
+ <sect2 id="function_modifiers">
+ <title>Using FunctionModifiers</title>
+ <para>In some cases you may need to translate the function differently or even insert
+ additional function calls above or below the function being translated. The JDBC translator provides
+ an abstract class <code>FunctionModifier</code> for this purpose.</para>
+ <para>During the start method a modifier instance can be registered against a given function name via a call to <code>JDBCExecutionFactory.registerFunctionModifier</code>.</para>
+ <para>The FunctionModifier has a method called <code>translate</code>. Use the translate method to change the way the function is represented.</para>
+
+<informalexample>
+ <para>An example of overriding the translate method to change the MOD(a, b) function into an infix operator for Sybase (a % b). The translate method returns a list of strings and language objects that will be assembled by the translator into a final string. The strings will be used as is and the language objects will be further processed by the translator.</para>
+
+ <programlisting><![CDATA[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;
+ }
+}]]></programlisting>
+</informalexample>
+
+ <para>In addition to building your own FunctionModifiers, there are a number of pre-built generic
+ function modifiers that are provided with the translator. </para>
+
+ <table frame='all'>
+ <title>Common Modifiers</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth=".4*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry><para>Modifier</para></entry>
+ <entry><para>Description</para></entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><para>AliasModifier</para></entry>
+ <entry><para>Handles simply renaming a function (“ucase” to “upper” for example)</para></entry>
+ </row>
+ <row>
+ <entry><para>EscapeSyntaxModifier</para></entry>
+ <entry><para>Wraps a function in the standard JDBC escape syntax for functions: {fn xxxx()}</para></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>To register the function modifiers for your supported functions,
+ you must call the <code>ExecutionFactory.registerFunctionModifier(String name, FunctionModifier modifier)</code> method.
+ <programlisting><![CDATA[public class ExtendedJDBCExecutionFactory extends JDBCExecutionFactory
+
+ @Override
+ public void start() {
+ super.start();
+
+ // register functions.
+ registerFunctionModifier("abs", new MyAbsModifier());
+ registerFunctionModifier("concat", new AliasModifier(“concat2”));
+ }
+}]]></programlisting></para>
+ <para>Support for the two functions being registered (“abs” and “concat”) must be declared
+ in the capabilities as well. Functions that do not have modifiers registered will be translated as usual.
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>Installing Extensions</title>
+ <para>Once you have developed an extension to the JDBC translator, you must install it into the Teiid Server.
+ The process of <link linkend="translator_package">packaging</link> or <link linkend="translator_deploy">deploying</link> the
+ extended JDBC translators is exactly as any other other translator. Since the RDMS is accessible already through its JDBC
+ driver, there is no need to develop a resource adapter for this source as JBoss AS provides a wrapper JCA connector (DataSource)
+ for any JDBC driver.
+ </para>
+ </sect1>
+</chapter>
Property changes on: trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/introduction.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/introduction.xml 2010-06-17 13:44:55 UTC (rev 2238)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/introduction.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -1,6 +1,13 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../../../../../../docbook/custom.dtd">
+%CustomDTD;
+]>
<chapter id="introduction">
- <title>Translators and Resource Adapters</title>
+ <title>Developing For Teiid</title>
+ <sect1>
+ <title>Introduction to the Teiid Connector Architecture</title>
+
<itemizedlist>
<para>Integrating data from a Enterprise Information System (EIS) into Teiid, is separated into two parts.</para>
<listitem>
@@ -40,6 +47,7 @@
</itemizedlist>
<para>Given a combination of a Translator + Resource Adapter, one can connect any EIS system to Teiid for their data integration needs.</para>
+ </sect1>
<sect1>
<title>Do You Need a New Translator?</title>
@@ -79,64 +87,32 @@
</para>
</listitem>
</itemizedlist>
-
- </sect1>
- <sect1>
- <title>Do You Need a New Resource Adapter?</title>
- <para>As mentioned above, for every Translator that needs to gather data from external source systems, it requires a resource adapter.
- </para>
-
- <itemizedlist>
- <para>The following resource adapters are available to Teiid.</para>
- <listitem>
- <para><emphasis>Data Source:</emphasis> This is provided by the JBoss AS container. This is used by the JDBC Translator.</para>
- </listitem>
- <listitem>
- <para><emphasis>File:</emphasis> Provides a JEE JCA based Connector to access defined directory on the file system. This is used by the File Translator</para>
- </listitem>
- <listitem>
- <para><emphasis>WS:</emphasis> Provides JEE JCA Connector to invoke Web Services using JBoss Web services stack. This is used by the WS Translator</para>
- </listitem>
- <listitem>
- <para>
- <emphasis>LDAP:</emphasis> Provides JEE JCA connector to access LDAP; Used by the LDAP Translator.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Salesforce:</emphasis> Provides JEE JCA connector to access Salesforce by invoking their Web Service interface. Used by the SalesForce Translator.
- </para>
- </listitem>
- </itemizedlist>
- <para></para>
- </sect1>
-
- <sect1>
+ <sect2>
<title>Custom Translators</title>
- <para>To write a translator, follow this procedure:</para>
<orderedlist numeration="arabic">
+ <para>High-level Translator development procedure:</para>
<listitem>
- <para>Create a new or use a Resource Adapater for the EIS system, to be used with this Translator</para>
+ <para><link linkend="custom_ra_intro"></link>Create a new or reuse an existing Resource Adapater for the EIS system, to be used with this Translator</para>
</listitem>
<listitem>
- <para>Implement the required interfaces defined by the Translator API.</para>
+ <para>Implement the required classes defined by the <link linkend="translator_api">Translator API</link>.</para>
<itemizedlist>
<listitem>
- <para>ExecutionFactory – Extend org.teiid.translator.ExecutionFactory class</para>
+ <para>Create an ExecutionFactory – Extend the <code>org.teiid.translator.ExecutionFactory</code> class</para>
</listitem>
<listitem>
- <para>Execution (and sub-interfaces) – specifies how to execute each type of command</para>
+ <para>Create relevant Executions (and sub-interfaces) – specifies how to execute each type of command</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
- <para>Define the Template for exposing configuration properties</para>
+ <para>Define the <link linkend="translator_package">template</link> for exposing configuration properties.</para>
</listitem>
<listitem>
- <para>Deploy your Translator into Teiid.</para>
+ <para><link linkend="translator_deploy">Deploy</link> your Translator.</para>
<itemizedlist>
<listitem>
- <para>Deploy a Virtual Database (VDB) with metadata corresponding to your Translator</para>
+ <para>Deploy a Virtual Database (VDB) utilizing your Translator.</para>
</listitem>
</itemizedlist>
</listitem>
@@ -146,18 +122,45 @@
</orderedlist>
<para>
This guide covers how to do each of these steps in detail. It also provides additional information for
- advanced topics, such as connection pooling, streaming large objects, and transactions. For a sample
+ advanced topics, such as streaming large objects. For sample
Translator code, please check the <ulink url="http://anonsvn.jboss.org/repos/teiid/trunk/connectors/">Teiid source code</ulink>
</para>
+ </sect2>
</sect1>
-
<sect1>
- <title>Required Items to write a JEE JCA based Custom Resource Adaptor</title>
- <para>To write a resource adaptor, follow this procedure:</para>
+ <title>Do You Need a New Resource Adapter?</title>
+ <para>As mentioned above, for every Translator that needs to gather data from external source systems, it requires a resource adapter.
+ </para>
+
+ <itemizedlist>
+ <para>The following resource adapters are available to Teiid.</para>
+ <listitem>
+ <para><emphasis>DataSource:</emphasis> This is provided by the JBoss AS container. This is used by the JDBC Translator.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>File:</emphasis> Provides a JEE JCA based Connector to access defined directory on the file system. This is used by the File Translator</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>WS:</emphasis> Provides JEE JCA Connector to invoke Web Services using JBoss Web services stack. This is used by the WS Translator</para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>LDAP:</emphasis> Provides JEE JCA connector to access LDAP; Used by the LDAP Translator.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Salesforce:</emphasis> Provides JEE JCA connector to access Salesforce by invoking their Web Service interface. Used by the SalesForce Translator.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <sect2 id="custom_ra_intro">
+ <title>Custom Resource Adapters</title>
<orderedlist numeration="arabic">
+ <para>High-level Resource Adapter development procedure:</para>
<listitem>
- <para>The specification is defined by the <ulink url="http://java.sun.com/j2ee/connector/">JEE JCA Connector</ulink>.
- You need to have basic idea about what JCA connectors are how they are developed and packaged.</para>
+ <para>Understand the <ulink url="http://java.sun.com/j2ee/connector/">JEE Connector</ulink> specification to have basic idea about what JCA connectors are how they are developed and packaged.</para>
</listitem>
<listitem>
<para>Gather all necessary information about your Enterprise Information System (EIS). You will need
@@ -181,7 +184,7 @@
</itemizedlist>
</listitem>
<listitem>
- <para>All the required supporting JCA SPI classes provided by the Teiid API. The JCA CCI support is not provided from Teiid</para>
+ <para>Base classes for all of the required supporting JCA SPI classes are provided by the Teiid API. The JCA CCI support is not provided from Teiid, since Teiid uses the Translator API as it's common client interface. You will want to extend:</para>
<itemizedlist>
<listitem>
<para>BasicConnectionFactory – Defines the Connection Factory</para>
@@ -195,16 +198,34 @@
</itemizedlist>
</listitem>
<listitem>
- <para>Package your resource adapter.</para>
+ <para><link linkend="ra_package">Package</link> your resource adapter.</para>
</listitem>
<listitem>
- <para>Deploy your resource adapter into Teiid.</para>
+ <para><link linkend="ra_package">Deploy</link> your resource adapter.</para>
</listitem>
</orderedlist>
<para>
This guide covers how to do each of these steps in detail. It also provides additional information for
- advanced topics such as streaming large objects and transactions. For a sample
- connector code, please check the <ulink url="http://anonsvn.jboss.org/repos/teiid/trunk/connectors/">Teiid Source code</ulink>
+ advanced topics, such as transactions. For a sample
+ resource adapter code, please check the <ulink url="http://anonsvn.jboss.org/repos/teiid/trunk/connectors/">Teiid Source code</ulink>
</para>
- </sect1>
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>Other Teiid Development</title>
+ <para>Teiid is highly extensible in other ways:</para>
+ <itemizedlist>
+ <listitem>
+ <para>You may add <link linkend="udfs">User Defined Functions</link>.</para>
+ </listitem>
+ <listitem>
+ <para>You may adapt <link linkend="logging">logging</link> to your needs, which is especially useful for custom audit or command logging.</para>
+ </listitem>
+ <listitem>
+ <para>You may change the <link linkend="custom_security">security</link> subsystem for custom authentication and authorization.</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
</chapter>
\ No newline at end of file
Copied: trunk/documentation/developer-guide/src/main/docbook/en-US/content/translator-api.xml (from rev 2238, trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml)
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/translator-api.xml (rev 0)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/translator-api.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -0,0 +1,1406 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../../../../../../docbook/custom.dtd">
+%CustomDTD;
+]>
+<chapter id="translator_api">
+ <title>Translator Development</title>
+ <sect1>
+ <title>Extending the ExecutionFactory Class</title>
+ <para>A component called the Connector Manager is controlling access to your translator. This chapter reviews
+ the basics of how the Connector Manager interacts with your translator while leaving reference details and
+ advanced topics to be covered in later chapters.</para>
+ <para>
+ A custom translator must extend <code>org.teiid.translator.ExecutionFactory</code>
+ to connect and query an enterprise data source. This extended class must provide a no-arg constructor
+ that can be constructed using Java reflection libraries. This Execution Factory need define/override following elements.
+ </para>
+
+ <sect2>
+ <title>ConnectionFactory</title>
+ <para>Defines the "ConnectionFactory" interface that is expected from resource adapter. This defined as part of
+ class definition using generics while extending the "ExecutionFactory" class</para>
+ </sect2>
+
+ <sect2>
+ <title>Connection</title>
+ <para>Defines the "Connection" interface that is expected from resource adapter. This defined as part of
+ class definition using generics while extending the "ExecutionFactory" class</para>
+ </sect2>
+
+ <sect2>
+ <title>Configuration Properties</title>
+ <para>Every software program requires some external configuration, that defines ways user can alter the behavior of a program.
+ If this translator needs configurable properties define a variable for every property as an attribute in the extended
+ "ExecutionFactory" class. Then define a "get" and "set" methods for each of them. Also, annotate each "get" method with
+ <code>@TranslatorProperty</code> annotation and provide the metadata about the property. For example, if you need a
+ property called "foo",
+ <programlisting><![CDATA[private String foo = "balh";
+
+@TranslatorProperty(display="Foo property", description="description about Foo")
+public String getFoo() {
+ return foo;
+}
+
+public void setFoo(String value) {
+ return this.foo = value;
+}]]> </programlisting>
+
+ by providing the annotation on these properties, the Teiid tooling will automatically interrogate and
+ provide graphical way to configure your
+ Translator. Only java primitive (int), 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 <emphasis>should</emphasis> 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.
+ </para>
+
+ <para>The <code>@TranslatorProperty</code> defines the following metadata that you can define about your property</para>
+ <itemizedlist>
+ <listitem>
+ <para>display: Display name of the property</para>
+ </listitem>
+ <listitem>
+ <para>description: Description about the property</para>
+ </listitem>
+ <listitem>
+ <para>required: The property is a required property</para>
+ </listitem>
+ <listitem>
+ <para>advanced: This is advanced property; A default should be provided. A property can not be "advanced" and "required" at same time.</para>
+ </listitem>
+ <listitem>
+ <para>masked: The tools need to mask the property; Do not show in plain text; used for passwords</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2>
+ <title>Initializing the Translator</title>
+ <para>Override and implement the <code>start</code> method (be sure to call
+ "super.start()") if your translator needs to do any initializing before it is used by the Teiid engine. This method
+ will be called by Teiid, once after all the configuration properties set above are injected into the class. </para>
+ </sect2>
+
+ <sect2>
+ <title>TranslatorCapabilities</title>
+ <para>These are various methods that typically begin with method
+ signature "supports" on the "ExecutionFactory" class. These methods need to be overridden to describe the execution
+ capabilities of the Translator. See <link linkend="translator_capabilities">Translator Capabilities</link> for more on these methods.</para>
+ </sect2>
+
+ <sect2>
+ <title>Execution (and sub-interfaces)</title>
+ <para>Based on types of executions you are supporting, the following methods need to be overridden
+ and need to provide implementations for these methods by extending respective interfaces.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><code>createResultSetExecution</code> - Define if you are doing read based operation that is
+ returning a rows of results.</para>
+ </listitem>
+ <listitem>
+ <para><code>createUpdateExecution</code> - Define if you are doing write based operations.</para>
+ </listitem>
+ <listitem>
+ <para><code>createProcedureExecution</code> - Define if you are doing procedure based operations.</para>
+ </listitem>
+ </itemizedlist>
+ <para>You can choose to implement all the execution modes or just what you need. See more details on this below.</para>
+ </sect2>
+
+ <sect2>
+ <title>Metadata</title>
+ <para>Override and implement the method <code>getMetadata()</code>, if you want to expose the
+ metadata about the source for use in Dynamic VDBs. This defines the tables, column names, procedures, parameters, etc. for use in the query engine.
+ This method is not yet used by Designer tooling. </para>
+ </sect2>
+
+ <sect2>
+ <title>Logging</title>
+ <para>Teiid provides <code>org.teiid.logging.LogManager</code> class for logging purposes.
+ Create a logging context and use the LogManager to log your messages. These will be automatically
+ sent to the main Teiid logs. You can edit the "jboss-log4j.xml" inside "conf" directory of the JBoss AS's profile
+ to add the custom context. Teiid uses Log4J as its underlying logging system.</para>
+ </sect2>
+
+ <sect2>
+ <title>Exceptions</title>
+ <para>If you need to bubble up any exception use <code>org.teiid.translator.TranslatorException</code>
+ class.</para>
+ </sect2>
+
+ <sect2>
+ <title>Default Name</title>
+ <para>Finally, you can define a default instance of your Translator by defining the
+ annotation <code>@Translator</code> on the "ExecutionFactory". When you define this, and after deployment
+ a default instance of this
+ Translator is available any VDB that would like to use by just mentioning its name in its "vdb.xml" configuration file.
+ VDB can also override the default properties and define another instance of this Translator too. The name you give here is the short
+ name used every where else in the Teiid configuration to refer to this translator.</para>
+ </sect2>
+
+ </sect1>
+
+
+ <sect1>
+ <title>Connections to Source</title>
+ <sect2>
+ <title>Obtaining connections</title>
+ <para>The extended "ExecutionFactory" must implement the <code>getConnection()</code> method to
+ allow the Connector Manager to obtain a connection. </para>
+ </sect2>
+ <sect2>
+ <title>Releasing Connections</title>
+ <para>Once the Connector Manager has obtained a connection, it will use that connection only for the
+ lifetime of the request. When the request has completed, the closeConnection() method called on the "ExecutionFactory".
+ You must also override this method to properly close the connection.</para>
+ <para>
+ In cases (such as when a connection is stateful and expensive to
+ create), connections should be pooled. If the resource adapter is JEE JCA connector based, then pooling is automatically
+ provided by the JBoss AS container. If your resource adapter does not implement the JEE JCA, then connection pooling
+ semantics are left to the user to define on their own.
+ </para>
+ </sect2>
+ </sect1>
+ <sect1>
+ <title>Executing Commands</title>
+ <sect2>
+ <title>Execution Modes</title>
+ <para>
+ The Teiid query engine uses the "ExecutionFactory" class to obtain the "Execution" interface for the command it is
+ executing. The actual queries themselves are sent to translators in the form of a set of objects, which are further
+ described in <link linkend="command_language">Command Language</link>.
+ translators are allowed to support any subset of the available execution modes.
+ </para>
+ <table frame='all'>
+ <title>Types of Execution Modes</title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth="1*" />
+ <colspec colname='c2' colwidth="1*" />
+ <colspec colname='c3' colwidth="2*" />
+ <thead>
+ <row>
+ <entry>Execution Interface</entry>
+ <entry>Command interface(s)</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <code>ResultSetExecution</code>
+ </entry>
+ <entry>
+ <code>QueryExpression</code>
+ </entry>
+ <entry>A query corresponding to a SQL SELECT or set query statement.</entry>
+ </row>
+ <row>
+ <entry>
+ <code>UpdateExecution</code>
+ </entry>
+ <entry>
+ <code>Insert, Update, Delete, BatchedUpdates</code>
+ </entry>
+ <entry>An insert, update, or delete, corresponding to a SQL INSERT, UPDATE, or DELETE command
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <code>ProcedureExecution</code>
+ </entry>
+ <entry>
+ <code>Call</code>
+ </entry>
+ <entry>A procedure execution that may return a result set and/or output values.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>All of the execution interfaces extend the base <code>Execution</code>
+ interface that defines how executions are
+ cancelled and closed. ProcedureExecution also extends ResultSetExecution, since procedures may also return resultsets.</para>
+ </sect2>
+ <sect2>
+ <title>ResultSetExecution</title>
+ <para>
+ Typically most commands executed against translators are QueryExpression.
+ While the command is being executed, the translator provides results via the
+ ResultSetExecution's "next" method. The "next" method should return null to indicate the end
+ of results. Note: the expected batch size can be obtained from the
+ ExecutionContext and used as a hint in fetching results from the EIS.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Update Execution</title>
+ <para>Each execution returns the update count(s) expected by the update command.
+ If possible BatchedUpdates should be executed atomically.
+ The ExecutionContext can be used to determine if the execution is already under a transaction.</para>
+ </sect2>
+ <sect2>
+ <title>Procedure Execution</title>
+ <para>Procedure commands correspond to the execution of a stored procedure or some other functional
+ construct. A procedure takes zero or more input values and can return a result
+ set and zero or more output values. Examples of procedure execution would be a stored procedure in a
+ relational database or a call to a web service.</para>
+ <para>If a result set is expected when a procedure is executed, all rows from it will be retrieved via the
+ ResultSetExecution interface first. Then, if any output values are expected, they will
+ be retrieved via the getOutputParameterValues() method.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Asynchronous Executions</title>
+ <para>In some scenarios, a translator needs to execute
+ asynchronously and allow the executing thread to perform other work. To allow this, you should Throw a DataNotAvailableExecption during a retrival method, rather than explicitly waiting or sleeping for the results. The
+ DataNotAvailableException may take a delay parameter in its
+ constructor to indicate how long the system should wait befor polling
+ for results. Any non-negative value is allowed.
+ </para>
+ <para>Since the exection and the associated connection are not closed until the work has completed, care should be taken if using asynchronous executions that hold a lot of state.</para>
+ </sect2>
+
+ <sect2>
+ <title>Bulk Execution</title>
+ <para> Non batched <code>Insert, Update, Delete</code>
+ commands may have <code>Literal</code> values marked as multiValued if the
+ capabilities shows support for BulkUpdate. Commands with
+ multiValued <code>Literal</code>s represent multiple executions of the same
+ command with different values. As with BatchedUpdates, bulk operations should be executed atomically if possible.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Command Completion</title>
+ <para>All normal command executions end with the calling of <code>close()</code> on the Execution object. Your
+ implementation of this method should do the appropriate clean-up work for all state created in the Execution object.</para>
+ </sect2>
+ <sect2>
+ <title>Command Cancellation</title>
+ <para>Commands submitted to Teiid may be aborted in several scenarios:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Client cancellation via the JDBC API (or other client APIs)
+ </para>
+ </listitem>
+ <listitem>
+ <para>Administrative cancellation</para>
+ </listitem>
+ <listitem>
+ <para>Clean-up during session termination</para>
+ </listitem>
+ <listitem>
+ <para>Clean-up if a query fails during processing</para>
+ </listitem>
+ </itemizedlist>
+ <para>Unlike the other execution methods, which are handled in a single-threaded manner,
+ calls to cancel happen asynchronously with respect to the execution thread.</para>
+ <para>Your connector implementation may choose to do nothing in response to this cancellation message. In
+ this instance, Teiid will call close() on the execution object after
+ current processing has completed. Implementing the cancel() method allows for faster
+ termination of queries being processed and may allow the underlying data source to terminate its operations
+ faster as well.</para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="command_language">
+ <title>Command Language</title>
+
+ <sect2>
+ <title>Language </title>
+ <para>
+ Teiid sends commands to your Translator in object form. These classes are all defined in the "org.teiid.language"
+ package. These objects can be combined to represent any possible
+ command that Teiid may send to the Translator. However, it is possible
+ to notify Teiid that your Translator can only accept certain kinds of
+ constructs via the capabilities defined on the "ExecutionFactory" class. See the section on using
+ <link linkend="translator_capabilities">Translator Capabilities</link>
+ for more information.
+ </para>
+ <para>The language objects all extend from the <code>LanguageObject</code> 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.</para>
+ <para>All commands sent to your Translator are in the form of these
+ language trees, where the root of the tree is a subclass of <code>Command</code>.
+ Command has several sub-interfaces, namely:
+
+ <itemizedlist>
+ <listitem><para><code>QueryExpression</code></para></listitem>
+ <listitem><para><code>Insert</code></para></listitem>
+ <listitem><para><code>Update</code></para></listitem>
+ <listitem><para><code>Delete</code></para></listitem>
+ <listitem><para><code>BatchedUpdates</code></para></listitem>
+ <listitem><para><code>Call</code></para></listitem>
+ </itemizedlist>
+
+ Important components of these commands are expressions, criteria, and joins, which are examined
+ in closer detail below. Also see the <ulink url="&javaDocUrl;">Teiid JavaDocs</ulink>
+ for more on the classes and interfaces described here.
+ </para>
+ <sect3>
+ <title>Expressions</title>
+ <para>An expression represents a single value in context, although in
+ some cases that value may change as the query is evaluated. For
+ example, a literal value, such as 5 represents an integer value. An
+ column reference such as "table.EmployeeName" represents a column in a data source
+ and may take on many values while the command is being
+ evaluated.</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <code>Expression</code>
+ – base expression interface
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>ColumnReference</code>
+ – represents an column in the data source
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>Literal</code>
+ – represents a literal scalar value, but may also be multi-valued in
+ the case of bulk updates.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>Function</code>
+ – represents a scalar function with parameters that are also Expressions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>Aggregate</code>
+ – represents an aggregate function which holds a single expression
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>ScalarSubquery</code>
+ – represents a subquery that returns a single value
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>SearchedCase, SearchedWhenClause</code>
+ – 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.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+ <sect3>
+ <title>Condition</title>
+ <para>A criteria is a combination of expressions and operators that
+ evaluates to true, false, or unknown. Criteria are most commonly used in the
+ WHERE or HAVING clauses.</para>
+
+ <itemizedlist>
+ <listitem><para><code>Condition</code> – the base criteria interface</para></listitem>
+ <listitem><para><code>Not</code> – used to NOT another criteria</para></listitem>
+ <listitem><para><code>AndOr</code> – used to combine other criteria via AND or OR</para></listitem>
+ <listitem><para><code>SubuqeryComparison</code> – represents a comparison criteria with a subquery including a quantifier such as SOME or ALL</para></listitem>
+ <listitem><para><code>Comparison</code> – represents a comparison criteria with =, >, <, etc.</para></listitem>
+ <listitem><para><code>BaseInCondition</code> – base class for an IN criteria</para></listitem>
+ <listitem><para><code>In</code> – represents an IN criteria that has a set of expressions for values</para></listitem>
+ <listitem><para><code>SubqueryIn</code> – represents an IN criteria that uses a subquery to produce the value set</para></listitem>
+ <listitem><para><code>IsNull</code> – represents an IS NULL criteria</para></listitem>
+ <listitem><para><code>Exists</code> – represents an EXISTS criteria that determines whether a subquery will return any values</para></listitem>
+ <listitem><para><code>Like</code> – represents a LIKE criteria that compares string values</para></listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3>
+ <title>The FROM Clause</title>
+ <para>The FROM clause contains a list of <code>TableReference</code>'s. </para>
+
+ <itemizedlist>
+ <listitem><para><code>NamedTable</code> – represents a single Table</para></listitem>
+ <listitem><para><code>Join</code> – has a left and right <code>TableReference</code> and information on the join between the items</para></listitem>
+ <listitem><para><code>DerivedTable</code> – represents a table defined by an inline <code>QueryExpression</code></para></listitem>
+ </itemizedlist>
+ <para>
+ A list of <code>TableReference</code>
+ 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
+ <code>Join</code>
+ 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. See
+ <link linkend="command_form_capabilities">Command Form Capabilities</link>
+ for more information.
+ </para>
+ </sect3>
+ <sect3>
+ <title>QueryExpression Structure</title>
+ <para><code>QueryExpression</code> is the base for both SELECT queries and set queries. It may optionally take an
+ <code>OrderBy</code> (representing a SQL ORDER BY clause) and a <code>Limit</code> (represent a SQL LIMIT clause)</para>
+ </sect3>
+
+ <sect3>
+ <title>Select Structure</title>
+
+ <para>Each <code>QueryExpression</code> can be a <code>Select</code> describing the expressions
+ (typically elements) being selected and an <code>TableReference</code> specifying the table
+ or tables being selected from, along with any join information. The
+ <code>Select</code> may optionally also supply an <code>Condition</code> (representing a SQL
+ WHERE clause), a <code>GroupBy</code> (representing a SQL GROUP BY clause), an
+ an <code>Condition</code> (representing a SQL HAVING clause).</para>
+ </sect3>
+
+ <sect3>
+ <title>SetQuery Structure</title>
+
+ <para>A <code>QueryExpression</code> can also be a <code>SetQuery</code> that represents on of the SQL set operations (UNION,
+ INTERSECT, EXCEPT) on two <code>QueryExpression</code>. The all flag may be set to
+ indicate UNION ALL (currently INTERSECT and EXCEPT ALL are not allowed in Teiid)</para>
+ </sect3>
+
+ <sect3>
+ <title>Insert Structure</title>
+
+ <para>Each <code>Insert</code> will have a single <code>NamedTable</code> specifying the table being
+ inserted into. It will also has a list of <code>ColumnReference</code> specifying the columns
+ of the <code>NamedTable</code> that are being inserted into. It also has
+ <code>InsertValueSource</code>, which will either be a list of
+ <code>Expression(ExpressionValueSource)</code> or <code>QueryExpression</code></para>
+ </sect3>
+
+ <sect3>
+ <title>Update Structure</title>
+
+ <para>Each <code>Update</code> will have a single <code>NamedTable</code> specifying the table being
+ updated and list of <code>SetClause</code> entries that specify <code>ColumnReference</code>
+ and <code>Expression</code> pairs for the update. The Update may optionally provide a criteria
+ <code>Condition</code> specifying which rows should be updated.</para>
+ </sect3>
+
+ <sect3>
+ <title>Delete Structure</title>
+
+ <para>Each <code>Delete</code> will have a single <code>NamedTable</code> specifying the table being
+ deleted from. It may also optionally have a criteria specifying which rows should be deleted. </para>
+ </sect3>
+
+ <sect3>
+ <title>Call Structure</title>
+
+ <para>Each <code>Call</code> has zero or more <code>Argument</code> objects. The
+ <code>Argument</code> objects describe the input parameters, the output result
+ set, and the output parameters. </para>
+ </sect3>
+
+ <sect3>
+ <title>BatchedUpdates Structure </title>
+ <para>Each <code>BatchedUpdates</code> has a list of <code>Command</code> objects (which must be either
+ <code>Insert</code>, <code>Update</code> or <code>Delete</code>) that compose the batch. </para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Language Utilities</title>
+ <para>This section covers utilities available when using, creating, and manipulating the language interfaces.</para>
+
+ <sect3>
+ <title>Data Types</title>
+ <para>The Translator API contains an interface <code>TypeFacility</code> that defines
+ data types and provides value translation facilities. This interface can be obtained from calling "getTypeFacility()"
+ method on the "ExecutionFactory" class.</para>
+
+ <para>
+ The TypeFacitlity interface has methods that support data type
+ transformation and detection of appropriate runtime or JDBC types.
+ The TypeFacility.RUNTIME_TYPES and TypeFacility.RUNTIME_NAMES
+ interfaces defines constants for all Teiid runtime data types. All
+ <code>Expression</code> instances define a data type based on this set of types.
+ These constants are often needed in understanding or creating language interfaces.</para>
+ </sect3>
+
+ <sect3>
+ <title>Language Manipulation</title>
+ <para>In Translators that support a fuller set of capabilities (those
+ that generally are translating to a language of comparable to SQL),
+ there is often a need to manipulate or create language interfaces to
+ move closer to the syntax of choice. Some utilities are provided for
+ this purpose:</para>
+ <para>Similar to the TypeFacility, you can call "getLanguageFactory()" method on
+ the "ExecutionFactory"
+ to get a reference to the <code>LanguageFactory</code> instance for your
+ translator. This interface is a factory that can be used to create new
+ instances of all the concrete language interface objects. </para>
+ <para>Some helpful utilities for working with <code>Condition</code> objects are
+ provided in the <code>LanguageUtil</code> class. This class has methods to combine
+ <code>Condition</code> with AND or to break an <code>Condition</code> apart based on AND
+ operators. These utilities are helpful for breaking apart a criteria
+ into individual filters that your translator can implement.</para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Runtime Metadata</title>
+ <para>Teiid uses a library of metadata, known as "runtime metadata” for
+ each virtual database that is deployed in Teiid. The runtime metadata
+ is a subset of metadata as defined by models in the Teiid models that
+ compose the virtual database. While builing your VDB in the Designer, you can define what
+ called "Extension Model", that defines any number of arbitary properties on a model and its objects.
+ At runtime, using this runtime metadata interface, you get access to those set properties defined during the
+ design time, to define/hint any execution behavior.</para>
+
+ <para>Translator gets access to the <code>RuntimeMetadata</code> interface at the time of <code>Excecution</code> creation.
+ Translators can access runtime metadata by using the interfaces
+ defined in <code>org.teiid.metadata</code> package. This package defines
+ API representing a Schema, Table, Columns and Procedures, and ways to navigate these objects.</para>
+
+ <sect3>
+ <title>Metadata Objects</title>
+ <para>All the language objects extend <code>AbstractMetadataRecord</code> class</para>
+ <itemizedlist>
+ <listitem><para>Column - returns Column metadata record</para></listitem>
+ <listitem><para>Table - returns a Table metadata record</para></listitem>
+ <listitem><para>Procedure - returns a Procedure metadata record</para></listitem>
+ <listitem><para>ProcedureParameter - returns a Procedure Parameter metadata record</para></listitem>
+ </itemizedlist>
+
+ <para>Once a metadata record has been obtained, it is possible to use its metadata about that object or to find other related metadata.</para>
+ </sect3>
+ <sect3>
+ <title>Access to Runtime Metadata</title>
+
+ <para>The RuntimeMetadata interface is passed in for the creation of an "Execution". See "createExecution"
+ method on the "ExecutionFactory" class. It provides the ability to look up
+ metadata records based on their fully qualified names in the VDB.</para>
+
+ <example>
+ <title>Obtaining Metadata Properties</title>
+ <para>The process of getting a Table's properties is sometimes needed for translator development. For example
+ to get the "NameInSource" property or all extension properties:</para>
+ <programlisting><![CDATA[
+//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();
+ ]]></programlisting>
+ </example>
+
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Language Visitors</title>
+
+ <sect3>
+ <title>Framework</title>
+ <para>The API provides a language visitor framework in the
+ <code>org.teiid.language.visitor</code> package. The framework
+ provides utilities useful in navigating and extracting information
+ from trees of language objects.</para>
+
+ <para>The visitor framework is a variant of the Visitor design pattern,
+ which is documented in several popular design pattern references. The
+ visitor pattern encompasses two primary operations: traversing the
+ nodes of a graph (also known as iteration) and performing some action
+ at each node of the graph. In this case, the nodes are language
+ interface objects and the graph is really a tree rooted at some node.
+ The provided framework allows for customization of both aspects of
+ visiting.</para>
+ <para>The base <code>AbstractLanguageVisitor</code> 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 just a
+ visitor shell – it performs no actions when visiting nodes and does
+ not provide any iteration.</para>
+ <para>The <code>HierarchyVisitor</code> provides the basic code for walking a
+ language object tree. <code>The HierarchyVisitor</code> performs no action as it
+ walks the tree – it just 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, etc) then you must either extend
+ HierarchyVisitor or build your own iteration visitor. In general,
+ that is not necessary.</para>
+ <para>The <code>DelegatingHierarchyVisitor</code> 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
+ <code>DelegatingHierarchyVisitor</code> to aid in executing pre- and post-order
+ visitors. </para>
+ </sect3>
+ <sect3>
+ <title>Provided Visitors</title>
+ <para>The <code>SQLStringVisitor</code> is a special visitor that can traverse a
+ tree of language interfaces and output the equivalent Teiid SQL. This
+ visitor can be used to print language objects for debugging and
+ logging. The <code>SQLStringVisitor</code> does not use the <code>HierarchyVisitor</code>
+ described in the last section; it provides both iteration and
+ processing type functionality in a single custom visitor. </para>
+ <para>The <code>CollectorVisitor</code> 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. </para>
+ </sect3>
+ <sect3>
+ <title>Writing a Visitor</title>
+ <para>Writing your own visitor can be quite easy if you use the
+ provided facilities. If the normal method of iterating the language
+ tree is sufficient, then just follow these steps:</para>
+ <para>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
+ <code>visit(ColumnReference)</code> method. Collect any state in local variables and
+ provide accessor methods for that state.</para>
+ <para>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.</para>
+ <para>Write code to execute your visitor using the utility methods on
+ DelegatingHierarchyVisitor:</para>
+ <programlisting><![CDATA[
+// 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();
+ ]]></programlisting>
+ </sect3>
+ </sect2>
+ <sect2 id="translator_capabilities">
+ <title>Translator Capabilities</title>
+ <para>The <code>ExecutionFactory</code> 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 <code>ExecutionFactory</code> class implements all the basic capabilities, which says
+ your translator does not support any cpabilities. Your extended
+ <code>ExecutionFactory</code> class must override the the necessary methods to specify which
+ capabilities your translator supports. </para>
+ <sect3>
+ <title>Capability Scope</title>
+ <para>
+ Note that if your capabilities will remain unchanged for the lifetime
+ of the translator, since the engine will cache them for reuse by all instances of that
+ translator. Capabilities based on connection/user are not supported.
+ </para>
+ </sect3>
+ <sect3>
+ <title>Capabilities</title>
+ <para>The following table lists the capabilities that can be specified in the <code>ExecutionFactory</code> class.</para>
+ <table frame='all'>
+ <title>Available Capabilities</title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth="1.5*" />
+ <colspec colname='c2' colwidth="1*" />
+ <colspec colname='c3' colwidth="2*" />
+ <thead>
+ <row>
+ <entry>
+ <para>Capability</para>
+ </entry>
+ <entry>
+ <para>Requires</para>
+ </entry>
+ <entry>
+ <para>Description</para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>SelectDistinct</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support SELECT DISTINCT in queries.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>SelectExpression</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support SELECT of more than just column references.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AliasedTable</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support Tables in the FROM clause that have an alias.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InnerJoins</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support inner and cross joins</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>SelfJoins</para>
+ </entry>
+ <entry>
+ <para>AliasedGroups and at least on of the join type supports.</para>
+ </entry>
+ <entry>
+ <para>Translator can support a self join between two aliased versions of the
+ same Table.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>OuterJoins</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support LEFT and RIGHT OUTER JOIN.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>FullOuterJoins</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support FULL OUTER JOIN.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InlineViews</para>
+ </entry>
+ <entry>
+ <para>AliasedTable</para>
+ </entry>
+ <entry>
+ <para>Translator can support a named subquery in the FROM clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>BetweenCriteria</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Not currently used - between criteria is rewriten as compound comparisions.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>CompareCriteriaEquals</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support comparison criteria with the operator "=”.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>CompareCriteriaOrdered</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support comparison criteria with the operator ">” or "<".</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>LikeCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support LIKE criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>LikeCriteriaEscapeCharacter</para>
+ </entry>
+ <entry>
+ <para>LikeCriteria</para>
+ </entry>
+ <entry>
+ <para>Translator can support LIKE criteria with an ESCAPE character clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InCriteria</para>
+ </entry>
+ <entry>
+ <para>MaxInCriteria</para>
+ </entry>
+ <entry>
+ <para>Translator can support IN predicate criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InCriteriaSubquery</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support IN predicate criteria where values are supplied by a
+ subquery.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>IsNullCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support IS NULL predicate criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>OrCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the OR logical criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>NotCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>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.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>ExistsCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support EXISTS predicate criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>QuantifiedCompareCriteriaAll</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support a quantified comparison criteria using the ALL
+ quantifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>QuantifiedCompareCriteriaSome</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support a quantified comparison criteria using the SOME or ANY
+ quantifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>OrderBy</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support the ORDER BY clause in queries.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>OrderByUnrelated</para>
+ </entry>
+ <entry>
+ <para>OrderBy</para>
+ </entry>
+ <entry>
+ <para>Translator can support the ORDER BY items that are not directly specified in the select clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>GroupBy</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support an explict GROUP BY clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Having</para>
+ </entry>
+ <entry>
+ <para>GroupBy</para>
+ </entry>
+ <entry>
+ <para>Translator can support the HAVING clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesAvg</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the AVG aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesCount</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the COUNT aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesCountStar</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the COUNT(*) aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesDistinct</para>
+ </entry>
+ <entry>
+ <para>At least one of the aggregate functions.</para>
+ </entry>
+ <entry>
+ <para>Translator can support the keyword DISTINCT inside an aggregate function. This
+ keyword indicates that duplicate values within a group of rows will be ignored.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesMax</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the MAX aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesMin</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the MIN aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesSum</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the SUM aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>ScalarSubqueries</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support the use of a subquery in a scalar context (wherever an
+ expression is valid).</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>CorrelatedSubqueries</para>
+ </entry>
+ <entry>
+ <para>At least one of the subquery pushdown capabilities.</para>
+ </entry>
+ <entry>
+ <para>Translator can support a correlated subquery that refers to an element in
+ the outer query.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>CaseExpressions</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Not currently used - simple case is rewriten as searched case.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>SearchedCaseExpressions</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support "searched” CASE expressions anywhere that expressions are
+ accepted.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Unions</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator support UNION and UNION ALL</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Intersect</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports INTERSECT</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Except</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports Except</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>SetQueryOrderBy</para>
+ </entry>
+ <entry>
+ <para>Unions, Intersect, or Except</para>
+ </entry>
+ <entry>
+ <para>Translator supports set queries with an ORDER BY</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>RowLimit</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the limit portion of the limit clause</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>RowOffset</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the offset portion of the limit clause</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>FunctionsInGroupBy</para>
+ </entry>
+ <entry>
+ <para>GroupBy</para>
+ </entry>
+ <entry>
+ <para>Not currently used - non-element expressions in the group by create an inline view.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InsertWithQueryExpression</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports INSERT statements with values specified by an QueryExpression.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>supportsBatchedUpdates</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports a batch of INSERT, UPDATE and DELETE commands to be executed together.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>supportsBulkUpdate</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports updates with multiple value sets</para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Note that any pushdown subquery must itself be compliant with the Translator capabilities.</para>
+ </sect3>
+
+ <sect3 id="command_form_capabilities">
+ <title>Command Form</title>
+ <para>The method <code>ExecutionFactory.useAnsiJoin()</code> should return true
+ if the Translator prefers the use of ANSI style join structure for
+ join trees that contain only INNER and CROSS joins.</para>
+ <para>The method <code>ExecutionFactory.requiresCriteria()</code> 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".</para>
+ </sect3>
+
+ <sect3>
+ <title>Scalar Functions</title>
+ <para>The method <code>ExecutionFactory.getSupportedFunctions()</code> can be
+ used to specify which scalar functions the Translator supports. The
+ set of possible functions is based on the set of functions supported
+ by Teiid. This set can be found in the <ulink url="&docUrl;">Reference</ulink>
+ documentation. If the Translator states that it supports a function,
+ it must support all type combinations and overloaded forms of that
+ function.</para>
+ <para>There are also five standard operators that can also be specified in the
+ supported function list: +, -, *, /, and ||.</para>
+ <para>The constants interface SourceSystemFunctions contains the string
+ names of all possible built-in pushdown functions. Note that not all
+ system functions appear in this list. This is because some system
+ functions will always be evaluted in Teiid, are simple aliases to
+ other functions, or are rewriten to a more standard expression.</para>
+ </sect3>
+
+ <sect3>
+ <title>Physical Limits</title>
+ <para>The method <code>ExecutionFactory.getMaxInCriteriaSize()</code> 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.</para>
+ <para>The method <code>ExecutionFactory.getMaxFromGroups()</code> can be used
+ to specify the maximum number of FROM Clause groups that can used in a
+ join. -1 indicates there is no limit.</para>
+ </sect3>
+
+ <sect3>
+ <title>Update Execution Modes</title>
+ <para>The method <code>ExecutionFactory.supportsBatchedUpdates()</code> can be
+ used to indicate that the Translator supports executing the <code>BatchedUpdates</code> command.
+ </para>
+ <para>The method <code>ExecutionFactory.supportsBulkUpdate()</code> can be used
+ to indicate that the Translator accepts update commands containg multi valued Literals.</para>
+ <para>Note that if the translator does not support either of these
+ update modes, the query engine will compensate by issuing the updates individually.</para>
+ </sect3>
+
+ </sect2>
+
+</sect1>
+ <sect1>
+ <title>Large Objects</title>
+ <para>This section examines how to use facilities provided by the Teiid
+ API to use large objects such as blobs, clobs, and xml in
+ your Translator.</para>
+ <sect2>
+ <title>Data Types</title>
+ <para>Teiid supports three large object runtime data types: blob,
+ clob, and xml. A blob is a “binary large object”, a clob is a
+ “character large object”, and “xml” is a “xml
+ document”. Columns modeled as a blob, clob, or xml are treated similarly by
+ the translator framework to support memory-safe streaming. </para>
+ </sect2>
+ <sect2>
+ <title>Why Use Large Object Support?</title>
+ <para>Teiid allows a Translator to return a large object through the
+ Teiid translator API by just returning a reference to the actual
+ large object. Access to that LOB will be streamed as appropriate rather
+ than retrieved all at once. This is useful for several reasons:</para>
+ <orderedlist>
+ <listitem>
+ <para>Reduces memory usage when returning the result set to the user.</para>
+ </listitem>
+ <listitem>
+ <para>Improves performance by passing less data in the result set.</para>
+ </listitem>
+ <listitem>
+ <para>Allows access to large objects when needed rather than assuming that users will
+ always use the large object data.</para>
+ </listitem>
+ <listitem>
+ <para>Allows the passing of arbitrarily large data values.</para>
+ </listitem>
+ </orderedlist>
+ <para>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.</para>
+ </sect2>
+
+ <sect2>
+ <title>Handling Large Objects</title>
+ <para>The Translator API automatically handles large objects (Blob/Clob/SQLXML) through
+ the creation of special purpose wrapper objects when it retrieves results.
+ </para>
+
+ <para>Once the wrapped object is returned, the streaming of LOB is
+ automatically supported. These LOB objects then can for example appear
+ in client results, in user defined functions, or sent to other translators.</para>
+
+ <para>A Execution is usually closed and the underlying
+ connection is either closed/released as soon as all rows for that
+ execution have been retrieved. However, LOB objects may need to be
+ read after their initial retrieval of results. When LOBs are detected
+ the default closing behavior is prevented by setting a flag on the
+ ExecutionContext. See ExecutionContext.keepAlive() method. </para>
+
+ <para>When the "keepAlive" alive flag is set, then the execution object is only closed when user's Statement is closed.</para>
+
+ <programlisting><![CDATA[executionContext.keepExecutionAlive(true);]]></programlisting>
+
+ </sect2>
+
+ <sect2>
+ <title>Inserting or Updating Large Objects</title>
+ <para>LOBs will be passed to the Translator in the
+ language objects as Literal containing a java.sql.Blob, java.sql.Clob, or
+ java.sql.SQLXML. You can use these interfaces to retrieve the data in
+ the large object and use it for insert or update.</para>
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="translator_package">
+ <title>Packaging</title>
+ <para>Once the "ExecutionFactory" class is implemented, package it in a JAR file. The only
+ additional requirement is provide a file called "jboss-beans.xml" in the "META-INF" directory of the JAR file, with
+ following contents.
+ <programlisting><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="translator-${name}-template" class="org.teiid.templates.TranslatorDeploymentTemplate">
+ <property name="info"><inject bean="translator-${name}"/></property>
+ <property name="managedObjectFactory"><inject bean="ManagedObjectFactory"/></property>
+ </bean>
+
+ <bean name="translator-${name}" class="org.teiid.templates.TranslatorTemplateInfo">
+ <constructor factoryMethod="createTemplateInfo">
+ <factory bean="TranslatorDeploymentTemplateInfoFactory"/>
+ <parameter class="java.lang.Class">org.teiid.templates.TranslatorTemplateInfo</parameter>
+ <parameter class="java.lang.Class">${execution-factory-class}</parameter>
+ <parameter class="java.lang.String">translator-${name}</parameter>
+ <parameter class="java.lang.String">${name}</parameter>
+ </constructor>
+ </bean>
+
+</deployment>]]></programlisting>
+
+ replace ${name} with name of your translator, and replace ${execution-factory-class} with your
+ overridden ExecutionFactory class name. This will register the Translator for use with tooling and Admin API.</para>
+ </sect1>
+
+ <sect1 id="translator_deploy">
+ <title>Deployment</title>
+ <para>Copy the JAR file that defines the Translator into "deploy" directory of the JBoss AS's chosen profile, and
+ the Translator will be deployed automatically. There is no restriction that, JBoss AS need to be restarted. However, if your Translator
+ has external dependencies to other JAR libraries, they need to be placed inside the "lib" directory of the JBoss AS's profile.
+ This will require a restart of the JBoss Server. Another option to avoid the restart is to bundle all the required JAR files into
+ the same JAR file as the Translator. It is user's responsibility to make sure they are not running into any conflicts with their
+ dependent libraries with those already exist in the JBoss environment.</para>
+ </sect1>
+</chapter>
\ No newline at end of file
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/main.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/main.xml 2010-06-17 13:44:55 UTC (rev 2238)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/main.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -47,8 +47,8 @@
<xi:include href="content/introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/develop-adapter.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="content/connector-api.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="content/extending-jdbc-connector.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="content/translator-api.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="content/extending-jdbc.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/udf.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/logging.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/security.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
Modified: trunk/documentation/docbook/en-US/legal_notice.xml
===================================================================
--- trunk/documentation/docbook/en-US/legal_notice.xml 2010-06-17 13:44:55 UTC (rev 2238)
+++ trunk/documentation/docbook/en-US/legal_notice.xml 2010-06-17 16:09:26 UTC (rev 2239)
@@ -37,7 +37,7 @@
<phone>Phone: +1 919 754 3700</phone>
<phone>Phone: 888 733 4281</phone>
<fax>Fax: +1 919 754 3701</fax>
- <pob>PO Box 13588</pob><city>Research Triangle Park</city>, <state>NC</state><postcode>27709</postcode><country>USA</country>
+ <pob>PO Box 13588 </pob><city>Research Triangle Park</city>, <state>NC</state><postcode>27709</postcode><country>USA</country>
</address>
</para>
<para>
Property changes on: trunk/documentation/reference
___________________________________________________________________
Name: svn:ignore
- target
.classpath
.project
.settings
+ target
.classpath
.project
.settings
Legal_Notice.html
14 years, 7 months
teiid SVN: r2238 - in trunk: connectors/connector-ws/src/main/rar/META-INF and 4 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-06-17 09:44:55 -0400 (Thu, 17 Jun 2010)
New Revision: 2238
Added:
trunk/documentation/developer-guide/src/main/docbook/en-US/content/udf.xml
Removed:
trunk/documentation/developer-guide/src/main/docbook/en-US/content/command-language.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/jdbc-translator-examples.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/lob-support.xml
Modified:
trunk/connectors/connector-ldap/src/main/rar/META-INF/ra.xml
trunk/connectors/connector-ws/src/main/rar/META-INF/ra.xml
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCBaseExecution.java
trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-a.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-b.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/develop-adapter.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/content/introduction.xml
trunk/documentation/developer-guide/src/main/docbook/en-US/main.xml
trunk/documentation/reference/src/main/docbook/en-US/content/datatypes.xml
trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml
Log:
TEIID-315 initial revisions to the developers guide
Modified: trunk/connectors/connector-ldap/src/main/rar/META-INF/ra.xml
===================================================================
--- trunk/connectors/connector-ldap/src/main/rar/META-INF/ra.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/connectors/connector-ldap/src/main/rar/META-INF/ra.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -68,7 +68,7 @@
</config-property>
<config-property>
- <description>{$display:"Ldap Context Factory",$description:"LDAP Context factory Class",$required:"true", readOnly="true"}</description>
+ <description>{$display:"Ldap Context Factory",$description:"LDAP Context factory Class",$required:"true", readOnly:"true"}</description>
<config-property-name>LdapContextFactory</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>com.sun.jndi.ldap.LdapCtxFactory</config-property-value>
Modified: trunk/connectors/connector-ws/src/main/rar/META-INF/ra.xml
===================================================================
--- trunk/connectors/connector-ws/src/main/rar/META-INF/ra.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/connectors/connector-ws/src/main/rar/META-INF/ra.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -41,13 +41,13 @@
<managedconnectionfactory-class>org.teiid.resource.adapter.ws.WSManagedConnectionFactory</managedconnectionfactory-class>
<config-property>
- <description>{$display:"URL, End Point",$description:"URL for HTTP, Service Endpoint for SOAP",$required="true"}</description>
+ <description>{$display:"URL, End Point",$description:"URL for HTTP, Service Endpoint for SOAP",$required:"true"}</description>
<config-property-name>EndPoint</config-property-name>
<config-property-type>java.lang.String</config-property-type>
</config-property>
<config-property>
- <description>{$display:"WebService Security Used(None, HTTPBasic, WS-Security)",$allowed="None,HTTPBasic,WSSecurity", $description:"Type of Authentication to used with the web service; If WS-Secuirty is being used, then WS-Secuirty type must be defined", $required:"true", $defaultValue="None"}</description>
+ <description>{$display:"WebService Security Used",$allowed:["None","HTTPBasic","WSSecurity"], $description:"Type of Authentication to used with the web service.", $required:"true", $defaultValue:"None"}</description>
<config-property-name>SecurityType</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>None</config-property-value>
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCBaseExecution.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCBaseExecution.java 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/JDBCBaseExecution.java 2010-06-17 13:44:55 UTC (rev 2238)
@@ -75,7 +75,7 @@
}
/**
- * Return true if this is a batched update
+ * Bind the values in the TranslatedCommand to the PreparedStatement
*/
protected void bindPreparedStatementValues(PreparedStatement stmt, TranslatedCommand tc, int rowCount) throws SQLException {
List<?> params = tc.getPreparedValues();
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-a.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-a.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-a.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -2,8 +2,7 @@
<title>ra.xml file Template</title>
<para> This appendix contains an example of the ra.xml file that can be used as a template
when creating a new Connector.</para>
- <programlisting><![CDATA[
-<?xml version="1.0" encoding="UTF-8"?>
+ <programlisting><![CDATA[<?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"
@@ -29,10 +28,10 @@
<!-- repeat for every configuration property -->
<config-property>
- <description>{$display:"Invocation Type",$description:"Service Invocation type (HTTP or SOAP)", $allowed="HTTP_GET, HTTP_POST, SOAP11, SOAP12", $required="true", $defaultValue="SOAP12"}</description>
+ <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>${optioal-property-value}</config-property-value>
+ <config-property-value>${optional-property-value}</config-property-value>
</config-property>
<!-- use the below as is if you used the Connection Factory interface -->
@@ -53,6 +52,7 @@
<reauthentication-support>false</reauthentication-support>
</outbound-resourceadapter>
</resourceadapter>
-</connector>
- ]]></programlisting>
+</connector>]]></programlisting>
+ <para>${...} indicates a value to be supplied by the developer.</para>
+ <para>The description entry can utilize a special format in {}, where extended metadata properties can be supplied. This use of the special format and all properties is optional. Property names begin with $ and are separated from the value with :. Double quotes identifies a single value. A pair of square brackets [] containing comma separated double quoted entries denotes a list value.</para>
</appendix>
\ No newline at end of file
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-b.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-b.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/appendix-b.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -1,7 +1,7 @@
<appendix id="advanced_topics">
<title>Advanced Topics</title>
<sect1>
- <title>Migration From Previous Versions</title>
+ <title>Security Migration From Previous Versions</title>
<para>It is recommended that customers who have utilized the internal JDBC membership domain from releases
prior to MetaMatrix 5.5 migrate those users and groups to an LDAP compliant directory server. Several free
and open source directory servers can be used including:</para>
@@ -17,7 +17,7 @@
Apache Directory Server
<ulink url="http://directory.apache.org/">http://directory.apache.org/</ulink>
</para>
- <para>If there are additional questions or the need for guidance in the migration process, please contact
+ <para>See the JBossAS security documentation for using an LDAP directory server. If there are additional questions or the need for guidance in the migration process, please contact
technical support.</para>
</sect1>
</appendix>
\ No newline at end of file
Deleted: trunk/documentation/developer-guide/src/main/docbook/en-US/content/command-language.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/command-language.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/command-language.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -1,1000 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
-<!ENTITY % CustomDTD SYSTEM "../../../../../../docbook/custom.dtd">
-%CustomDTD;
-]>
-<chapter id="command_language">
- <title>Command Language</title>
-
- <sect1>
- <title>Language Interfaces</title>
- <para>
- Teiid sends commands to your Translator in object form. The interfaces
- for these objects are all defined in the "org.teiid.language"
- package. These interfaces can be combined to represent any possible
- command that Teiid may send to the Translator. However, it is possible
- to notify Teiid that your Translator can only accept certain kinds of
- commands via the capabilities defined on the "ExecutionFactory" class. See the section on using
- <link linkend="translator_capabilities">Translator Capabilities</link>
- for more information.
- </para>
- <para>The language interfaces all extend from the <emphasis>LanguageObject</emphasis> 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.</para>
- <para>All commands sent to your Translator are in the form of these
- language trees, where the root of the tree is a subclass of <emphasis>Command</emphasis>.
- Command has several sub-interfaces, namely:
-
- <itemizedlist>
- <listitem><para><code>QueryExpression</code></para></listitem>
- <listitem><para><code>Insert</code></para></listitem>
- <listitem><para><code>Update</code></para></listitem>
- <listitem><para><code>Delete</code></para></listitem>
- <listitem><para><code>BatchedUpdate</code></para></listitem>
- <listitem><para><code>Call</code></para></listitem>
- </itemizedlist>
-
- Important components of these commands are expressions, criteria, and joins, which are examined
- in closer detail below. Also see the <ulink url="&javaDocUrl;">Teiid JavaDocs</ulink>
- for more on the classes and interfaces described here.
- </para>
- <sect2>
- <title>Expressions</title>
- <para>An expression represents a single value in context, although in
- some cases that value may change as the query is evaluated. For
- example, a literal value, such as 5 represents an integer value. An
- element reference such as "table.EmployeeName" represents a column in a data source
- and may logically take on many values while the command is being
- evaluated.</para>
- <itemizedlist>
- <listitem>
- <para>
- <code>Expression</code>
- – base expression interface
- </para>
- </listitem>
- <listitem>
- <para>
- <code>Element</code>
- – represents an element in the data source
- </para>
- </listitem>
- <listitem>
- <para>
- <code>Literal</code>
- – represents a literal scalar value, but may also be multi-valued in
- the case of bulk updates.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>Function</code>
- – represents a scalar function with parameters that are also Expressions
- </para>
- </listitem>
- <listitem>
- <para>
- <code>Aggregate</code>
- – represents an aggregate function which holds a single expression
- </para>
- </listitem>
- <listitem>
- <para>
- <code>ScalarSubquery</code>
- – represents a subquery that returns a single value
- </para>
- </listitem>
- <listitem>
- <para>
- <code>SearchedCase, SearchedWhenClause</code>
- – 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.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2>
- <title>Condition</title>
- <para>A criteria is a combination of expressions and operators that
- evaluates to true, false, or unknown. Criteria are most commonly used in the
- WHERE or HAVING clauses.</para>
-
- <itemizedlist>
- <listitem><para><code>Condition</code> – the base criteria interface</para></listitem>
- <listitem><para><code>Not</code> – used to NOT another criteria</para></listitem>
- <listitem><para><code>AndOr</code> – used to combine other criteria via AND or OR</para></listitem>
- <listitem><para><code>SubuqeryComparison</code> – represents a comparison criteria with a subquery including a quantifier such as SOME or ALL</para></listitem>
- <listitem><para><code>Comparison</code> – represents a comparison criteria with =, >, <, etc.</para></listitem>
- <listitem><para><code>BaseInCondition</code> – base class for an IN criteria</para></listitem>
- <listitem><para><code>In</code> – represents an IN criteria that has a set of expressions for values</para></listitem>
- <listitem><para><code>SubqueryIn</code> – represents an IN criteria that uses a subquery to produce the value set</para></listitem>
- <listitem><para><code>IsNull</code> – represents an IS NULL criteria</para></listitem>
- <listitem><para><code>Exists</code> – represents an EXISTS criteria that determines whether a subquery will return any values</para></listitem>
- <listitem><para><code>Like</code> – represents a LIKE criteria that compares string values</para></listitem>
- </itemizedlist>
- </sect2>
-
- <sect2>
- <title>The FROM Clause</title>
- <para>The FROM clause contains a list of <emphasis>TableReference</emphasis>. </para>
-
- <itemizedlist>
- <listitem><para><code>TableReference</code> – represents a single Table</para></listitem>
- <listitem><para><code>Join</code> – has a left and right <code>TableReference</code> and information on the join between the items</para></listitem>
- <listitem><para><code>DerivedTable</code> – represents a table defined by an inline <code>QueryExpression</code></para></listitem>
- </itemizedlist>
- <para>
- A list of <emphasis>TableReference</emphasis>
- 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
- <code>Join</code>
- 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. See
- <link linkend="command_form_capabilities">Command Form Capabilities</link>
- for more information.
- </para>
- </sect2>
- <sect2>
- <title>QueryExpression Structure</title>
- <para><emphasis>QueryExpression</emphasis> is the base for both queries and set queries. It may optionally take an
- <emphasis>OrderBy</emphasis> (representing a SQL ORDER BY clause) and a <emphasis>Limit</emphasis> (represent a SQL LIMIT clause)</para>
- </sect2>
-
- <sect2>
- <title>Select Structure</title>
-
- <para>Each <emphasis>QueryExpression</emphasis> can be a <emphasis>Select</emphasis> describing the expressions
- (typically elements) being selected and an <emphasis>TableReference</emphasis> specifying the table
- or tables being selected from, along with any join information. The
- <emphasis>Select</emphasis> may optionally also supply an <emphasis>Condition</emphasis> (representing a SQL
- WHERE clause), an <emphasis>GroupBy</emphasis> (representing a SQL GROUP BY clause), an
- an <emphasis>Condition</emphasis> (representing a SQL HAVING clause).</para>
- </sect2>
-
- <sect2>
- <title>SetQuery Structure</title>
-
- <para>A <emphasis>QueryExpression</emphasis> can also be a <emphasis>SetQuery</emphasis> that represents on of the SQL set operations (UNION,
- INTERSECT, EXCEPT) on two <emphasis>QueryExpression</emphasis>. The all flag may be set to
- indicate UNION ALL (currently INTERSECT and EXCEPT ALL are not allowed in Teiid)</para>
- </sect2>
-
- <sect2>
- <title>Insert Structure</title>
-
- <para>Each <emphasis>Insert</emphasis> will have a single <emphasis>NamedTable</emphasis> specifying the table being
- inserted into. It will also has a list of <emphasis>ColumnReference</emphasis> specifying the columns
- of the <emphasis>TableReference</emphasis> that are being inserted into. It also has
- <emphasis>InsertValueSource</emphasis>, which will either be a list of
- <emphasis>Expression(ExpressionValueSource)</emphasis> or <emphasis>QueryExpression</emphasis></para>
- </sect2>
-
- <sect2>
- <title>Update Structure</title>
-
- <para>Each <emphasis>Update</emphasis> will have a single <emphasis>NamedTable</emphasis> specifying the table being
- updated and list of <emphasis>SetClause</emphasis> entries that specify <emphasis>ColumnReference</emphasis>
- and <emphasis>Expression</emphasis> pairs for the update. The Update may optionally provide a criteria
- <emphasis>Condition</emphasis> specifying which rows should be updated.</para>
- </sect2>
-
- <sect2>
- <title>Delete Structure</title>
-
- <para>Each <emphasis>Delete</emphasis> will have a single <emphasis>NamedTable</emphasis> specifying the table being
- deleted from. It may also optionally have a criteria specifying which rows should be deleted. </para>
- </sect2>
-
- <sect2>
- <title>Call Structure</title>
-
- <para>Each <emphasis>Call</emphasis> has zero or more <emphasis>Argument</emphasis> objects. The
- <emphasis>Argument</emphasis> objects describe the input parameters, the output result
- set, and the output parameters. </para>
- </sect2>
-
- <sect2>
- <title>BatchedUpdates Structure </title>
- <para>Each <emphasis>BatchedUpdates</emphasis> has a list of <emphasis>Command</emphasis> objects (which must be either
- <emphasis>Insert</emphasis>, <emphasis>Update</emphasis> or <emphasis>Delete</emphasis>) that compose the batch. </para>
- </sect2>
- </sect1>
-
- <sect1>
- <title>Language Utilities</title>
- <para>This section covers utilities available when using, creating, and manipulating the language interfaces.</para>
-
- <sect2>
- <title>Data Types</title>
- <para>The Translator API contains an interface <emphasis>TypeFacility</emphasis> that defines
- data types and provides value translation facilities. This interface can be obtained from calling "getTypeFacility()"
- method on the "ExecutionFactory" class.</para>
-
- <para>
- The TypeFacitlity interface has methods that support data type
- transformation and detection of appropriate runtime or JDBC types.
- The TypeFacility.RUNTIME_TYPES and TypeFacility.RUNTIME_NAMES
- interfaces defines constants for all Teiid runtime data types. All
- <emphasis>Expression</emphasis> instances define a data type based on this set of types.
- These constants are often needed in understanding or creating language interfaces.</para>
- </sect2>
-
- <sect2>
- <title>Language Manipulation</title>
- <para>In Translators that support a fuller set of capabilities (those
- that generally are translating to a language of comparable to SQL),
- there is often a need to manipulate or create language interfaces to
- move closer to the syntax of choice. Some utilities are provided for
- this purpose:</para>
- <para>Similar to the TypeFacility, you can call "getLanguageFactory()" method on
- the "ExecutionFactory"
- to get a reference to the <emphasis>LanguageFactory</emphasis> instance for your
- translator. This interface is a factory that can be used to create new
- instances of all the concrete language interface objects. </para>
- <para>Some helpful utilities for working with <emphasis>Condition</emphasis> objects are
- provided in the <emphasis>LanguageUtil</emphasis> class. This class has methods to combine
- <emphasis>Condition</emphasis> with AND or to break an <emphasis>Condition</emphasis> apart based on AND
- operators. These utilities are helpful for breaking apart a criteria
- into individual filters that your translator can implement.</para>
- </sect2>
- </sect1>
-
- <sect1>
- <title>Runtime Metadata</title>
- <para>Teiid uses a library of metadata, known as "runtime metadata” for
- each virtual database that is deployed in Teiid. The runtime metadata
- is a subset of metadata as defined by models in the Teiid models that
- compose the virtual database. While builing your VDB in the Designer, you can define what
- called "Extension Model", that defines any number of arbitary properties on a model and its objects.
- At runtime, using this runtime metadata interface, you get access to those set properties defined during the
- design time, to define/hint any execution behavior. For example, a XML model could define the 'xpath' as
- one of the property on Column of a Table.</para>
-
- <para>Translator gets access to the <emphasis>RuntimeMetadata</emphasis> interface at the time of <emphasis>Excecution</emphasis> creation.
- Translators can access runtime metadata by using the interfaces
- defined in <emphasis>org.teiid.metadata</emphasis> package. This package defines
- API representing a Schema, Table, Columns and Procedures, and ways to navigate these objects.</para>
-
- <sect2>
- <title>Language Objects</title>
- <para>All the language objects extend <emphasis>AbstractMetadataRecord</emphasis> class</para>
- <itemizedlist>
- <listitem><para>Column - returns Column metadata record</para></listitem>
- <listitem><para>Table - returns a Table metadata record</para></listitem>
- <listitem><para>Procedure - returns a Procedure metadata record</para></listitem>
- <listitem><para>ProcedureParameter - returns a Procedure Parameter metadata record</para></listitem>
- </itemizedlist>
-
- <para>Once a metadata record has been obtained, it is possible to use its metadata about that object or to find other related or objects.</para>
- </sect2>
- <sect2>
- <title>Access to Runtime Metadata</title>
-
- <para>The RuntimeMetadata interface is passed in for the creation of an "Execution". See "createExecution"
- method on the "ExecutionFactory" class. It provides the ability to look up
- metadta records based on their fully qualified names in the VDB. There are several kinds of
- metadata objects and they can be used to find more information about
- the objects in runtime metadata. </para>
-
-
- <para><emphasis>Obtaining Metadata Properties Example</emphasis></para>
-
- <para>The process of getting an Table's properties is sometimes needed for translator development. For example
- to get the "NameInSource" property or all extension properties:</para>
- <programlisting><![CDATA[
-//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
-Properties props = table.getProperties();
- ]]></programlisting>
-
- </sect2>
- </sect1>
-
- <sect1>
- <title>Language Visitors</title>
-
- <sect2>
- <title>Framework</title>
- <para>The API provides a language visitor framework in the
- <emphasis>org.teiid.language.visitor</emphasis> package. The framework
- provides utilities useful in navigating and extracting information
- from trees of language objects.</para>
-
- <para>The visitor framework is a variant of the Visitor design pattern,
- which is documented in several popular design pattern references. The
- visitor pattern encompasses two primary operations: traversing the
- nodes of a graph (also known as iteration) and performing some action
- at each node of the graph. In this case, the nodes are language
- interface objects and the graph is really a tree rooted at some node.
- The provided framework allows for customization of both aspects of
- visiting.</para>
- <para>The base <emphasis>AbstractLanguageVisitor</emphasis> 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 just a
- visitor shell – it performs no actions when visiting nodes and does
- not provide any iteration.</para>
- <para>The <emphasis>HierarchyVisitor</emphasis> provides the basic code for walking a
- language object tree. <emphasis>The HierarchyVisitor</emphasis> performs no action as it
- walks the tree – it just 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, etc) then you must either extend
- HierarchyVisitor or build your own iteration visitor. In general,
- that is not necessary.</para>
- <para>The <emphasis>DelegatingHierarchyVisitor</emphasis> 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
- <emphasis>DelegatingHierarchyVisitor</emphasis> to aid in executing pre- and post-order
- visitors. </para>
- </sect2>
- <sect2>
- <title>Provided Visitors</title>
- <para>The <emphasis>SQLStringVisitor</emphasis> is a special visitor that can traverse a
- tree of language interfaces and output the equivalent Teiid SQL. This
- visitor can be used to print language objects for debugging and
- logging. The <emphasis>SQLStringVisitor</emphasis> does not use the <emphasis>HierarchyVisitor</emphasis>
- described in the last section; it provides both iteration and
- processing type functionality in a single custom visitor. </para>
- <para>The <emphasis>CollectorVisitor</emphasis> 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. </para>
- </sect2>
- <sect2>
- <title>Writing a Visitor</title>
- <para>Writing your own visitor can be quite easy if you use the
- provided facilities. If the normal method of iterating the language
- tree is sufficient, then just follow these steps:</para>
- <para>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
- <emphasis>visit(ColumnReference)</emphasis> method. Collect any state in local variables and
- provide accessor methods for that state.</para>
- <para>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.</para>
- <para>Write code to execute your visitor using the utility methods on
- DelegatingHierarchyVisitor:</para>
- <programlisting><![CDATA[
-// 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();
- ]]></programlisting>
- </sect2>
- </sect1>
- <sect1 id="translator_capabilities">
- <title>Translator Capabilities</title>
- <para>The <emphasis>ExecutionFactory</emphasis> 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 <emphasis>ExecutionFactory</emphasis> class implements all the basic capabilities, which says
- your translator does not support any cpabilities. Your extended
- <emphasis>ExecutionFactory</emphasis> class must override the the necessary methods to specify which
- capabilities your translator supports. </para>
- <sect2>
- <title>Capability Scope</title>
- <para>
- Note that if your capabilities will remain unchanged for the lifetime
- of the translator, since the engine will cache them for reuse by all instances of that
- translator. Capabilities based on connection/user are not supported.
- </para>
- </sect2>
- <sect2>
- <title>Capabilities</title>
- <para>The following table lists the capabilities that can be specified in the <emphasis>ExecutionFactory</emphasis> class.</para>
- <table frame='all'>
- <title>Available Capabilities</title>
- <tgroup cols='3' align='left' colsep='1' rowsep='1'>
- <colspec colname='c1' colwidth="1.5*" />
- <colspec colname='c2' colwidth="1*" />
- <colspec colname='c3' colwidth="2*" />
- <thead>
- <row>
- <entry>
- <para>Capability</para>
- </entry>
- <entry>
- <para>Requires</para>
- </entry>
- <entry>
- <para>Description</para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>SelectDistinct</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support SELECT DISTINCT in queries.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>SelectExpression</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support SELECT of more than just column references.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AliasedTable</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support Tables in the FROM clause that have an alias.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InnerJoins</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support inner and cross joins</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>SelfJoins</para>
- </entry>
- <entry>
- <para>AliasedGroups and at least on of the join type supports.</para>
- </entry>
- <entry>
- <para>Translator can support a self join between two aliased versions of the
- same Table.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>OuterJoins</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support LEFT and RIGHT OUTER JOIN.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>FullOuterJoins</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support FULL OUTER JOIN.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InlineViews</para>
- </entry>
- <entry>
- <para>AliasedTable</para>
- </entry>
- <entry>
- <para>Translator can support a named subquery in the FROM clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>BetweenCriteria</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Not currently used - between criteria is rewriten as compound comparisions.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>CompareCriteriaEquals</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support comparison criteria with the operator "=”.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>CompareCriteriaOrdered</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support comparison criteria with the operator ">” or "<".</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>LikeCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support LIKE criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>LikeCriteriaEscapeCharacter</para>
- </entry>
- <entry>
- <para>LikeCriteria</para>
- </entry>
- <entry>
- <para>Translator can support LIKE criteria with an ESCAPE character clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InCriteria</para>
- </entry>
- <entry>
- <para>MaxInCriteria</para>
- </entry>
- <entry>
- <para>Translator can support IN predicate criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InCriteriaSubquery</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support IN predicate criteria where values are supplied by a
- subquery.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>IsNullCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support IS NULL predicate criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>OrCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the OR logical criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>NotCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>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.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>ExistsCriteria</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support EXISTS predicate criteria.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>QuantifiedCompareCriteriaAll</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support a quantified comparison criteria using the ALL
- quantifier.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>QuantifiedCompareCriteriaSome</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support a quantified comparison criteria using the SOME or ANY
- quantifier.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>OrderBy</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support the ORDER BY clause in queries.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>OrderByUnrelated</para>
- </entry>
- <entry>
- <para>OrderBy</para>
- </entry>
- <entry>
- <para>Translator can support the ORDER BY items that are not directly specified in the select clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>GroupBy</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support an explict GROUP BY clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>Having</para>
- </entry>
- <entry>
- <para>GroupBy</para>
- </entry>
- <entry>
- <para>Translator can support the HAVING clause.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesAvg</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the AVG aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesCount</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the COUNT aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesCountStar</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the COUNT(*) aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesDistinct</para>
- </entry>
- <entry>
- <para>At least one of the aggregate functions.</para>
- </entry>
- <entry>
- <para>Translator can support the keyword DISTINCT inside an aggregate function. This
- keyword indicates that duplicate values within a group of rows will be ignored.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesMax</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the MAX aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesMin</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the MIN aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>AggregatesSum</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the SUM aggregate function.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>ScalarSubqueries</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support the use of a subquery in a scalar context (wherever an
- expression is valid).</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>CorrelatedSubqueries</para>
- </entry>
- <entry>
- <para>At least one of the subquery pushdown capabilities.</para>
- </entry>
- <entry>
- <para>Translator can support a correlated subquery that refers to an element in
- the outer query.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>CaseExpressions</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Not currently used - simple case is rewriten as searched case.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>SearchedCaseExpressions</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator can support "searched” CASE expressions anywhere that expressions are
- accepted.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>Unions</para>
- </entry>
- <entry>
- <para />
- </entry>
- <entry>
- <para>Translator support UNION and UNION ALL</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>Intersect</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports INTERSECT</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>Except</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports Except</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>SetQueryOrderBy</para>
- </entry>
- <entry>
- <para>Unions, Intersect, or Except</para>
- </entry>
- <entry>
- <para>Translator supports set queries with an ORDER BY</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>RowLimit</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the limit portion of the limit clause</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>RowOffset</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator can support the offset portion of the limit clause</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>FunctionsInGroupBy</para>
- </entry>
- <entry>
- <para>GroupBy</para>
- </entry>
- <entry>
- <para>Not currently used - non-element expressions in the group by create an inline view.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>InsertWithQueryExpression</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports INSERT statements with values specified by an QueryExpression.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>supportsBatchedUpdates</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports a batch of INSERT, UPDATE and DELETE commands to be executed together.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>supportsBulkUpdate</para>
- </entry>
- <entry>
- <para/>
- </entry>
- <entry>
- <para>Translator supports updates with multiple value sets</para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Note that any pushdown subquery must itself be compliant with the Translator capabilities.</para>
- </sect2>
-
- <sect2 id="command_form_capabilities">
- <title>Command Form</title>
- <para>The method <emphasis>ExecutionFactory.useAnsiJoin()</emphasis> should return true
- if the Translator prefers the use of ANSI style join structure for
- join trees that contain only INNER and CROSS joins.</para>
- <para>The method <emphasis>ExecutionFactory.requiresCriteria()</emphasis> 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".</para>
- </sect2>
-
- <sect2>
- <title>Scalar Functions</title>
- <para>The method <emphasis>ExecutionFactory.getSupportedFunctions()</emphasis> can be
- used to specify which scalar functions the Translator supports. The
- set of possible functions is based on the set of functions supported
- by Teiid. This set can be found in the <ulink url="&docUrl;">Reference</ulink>
- documentation. If the Translator states that it supports a function,
- it must support all type combinations and overloaded forms of that
- function.</para>
- <para>There are also five standard operators that can also be specified in the
- supported function list: +, -, *, /, and ||.</para>
- <para>The constants interface SourceSystemFunctions contains the string
- names of all possible built-in pushdown functions. Note that not all
- system functions appear in this list. This is because some system
- functions will always be evaluted in Teiid, are simple aliases to
- other functions, or are rewriten to a more standard expression.</para>
- </sect2>
-
- <sect2>
- <title>Physical Limits</title>
- <para>The method <emphasis>ExecutionFactory.getMaxInCriteriaSize()</emphasis> 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.</para>
- <para>The method <emphasis>ExecutionFactory.getMaxFromGroups()</emphasis> can be used
- to specify the maximum number of FROM Clause groups that can used in a
- join. -1 indicates there is no limit.</para>
- </sect2>
-
- <sect2>
- <title>Update Execution Modes</title>
- <para>The method <emphasis>ExecutionFactory.supportsBatchedUpdates()</emphasis> can be
- used to indicate that the Translator supports executing the <emphasis>BatchedUpdates</emphasis> command.
- </para>
- <para>The method <emphasis>ExecutionFactory.supportsBulkUpdate()</emphasis> can be used
- to indicate that the Translator accepts update commands containg multi valued Literals.</para>
- <para>Note that if the translator does not support either of these
- update modes, the query engine will compensate by issuing the updates individually.</para>
- </sect2>
-
- </sect1>
-
-</chapter>
\ No newline at end of file
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/connector-api.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -3,14 +3,14 @@
%CustomDTD;
]>
<chapter id="translator_api">
- <title>Developing a Translator</title>
+ <title>Translator Development</title>
<sect1>
<title>Extending the ExecutionFactory Class</title>
<para>A component called the Connector Manager is controlling access to your translator. This chapter reviews
the basics of how the Connector Manager interacts with your translator while leaving reference details and
advanced topics to be covered in later chapters.</para>
<para>
- A custom translator must extend <emphasis>org.teiid.translator.ExecutionFactory</emphasis>
+ A custom translator must extend <code>org.teiid.translator.ExecutionFactory</code>
to connect and query an enterprise data source. This extended class must provide a no-arg constructor
that can be constructed using Java reflection libraries. This Execution Factory need define/override following elements.
</para>
@@ -32,10 +32,9 @@
<para>Every software program requires some external configuration, that defines ways user can alter the behavior of a program.
If this translator needs configurable properties define a variable for every property as an attribute in the extended
"ExecutionFactory" class. Then define a "get" and "set" methods for each of them. Also, annotate each "get" method with
- <emphasis>@TranslatorProperty</emphasis> annotation and provide the metadata about the property. For example, if you need a
+ <code>@TranslatorProperty</code> annotation and provide the metadata about the property. For example, if you need a
property called "foo",
- <programlisting><![CDATA[
-String foo = "balh";
+ <programlisting><![CDATA[String foo = "balh";
@TranslatorProperty(display="Foo property", description="description about Foo")
public String getFoo() {
@@ -44,19 +43,17 @@
public void setFoo(String value) {
return this.foo = value;
-}
- ]]> </programlisting>
+}]]> </programlisting>
by providing the annotation on these properties, the Teiid tooling will automatically interrogate and
provide graphical way to configure your
- Translator. Only "java.lang" and java "primitive" types are supported as Translator properties.
- If you do not provide the property during the configuration, the default value defined in this class will be used.
- All the properties <emphasis>should</emphasis> have a default value. If you can not provide a default value,
- validate all the required properties during the initialization, fail if one is not provided. Repeat this
- process for all the properties that you require to configure the Translator.
+ Translator. Only java primitive (int), 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 <emphasis>should</emphasis> 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.
</para>
- <para>The <emphasis>@TranslatorProperty</emphasis> defines the following metadata that you can define about your property</para>
+ <para>The <code>@TranslatorProperty</code> defines the following metadata that you can define about your property</para>
<itemizedlist>
<listitem>
<para>display: Display name of the property</para>
@@ -65,10 +62,10 @@
<para>description: Description about the property</para>
</listitem>
<listitem>
- <para>required: The property is a required property; or optional and a default is supplied</para>
+ <para>required: The property is a required property</para>
</listitem>
<listitem>
- <para>advanced: This is advanced property; A default must be provided. A property can not be "advanced" and "required" at same time.</para>
+ <para>advanced: This is advanced property; A default should be provided. A property can not be "advanced" and "required" at same time.</para>
</listitem>
<listitem>
<para>masked: The tools need to mask the property; Do not show in plain text; used for passwords</para>
@@ -78,7 +75,7 @@
<sect2>
<title>Initializing the Translator</title>
- <para>Override and implement the <emphasis>start</emphasis> method (be sure to call
+ <para>Override and implement the <code>start</code> method (be sure to call
"super.start()") if your translator needs to do any initializing before it is used by the Teiid engine. This method
will be called by Teiid, once after all the configuration properties set above are injected into the class. </para>
</sect2>
@@ -86,9 +83,8 @@
<sect2>
<title>TranslatorCapabilities</title>
<para>These are various methods that typically begin with method
- signature "supports" on the "ExecutionFactory" calss. These methods need to be overridden to describe the execution
- capabilities of the Translator. These will be used by the query engine to determine the capabilities of the Translator.
- More information on what these are in the next chapter.</para>
+ signature "supports" on the "ExecutionFactory" class. These methods need to be overridden to describe the execution
+ capabilities of the Translator. See <link linkend="translator_capabilities">Translator Capabilities</link> for more on these methods.</para>
</sect2>
<sect2>
@@ -98,31 +94,29 @@
<itemizedlist>
<listitem>
- <para><emphasis>createResultSetExecution</emphasis> - Define if you are doing read based operation that is
+ <para><code>createResultSetExecution</code> - Define if you are doing read based operation that is
returning a rows of results.</para>
</listitem>
<listitem>
- <para><emphasis>createUpdateExecution</emphasis> - Define if you are doing write based operations.</para>
+ <para><code>createUpdateExecution</code> - Define if you are doing write based operations.</para>
</listitem>
<listitem>
- <para><emphasis>createProcedureExecution</emphasis> - Define if you are doing procedure based operations.</para>
+ <para><code>createProcedureExecution</code> - Define if you are doing procedure based operations.</para>
</listitem>
</itemizedlist>
- <para>You can choose to implement all the execution modes or just what you need. There is no restriction, but it must
- implement at least one type of execution. See more details on this below.</para>
+ <para>You can choose to implement all the execution modes or just what you need. See more details on this below.</para>
</sect2>
<sect2>
<title>Metadata</title>
- <para>Override and implement the method <emphasis>getMetadata()</emphasis>, if you want to expose the
- metadata about the source. This defines the tables with its column names, procedures with its parameter that
- this translator exposing to the query engine. If you expect your translator to work with Dynamic VDB, you must override this
- method, if are always going to use Designer to build the VDB then this is optional. </para>
+ <para>Override and implement the method <code>getMetadata()</code>, if you want to expose the
+ metadata about the source for use in Dynamic VDBs. This defines the tables, column names, procedures, parameters, etc. for use in the query engine.
+ This method is not yet used by Designer tooling. </para>
</sect2>
<sect2>
<title>Logging</title>
- <para>Teiid provides <emphasis>org.teiid.logging.LogManager</emphasis> class for logging purposes.
+ <para>Teiid provides <code>org.teiid.logging.LogManager</code> class for logging purposes.
Create a logging context and use the LogManager to log your messages. These will be automatically
sent to the main Teiid logs. You can edit the "jboss-log4j.xml" inside "conf" directory of the JBoss AS's profile
to add the custom context. Teiid uses Log4J as its underlying logging system.</para>
@@ -130,14 +124,14 @@
<sect2>
<title>Exceptions</title>
- <para>If you need to bubble up any exception use <emphasis>org.teiid.translator.TranslatorException</emphasis>
+ <para>If you need to bubble up any exception use <code>org.teiid.translator.TranslatorException</code>
class.</para>
</sect2>
<sect2>
<title>Default Name</title>
<para>Finally, you can define a default instance of your Translator by defining the
- annotation <emphasis>@Translator</emphasis> on the "ExecutionFactory". When you define this, and after deployment
+ annotation <code>@Translator</code> on the "ExecutionFactory". When you define this, and after deployment
a default instance of this
Translator is available any VDB that would like to use by just mentioning its name in its "vdb.xml" configuration file.
VDB can also override the default properties and define another instance of this Translator too. The name you give here is the short
@@ -151,7 +145,7 @@
<title>Connections to Source</title>
<sect2>
<title>Obtaining connections</title>
- <para>The extended "ExecutionFactory" must implement the <emphasis>getConnection()</emphasis> method to
+ <para>The extended "ExecutionFactory" must implement the <code>getConnection()</code> method to
allow the Connector Manager to obtain a connection. </para>
</sect2>
<sect2>
@@ -163,7 +157,7 @@
In cases (such as when a connection is stateful and expensive to
create), connections should be pooled. If the resource adapter is JEE JCA connector based, then pooling is automatically
provided by the JBoss AS container. If your resource adapter does not implement the JEE JCA, then connection pooling
- sematics are left to the user to define on their own.
+ semantics are left to the user to define on their own.
</para>
</sect2>
</sect1>
@@ -174,7 +168,7 @@
<para>
The Teiid query engine uses the "ExecutionFactory" class to obtain the "Execution" interface for the command it is
executing. The actual queries themselves are sent to translators in the form of a set of objects, which are further
- described in Chapter <link linkend="command_language">Command Language</link>.
+ described in <link linkend="command_language">Command Language</link>.
translators are allowed to support any subset of the available execution modes.
</para>
<table frame='all'>
@@ -217,7 +211,7 @@
<entry>
<code>Call</code>
</entry>
- <entry>A procedure execution that may return a result set and/or output values.</entry>
+ <entry>A procedure execution that may return a result set and/or output values.</entry>
</row>
</tbody>
</tgroup>
@@ -253,32 +247,18 @@
be retrieved via the getOutputParameterValues() method.
</para>
</sect2>
- <!--
+
<sect2>
<title>Asynchronous Executions</title>
<para>In some scenarios, a translator needs to execute
- asynchronously and allow the executing thread to perform other work. To allow this, you should:
- </para>
- <itemizedlist>
- <listitem>
- <para>Set either the SynchronousWorkers annotation or the connector
- binding property SynchWorkers to false - this overrides the default
- behavior in which connector threads stay associated with their
- Execution until the Execution is closed.</para>
- </listitem>
- <listitem>
- <para>Throw a DataNotAvailableExecption during a retrival method, rather than explicitly waiting or sleeping for the results. The
+ asynchronously and allow the executing thread to perform other work. To allow this, you should Throw a DataNotAvailableExecption during a retrival method, rather than explicitly waiting or sleeping for the results. The
DataNotAvailableException may take a delay parameter in its
constructor to indicate how long the system should wait befor polling
for results. Any non-negative value is allowed.
- </para>
- </listitem>
- <listitem>
- <para>Be aware that a connector with asynchronous workers cannot be transactional.</para>
- </listitem>
- </itemizedlist>
+ </para>
+ <para>Since the exection and the associated connection are not closed until the work has completed, care should be taken if using asynchronous executions that hold a lot of state.</para>
</sect2>
- -->
+
<sect2>
<title>Bulk Execution</title>
<para> Non batched <code>Insert, Update, Delete</code>
@@ -291,7 +271,7 @@
<sect2>
<title>Command Completion</title>
<para>All normal command executions end with the calling of <code>close()</code> on the Execution object. Your
- implementation of this method should do the appropriate clean-up work for all state in the Execution object.</para>
+ implementation of this method should do the appropriate clean-up work for all state created in the Execution object.</para>
</sect2>
<sect2>
<title>Command Cancellation</title>
@@ -320,43 +300,1104 @@
faster as well.</para>
</sect2>
</sect1>
+
+ <sect1 id="command_language">
+ <title>Command Language</title>
+
+ <sect2>
+ <title>Language </title>
+ <para>
+ Teiid sends commands to your Translator in object form. These classes are all defined in the "org.teiid.language"
+ package. These objects can be combined to represent any possible
+ command that Teiid may send to the Translator. However, it is possible
+ to notify Teiid that your Translator can only accept certain kinds of
+ constructs via the capabilities defined on the "ExecutionFactory" class. See the section on using
+ <link linkend="translator_capabilities">Translator Capabilities</link>
+ for more information.
+ </para>
+ <para>The language objects all extend from the <code>LanguageObject</code> 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.</para>
+ <para>All commands sent to your Translator are in the form of these
+ language trees, where the root of the tree is a subclass of <code>Command</code>.
+ Command has several sub-interfaces, namely:
+
+ <itemizedlist>
+ <listitem><para><code>QueryExpression</code></para></listitem>
+ <listitem><para><code>Insert</code></para></listitem>
+ <listitem><para><code>Update</code></para></listitem>
+ <listitem><para><code>Delete</code></para></listitem>
+ <listitem><para><code>BatchedUpdates</code></para></listitem>
+ <listitem><para><code>Call</code></para></listitem>
+ </itemizedlist>
+
+ Important components of these commands are expressions, criteria, and joins, which are examined
+ in closer detail below. Also see the <ulink url="&javaDocUrl;">Teiid JavaDocs</ulink>
+ for more on the classes and interfaces described here.
+ </para>
+ <sect3>
+ <title>Expressions</title>
+ <para>An expression represents a single value in context, although in
+ some cases that value may change as the query is evaluated. For
+ example, a literal value, such as 5 represents an integer value. An
+ column reference such as "table.EmployeeName" represents a column in a data source
+ and may take on many values while the command is being
+ evaluated.</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <code>Expression</code>
+ – base expression interface
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>ColumnReference</code>
+ – represents an column in the data source
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>Literal</code>
+ – represents a literal scalar value, but may also be multi-valued in
+ the case of bulk updates.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>Function</code>
+ – represents a scalar function with parameters that are also Expressions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>Aggregate</code>
+ – represents an aggregate function which holds a single expression
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>ScalarSubquery</code>
+ – represents a subquery that returns a single value
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <code>SearchedCase, SearchedWhenClause</code>
+ – 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.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+ <sect3>
+ <title>Condition</title>
+ <para>A criteria is a combination of expressions and operators that
+ evaluates to true, false, or unknown. Criteria are most commonly used in the
+ WHERE or HAVING clauses.</para>
+
+ <itemizedlist>
+ <listitem><para><code>Condition</code> – the base criteria interface</para></listitem>
+ <listitem><para><code>Not</code> – used to NOT another criteria</para></listitem>
+ <listitem><para><code>AndOr</code> – used to combine other criteria via AND or OR</para></listitem>
+ <listitem><para><code>SubuqeryComparison</code> – represents a comparison criteria with a subquery including a quantifier such as SOME or ALL</para></listitem>
+ <listitem><para><code>Comparison</code> – represents a comparison criteria with =, >, <, etc.</para></listitem>
+ <listitem><para><code>BaseInCondition</code> – base class for an IN criteria</para></listitem>
+ <listitem><para><code>In</code> – represents an IN criteria that has a set of expressions for values</para></listitem>
+ <listitem><para><code>SubqueryIn</code> – represents an IN criteria that uses a subquery to produce the value set</para></listitem>
+ <listitem><para><code>IsNull</code> – represents an IS NULL criteria</para></listitem>
+ <listitem><para><code>Exists</code> – represents an EXISTS criteria that determines whether a subquery will return any values</para></listitem>
+ <listitem><para><code>Like</code> – represents a LIKE criteria that compares string values</para></listitem>
+ </itemizedlist>
+ </sect3>
+ <sect3>
+ <title>The FROM Clause</title>
+ <para>The FROM clause contains a list of <code>TableReference</code>'s. </para>
+
+ <itemizedlist>
+ <listitem><para><code>NamedTable</code> – represents a single Table</para></listitem>
+ <listitem><para><code>Join</code> – has a left and right <code>TableReference</code> and information on the join between the items</para></listitem>
+ <listitem><para><code>DerivedTable</code> – represents a table defined by an inline <code>QueryExpression</code></para></listitem>
+ </itemizedlist>
+ <para>
+ A list of <code>TableReference</code>
+ 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
+ <code>Join</code>
+ 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. See
+ <link linkend="command_form_capabilities">Command Form Capabilities</link>
+ for more information.
+ </para>
+ </sect3>
+ <sect3>
+ <title>QueryExpression Structure</title>
+ <para><code>QueryExpression</code> is the base for both SELECT queries and set queries. It may optionally take an
+ <code>OrderBy</code> (representing a SQL ORDER BY clause) and a <code>Limit</code> (represent a SQL LIMIT clause)</para>
+ </sect3>
+
+ <sect3>
+ <title>Select Structure</title>
+
+ <para>Each <code>QueryExpression</code> can be a <code>Select</code> describing the expressions
+ (typically elements) being selected and an <code>TableReference</code> specifying the table
+ or tables being selected from, along with any join information. The
+ <code>Select</code> may optionally also supply an <code>Condition</code> (representing a SQL
+ WHERE clause), a <code>GroupBy</code> (representing a SQL GROUP BY clause), an
+ an <code>Condition</code> (representing a SQL HAVING clause).</para>
+ </sect3>
+
+ <sect3>
+ <title>SetQuery Structure</title>
+
+ <para>A <code>QueryExpression</code> can also be a <code>SetQuery</code> that represents on of the SQL set operations (UNION,
+ INTERSECT, EXCEPT) on two <code>QueryExpression</code>. The all flag may be set to
+ indicate UNION ALL (currently INTERSECT and EXCEPT ALL are not allowed in Teiid)</para>
+ </sect3>
+
+ <sect3>
+ <title>Insert Structure</title>
+
+ <para>Each <code>Insert</code> will have a single <code>NamedTable</code> specifying the table being
+ inserted into. It will also has a list of <code>ColumnReference</code> specifying the columns
+ of the <code>NamedTable</code> that are being inserted into. It also has
+ <code>InsertValueSource</code>, which will either be a list of
+ <code>Expression(ExpressionValueSource)</code> or <code>QueryExpression</code></para>
+ </sect3>
+
+ <sect3>
+ <title>Update Structure</title>
+
+ <para>Each <code>Update</code> will have a single <code>NamedTable</code> specifying the table being
+ updated and list of <code>SetClause</code> entries that specify <code>ColumnReference</code>
+ and <code>Expression</code> pairs for the update. The Update may optionally provide a criteria
+ <code>Condition</code> specifying which rows should be updated.</para>
+ </sect3>
+
+ <sect3>
+ <title>Delete Structure</title>
+
+ <para>Each <code>Delete</code> will have a single <code>NamedTable</code> specifying the table being
+ deleted from. It may also optionally have a criteria specifying which rows should be deleted. </para>
+ </sect3>
+
+ <sect3>
+ <title>Call Structure</title>
+
+ <para>Each <code>Call</code> has zero or more <code>Argument</code> objects. The
+ <code>Argument</code> objects describe the input parameters, the output result
+ set, and the output parameters. </para>
+ </sect3>
+
+ <sect3>
+ <title>BatchedUpdates Structure </title>
+ <para>Each <code>BatchedUpdates</code> has a list of <code>Command</code> objects (which must be either
+ <code>Insert</code>, <code>Update</code> or <code>Delete</code>) that compose the batch. </para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Language Utilities</title>
+ <para>This section covers utilities available when using, creating, and manipulating the language interfaces.</para>
+
+ <sect3>
+ <title>Data Types</title>
+ <para>The Translator API contains an interface <code>TypeFacility</code> that defines
+ data types and provides value translation facilities. This interface can be obtained from calling "getTypeFacility()"
+ method on the "ExecutionFactory" class.</para>
+
+ <para>
+ The TypeFacitlity interface has methods that support data type
+ transformation and detection of appropriate runtime or JDBC types.
+ The TypeFacility.RUNTIME_TYPES and TypeFacility.RUNTIME_NAMES
+ interfaces defines constants for all Teiid runtime data types. All
+ <code>Expression</code> instances define a data type based on this set of types.
+ These constants are often needed in understanding or creating language interfaces.</para>
+ </sect3>
+
+ <sect3>
+ <title>Language Manipulation</title>
+ <para>In Translators that support a fuller set of capabilities (those
+ that generally are translating to a language of comparable to SQL),
+ there is often a need to manipulate or create language interfaces to
+ move closer to the syntax of choice. Some utilities are provided for
+ this purpose:</para>
+ <para>Similar to the TypeFacility, you can call "getLanguageFactory()" method on
+ the "ExecutionFactory"
+ to get a reference to the <code>LanguageFactory</code> instance for your
+ translator. This interface is a factory that can be used to create new
+ instances of all the concrete language interface objects. </para>
+ <para>Some helpful utilities for working with <code>Condition</code> objects are
+ provided in the <code>LanguageUtil</code> class. This class has methods to combine
+ <code>Condition</code> with AND or to break an <code>Condition</code> apart based on AND
+ operators. These utilities are helpful for breaking apart a criteria
+ into individual filters that your translator can implement.</para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Runtime Metadata</title>
+ <para>Teiid uses a library of metadata, known as "runtime metadata” for
+ each virtual database that is deployed in Teiid. The runtime metadata
+ is a subset of metadata as defined by models in the Teiid models that
+ compose the virtual database. While builing your VDB in the Designer, you can define what
+ called "Extension Model", that defines any number of arbitary properties on a model and its objects.
+ At runtime, using this runtime metadata interface, you get access to those set properties defined during the
+ design time, to define/hint any execution behavior.</para>
+
+ <para>Translator gets access to the <code>RuntimeMetadata</code> interface at the time of <code>Excecution</code> creation.
+ Translators can access runtime metadata by using the interfaces
+ defined in <code>org.teiid.metadata</code> package. This package defines
+ API representing a Schema, Table, Columns and Procedures, and ways to navigate these objects.</para>
+
+ <sect3>
+ <title>Metadata Objects</title>
+ <para>All the language objects extend <code>AbstractMetadataRecord</code> class</para>
+ <itemizedlist>
+ <listitem><para>Column - returns Column metadata record</para></listitem>
+ <listitem><para>Table - returns a Table metadata record</para></listitem>
+ <listitem><para>Procedure - returns a Procedure metadata record</para></listitem>
+ <listitem><para>ProcedureParameter - returns a Procedure Parameter metadata record</para></listitem>
+ </itemizedlist>
+
+ <para>Once a metadata record has been obtained, it is possible to use its metadata about that object or to find other related metadata.</para>
+ </sect3>
+ <sect3>
+ <title>Access to Runtime Metadata</title>
+
+ <para>The RuntimeMetadata interface is passed in for the creation of an "Execution". See "createExecution"
+ method on the "ExecutionFactory" class. It provides the ability to look up
+ metadata records based on their fully qualified names in the VDB.</para>
+
+ <example>
+ <title>Obtaining Metadata Properties</title>
+ <para>The process of getting a Table's properties is sometimes needed for translator development. For example
+ to get the "NameInSource" property or all extension properties:</para>
+ <programlisting><![CDATA[
+//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();
+ ]]></programlisting>
+ </example>
+
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Language Visitors</title>
+
+ <sect3>
+ <title>Framework</title>
+ <para>The API provides a language visitor framework in the
+ <code>org.teiid.language.visitor</code> package. The framework
+ provides utilities useful in navigating and extracting information
+ from trees of language objects.</para>
+
+ <para>The visitor framework is a variant of the Visitor design pattern,
+ which is documented in several popular design pattern references. The
+ visitor pattern encompasses two primary operations: traversing the
+ nodes of a graph (also known as iteration) and performing some action
+ at each node of the graph. In this case, the nodes are language
+ interface objects and the graph is really a tree rooted at some node.
+ The provided framework allows for customization of both aspects of
+ visiting.</para>
+ <para>The base <code>AbstractLanguageVisitor</code> 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 just a
+ visitor shell – it performs no actions when visiting nodes and does
+ not provide any iteration.</para>
+ <para>The <code>HierarchyVisitor</code> provides the basic code for walking a
+ language object tree. <code>The HierarchyVisitor</code> performs no action as it
+ walks the tree – it just 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, etc) then you must either extend
+ HierarchyVisitor or build your own iteration visitor. In general,
+ that is not necessary.</para>
+ <para>The <code>DelegatingHierarchyVisitor</code> 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
+ <code>DelegatingHierarchyVisitor</code> to aid in executing pre- and post-order
+ visitors. </para>
+ </sect3>
+ <sect3>
+ <title>Provided Visitors</title>
+ <para>The <code>SQLStringVisitor</code> is a special visitor that can traverse a
+ tree of language interfaces and output the equivalent Teiid SQL. This
+ visitor can be used to print language objects for debugging and
+ logging. The <code>SQLStringVisitor</code> does not use the <code>HierarchyVisitor</code>
+ described in the last section; it provides both iteration and
+ processing type functionality in a single custom visitor. </para>
+ <para>The <code>CollectorVisitor</code> 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. </para>
+ </sect3>
+ <sect3>
+ <title>Writing a Visitor</title>
+ <para>Writing your own visitor can be quite easy if you use the
+ provided facilities. If the normal method of iterating the language
+ tree is sufficient, then just follow these steps:</para>
+ <para>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
+ <code>visit(ColumnReference)</code> method. Collect any state in local variables and
+ provide accessor methods for that state.</para>
+ <para>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.</para>
+ <para>Write code to execute your visitor using the utility methods on
+ DelegatingHierarchyVisitor:</para>
+ <programlisting><![CDATA[
+// 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();
+ ]]></programlisting>
+ </sect3>
+ </sect2>
+ <sect2 id="translator_capabilities">
+ <title>Translator Capabilities</title>
+ <para>The <code>ExecutionFactory</code> 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 <code>ExecutionFactory</code> class implements all the basic capabilities, which says
+ your translator does not support any cpabilities. Your extended
+ <code>ExecutionFactory</code> class must override the the necessary methods to specify which
+ capabilities your translator supports. </para>
+ <sect3>
+ <title>Capability Scope</title>
+ <para>
+ Note that if your capabilities will remain unchanged for the lifetime
+ of the translator, since the engine will cache them for reuse by all instances of that
+ translator. Capabilities based on connection/user are not supported.
+ </para>
+ </sect3>
+ <sect3>
+ <title>Capabilities</title>
+ <para>The following table lists the capabilities that can be specified in the <code>ExecutionFactory</code> class.</para>
+ <table frame='all'>
+ <title>Available Capabilities</title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth="1.5*" />
+ <colspec colname='c2' colwidth="1*" />
+ <colspec colname='c3' colwidth="2*" />
+ <thead>
+ <row>
+ <entry>
+ <para>Capability</para>
+ </entry>
+ <entry>
+ <para>Requires</para>
+ </entry>
+ <entry>
+ <para>Description</para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>SelectDistinct</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support SELECT DISTINCT in queries.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>SelectExpression</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support SELECT of more than just column references.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AliasedTable</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support Tables in the FROM clause that have an alias.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InnerJoins</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support inner and cross joins</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>SelfJoins</para>
+ </entry>
+ <entry>
+ <para>AliasedGroups and at least on of the join type supports.</para>
+ </entry>
+ <entry>
+ <para>Translator can support a self join between two aliased versions of the
+ same Table.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>OuterJoins</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support LEFT and RIGHT OUTER JOIN.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>FullOuterJoins</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support FULL OUTER JOIN.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InlineViews</para>
+ </entry>
+ <entry>
+ <para>AliasedTable</para>
+ </entry>
+ <entry>
+ <para>Translator can support a named subquery in the FROM clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>BetweenCriteria</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Not currently used - between criteria is rewriten as compound comparisions.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>CompareCriteriaEquals</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support comparison criteria with the operator "=”.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>CompareCriteriaOrdered</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support comparison criteria with the operator ">” or "<".</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>LikeCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support LIKE criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>LikeCriteriaEscapeCharacter</para>
+ </entry>
+ <entry>
+ <para>LikeCriteria</para>
+ </entry>
+ <entry>
+ <para>Translator can support LIKE criteria with an ESCAPE character clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InCriteria</para>
+ </entry>
+ <entry>
+ <para>MaxInCriteria</para>
+ </entry>
+ <entry>
+ <para>Translator can support IN predicate criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InCriteriaSubquery</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support IN predicate criteria where values are supplied by a
+ subquery.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>IsNullCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support IS NULL predicate criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>OrCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the OR logical criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>NotCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>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.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>ExistsCriteria</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support EXISTS predicate criteria.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>QuantifiedCompareCriteriaAll</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support a quantified comparison criteria using the ALL
+ quantifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>QuantifiedCompareCriteriaSome</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support a quantified comparison criteria using the SOME or ANY
+ quantifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>OrderBy</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support the ORDER BY clause in queries.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>OrderByUnrelated</para>
+ </entry>
+ <entry>
+ <para>OrderBy</para>
+ </entry>
+ <entry>
+ <para>Translator can support the ORDER BY items that are not directly specified in the select clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>GroupBy</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support an explict GROUP BY clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Having</para>
+ </entry>
+ <entry>
+ <para>GroupBy</para>
+ </entry>
+ <entry>
+ <para>Translator can support the HAVING clause.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesAvg</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the AVG aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesCount</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the COUNT aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesCountStar</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the COUNT(*) aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesDistinct</para>
+ </entry>
+ <entry>
+ <para>At least one of the aggregate functions.</para>
+ </entry>
+ <entry>
+ <para>Translator can support the keyword DISTINCT inside an aggregate function. This
+ keyword indicates that duplicate values within a group of rows will be ignored.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesMax</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the MAX aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesMin</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the MIN aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>AggregatesSum</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the SUM aggregate function.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>ScalarSubqueries</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support the use of a subquery in a scalar context (wherever an
+ expression is valid).</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>CorrelatedSubqueries</para>
+ </entry>
+ <entry>
+ <para>At least one of the subquery pushdown capabilities.</para>
+ </entry>
+ <entry>
+ <para>Translator can support a correlated subquery that refers to an element in
+ the outer query.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>CaseExpressions</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Not currently used - simple case is rewriten as searched case.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>SearchedCaseExpressions</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator can support "searched” CASE expressions anywhere that expressions are
+ accepted.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Unions</para>
+ </entry>
+ <entry>
+ <para />
+ </entry>
+ <entry>
+ <para>Translator support UNION and UNION ALL</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Intersect</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports INTERSECT</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Except</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports Except</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>SetQueryOrderBy</para>
+ </entry>
+ <entry>
+ <para>Unions, Intersect, or Except</para>
+ </entry>
+ <entry>
+ <para>Translator supports set queries with an ORDER BY</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>RowLimit</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the limit portion of the limit clause</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>RowOffset</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator can support the offset portion of the limit clause</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>FunctionsInGroupBy</para>
+ </entry>
+ <entry>
+ <para>GroupBy</para>
+ </entry>
+ <entry>
+ <para>Not currently used - non-element expressions in the group by create an inline view.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>InsertWithQueryExpression</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports INSERT statements with values specified by an QueryExpression.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>supportsBatchedUpdates</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports a batch of INSERT, UPDATE and DELETE commands to be executed together.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>supportsBulkUpdate</para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para>Translator supports updates with multiple value sets</para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Note that any pushdown subquery must itself be compliant with the Translator capabilities.</para>
+ </sect3>
+
+ <sect3 id="command_form_capabilities">
+ <title>Command Form</title>
+ <para>The method <code>ExecutionFactory.useAnsiJoin()</code> should return true
+ if the Translator prefers the use of ANSI style join structure for
+ join trees that contain only INNER and CROSS joins.</para>
+ <para>The method <code>ExecutionFactory.requiresCriteria()</code> 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".</para>
+ </sect3>
+
+ <sect3>
+ <title>Scalar Functions</title>
+ <para>The method <code>ExecutionFactory.getSupportedFunctions()</code> can be
+ used to specify which scalar functions the Translator supports. The
+ set of possible functions is based on the set of functions supported
+ by Teiid. This set can be found in the <ulink url="&docUrl;">Reference</ulink>
+ documentation. If the Translator states that it supports a function,
+ it must support all type combinations and overloaded forms of that
+ function.</para>
+ <para>There are also five standard operators that can also be specified in the
+ supported function list: +, -, *, /, and ||.</para>
+ <para>The constants interface SourceSystemFunctions contains the string
+ names of all possible built-in pushdown functions. Note that not all
+ system functions appear in this list. This is because some system
+ functions will always be evaluted in Teiid, are simple aliases to
+ other functions, or are rewriten to a more standard expression.</para>
+ </sect3>
+
+ <sect3>
+ <title>Physical Limits</title>
+ <para>The method <code>ExecutionFactory.getMaxInCriteriaSize()</code> 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.</para>
+ <para>The method <code>ExecutionFactory.getMaxFromGroups()</code> can be used
+ to specify the maximum number of FROM Clause groups that can used in a
+ join. -1 indicates there is no limit.</para>
+ </sect3>
+
+ <sect3>
+ <title>Update Execution Modes</title>
+ <para>The method <code>ExecutionFactory.supportsBatchedUpdates()</code> can be
+ used to indicate that the Translator supports executing the <code>BatchedUpdates</code> command.
+ </para>
+ <para>The method <code>ExecutionFactory.supportsBulkUpdate()</code> can be used
+ to indicate that the Translator accepts update commands containg multi valued Literals.</para>
+ <para>Note that if the translator does not support either of these
+ update modes, the query engine will compensate by issuing the updates individually.</para>
+ </sect3>
+
+ </sect2>
+
+</sect1>
+ <sect1>
+ <title>Large Objects</title>
+ <para>This section examines how to use facilities provided by the Teiid
+ API to use large objects such as blobs, clobs, and xml in
+ your Translator.</para>
+ <sect2>
+ <title>Data Types</title>
+ <para>Teiid supports three large object runtime data types: blob,
+ clob, and xml. A blob is a “binary large object”, a clob is a
+ “character large object”, and “xml” is a “xml
+ document”. Columns modeled as a blob, clob, or xml are treated similarly by
+ the translator framework to support memory-safe streaming. </para>
+ </sect2>
+ <sect2>
+ <title>Why Use Large Object Support?</title>
+ <para>Teiid allows a Translator to return a large object through the
+ Teiid translator API by just returning a reference to the actual
+ large object. Access to that LOB will be streamed as appropriate rather
+ than retrieved all at once. This is useful for several reasons:</para>
+ <orderedlist>
+ <listitem>
+ <para>Reduces memory usage when returning the result set to the user.</para>
+ </listitem>
+ <listitem>
+ <para>Improves performance by passing less data in the result set.</para>
+ </listitem>
+ <listitem>
+ <para>Allows access to large objects when needed rather than assuming that users will
+ always use the large object data.</para>
+ </listitem>
+ <listitem>
+ <para>Allows the passing of arbitrarily large data values.</para>
+ </listitem>
+ </orderedlist>
+ <para>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.</para>
+ </sect2>
+
+ <sect2>
+ <title>Handling Large Objects</title>
+ <para>The Translator API automatically handles large objects (Blob/Clob/SQLXML) through
+ the creation of special purpose wrapper objects when it retrieves results.
+ </para>
+
+ <para>Once the wrapped object is returned, the streaming of LOB is
+ automatically supported. These LOB objects then can for example appear
+ in client results, in user defined functions, or sent to other translators.</para>
+
+ <para>A Execution is usually closed and the underlying
+ connection is either closed/released as soon as all rows for that
+ execution have been retrieved. However, LOB objects may need to be
+ read after their initial retrieval of results. When LOBs are detected
+ the default closing behavior is prevented by setting a flag on the
+ ExecutionContext. See ExecutionContext.keepAlive() method. </para>
+
+ <para>When the "keepAlive" alive flag is set, then the execution object is only closed when user's Statement is closed.</para>
+
+ <programlisting><![CDATA[executionContext.keepExecutionAlive(true);]]></programlisting>
+
+ </sect2>
+
+ <sect2>
+ <title>Inserting or Updating Large Objects</title>
+ <para>LOBs will be passed to the Translator in the
+ language objects as Literal containing a java.sql.Blob, java.sql.Clob, or
+ java.sql.SQLXML. You can use these interfaces to retrieve the data in
+ the large object and use it for insert or update.</para>
+ </sect2>
+
+ </sect1>
+
<sect1 id="translator_package">
<title>Packaging</title>
<para>Once the "ExecutionFactory" class is implemented, package it in a JAR file. The only
additional requirement is provide a file called "jboss-beans.xml" in the "META-INF" directory of the JAR file, with
following contents.
- <programlisting><![CDATA[
- <?xml version="1.0" encoding="UTF-8"?>
- <deployment xmlns="urn:jboss:bean-deployer:2.0">
-
- <bean name="translator-${name}-template" class="org.teiid.templates.TranslatorDeploymentTemplate">
- <property name="info"><inject bean="translator-${name}"/></property>
- <property name="managedObjectFactory"><inject bean="ManagedObjectFactory"/></property>
- </bean>
-
- <bean name="translator-${name}" class="org.teiid.templates.TranslatorTemplateInfo">
- <constructor factoryMethod="createTemplateInfo">
- <factory bean="TranslatorDeploymentTemplateInfoFactory"/>
- <parameter class="java.lang.Class">org.teiid.templates.TranslatorTemplateInfo</parameter>
- <parameter class="java.lang.Class">${execution-factory-class}</parameter>
- <parameter class="java.lang.String">translator-${name}</parameter>
- <parameter class="java.lang.String">${name}</parameter>
- </constructor>
- </bean>
-
- </deployment>
- ]]> </programlisting>
+ <programlisting><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="translator-${name}-template" class="org.teiid.templates.TranslatorDeploymentTemplate">
+ <property name="info"><inject bean="translator-${name}"/></property>
+ <property name="managedObjectFactory"><inject bean="ManagedObjectFactory"/></property>
+ </bean>
+
+ <bean name="translator-${name}" class="org.teiid.templates.TranslatorTemplateInfo">
+ <constructor factoryMethod="createTemplateInfo">
+ <factory bean="TranslatorDeploymentTemplateInfoFactory"/>
+ <parameter class="java.lang.Class">org.teiid.templates.TranslatorTemplateInfo</parameter>
+ <parameter class="java.lang.Class">${execution-factory-class}</parameter>
+ <parameter class="java.lang.String">translator-${name}</parameter>
+ <parameter class="java.lang.String">${name}</parameter>
+ </constructor>
+ </bean>
+
+</deployment>]]></programlisting>
replace ${name} with name of your translator, and replace ${execution-factory-class} with your
- overridden Execution Factory class name. This will create Java bean in the JBoss AS, that facilitates to interrogate
- available properties in configuration for this Translator for tooling and Admin API.</para>
+ overridden ExecutionFactory class name. This will register the Translator for use with tooling and Admin API.</para>
</sect1>
<sect1 id="translator_deploy">
<title>Deployment</title>
<para>Copy the JAR file that defines the Translator into "deploy" directory of the JBoss AS's chosen profile, and
- Translator will be deployed automatically. There is no restriction that, JBoss AS need to be restarted. However, if your Translator
+ the Translator will be deployed automatically. There is no restriction that, JBoss AS need to be restarted. However, if your Translator
has external dependencies to other JAR libraries, they need to be placed inside the "lib" directory of the JBoss AS's profile.
This will require a restart of the JBoss Server. Another option to avoid the restart is to bundle all the required JAR files into
the same JAR file as the Translator. It is user's responsibility to make sure they are not running into any conflicts with their
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/develop-adapter.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/develop-adapter.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/develop-adapter.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -3,7 +3,7 @@
%CustomDTD;
]>
<chapter id="develop_adapter">
- <title>Developing JEE JCA Adapters for Teiid Translators</title>
+ <title>Developing JEE Connectors</title>
<para>This chapter examines how to use facilities provided by the Teiid
API to develop a JEE JCA Connector that can be used with the Teiid Translator. Please note that these are
standard JEE JCA connectors, nothing special needs to be done for Teiid. As an aid to our Translator
@@ -17,9 +17,9 @@
<para>Check out the following links <ulink url="http://docs.jboss.org/jbossas/jboss4guide/r4/html/ch7.chapt.html">Connectors on JBoss</ulink> </para>
<sect1>
- <title>Develop Adapter using the Teiid Framework</title>
+ <title>Using the Teiid Framework</title>
<para>If you are going to use the Teiid framework for developing a JCA connector, follow these steps. The required classes are in
- <emphasis>org.teiid.resource.api</emphasis> package. Please note that Teiid framework does not make use JCA's CCI framework. It
+ <code>org.teiid.resource.api</code> package. Please note that Teiid framework does not make use JCA's CCI framework. It
only uses the JCA's SPI interfaces. </para>
<itemizedlist>
@@ -39,59 +39,53 @@
<sect2 id="managed_connection_factory">
<title>Define Managed Connection Factory</title>
- <para>Extend the <emphasis>BasicManagedConnectionFactory</emphasis>, and provide a implementation for the
+ <para>Extend the <code>BasicManagedConnectionFactory</code>, and provide a implementation for the
"createConnectionFactory()" method. This method defines a factory method that can create connections.</para>
<para>This class also defines configuration variables, like user, password, URL etc to connect to the EIS system. Define an
attribute for each configuration variable, and then provide both "getter" and "setter" methods for them.
Note to use only "java.lang" objects as the attributes, DO NOT use Java primitives for defining and accessing the properties.
See the following code for an example.</para>
- <programlisting><![CDATA[
- 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;
- }
- }
- ]]></programlisting>
+ <programlisting><![CDATA[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;
+ }
+}]]></programlisting>
</sect2>
<sect2>
<title>Define the Connection Factory class</title>
- <para>Extend the <emphasis>BasicConnectionFactory</emphasis> class, and provide a implementation for the "getConnection()" method.</para>
- <programlisting><![CDATA[
- public class MyConnectionFactory extends BasicConnectionFactory {
- @Override
- public MyConnection getConnection() throws ResourceException {
- return new MyConnection();
- }
- }
- ]]></programlisting>
+ <para>Extend the <code>BasicConnectionFactory</code> class, and provide a implementation for the "getConnection()" method.</para>
+ <programlisting><![CDATA[public class MyConnectionFactory extends BasicConnectionFactory {
+ @Override
+ public MyConnection getConnection() throws ResourceException {
+ return new MyConnection();
+ }
+}]]></programlisting>
<para>Since the Managed connection object created the "ConnectionFactory" class it has access to all the configuration
parameters, if "getConnection" method needs to do pass any of credentials to the underlying EIS system.
- The Connection Factory class can also get reference to the calling user's <emphasis>javax.security.auth.Subject</emphasis> during
+ The Connection Factory class can also get reference to the calling user's <code>javax.security.auth.Subject</code> during
"getConnection" method by calling
- <programlisting><![CDATA[
- Subject subject = ConnectionContext.getSubject();
- ]]></programlisting>
+ <programlisting><![CDATA[Subject subject = ConnectionContext.getSubject();]]></programlisting>
This "Subject" object can give access to logged-in user's credentials and roles that are defined. Note that this may be null.
</para>
<para>Note that you can define "security-domain" for this resource adapter, that is separate from
@@ -101,29 +95,27 @@
<sect2 id="connection">
<title>Define the Connection class</title>
- <para>Extend the <emphasis>BasicConnection</emphasis> class, and provide a implementation based on your access
+ <para>Extend the <code>BasicConnection</code> class, and provide a implementation based on your access
of the Connection object in the Translator. If your
connection is stateful, then override "isAlive()" and "cleanup()" methods and provide proper implementations. These are called
to check if a Connection is stale or need to flush them from the connection pool etc. by the Container.</para>
- <programlisting><![CDATA[
- public class MyConnection extends BasicConnection {
+ <programlisting><![CDATA[public class MyConnection extends BasicConnection {
- public void doSomeOperation(command){
- // do some operation with EIS system..
- // 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() {
-
- }
- }
- ]]></programlisting>
+ public void doSomeOperation(command){
+ // do some operation with EIS system..
+ // 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() {
+
+ }
+}]]></programlisting>
</sect2>
<sect2>
@@ -146,14 +138,12 @@
fragment inside the "ra.xml" file. These properties are used by user to configure instance of this Connector inside a
Container. Also, during the startup the Container reads these properties from this file and knows how to inject
provided values in the "-ds.xml" file into a instance of "ManagedConnectionFactory" to create the Connection.</para>
- <programlisting><![CDATA[
- <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>${optioal-property-value}</config-property-value>
- </config-property>
- ]]></programlisting>
+ <programlisting><![CDATA[<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>${optioal-property-value}</config-property-value>
+</config-property>]]></programlisting>
<para>The format and contents of "<description>" element is a Teiid extension to provide the extended metadata for tooling purpose. The
JCA specification does not define enough metadata on these properties so Teiid fills in the gap with its own extension.
@@ -206,35 +196,33 @@
<para>Maven: If you are using maven, use <packaging> element value as "rar". Teiid uses maven, you can look at any of
the "connector" projects for sample "pom.xml" file. Here is sample pom.xml file.</para>
- <programlisting><![CDATA[
- <?xml version="1.0" encoding="UTF-8"?>
- <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <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>
- </project>
- ]]></programlisting>
+ <programlisting><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <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>
+</project>]]></programlisting>
</listitem>
</itemizedlist>
<para>Make sure that the RAR file, under its "META-INF" directory has the "ra.xml" file. If you are using maven
@@ -255,24 +243,22 @@
<itemizedlist>
<listitem>
<para>Create "${name}-ds.xml" file, and copy it into "deploy" directory of JBoss AS.
- <programlisting><![CDATA[
- <!DOCTYPE connection-factories PUBLIC
- "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
- "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
-
- <connection-factories>
- <no-tx-connection-factory>
- <jndi-name>${jndi-name}</jndi-name>
- <rar-name>${name}.rar</rar-name>
- <connection-definition>javax.resource.cci.ConnectionFactory</connection-definition>
-
- <!-- define all the properties defined in the "ra.xml" that required or needs to be modified from defaults -->
- <!-- each property is defined in single element -->
- <config-property name="prop-name" type="java.lang.String">prop-value</config-property>
-
- </no-tx-connection-factory>
- </connection-factories>
- ]]></programlisting>
+ <programlisting><![CDATA[<!DOCTYPE connection-factories PUBLIC
+ "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
+ "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
+
+<connection-factories>
+ <no-tx-connection-factory>
+ <jndi-name>${jndi-name}</jndi-name>
+ <rar-name>${name}.rar</rar-name>
+ <connection-definition>javax.resource.cci.ConnectionFactory</connection-definition>
+
+ <!-- define all the properties defined in the "ra.xml" that required or needs to be modified from defaults -->
+ <!-- each property is defined in single element -->
+ <config-property name="prop-name" type="java.lang.String">prop-value</config-property>
+
+ </no-tx-connection-factory>
+</connection-factories>]]></programlisting>
There are lot more properties that you can define for pooling, transactions, security etc in this file.
Check JBoss AS documentation for all the avaialble properties.
</para>
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/extending-jdbc-connector.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -1,19 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="extendingjdbc">
- <title>Extending the JDBC Connector</title>
- <para>The JDBC Connector can be extended to handle new JDBC drivers and database versions. This chapter
- outlines the process by which a user can modify the behavior of the JDBC Connector for a new source</para>
+ <title>Extending The JDBC Translator</title>
+ <para>The JDBC Translator can be extended to handle new JDBC drivers and database versions. This is one of the most common needs of custom Translator development. This chapter
+ outlines the process by which a user can modify the behavior of the JDBC Translator for a new source, rather than starting from scratch.</para>
-
- <sect1>
- <title>Extension Interfaces</title>
- <para>To design JDBC Translator for any RDMS that are not already provided by the Teiid, extend the
- <emphasis>org.teiid.translator.jdbc.JDBCExecutionFactory</emphasis> class in the "translator-jdbc" module. There
+ <para>To design a JDBC Translator for any RDMS that is not already provided by the Teiid, extend the
+ <code>org.teiid.translator.jdbc.JDBCExecutionFactory</code> 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.</para>
<table frame='all'>
- <title>Extension methods</title>
+ <title>Extensions</title>
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname='c1' colwidth="1*"/>
<colspec colname='c2' colwidth="2*"/>
@@ -25,23 +22,23 @@
</thead>
<tbody>
<row>
- <entry><para>Translator Capabilities</para></entry>
+ <entry><para>Capabilities</para></entry>
<entry><para>Specify the SQL syntax and functions the source supports.</para></entry>
</row>
<row>
- <entry><para>SQL Translator</para></entry>
+ <entry><para>SQL Translation</para></entry>
<entry><para>Customize what SQL syntax is used, how source-specific functions are supported, how procedures are executed.</para></entry>
</row>
<row>
- <entry><para>Results Translator</para></entry>
+ <entry><para>Results Translation</para></entry>
<entry><para>Customize how results are retrieved from JDBC and translated.</para></entry>
</row>
</tbody>
</tgroup>
</table>
- <sect2>
- <title>Translator Capabilities Extension</title>
+ <sect1>
+ <title>Capabilities Extension</title>
<para>This extension must override the methods that begin with "supports" that describe translator capabilities.
For all the available translator capabilities please see <link linkend="translator_capabilities">this</link>.</para>
@@ -50,66 +47,149 @@
to execute the function and often modifying the SQL Translator to translate the function appropriately for the source.</para>
<para>Another common example is turning off unsupported SQL capabilities (such as outer joins or subqueries)
for less sophisticated JDBC sources. </para>
- </sect2>
+ </sect1>
- <sect2>
+ <sect1>
<title>SQL Translation Extension</title>
- <para>It provides ways to modify the command entering the JDBC Connector (in object form) before it is sent to the
- JDBC driver (as an SQL string).</para>
+ <para>The JDBCExcecutionFactory provides several methods to modify the command and the string form of the resulting syntax before it is sent to the
+ JDBC driver, including:</para>
- <para>Common functions that the SQLTranslator can perform are:</para>
-
- <orderedlist>
+ <itemizedlist>
<listitem>
- <para>Arbitrarily modify the object form of a command before translation </para>
+ <para>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.</para>
</listitem>
<listitem>
- <para>Register one or more “function modifiers” that define how a scalar function should be modified or transformed</para>
+ <para>Register one or more <link linkend="function_modifiers">FunctionModifiers</link> that define how a scalar function should be modified or transformed.</para>
</listitem>
<listitem>
- <para>Change the way SQL strings are formed from the object for m of a command</para>
+ <para>Modify a LanguageObject. - see the translate, translateXXX, and <link linkend="function_modifiers">FunctionModifiers</link>.translate methods. Modify the passed in object and return null to indicate that the standard syntax output should be used.</para>
</listitem>
- </orderedlist>
- <para>For more information on how these functions can be performed, see the examples later in this chapter.</para>
- </sect2>
+ <listitem>
+ <para>Change the way SQL strings are formed for a LanguageObject. - - see the translate, translateXXX, and <link linkend="function_modifiers">FunctionModifiers</link>.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.</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
- <sect2>
+ <sect1>
<title>Results Translation Extension</title>
- <para>This defines ways to modify the results
- as they are read and returned from the JDBC driver to the Teiid Server. Common functions that the
- ResultsTranslator can perform are:</para>
+ <para>The JDBCExecutionFactory provides several methods to modify the java.sql.Statement and java.sql.ResultSet interactions, including:</para>
<orderedlist>
<listitem>
- <para>Execute a stored procedure against the driver</para>
+ <para>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.</para>
</listitem>
<listitem>
- <para>Execute a prepared statement with large objects against the driver</para>
+ <para>Retrieve values from the JDBC ResultSet or CallableStatement - see the retrieveValue methods.</para>
</listitem>
+ </orderedlist>
+
+ </sect1>
+
+ <sect1>
+ <title>Adding Function Support</title>
+ <para>See <link linkend="udfs">User Defined Functions</link> for adding new functions to Teiid. This example will show you how to declare support for the function
+ and modify how the function is passed to the data source.</para>
+ <para>Following is a summary of all coding steps in supporting a new scalar function:</para>
+ <orderedlist>
<listitem>
- <para>Execute a statement for bulk insert</para>
+ <para>Override the capabilities method to declare support for the function (REQUIRED)</para>
</listitem>
<listitem>
- <para>Retrieve values from the JDBC ResultSet</para>
+ <para>Implement a FunctionModifier to change how a function is translated and register it for use (OPTIONAL)</para>
</listitem>
- <listitem>
- <para>Translate values returned from JDBC into the types expected by MetaMatrix</para>
- </listitem>
- <listitem>
- <para>Arbitrarily modify a batch of results</para>
- </listitem>
- </orderedlist>
+ </orderedlist>
+ <para>There is a capabilities method getSupportedFunctions() that declares all supported scalar functions.</para>
+ <informalexample>
+ <para>An example of an extended capabilities class to add support for the “abs” absolute value function:</para>
+ <programlisting><![CDATA[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;
+ }
+}]]></programlisting></informalexample>
+ <para>In general, it is a good idea to call super.getSupportedFunctions() to ensure that you retain any function
+ support provided by the translator you are extending.</para>
+ <para>This may be all that is needed to support a Teiid function if the JDBC data source supports the
+ same syntax as Teiid. The built-in SQL translation will translate most functions as: “function(arg1, arg2, …)”.</para>
+ <sect2 id="function_modifiers">
+ <title>Using FunctionModifiers</title>
+ <para>In some cases you may need to translate the function differently or even insert
+ additional function calls above or below the function being translated. The JDBC translator provides
+ an abstract class <code>FunctionModifier</code> for this purpose.</para>
+ <para>During the start method a modifier instance can be registered against a given function name via a call to <code>JDBCExecutionFactory.registerFunctionModifier</code>.</para>
+ <para>The FunctionModifier has a method called <code>translate</code>. Use the translate method to change the way the function is represented.</para>
+
+<informalexample>
+ <para>An example of overriding the translate method to change the MOD(a, b) function into an infix operator for Sybase (a % b). The translate method returns a list of strings and language objects that will be assembled by the translator into a final string. The strings will be used as is and the language objects will be further processed by the translator.</para>
- <para>For more information on how these functions can be performed, see the examples later in this chapter.</para>
- </sect2>
+ <programlisting><![CDATA[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;
+ }
+}]]></programlisting>
+</informalexample>
+
+ <para>In addition to building your own FunctionModifiers, there are a number of pre-built generic
+ function modifiers that are provided with the translator. </para>
+
+ <table frame='all'>
+ <title>Common Modifiers</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth=".4*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry><para>Modifier</para></entry>
+ <entry><para>Description</para></entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><para>AliasModifier</para></entry>
+ <entry><para>Handles simply renaming a function (“ucase” to “upper” for example)</para></entry>
+ </row>
+ <row>
+ <entry><para>EscapeSyntaxModifier</para></entry>
+ <entry><para>Wraps a function in the standard JDBC escape syntax for functions: {fn xxxx()}</para></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>To register the function modifiers for your supported functions,
+ you must call the <code>ExecutionFactory.registerFunctionModifier(String name, FunctionModifier modifier)</code> method.
+ <programlisting><![CDATA[public class ExtendedJDBCExecutionFactory extends JDBCExecutionFactory
+
+ @Override
+ public void start() {
+ super.start();
+
+ // register functions.
+ registerFunctionModifier("abs", new MyAbsModifier());
+ registerFunctionModifier("concat", new AliasModifier(“concat2”));
+ }
+}]]></programlisting></para>
+ <para>Support for the two functions being registered (“abs” and “concat”) must be declared
+ in the capabilities as well. Functions that do not have modifiers registered will be translated as usual.
+ </para>
+ </sect2>
</sect1>
-
+
<sect1>
- <title>Developing Extensions</title>
- <para>When developing a new JDBC Translator extension, you should start with the development environment used to develop
- any translator, as defined in the Translator Developer’s Guide.</para>
- </sect1>
-
- <sect1>
<title>Installing Extensions</title>
<para>Once you have developed an extension to the JDBC translator, you must install it into the Teiid Server.
The process of <link linkend="translator_package">packaging</link> or <link linkend="translator_deploy">deploying</link> the
@@ -118,4 +198,4 @@
for any JDBC driver.
</para>
</sect1>
-</chapter>
\ No newline at end of file
+</chapter>
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/content/introduction.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/introduction.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/introduction.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -1,13 +1,13 @@
<chapter id="introduction">
- <title>Translators and Resource Adapters in Teiid</title>
+ <title>Translators and Resource Adapters</title>
- <para>To integrate data from a Enterprise Information System (EIS) into Teiid, Teiid requires two separate modules </para>
<itemizedlist>
- <listitem>
- <para>Translator</para>
+ <para>Integrating data from a Enterprise Information System (EIS) into Teiid, is separated into two parts.</para>
+ <listitem>
+ <para>A Translator, which is required.</para>
</listitem>
<listitem>
- <para>Resource Adapter (also sometimes called as Connector or J2EE Connector or JCA Connector or RAR file) </para>
+ <para>An optional Resource Adapter, which will typically be a JCA Resource Adapter (also called a JEE Connector) </para>
</listitem>
</itemizedlist>
@@ -20,27 +20,26 @@
<para>Execute the command.</para>
</listitem>
<listitem>
- <para>Return batches of results in relational form.</para>
+ <para>Return batches of results translated to expected Teiid types.</para>
</listitem>
</itemizedlist>
- <para>A Resource Adapter is:</para>
+ <para>A Resource Adapter:</para>
<itemizedlist>
<listitem>
- <para>Handle all communications with individual enterprise information system(EIS), which can include databases, data feeds, flat files, etc.</para>
+ <para>Handles all communications with individual enterprise information system (EIS), which can include databases, data feeds, flat files, etc.</para>
</listitem>
<listitem>
- <para>This adapter can be a <ulink url="http://java.sun.com/j2ee/connector/">JEE JCA Connector</ulink> or any other custom connection provider.
- The reason Teiid uses JEE JCA is, this specification defines how one can write, package and configure access to EIS system in consistent manner.
- Also, there are various commercial/open source software vendors already provide JCA Connectors that provide
- access mechanisms to variety of back-end systems.</para>
+ <para>Can be a <ulink url="http://java.sun.com/j2ee/connector/">JCA Connector</ulink> or any other custom connection provider.
+ The reason Teiid recommends and uses JCA is this specification defines how one can write, package, and configure access to EIS system in consistent manner.
+ There are also various commercial/open source software vendors already providing JCA Connectors to access a variety of back-end systems.</para>
</listitem>
<listitem>
- <para>Helps to execute the command and fetch results from source systems for a given Translator</para>
+ <para>Abstracts Translators from many common concerns, such as connection information, resource pooling, or authentication.</para>
</listitem>
</itemizedlist>
- <para>Given a combination of a Translator + Resource Adapter, one can connect any EIS system to Teiid for their data integration needs</para>
+ <para>Given a combination of a Translator + Resource Adapter, one can connect any EIS system to Teiid for their data integration needs.</para>
<sect1>
<title>Do You Need a New Translator?</title>
@@ -66,7 +65,7 @@
</listitem>
<listitem>
<para>
- <emphasis>XML:</emphasis> Provides a procedural way to access XML content on the File system or in a Web-Service.
+ <emphasis>WS:</emphasis> Provides procedural access to XML content via Web Services.
</para>
</listitem>
<listitem>
@@ -85,18 +84,18 @@
<sect1>
<title>Do You Need a New Resource Adapter?</title>
<para>As mentioned above, for every Translator that needs to gather data from external source systems, it requires a resource adapter.
- The following resource adapters are provided by Teiid distribution to work with above Translators.
</para>
<itemizedlist>
+ <para>The following resource adapters are available to Teiid.</para>
<listitem>
<para><emphasis>Data Source:</emphasis> This is provided by the JBoss AS container. This is used by the JDBC Translator.</para>
</listitem>
<listitem>
- <para><emphasis>File:</emphasis> Provides a JEE JCA based Connector to access defined directory on the file system. This used by XML and File Translators</para>
+ <para><emphasis>File:</emphasis> Provides a JEE JCA based Connector to access defined directory on the file system. This is used by the File Translator</para>
</listitem>
<listitem>
- <para><emphasis>XML:</emphasis> Provides JEE JCA Connector to invoke Web Services using JBoss Web services stack. This is used by the XML Translator</para>
+ <para><emphasis>WS:</emphasis> Provides JEE JCA Connector to invoke Web Services using JBoss Web services stack. This is used by the WS Translator</para>
</listitem>
<listitem>
<para>
@@ -113,7 +112,7 @@
</sect1>
<sect1>
- <title>Required Items to Write a Custom Translator</title>
+ <title>Custom Translators</title>
<para>To write a translator, follow this procedure:</para>
<orderedlist numeration="arabic">
<listitem>
Deleted: trunk/documentation/developer-guide/src/main/docbook/en-US/content/jdbc-translator-examples.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/jdbc-translator-examples.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/jdbc-translator-examples.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -1,183 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="examples">
- <title>JDBC Extension Examples</title>
- <para>This chapter contains a series of examples showing how to extend the JDBC Connector for different common scenarios. </para>
- <sect1>
- <title>Adding Support for a Scalar Function</title>
- <sect2>
- <title>Overview</title>
- <para>For this example we consider how a translator might provide support for accepting
- a function supported by Teiid. See the following section for adding support for a new
- function unknown to Teiid. This example will show you how to declare support for the function
- and modify how the function is passed to the data source.</para>
- <para>Following is a summary of all the steps in supporting a new scalar function:</para>
- <orderedlist>
- <listitem>
- <para>Override the capabilities method to declare support for the function (REQUIRED)</para>
- </listitem>
- <listitem>
- <para>Implement a FunctionModifier to change how a function is translated (OPTIONAL)</para>
- </listitem>
- <listitem>
- <para>Implement a SQLTranslator extension and register the new function modifier (OPTIONAL)</para>
- </listitem>
- </orderedlist>
- <para>The capabilities class has a method getSupportedFunctions() that declares all the scalar functions that can be supported by the connector. To add support for a new function, extend an existing capabilities class (like the base JDBC class JDBCCapabilities or the provided base class in the Connector API, BasicConnectorCapabilities). </para>
- <para>Below is an example of an extended capabilities class to add support for the “abs” absolute value function:</para>
- <programlisting><![CDATA[
- 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;
- }
- }
- ]]></programlisting>
- <para>In general, it is a good idea to call super.getSupportedFunctions() to ensure that you retain any function
- support provided by the translator you are extending.</para>
- <para>This may be all that is needed to support a Teiid function if the JDBC data source supports the
- same syntax as Teiid. The built-in SQL translation will translate most functions as: “function(arg1, arg2, …)”.</para>
- </sect2>
- <sect2>
- <title>Using FunctionModifiers</title>
- <para>In some cases you may need to translate the function differently or even insert
- additional function calls above or below the function being translated. The JDBC translator provides
- an abstract class <emphasis>FunctionModifier</emphasis> can be used to register function
- translations in a SQLTranslator extension. </para>
-
- <para>The FunctionModifier has method called "translate". Generally, it is recommended
- to subclass FunctionModifier and override the method.
- Use the translate method to change the way the function is represented;
- this is typically only necessary when using a non-standard function form with special operators or
- ways of representing parameters. </para>
-
- <para>Below is an example of overriding just the translate method to translate the MOD(a, b) function into an operator form for Sybase (a % b). The translate method returns a list of strings and language objects that will be assembled by the translator into a final string. The strings will be used as is and the language objects will be further processed by the translator.</para>
-
- <programlisting><![CDATA[
-
- 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;
- }
- }
- ]]></programlisting>
-
- <para>You can also extend the <emphasis>AliasModifier</emphasis> that defines a method called "modify"
- using which you can modify in coming function from Teiid server into some thing that is source specific.</para>
-
- <para>Below is an example of using a AliasFunctionModifier to modify the incoming function. This particular
- example is from the Oracle JDBC Translator and is translating the Teiid function HOUR(ts) which takes a
- timestamp and returns the hour part into the Oracle equivalent TO_NUMBER(TO_CHAR(ts, ‘HH24’)).
- It demonstrates the use of the LanguageFactory to construct new functions and literal values.</para>
- <programlisting><![CDATA[
- /**
- * Convert the HOUR function into an equivalent Oracle function.
- * HOUR(ts) --> TO_NUMBER(TO_CHAR(ts, 'HH24'))
- */
- public class HourFunctionModifier extends AliasFunctionModifier {
-
- private LanguageFactory langFactory;
-
- public HourFunctionModifier(LanguageFactory langFactory) {
- this.langFactory = langFactory;
- }
-
- public Expression modify(Function function) {
- Expression[] args = function.getParameters();
-
- Function innerFunction = langFactory.createFunction("TO_CHAR",
- new Expression[] {
- args[0],
- langFactory.createLiteral("HH24", String.class)}, String.class);
-
- Function outerFunction = langFactory.createFunction("TO_NUMBER",
- new Expression[] { innerFunction },Integer.class);
-
- return outerFunction;
- }
- }
- ]]></programlisting>
-
- <para>In addition to building your own FunctionModifiers, there are a number of pre-built generic
- function modifiers that are provided with the translator. </para>
-
- <table frame='all'>
- <title>Connection Factories</title>
- <tgroup cols='2' align='left' colsep='1' rowsep='1'>
- <colspec colname='c1' colwidth="1*"/>
- <colspec colname='c2' colwidth=".5*"/>
- <thead>
- <row>
- <entry><para>Modifier</para></entry>
- <entry><para>Description</para></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><para>AliasModifier</para></entry>
- <entry><para>Handles simply renaming a function (“ucase” to “upper” for example)</para></entry>
- </row>
- <row>
- <entry><para>DropFunctionModifier</para></entry>
- <entry><para>Replaces a function with the function’s first argument, effectively dropping the function call if it is unnecessary – useful with unneeded type conversions</para></entry>
- </row>
- <row>
- <entry><para>EscapeSyntaxModifier</para></entry>
- <entry><para>Wraps a function in the standard JDBC escape syntax for functions: {fn xxxx()}</para></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>To register the function modifiers for your supported functions,
- you must implement call " public void registerFunctionModifier(String name, FunctionModifier modifier)" method.
- Below is an example that registers some functions.</para>
- <programlisting><![CDATA[
-
- public class ExtendedJDBCExecutionFactory extends JDBCExecutionFactory
-
- @Override
- public void start() {
- super.start();
-
- // register functions.
- registerFunctionModifier("abs", new MyAbsModifier());
- registerFunctionModifier("concat", new AliasModifier(“concat2”));
- }
- }
- ]]></programlisting>
- <para>Support for the two functions being registered (“abs” and “concat”) must be declared
- in the capabilities as well. Functions that do not have modifiers registered will be translated as usual.
- </para>
- </sect2>
- </sect1>
- <sect1>
- <title>Pushdown Scalar Functions</title>
- <para>“Pushdown” scalar functions are special in that they are functions new to Teiid that can be “pushed down”
- to the translator. Implementing support for a pushdown scalar function is identical to implementing support
- for a standard Teiid function except that the function must be declared to Teiid as such. This allows
- Teiid to properly parse and resolve queries using the pushdown function.</para>
- <para>Pushdown scalar functions are modeled as user-defined functions with a special attribute.
- They differ from normal user-defined functions in that no code is provided and the
- Teiid engine does not how to execute the function. Pushdown functions typically must be passed
- to the translator for evaluation. User-defined scalar functions have a special pushdown attribute that should be
- set to “Required” when modeling a pushdown function. </para>
- <para>For more information on modeling user-defined scalar functions, see the Reference manual.</para>
- </sect1>
-
-</chapter>
\ No newline at end of file
Deleted: trunk/documentation/developer-guide/src/main/docbook/en-US/content/lob-support.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/lob-support.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/lob-support.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -1,77 +0,0 @@
-<chapter id="lob_support">
- <title>Handling Large Objects</title>
- <para>This chapter examines how to use facilities provided by the Teiid
- API to use large objects such as blobs, clobs, and xml in
- your Translator.</para>
-
- <sect1>
- <title>Large Objects</title>
-
- <sect2>
- <title>Data Types</title>
- <para>Teiid supports three large object runtime data types: blob,
- clob, and xml. A blob is a “binary large object”, a clob is a
- “character large object”, and “xml” is a “xml
- document”. Columns modeled as a blob, clob, or xml are treated similarly by
- the translator framework to support memory-safe streaming. </para>
- </sect2>
- <sect2>
- <title>Why Use Large Object Support?</title>
- <para>Teiid allows a Translator to return a large object through the
- Teiid translator API by just returning a reference to the actual
- large object. Access to that LOB will be streamed as appropriate rather
- than retrieved all at once. This is useful for several reasons:</para>
- <orderedlist>
- <listitem>
- <para>Reduces memory usage when returning the result set to the user.</para>
- </listitem>
- <listitem>
- <para>Improves performance by passing less data in the result set.</para>
- </listitem>
- <listitem>
- <para>Allows access to large objects when needed rather than assuming that users will
- always use the large object data.</para>
- </listitem>
- <listitem>
- <para>Allows the passing of arbitrarily large data values.</para>
- </listitem>
- </orderedlist>
- <para>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.</para>
- </sect2>
- </sect1>
-
- <sect1>
- <title>Handling Large Objects</title>
- <para>The Translator API automatically handles large objects (Blob/Clob/SQLXML) through
- the creation of special purpose wrapper objects when it retrieves results.
- </para>
-
- <para>Once the wrapped object is returned, the streaming of LOB is
- automatically supported. These LOB objects then can for example appear
- in client results, in user defined functions, or sent to other translators.</para>
-
- <para>A Execution is usually closed and the underlying
- connection is either closed/released as soon as all rows for that
- execution have been retrieved. However, LOB objects may need to be
- read after their initial retrieval of results. When LOBs are detected
- the default closing behavior is prevented by setting a flag on the
- ExecutionContext. See ExecutionContext.keepAlive() method. </para>
-
- <para>When the "keepAlive" alive flag is set, then the execution object is only closed when user's Statement is closed.</para>
-
- <programlisting><![CDATA[
- executionContext.keepExecutionAlive(true);
- ]]></programlisting>
-
- </sect1>
-
- <sect1>
- <title>Inserting or Updating Large Objects</title>
- <para>LOBs will be passed to the Translator in the
- language objects as Literal containing a java.sql.Blob, java.sql.Clob, or
- java.sql.SQLXML. You can use these interfaces to retrieve the data in
- the large object and use it for insert or update.</para>
- </sect1>
-</chapter>
\ No newline at end of file
Added: trunk/documentation/developer-guide/src/main/docbook/en-US/content/udf.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/content/udf.xml (rev 0)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/content/udf.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="udfs">
+ <title>User Defined Functions</title>
+ <para>If you need to extends Teiid's scalar function library,
+ then Teiid provides a means to define custom scalar functions or
+ User Defined Functions(UDF). The following steps need to be taken in
+ creating a UDF.</para>
+ <sect1 id="define_udf">
+ <title>UDF Definition</title>
+ <para>The FunctionDefinition.xmi file provides metadata to the
+ query engine on User Defined Functions. See the Designer Documentation for more on creating a Function Definition Model.</para>
+ <itemizedlist>
+ <para>The following are used to define a UDF.</para>
+ <listitem>
+ <para>
+ <emphasis>Function Name</emphasis>
+ When you create the function name, keep these requirements in
+ mind:
+ <itemizedlist>
+ <listitem>
+ <para>You cannot use a reserved word, which includes
+ existing Teiid System function names. You cannot
+ overload existing Teiid System functions.</para>
+ </listitem>
+ <listitem>
+ <para>The function name must be unique among user-defined
+ functions 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.</para>
+ </listitem>
+ <listitem>
+ <para>The function name can only contain letters,
+ numbers, and the underscore (_). Your function name must
+ start with a letter.</para>
+ </listitem>
+ <listitem>
+ <para>The function name cannot exceed 128 characters.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Input Parameters</emphasis>
+ - defines a type specific signature list. All arguments are
+ considered
+ required.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Return Type</emphasis>
+ - the expected type of the returned scalar value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Pushdown</emphasis>
+ - 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.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>invocationClass/invocationMethod
+ </emphasis>
+ - optional properties indicating the static method to invoke when
+ the UDF is not pushed down.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Deterministic</emphasis>
+ - if the method will always return the same result for the same
+ input parameters.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>Even pushdown required functions need to be added as a UDF to allow
+ Teiid to properly parse and resolve the function. Pushdown scalar functions differ from normal user-defined functions in that no code is provided for evaluation in the engine.
+ An exception will be raised if a pushdown required function cannot be evaluated by the appropriate source.</para>
+ </sect1>
+ <sect1>
+ <title>Source Supported UDF</title>
+ <para>While Teiid provides an extensive scalar function
+ library, it contains only those functions that can be evaluated
+ within the query engine. In many circumstances, especially for
+ performance, a user defined function allows for calling a source
+ specific function.</para>
+
+ <para>For example, suppose you want to use the Oracle-specific
+ functions score and contains:
+ </para>
+ <informalexample>
+ <programlisting>SELECT score(1), ID, FREEDATA FROM Docs WHERE contains(freedata, 'nick', 1) > 0</programlisting>
+ </informalexample>
+ <para>
+ The
+ <function>score</function>
+ and
+ <function>contains</function>
+ functions are not part of built-in scalar function library. While
+ you could write your own custom scalar function to mimic their
+ behavior, it's more likely that you would want to use the actual
+ Oracle functions that are provided by Oracle when using the Oracle
+ Free Text functionality.
+ </para>
+ <para>
+ In addition to the normal steps outlined in the section to create and
+ install a function model (FunctionDefinitions.xmi), you will need to
+ extend the appropriate connector(s).
+ </para>
+ <itemizedlist>
+ <para>For example, to extend the Oracle Connector</para>
+ <listitem>
+ <para>
+ <emphasis>Required</emphasis>
+ - extend the OracleExecutionFactory and add SCORE and CONTAINS as
+ supported functions. For this example, we'll call the class
+ MyOracleExecutionFactory. Add the
+ <code>org.teiid.translator.Translator</code>
+ annotation to the class, e.g.
+ <code>@Translator(name="myoracle")</code>
+ </para>
+ </listitem>
+ <listitem>
+ <para>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 isn't needed - the default translation
+ should work.</para>
+ </listitem>
+ <listitem>
+ <para>
+ Create a new translator jar containing your custom
+ ExecutionFactory. See <link linkend="translator_package">packaging</link> and <link linkend="translator_deploy">deployment</link> instructions for using the jar.</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+ <sect1>
+ <title>Non-pushdown Support for User-Defined Functions</title>
+ <para>Non-pushdown support requires a Java function
+ that matches the metadata supplied in the FunctionDefinitions.xmi
+ file. You must create a Java method that contains the function’s
+ logic. This Java method should accept the necessary arguments, which
+ the Teiid System will pass to it at runtime, and function should
+ return the calculated or altered value.</para>
+ <sect2>
+ <title>Java Code</title>
+ <itemizedlist>
+ <para>Code Requirements</para>
+ <listitem>
+ <para>The java class containing the function method must be defined
+ public.
+ </para>
+ </listitem>
+ <listitem>
+ <para>The function method must be public and static.</para>
+ </listitem>
+ <listitem>
+ <para>
+ Number of input arguments must match the function metadata defined
+ in section
+ <link linkend="define_udf">Install user-defined functions</link>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Any exception can be thrown, but Teiid will rethrow the exception
+ as a
+ <classname>FunctionExecutionException</classname>
+ .
+ </para>
+ </listitem>
+ </itemizedlist>
+ <example>
+ <title>Sample code</title>
+ <programlisting><![CDATA[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;
+ }
+}]]></programlisting>
+ </example>
+ </sect2>
+ <sect2>
+ <title>Post Code Activities</title>
+ <orderedlist>
+ <listitem>
+ <para> After coding the functions you should compile the Java
+ code into a Java Archive (JAR) file.</para>
+ </listitem>
+ <listitem>
+ <para>The JAR should be available in the classpath of Teiid - this
+ could be the server profile lib, or the deployers/teiid.deployer
+ directory depending upon your preference.</para>
+ </listitem>
+ </orderedlist>
+ </sect2>
+ </sect1>
+ <sect1>
+ <title>Installing user-defined functions</title>
+ <para>
+ Once a user-defined function model (FunctionDefinitions.xmi) has been
+ created in in the Designer Tool, it can be added to the VDB for use
+ by Teiid.</para>
+ </sect1>
+</chapter>
\ No newline at end of file
Property changes on: trunk/documentation/developer-guide/src/main/docbook/en-US/content/udf.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/documentation/developer-guide/src/main/docbook/en-US/main.xml
===================================================================
--- trunk/documentation/developer-guide/src/main/docbook/en-US/main.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/developer-guide/src/main/docbook/en-US/main.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -32,7 +32,7 @@
<bookinfo>
<title>Teiid - Scalable Information Integration</title>
- <subtitle>Teiid Translator and Resource Adapter Developer's Guide</subtitle>
+ <subtitle>Teiid Developer's Guide</subtitle>
<releaseinfo>&versionNumber;</releaseinfo>
<productnumber>&versionNumber;</productnumber>
<issuenum>1</issuenum>
@@ -48,10 +48,8 @@
<xi:include href="content/introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/develop-adapter.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/connector-api.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="content/command-language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="content/lob-support.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/extending-jdbc-connector.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="content/jdbc-translator-examples.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="content/udf.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/logging.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/security.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/appendix-a.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/datatypes.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/datatypes.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/datatypes.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -435,10 +435,7 @@
</row>
<row>
<entry>
- yyyy-mm-dd hh:mm:ss.fffffffff
- <footnote>
- <para>fractional seconds are optional</para>
- </footnote>
+ yyyy-mm-dd hh:mm:ss.[fff...]
</entry>
<entry>TIMESTAMP</entry>
</row>
@@ -474,10 +471,6 @@
</thead>
<tbody>
<row>
- <entry>BOOLEAN</entry>
- <entry>{b 'true'} or {b 'false'}</entry>
- </row>
- <row>
<entry>DATE</entry>
<entry>{d 'yyyy-mm-dd'}</entry>
</row>
@@ -488,18 +481,9 @@
<row>
<entry>TIMESTAMP</entry>
<entry>
- {ts 'yyyy-mm-dd hh:mm:ss.fffffffff'}
- <footnote>
- <para>fractional seconds are optional</para>
- </footnote>
+ {ts 'yyyy-mm-dd hh:mm:ss.[fff...]'}
</entry>
</row>
- <row>
- <entry>XML</entry>
- <entry>
- {x 'well-formed doc'}
- </entry>
- </row>
</tbody>
</tgroup>
</table>
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -7,9 +7,7 @@
<link linkend="sql_support">SQL Support</link>
and
<link linkend="datatypes">Datatypes</link>
- . In addition, Teiid provides the capability for
- <link linkend="udfs">user defined functions or UDFs</link>
- .
+ . In addition, Teiid provides the capability for user defined functions or UDFs. See the Developers Guide for adding UDFs. Once added UDFs may be called just like any other function.
</para>
<sect1 id="numeric_functions">
<title>Numeric Functions</title>
@@ -767,7 +765,7 @@
</entry>
<entry>
<para>Provide the character for ASCII value x
- <footnote label="1" id="nonAscii"><para>Non-ASCII range characters or integers used in these functions
+ <footnote id="nonAscii"><para>Non-ASCII range characters or integers used in these functions
may produce different results or exceptions depending on where the function is evalutated (Teiid vs. source).
Teiid's uses Java default int to char and char to int conversions, which operates over UTF16 values.</para></footnote>
</para>
@@ -803,6 +801,27 @@
</row>
<row>
<entry>
+ <para>ENCODE(x, encoding)</para>
+ </entry>
+ <entry>
+ <para>Return a clob from the blob with the given encoding. The builtin Java Charset<footnote id="charset"><para>See the <ulink url="http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/Charset.html">Charset JavaDoc</ulink></para></footnote> names are valid values for encoding.</para>
+ </entry>
+ <entry>
+ <para>x is a blob, encoding is a string, and returns a clob</para>
+ </entry>
+ </row><row>
+ <entry>
+ <para>DECODE(x, encoding)</para>
+ </entry>
+ <entry>
+ <para>Return a blob from the clob with the given encoding. The builtin Java Charset<footnoteref linkend="charset"/> names are valid values for encoding.</para>
+ </entry>
+ <entry>
+ <para>x in a clob, encoding is a string, and returns a blob</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
<para>INITCAP(x)</para>
</entry>
<entry>
@@ -920,7 +939,7 @@
</row>
<row>
<entry>
- <para>(7.0+) QUERYSTRING(path [, expr [AS name] ...])</para>
+ <para>QUERYSTRING(path [, expr [AS name] ...])</para>
</entry>
<entry>
<para>Returns a properly encoded query string appended to the given path. Null valued expressions are omitted, and a null path is treated as ''.</para>
@@ -1783,8 +1802,7 @@
<itemizedlist>
<listitem>
<para>The keyColumn is expected to contain unique key
- values. If the column contains duplicate values, an exception will be thrown. The
- lookup caches can be flushed via the svcmgr.</para>
+ values. If the column contains duplicate values, an exception will be thrown.</para>
</listitem>
<listitem>
<para>Cached lookup tables might consume significant memory. You
@@ -1831,23 +1849,6 @@
</tbody>
</tgroup>
</informaltable>
- <sect2>
- <!-- TODO: move to administrative section -->
- <title>Clearing the Cache</title>
- <para>You can force a cache clearing by using the expert mode of
- the svcmgr command, found under the \bin directory of your
- Teiid server installation.</para>
- <para>Launch the appropriate command:</para>
- <orderedlist>
- <listitem>
- <para><command>svcmgr.cmd</command> (Windows)</para>
- </listitem>
- <listitem>
- <para><command>svcmgr.sh</command> (Solaris or Linux)</para>
- </listitem>
- </orderedlist>
- <para>From the command line enter ClearCodeTableCaches.</para>
- </sect2>
</sect1>
<sect1>
<title>System Functions</title>
@@ -1927,420 +1928,113 @@
<sect1 id="xml_functions">
<title>XML Functions</title>
<para>XML functions provide functionality for working with XML data. </para>
- <informaltable frame="all">
- <tgroup cols="3">
- <thead>
- <row>
- <entry>
- <para>Function</para>
- </entry>
- <entry>
- <para>Definition</para>
- </entry>
- <entry>
- <para>Datatype Constraint</para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para><code>XPATHVALUE(doc, xpath)</code></para>
- </entry>
- <entry>
- <para>Applies the XPATH query to the document and returns a
- string value for the first matching result. An attempt is made to provide a
- meaningful result for non-text nodes.</para>
- </entry>
- <entry>
- <para>Doc in {string, clob, xml} and xpath. Return value is a string.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para><code>(7.0+) XSLTRANSFORM(doc, xsl)</code></para>
- </entry>
- <entry>
- <para>Applies an xsl stylesheet to the given document. If either argument is null, the result is null.</para>
- </entry>
- <entry>
- <para>Doc, xsl in {string, clob, xml}. Return value is a clob.
- </para>
- </entry>
- </row>
- <row id="xmlquery">
- <entry>
- <para><code>(7.0+) XMLQUERY([<NSP>] xquery [<PASSING>] [(NULL|EMPTY) ON EMPTY]]</code></para>
- <para>PASSING:=<code>PASSING exp [AS name] [, exp [AS name]]*</code></para>
- </entry>
- <entry>
- <para>Returns the XML result from evaluating the given xquery.</para>
- <para>See XMLELEMENT for the definition of NSP - <link linkend="xmlnamespaces">XMLNAMESPACES</link>.</para><para>Namespaces may also be directly declared in the xquery prolog.</para>
- <para id="passing">The optional PASSING clause is used to provide the context item, which does not have a name, and named global variable values.
- If the xquery uses a context item and none is provided, then an exception will be raised.
- Only one context item may be specified and should be an XML type. All non-context non-XML passing values will be converted to an appropriate XML type.</para>
- <para>The ON EMPTY clause is used to specify the result when the evaluted sequence is empty.
- EMPTY ON EMPTY, the default, returns an empty XML result. NULL ON EMPTY returns a null result.</para>
- <para>See also <link linkend="xmltable">XMLTABLE</link></para>
- <note><para>A technique known as document projection is used to reduce the memory footprint of the context item document. Only the parts of the document needed by the xquery will be loaded into memory.</para></note>
- </entry>
- <entry>
- <para>xquery in string. Return value is xml.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para><code>XMLELEMENT([NAME] name [, <NSP>] [, <ATTR>][, exp]*)</code></para>
- <para>ATTR:=<code>XMLATTRIBUTES(exp [AS name] [, exp [AS name]]*)</code></para>
- <para>NSP:=<code>XMLNAMESPACES((uri AS prefix | DEFAULT uri | NO DEFAULT))+</code></para>
- </entry>
- <entry>
- <para>Returns an XML element with the given name and content. If the content value is of a type other than xml,
- it will be escaped when added to the parent element. Null content values are ignored.
- Whitespace in XML or the string values of the content is preserved, but no whitespace is added between content values.</para>
- <para id="xmlnamespaces">XMLNAMESPACES is used provide namespace information. NO DEFAULT is equivalent to defining the default namespace to the null uri - xmlns="".
- Only one DEFAULT or NO DEFAULT namespace item may be specified. The namespace prefixes xmlns and xml are reserved.</para>
- <para>If a attribute name is not supplied, the expression must be a column reference, in which case the attribute name will be the column name. Null attribute values are ignored.</para>
- <para>Example: with an xml_value of <doc/>, <code>xmlelement('elem', 1, '<2/>', xml_value)</code>
- Returns: <code><elem>1&lt;2/&gt;<doc/><elem/></code>
- </para>
- </entry>
- <entry>
- <para>Name, prefix are identifiers. uri is a string literal. exp can be any type. Return value is xml.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para><code>XMLCONCAT(xml [, other]*)</code></para>
- </entry>
- <entry>
- <para>Returns an XML with the concatination of the given xml types. If a value is null, it will be ignored.
- </para>
- </entry>
- <entry>
- <para>Name is an identifier. Content can be any type. Return value is xml.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para><code>XMLFOREST(exp [AS name] [, <NSP>] [, exp [AS name]]*)</code></para>
- </entry>
- <entry>
- <para>Returns an concatination of an XML element for each non-null expression exp. If a name is not supplied, the expression must be a column reference, in which case the element name will be the column name.
- </para>
- <para>See XMLELEMENT for the definition of NSP - <link linkend="xmlnamespaces">XMLNAMESPACES</link>.</para>
- </entry>
- <entry>
- <para>Name is an identifier. Exp can be any type. Return value is xml.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para><code>XMLCOMMENT(comment)</code></para>
- </entry>
- <entry>
- <para>Returns an xml comment.
- </para>
- </entry>
- <entry>
- <para>Comment is a string. Return value is xml.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para><code>XMLPI([NAME] name [, content])</code></para>
- </entry>
- <entry>
- <para>Returns an xml processing instruction.
- </para>
- </entry>
- <entry>
- <para>Name is an identifier. Content is a string. Return value is xml.
- </para>
- </entry>
- </row>
- <row>
- <entry id="xmlserialize">
- <para><code>XMLSERIALIZE([(DOCUMENT|CONTENT)] exp [AS datatype])</code></para>
- </entry>
- <entry>
- <para>Returns a character type representation of the exp expression.
- Only a character type (string, varchar, clob) may be specified as the datatype. CONTENT is the default.
+ <sect2>
+ <title>XMLCOMMENT</title>
+ <para>Returns an xml comment.</para>
+ <para><synopsis>XMLCOMMENT(comment)</synopsis></para>
+ <para>Comment is a string. Return value is xml.</para>
+ </sect2>
+ <sect2>
+ <title>XMLCONCAT</title>
+ <para>Returns an XML with the concatination of the given xml types.</para>
+ <para><synopsis>XMLCONCAT(content [, content]*)</synopsis></para>
+ <para>Content is xml. Return value is xml.</para>
+ <para>If a value is null, it will be ignored. If all values are null, null is returned.</para>
+ </sect2>
+ <sect2>
+ <title>XMLELEMENT</title>
+ <para>Returns an XML element with the given name and content.</para>
+ <para><synopsis>XMLELEMENT([NAME] name [, <NSP>] [, <ATTR>][, content]*)</synopsis></para>
+ <para><synopsis>ATTR:=XMLATTRIBUTES(exp [AS name] [, exp [AS name]]*)</synopsis></para>
+ <para><synopsis>NSP:=XMLNAMESPACES((uri AS prefix | DEFAULT uri | NO DEFAULT))+</synopsis></para>
+ <para>If the content value is of a type other than xml, it will be escaped when added to the parent element. Null content values are ignored.
+ Whitespace in XML or the string values of the content is preserved, but no whitespace is added between content values.</para>
+ <para id="xmlnamespaces">XMLNAMESPACES is used provide namespace information. NO DEFAULT is equivalent to defining the default namespace to the null uri - xmlns="".
+ Only one DEFAULT or NO DEFAULT namespace item may be specified. The namespace prefixes xmlns and xml are reserved.</para>
+ <para>If a attribute name is not supplied, the expression must be a column reference, in which case the attribute name will be the column name. Null attribute values are ignored.</para>
+ <para>Name, prefix are identifiers. uri is a string literal. content can be any type. Return value is xml. The return value is valid for use in places where a document is expected.</para>
+ <para><emphasis>Example</emphasis>: with an xml_value of <doc/>, <programlisting>xmlelement('elem', 1, '<2/>', xml_value)</programlisting>
+ Returns: <code><elem>1&lt;2/&gt;<doc/><elem/></code>
+ </para>
+ </sect2>
+ <sect2>
+ <title>XMLFOREST</title>
+ <para>Returns an concatination of XML elements for each content item.</para>
+ <para><synopsis>XMLFOREST(content [AS name] [, <NSP>] [, content [AS name]]*)</synopsis></para>
+ <para>See XMLELEMENT for the definition of NSP - <link linkend="xmlnamespaces">XMLNAMESPACES</link>.</para>
+ <para>Name is an identifier. Content can be any type. Return value is xml.</para>
+ <para>If a name is not supplied for a content item, the expression must be a column reference, in which case the element name will be a partially escaped version of the column name.</para>
+ </sect2>
+ <sect2 id="xmlparse">
+ <title>XMLPARSE</title>
+ <para>Returns an XML type representation of the string value expression.</para>
+ <para><synopsis>XMLPARSE((DOCUMENT|CONTENT) expr [WELLFORMED])</synopsis></para>
+ <para>expr in {string, clob, blob}. Return value is xml.</para>
+ <para>If DOCIMENT is specfied then the expression must have a single
+ root element and may or may not contain an XML declaration.</para>
+ <para>
+ If WELLFORMED is specified then validation is skipped; this is especially useful for CLOB and BLOB known to already be valid.
+ </para>
+ </sect2>
+ <sect2>
+ <title>XMLPI</title>
+ <para>Returns an xml processing instruction.</para>
+ <para><synopsis>XMLPI([NAME] name [, content])</synopsis></para>
+ <para>Name is an identifier. Content is a string. Return value is xml.</para>
+ </sect2>
+ <sect2 id="xmlquery">
+ <title>XMLQUERY</title>
+ <para>Returns the XML result from evaluating the given xquery.</para>
+ <para><synopsis>XMLQUERY([<NSP>] xquery [<PASSING>] [(NULL|EMPTY) ON EMPTY]]</synopsis></para>
+ <para><synopsis>PASSING:=PASSING exp [AS name] [, exp [AS name]]*</synopsis></para>
+ <para>See XMLELEMENT for the definition of NSP - <link linkend="xmlnamespaces">XMLNAMESPACES</link>.</para><para>Namespaces may also be directly declared in the xquery prolog.</para>
+ <para id="passing">The optional PASSING clause is used to provide the context item, which does not have a name, and named global variable values.
+ If the xquery uses a context item and none is provided, then an exception will be raised.
+ Only one context item may be specified and should be an XML type. All non-context non-XML passing values will be converted to an appropriate XML type.</para>
+ <para>The ON EMPTY clause is used to specify the result when the evaluted sequence is empty.
+ EMPTY ON EMPTY, the default, returns an empty XML result. NULL ON EMPTY returns a null result.</para>
+ <para>xquery in string. Return value is xml.</para>
+ <para>XMLQUERY is part of the SQL/XML 2006 specification.</para>
+ <para>See also <link linkend="xmltable">XMLTABLE</link></para>
+ <note><para>A technique known as document projection is used to reduce the memory footprint of the context item document. Only the parts of the document needed by the xquery will be loaded into memory.</para></note>
+
+ </sect2>
+ <sect2 id="xmlserialize">
+ <title>XMLSERIALIZE</title>
+ <para>Returns a character type representation of the xml expression.</para>
+ <para><synopsis>XMLSERIALIZE([(DOCUMENT|CONTENT)] xml [AS datatype])</synopsis></para>
+ <para>Return value mathces datatype.</para>
+ <para>Only a character type (string, varchar, clob) may be specified as the datatype. CONTENT is the default.
If DOCUMENT is specified and the xml is not a valid document or fragment, then an exception is raised.
</para>
- </entry>
- <entry>
- <para>Exp is xml. Return value mathces datatype.
- </para>
- </entry>
- </row>
- <row>
- <entry id="xmlparse">
- <para><code>XMLPARSE((DOCUMENT|CONTENT) exp [WELLFORMED])</code></para>
- </entry>
- <entry>
- <para>Returns an XML type representation of the exp expression. If DOCIMENT is specfied then the expression must have a single
- root element and may or may not contain an XML declaration.</para>
- <para>
- If WELLFORMED is specified then validation is skipped; this is especially useful for CLOB and BLOB known to already be valid.
- </para>
- </entry>
- <entry>
- <para>Exp in {string, clob, blob}. Return value is xml.
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
+ </sect2>
+ <sect2>
+ <title>XSLTRANSFORM</title>
+ <para>Applies an XSL stylesheet to the given document.</para>
+ <para><synopsis>XSLTRANSFORM(doc, xsl)</synopsis></para>
+ <para>Doc, xsl in {string, clob, xml}. Return value is a clob.</para>
+ <para>If either argument is null, the result is null.</para>
+ </sect2>
+ <sect2>
+ <title>XPATHVALUE</title>
+ <para>Applies the XPATH expression to the document and returns a
+ string value for the first matching result.</para>
+ <para><synopsis>XPATHVALUE(doc, xpath)</synopsis></para>
+ <para>Doc and xpath in {string, clob, xml}. Return value is a string.</para>
+ <para>An attempt is made to provide a meaningful result for non-text nodes.</para>
+ </sect2>
</sect1>
<sect1>
<title>Security Functions</title>
<para>Security functions provide the ability to interact
with the security system.</para>
- <informaltable frame="all">
- <tgroup cols="3">
- <thead>
- <row>
- <entry>
- <para>Function</para>
- </entry>
- <entry>
- <para>Definition</para>
- </entry>
- <entry>
- <para>Datatype Constraint</para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para><code>hasRole(roleName)</code>
- </para>
- </entry>
- <entry>
- <para>Whether the current caller has the role
- roleName.</para>
- </entry>
- <entry>
- <para>roleName must be a string, the return
- type is Boolean.</para>
- </entry>
- </row>
- <row>
- <entry>
- <para><code>hasRole(roleType, roleName)</code>
- </para>
- </entry>
- <entry>
- <para>Whether the current caller has the role
- roleName of roleType. See the 1 argument version above.</para>
- </entry>
- <entry>
- <para>roleType must be 'data' and roleName must be a string, the return
- type is Boolean.</para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect1>
- <sect1 id="udfs">
- <title>User Defined Functions</title>
- <para>If you need to extends Teiid's scalar function library,
- then Teiid provides a means to define custom scalar functions or
- User Defined Functions(UDF). The following steps need to be taken in
- creating a UDF.</para>
- <sect2 id="define_udf">
- <title>UDF Definition</title>
- <para>The FunctionDefinition.xmi file provides metadata to the
- query engine on User Defined Functions. See our product document on
- "Creating User-defined Functions" for a more extensive reference on
- creating that file through the Designer Tool.</para>
- <itemizedlist>
- <para>The following are used to define a UDF.</para>
- <listitem>
- <para>
- <emphasis>Function Name</emphasis>
- When you create the function name, keep these requirements in
- mind:
- <itemizedlist>
- <listitem>
- <para>You cannot use a reserved word, which includes
- existing Teiid System function names. You cannot
- overload existing Teiid System functions.</para>
- </listitem>
- <listitem>
- <para>The function name must be unique among user-defined
- functions 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.</para>
- </listitem>
- <listitem>
- <para>The function name can only contain letters,
- numbers, and the underscore (_). Your function name must
- start with a letter.</para>
- </listitem>
- <listitem>
- <para>The function name cannot exceed 128 characters.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Input Parameters</emphasis>
- - defines a type specific signature list. All arguments are considered
- required.</para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Return Type</emphasis> - the expected type of the returned scalar value.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Pushdown</emphasis>
- - 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.</para>
- </listitem>
- <listitem>
- <para>
- <emphasis>invocationClass/invocationMethod
- </emphasis>
- - optional properties indicating the static method to invoke when
- the UDF is not pushed down.
- </para>
- </listitem>
- <listitem>
- <para><emphasis>Deterministic</emphasis> - if the method will always return the same result for the same input parameters.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
<sect2>
- <title>Source Supported UDF</title>
- <para>While Teiid provides an extensive scalar function
- library, it contains only those functions that can be evaluated
- within the query engine. In many circumstances, especially for
- performance, a user defined function allows for calling a source
- specific function.</para>
- <para>For example, suppose you want to use the Oracle-specific functions score and contains:
- </para>
- <informalexample>
- <programlisting>SELECT score(1), ID, FREEDATA FROM Docs WHERE contains(freedata, 'nick', 1) > 0</programlisting>
- </informalexample>
- <para>
- The
- <function>score</function>
- and
- <function>contains</function>
- functions are not part of built-in scalar function library. While
- you could write your own custom scalar function to mimic their
- behavior, it's more likely that you would want to use the actual
- Oracle functions that are provided by Oracle when using the Oracle
- Free Text functionality.</para>
- <para>
- In addition to the normal steps outlined in the section to create and install a function model (FunctionDefinitions.xmi), you will need to extend the appropriate connector(s).
- </para>
- <itemizedlist>
- <para>For example, to extend the Oracle Connector</para>
- <listitem>
- <para><emphasis>Required</emphasis> - extend OracleCapabilities and set up SCORE and CONTAINS as supported functions (this lets Teiid know that the connector can accept these functions).</para>
- </listitem>
- <listitem>
- <para>Optionally extend the OracleSQLTranslator to insert new FunctionModifiers to handle translation of these functions. Given that the syntax of these functions is same as other typical functions, this probably isn't needed - the default translation should work.</para>
- </listitem>
- <listitem>
- <para>Create a new connector - The easiest way is to copy JDBC connector rar file from the distribution and modify the "ra.xml" file. Change the capabilities class (to use the extended version) and possibly the translation class (if that was extended for b. Also, include a new jar of your changes above in the same rar file. Rename the RAR file to different name to differentiate from original JDBC rar file.</para>
- </listitem>
- </itemizedlist>
+ <title>HASROLE</title>
+ <para>Whether the current caller has the role roleName.</para>
+ <para><synopsis>hasRole([roleType,] roleName)</synopsis></para>
+ <para>roleName must be a string, the return type is boolean.</para>
+ <para>The two argument form is provided for backwards compatibility. roleType is a string and must be 'data'</para>
</sect2>
- <sect2>
- <title>Non-pushdown Support for User-Defined Functions</title>
- <para>Non-pushdown support requires a Java function
- that matches the metadata supplied in the FunctionDefinitions.xmi
- file. You must create a Java method that contains the function’s
- logic. This Java method should accept the necessary arguments, which
- the Teiid System will pass to it at runtime, and function should
- return the calculated or altered value.</para>
- <sect3>
- <title>Java Code</title>
- <itemizedlist>
- <para>Code Requirements</para>
- <listitem>
- <para>The java class containing the function method must be defined public.
- </para>
- </listitem>
- <listitem>
- <para>The function method must be public and static.</para>
- </listitem>
- <listitem>
- <para>
- Number of input arguments must match the function metadata defined in section
- <link linkend="define_udf">Install user-defined functions</link>
- </para>
- </listitem>
- <listitem>
- <para>Any exception can be thrown, but Teiid will rethrow the exception as a <classname>FunctionExecutionException</classname>.</para>
- </listitem>
- </itemizedlist>
- <example>
- <title>Sample code</title>
- <programlisting><![CDATA[package userdefinedfunctions;
-
-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;
- }
-}]]></programlisting>
- </example>
- </sect3>
- <sect3>
- <title>Post Code Activities</title>
- <orderedlist>
- <listitem>
- <para> After coding the functions you should compile the Java
- code into a Java Archive (JAR) file, so that you can add it to
- the Teiid System as an Extension Module.</para>
- </listitem>
- <listitem>
- <para> After adding the jar file as an extension module, the
- name of jar file need to be added to user defined functions
- classpath using Console tool.</para>
- </listitem>
- </orderedlist>
- </sect3>
- </sect2>
- <sect2>
- <title>Installing user-defined functions</title>
- <para>
- Once a user-defined function model (FunctionDefinitions.xmi) has been
- created in in the Designer Tool, it should be installed by replacing
- the existing version under the Extension Modules (for the Enterprise
- product this will be done through the Console). That will allow the
- query engine to know about and use functions</para>
- </sect2>
</sect1>
<sect1 id="nondeterministic_functions">
<title>Nondeterministic Function Handling</title>
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -724,7 +724,7 @@
</note>
<sect3 id="nested_table">
<title>Nested Table Reference</title>
- <para>(7.0+) Nested tables may appear in the FROM clause with the TABLE
+ <para>Nested tables may appear in the FROM clause with the TABLE
keyword. They are an alternative to using a view with normal join
semantics. The columns projected from the command contained in the nested table
may be used just as any of the other FROM clause projected columns in join criteria, the where clause, etc.
@@ -748,7 +748,7 @@
</sect3>
<sect3 id="texttable">
<title>TEXTTABLE</title>
- <para>(7.0+) The TEXTTABLE funciton processes character input to produce tabular ouptut. It supports both fixed and delimited file format parsing.
+ <para>The TEXTTABLE funciton processes character input to produce tabular ouptut. It supports both fixed and delimited file format parsing.
The function itself defines what columns it projects.
The TEXTTABLE function is implicitly a nested table and may be correlated to preceeding FROM clause entries.
</para>
@@ -826,7 +826,7 @@
</sect3>
<sect3 id="xmltable">
<title>XMLTABLE</title>
- <para>(7.0+) The XMLTABLE funciton uses XQuery to produce tabular ouptut.
+ <para>The XMLTABLE funciton uses XQuery to produce tabular ouptut.
The XMLTABLE function is implicitly a nested table and may be correlated to preceeding FROM clause entries. XMLTABLE is part of the SQL/XML 2006 specification.
</para>
<para>
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml 2010-06-16 19:02:47 UTC (rev 2237)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml 2010-06-17 13:44:55 UTC (rev 2238)
@@ -266,12 +266,12 @@
</row>
<row>
<entry>widenUnsignedTypes</entry>
-<entry>(7.0+) true to convert unsigned types to the next widest type. For example SQL Server reports tinyint as an unsigned type. With this option enabled, tinyint would be imported as a short instead of a byte.</entry>
+<entry>true to convert unsigned types to the next widest type. For example SQL Server reports tinyint as an unsigned type. With this option enabled, tinyint would be imported as a short instead of a byte.</entry>
<entry>true</entry>
</row>
<row>
<entry>quoteNameInSource</entry>
-<entry>(7.0+) false will override the default and direct Teiid to create source queries using unquoted identifiers.</entry>
+<entry>false will override the default and direct Teiid to create source queries using unquoted identifiers.</entry>
<entry>true</entry>
</row>
</tbody>
14 years, 7 months