teiid SVN: r2761 - in trunk: documentation/reference/src/main/docbook/en-US/content and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-06 21:13:52 -0500 (Mon, 06 Dec 2010)
New Revision: 2761
Modified:
trunk/build/kits/jboss-container/teiid-releasenotes.html
trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml
trunk/documentation/reference/src/main/docbook/en-US/content/updatable_views.xml
Log:
TEIID-1351 adding documentation for the new update procedures
Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-12-06 18:06:30 UTC (rev 2760)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-12-07 02:13:52 UTC (rev 2761)
@@ -27,7 +27,11 @@
<H2><A NAME="Highlights"></A>Highlights</H2>
<UL>
<LI><B>Subquery Optimization</B> - added rewrite to INNER JOIN for applicable WHERE clause subqueries. Also added cost based SEMI and ANTI-SEMI join handling for applicable non-pushed WHERE and HAVING subqueries.
- <LI><B>Updatable Views</B> - added support to perform simple pass-through and more complicated updates through views by default.
+ <LI><B>Updatable Views</B>
+ <UL>
+ <LI>Added support to perform simple pass-through and more complicated updates through views by default.
+ <LI>Added support for "FOR EACH ROW" update procedure handling (similar to INSTEAD OF triggers in other DBMS's), which should be used instead of the deprecated TRANSLATE criteria approach.
+ </UL>
<LI><B>UDF</B> - new API objects added to teiid-api to support user defined functions that are capable of pushdown to source.
</UL>
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml 2010-12-06 18:06:30 UTC (rev 2760)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml 2010-12-07 02:13:52 UTC (rev 2761)
@@ -420,200 +420,6 @@
through result sets, use loops, and use conditional logic.
</para>
<section>
- <title>Update Procedure Definition</title>
- <para>
- Usage:
- <synopsis label="Usage" >CREATE PROCEDURE
-BEGIN
- ...
-END</synopsis>
- </para>
- <para>The CREATE PROCEDURE line demarcates the beginning of
- the procedure. The BEGIN and END keywords are used to denote block
- boundaries. Within the body of the procedure, any valid <link linkend="procedure_language">statement</link> may be used.
- </para>
- </section>
- <section>
- <title>Special Variables</title>
- <para>You can use a number of special variables when defining your update procedure.</para>
- <section id="input_variables">
- <title>INPUT Variables</title>
- <para>Every attribute in the view whose UPDATE and INSERT transformations you are defining has an equivalent variable named INPUTS.<column_name></para>
- <para>When an INSERT or an UPDATE command is executed against the view, these variables are initialized to the values in the INSERT VALUES clause or the UPDATE SET clause respectively.</para>
- <para>In an UPDATE procedure, the default value of these variables, if they are not set by the command, is null. In an INSERT procedure, the default value of these variables is the default value of the virtual table attributes, based on their defined types. See <link linkend="changing_variables">CHANGING Variables</link> for distinguishing defaults from passed values.</para>
- <warning>
- <para>In prior release of Teiid INPUT was also accepted as the quailifer for an input variable. As of Teidd 7, INPUT is a reserved word, so INPUTS is the preferred qualifier.</para>
- </warning>
- </section>
- <section id="changing_variables">
- <title>CHANGING Variables</title>
- <para>Similar to INPUT Variables, every attribute in the view whose UPDATE and INSERT transformations you are defining has an equivalent variable named CHANGING.<column_name></para>
- <para>When an INSERT or an UPDATE command is executed against the view, these variables are initialized to <literal>true</literal> or <literal>false</literal> depending on whether the INPUT variable was set by the command.</para>
- <para>For example, for a view with columns A, B, C:</para>
- <informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>If User Executes...</entry>
- <entry>Then...</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><code>INSERT INTO VT (A, B) VALUES (0, 1)</code></entry>
- <entry>CHANGING.A = true, CHANGING.B = true, CHANGING.C = false</entry>
- </row>
- <row>
- <entry><code>UPDATE VT SET C = 2</code></entry>
- <entry>CHANGING.A = false, CHANGING.B = false, CHANGING.C = true</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </section>
- <section id="rowsupdated_variable">
- <title>ROWS_UPDATED Variable</title>
- <para> Teiid returns the value of the integer VARIABLES.ROWS_UPDATED variable as a response to an update command executed against
- the view. Your procedure must set the value that returns
- when an application executes an update command against the view,
- which triggers invocation of the update procedure. For
- example, if an UPDATE command is issued that affects 5 records, the
- ROWS_UPDATED should be set appropriately so that the user will
- receive '5' for the count of records affected.</para>
- <example>
- <title>Sample Usage</title>
- <programlisting language="SQL"><![CDATA[...
-UPDATE FOO SET X = 1 WHERE TRANSLATE CRITERIA;
-VARIABLES.ROWS_UPDATED = VARIABLES.ROWCOUNT;
-...]]></programlisting>
- </example>
- </section>
- </section>
- <section>
- <title>Update Procedure Command Criteria</title>
- <para> You can use a number of special SQL clauses when defining
- UPDATE or DELETE procedures. These make it easier to do variable
- substitutions in WHERE clauses or to check on the change state of
- variables without using a lot of conditional logic.</para>
- <section>
- <title>HAS CRITERIA</title>
- <para>You can use the HAS CRITERIA clause to check whether the user’s command has a particular kind of criteria on a particular set of attributes. This clause evaluates to either true or false. You can use it anywhere you can use a criteria within a procedure.</para>
- <para>
- Usage:
- <synopsis>HAS [criteria operator] CRITERIA [ON (column list)]</synopsis>
- </para>
- <itemizedlist>
- <para>Syntax Rules</para>
- <listitem>
- <para>The criteria operator, can be one of =, <, >, <=, >=, <>, LIKE, IS NULL, or IN.
- </para>
- </listitem>
- <listitem>
- <para>If the ON clause is present, HAS CRITERIA will return true only if criteria was present on all of the specified columns.
- </para>
- </listitem>
- <listitem>
- <para>The columns in a HAS CRITERIA ON clause always refer to view columns.
- </para>
- </listitem>
- </itemizedlist>
- <para>Some samples of the HAS CRITERIA clause:</para>
- <informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>SQL</entry>
- <entry>Result</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><code>HAS CRITERIA</code></entry>
- <entry>Checks simply whether there was any criteria at all.</entry>
- </row>
- <row>
- <entry><code>HAS CRITERIA ON (column1, column2)</code></entry>
- <entry>Checks whether the criteria uses column1 and column2.</entry>
- </row>
- <row>
- <entry><code>HAS = CRITERIA ON (column1)</code></entry>
- <entry>Checks whether the criteria has a comparison criteria with = operator.</entry>
- </row>
- <row>
- <entry><code>HAS LIKE CRITERIA</code></entry>
- <entry>Checks whether the criteria has a match criteria using LIKE.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- <para>The HAS CRITERIA predicate is most commonly used in
- an IF clause, to determine if the user issued a particular form of
- command and to respond appropriately.</para>
- </section>
- <section>
- <title>TRANSLATE CRITERIA</title>
- <warning><para>TRANSLATE CRITERIA has been deprecated. An alternative approach to update procedures will be introduced in a subsequent version.</para></warning>
- <para>You can use the TRANSLATE CRITERIA clause to convert the criteria from the user application’s SQL command into the form required to interact with the target source or view tables. The TRANSLATE CRITERIA statement uses the SELECT transformation to infer the column mapping. This clause evaluates to a translated criteria that is evaluated in the context of a command.
- You can use these mappings either to replace the default mappings generated from the SELECT transformation or to specify a reverse expression when a virtual column is defined by an expression.</para>
- <para>
- Usage:
- <synopsis>TRANSLATE [criteria operator] CRITERIA [ON (column list)] [WITH (mapping list)]</synopsis>
- </para>
- <para>If there is no user criteria, then the translated criteria is always treated as TRUE.</para>
- <itemizedlist>
- <para>Syntax Rules</para>
- <listitem>
- <para>The criteria operator, can be one of =, <, >, <=, >=, <>, LIKE, IS NULL, or IN.
- </para>
- </listitem>
- <listitem>
- <para>If the ON clause is present, TRANSLATE CRITERIA will only form criteria using the specified columns.
- </para>
- </listitem>
- <listitem>
- <para>The columns in a TRANSLATE CRITERIA ON clause always refer to view columns.
- </para>
- </listitem>
- <listitem>
- <para>The WITH clause always has items with form <elem> = <expression> where the left hand side must refer to a view column.
- </para>
- </listitem>
- <listitem>
- <para>If the WITH clause or a specific mapping is not specified, then a mapping is created based on the SELECT clause of the SELECT transformation (the view column gets mapped to expression in SELECT clause at same position).
- </para>
- </listitem>
- </itemizedlist>
- <para>Some samples of TRANSLATE CRITERIA:</para>
- <informaltable>
- <tgroup cols="2">
- <colspec colwidth="1*"/>
- <colspec colwidth="1*"/>
- <thead>
- <row>
- <entry>SQL</entry>
- <entry>Result</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><code>TRANSLATE CRITERIA</code></entry>
- <entry>Translates any user criteria using the default mappings.</entry>
- </row>
- <row>
- <entry>TRANSLATE CRITERIA WITH (column1 = 'A', column2 = INPUTS.column2 + 2)</entry>
- <entry>Translates any criteria with some additional mappings: column1 is always mapped to 'A' and column2 is mapped to the incoming column2 value + 2.</entry>
- </row>
- <row>
- <entry><code>TRANSLATE = CRITERIA ON (column1)</code></entry>
- <entry>Translates only criteria that have = comparison operator and involve column1.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- <note><para>If a specific predicate type or column set is specified by TRANSALATE CRITERIA, but the user criteria has predicates that do not match, then an exception will be thrown.</para></note>
- </section>
- </section>
- <section>
<title>Update Procedure Processing</title>
<orderedlist>
<listitem>
@@ -633,7 +439,7 @@
</para>
</listitem>
<listitem>
- <para>Commands, as described in the procedure, as issued to the individual physical data sources or other views.
+ <para>Commands, as described in the procedure, are issued to the individual physical data sources or other views.
</para>
</listitem>
<listitem>
@@ -642,5 +448,287 @@
</listitem>
</orderedlist>
</section>
+ <section>
+ <title>For Each Row</title>
+ <para>A FOR EACH ROW procedure will evaluate its block for each row of the view affected by the update statement.
+ For UPDATE and DELETE statements this will be every row that passes the WHERE condition. For INSERT statements there will be 1 new row for each set of values from the VALUES or query expression.
+ The rows updated is reported as this number regardless of the affect of the underlying procedure logic.</para>
+ <section>
+ <title>Definition</title>
+ <para>
+ Usage:
+ <synopsis label="Usage" >FOR EACH ROW
+ BEGIN
+ ...
+ END</synopsis>
+ </para>
+ <para>The BEGIN and END keywords are used to denote block
+ boundaries. Within the body of the procedure, any valid <link linkend="procedure_language">statement</link> may be used.
+ </para>
+ </section>
+ <section>
+ <title>Special Variables</title>
+ <para>You can use a number of special variables when defining your update procedure.</para>
+ <section id="new_variables">
+ <title>NEW Variables</title>
+ <para>Every attribute in the view whose UPDATE and INSERT transformations you are defining has an equivalent variable named NEW.<column_name></para>
+ <para>When an INSERT or an UPDATE command is executed against the view, these variables are initialized to the values in the INSERT VALUES clause or the UPDATE SET clause respectively.</para>
+ <para>In an UPDATE procedure, the default value of these variables, if they are not set by the command, is the old value. In an INSERT procedure, the default value of these variables is the default value of the virtual table attributes. See CHANGING Variables for distinguishing defaults from passed values.</para>
+ </section>
+ <section id="old_variables">
+ <title>OLD Variables</title>
+ <para>Every attribute in the view whose UPDATE and DELETE transformations you are defining has an equivalent variable named OLD.<column_name></para>
+ <para>When a DELETE or UPDATE command is executed against the view, these variables are initialized to the current values of the row being deleted or updated respectively.</para>
+ </section>
+ <section id="changing_variables">
+ <title>CHANGING Variables</title>
+ <para>Every attribute in the view whose UPDATE and INSERT transformations you are defining has an equivalent variable named CHANGING.<column_name></para>
+ <para>When an INSERT or an UPDATE command is executed against the view, these variables are initialized to <literal>true</literal> or <literal>false</literal> depending on whether the INPUT variable was set by the command.
+ A CHANGING variable is commonly used to differentiate between a default insert value and one specified in the user query.</para>
+ <para>For example, for a view with columns A, B, C:</para>
+ <informaltable>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>If User Executes...</entry>
+ <entry>Then...</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><code>INSERT INTO VT (A, B) VALUES (0, 1)</code></entry>
+ <entry>CHANGING.A = true, CHANGING.B = true, CHANGING.C = false</entry>
+ </row>
+ <row>
+ <entry><code>UPDATE VT SET C = 2</code></entry>
+ <entry>CHANGING.A = false, CHANGING.B = false, CHANGING.C = true</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </section>
+ </section>
+ <section>
+ <title>Examples</title>
+ <para>For example, for a view with columns A, B, C:</para>
+ <example>
+ <title>Sample DELETE Procedure</title>
+ <programlisting language="SQL"><![CDATA[FOR EACH ROW
+BEGIN
+ DELETE FROM X WHERE Y = OLD.A;
+ DELETE FROM Z WHERE Y = OLD.A; // cascade the delete
+END]]></programlisting>
+ </example>
+ <example>
+ <title>Sample UPDATE Procedure</title>
+ <programlisting language="SQL"><![CDATA[FOR EACH ROW
+BEGIN
+ IF (CHANGING.B)
+ BEGIN
+ UPDATE Z SET Y = NEW.B WHERE Y = OLD.B;
+ END
+END]]></programlisting>
+ </example>
+ </section>
+ </section>
+ <section>
+ <title>Create Procedure</title>
+ <para>Update procedures defined by "CREATE PROCEDURE ..." have been deprecated.
+ The TRANSLATE CRITERIA mechanism and associated logic is typically not adequite to correctly define an updatable view.</para>
+ <section>
+ <title>Definition</title>
+ <para>
+ Usage:
+ <synopsis label="Usage" >CREATE PROCEDURE
+ BEGIN
+ ...
+ END</synopsis>
+ </para>
+ <para>The CREATE PROCEDURE line demarcates the beginning of
+ the procedure. The BEGIN and END keywords are used to denote block
+ boundaries. Within the body of the procedure, any valid <link linkend="procedure_language">statement</link> may be used.
+ </para>
+ </section>
+ <section>
+ <title>Special Variables</title>
+ <para>You can use a number of special variables when defining your update procedure.</para>
+ <section id="input_variables">
+ <title>INPUT Variables</title>
+ <para>Every attribute in the view whose UPDATE and INSERT transformations you are defining has an equivalent variable named INPUTS.<column_name></para>
+ <para>When an INSERT or an UPDATE command is executed against the view, these variables are initialized to the values in the INSERT VALUES clause or the UPDATE SET clause respectively.</para>
+ <para>In an UPDATE procedure, the default value of these variables, if they are not set by the command, is null. In an INSERT procedure, the default value of these variables is the default value of the virtual table attributes, based on their defined types. See CHANGING Variables for distinguishing defaults from passed values.</para>
+ <warning>
+ <para>In prior release of Teiid INPUT was also accepted as the quailifer for an input variable. As of Teidd 7, INPUT is a reserved word, so INPUTS is the preferred qualifier.</para>
+ </warning>
+ </section>
+ <section>
+ <title>CHANGING Variables</title>
+ <para>Similar to INPUT Variables, every attribute in the view whose UPDATE and INSERT transformations you are defining has an equivalent variable named CHANGING.<column_name></para>
+ <para>When an INSERT or an UPDATE command is executed against the view, these variables are initialized to <literal>true</literal> or <literal>false</literal> depending on whether the INPUT variable was set by the command.</para>
+ <para>For example, for a view with columns A, B, C:</para>
+ <informaltable>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>If User Executes...</entry>
+ <entry>Then...</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><code>INSERT INTO VT (A, B) VALUES (0, 1)</code></entry>
+ <entry>CHANGING.A = true, CHANGING.B = true, CHANGING.C = false</entry>
+ </row>
+ <row>
+ <entry><code>UPDATE VT SET C = 2</code></entry>
+ <entry>CHANGING.A = false, CHANGING.B = false, CHANGING.C = true</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </section>
+ <section id="rowsupdated_variable">
+ <title>ROWS_UPDATED Variable</title>
+ <para> Teiid returns the value of the integer VARIABLES.ROWS_UPDATED variable as a response to an update command executed against
+ the view. Your procedure must set the value that returns
+ when an application executes an update command against the view,
+ which triggers invocation of the update procedure. For
+ example, if an UPDATE command is issued that affects 5 records, the
+ ROWS_UPDATED should be set appropriately so that the user will
+ receive '5' for the count of records affected.</para>
+ <example>
+ <title>Sample Usage</title>
+ <programlisting language="SQL"><![CDATA[...
+ UPDATE FOO SET X = 1 WHERE TRANSLATE CRITERIA;
+ VARIABLES.ROWS_UPDATED = VARIABLES.ROWCOUNT;
+ ...]]></programlisting>
+ </example>
+ </section>
+ </section>
+ <section>
+ <title>Update Procedure Command Criteria</title>
+ <para> You can use a number of special SQL clauses when defining
+ UPDATE or DELETE procedures. These make it easier to do variable
+ substitutions in WHERE clauses or to check on the change state of
+ variables without using a lot of conditional logic.</para>
+ <section>
+ <title>HAS CRITERIA</title>
+ <para>You can use the HAS CRITERIA clause to check whether the user’s command has a particular kind of criteria on a particular set of attributes. This clause evaluates to either true or false. You can use it anywhere you can use a criteria within a procedure.</para>
+ <para>
+ Usage:
+ <synopsis>HAS [criteria operator] CRITERIA [ON (column list)]</synopsis>
+ </para>
+ <itemizedlist>
+ <para>Syntax Rules</para>
+ <listitem>
+ <para>The criteria operator, can be one of =, <, >, <=, >=, <>, LIKE, IS NULL, or IN.
+ </para>
+ </listitem>
+ <listitem>
+ <para>If the ON clause is present, HAS CRITERIA will return true only if criteria was present on all of the specified columns.
+ </para>
+ </listitem>
+ <listitem>
+ <para>The columns in a HAS CRITERIA ON clause always refer to view columns.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>Some samples of the HAS CRITERIA clause:</para>
+ <informaltable>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>SQL</entry>
+ <entry>Result</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><code>HAS CRITERIA</code></entry>
+ <entry>Checks simply whether there was any criteria at all.</entry>
+ </row>
+ <row>
+ <entry><code>HAS CRITERIA ON (column1, column2)</code></entry>
+ <entry>Checks whether the criteria uses column1 and column2.</entry>
+ </row>
+ <row>
+ <entry><code>HAS = CRITERIA ON (column1)</code></entry>
+ <entry>Checks whether the criteria has a comparison criteria with = operator.</entry>
+ </row>
+ <row>
+ <entry><code>HAS LIKE CRITERIA</code></entry>
+ <entry>Checks whether the criteria has a match criteria using LIKE.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>The HAS CRITERIA predicate is most commonly used in
+ an IF clause, to determine if the user issued a particular form of
+ command and to respond appropriately.</para>
+ </section>
+ <section>
+ <title>TRANSLATE CRITERIA</title>
+ <warning><para>TRANSLATE CRITERIA. An alternative approach to update procedures will be introduced in a subsequent version.</para></warning>
+ <para>You can use the TRANSLATE CRITERIA clause to convert the criteria from the user application’s SQL command into the form required to interact with the target source or view tables. The TRANSLATE CRITERIA statement uses the SELECT transformation to infer the column mapping. This clause evaluates to a translated criteria that is evaluated in the context of a command.
+ You can use these mappings either to replace the default mappings generated from the SELECT transformation or to specify a reverse expression when a virtual column is defined by an expression.</para>
+ <para>
+ Usage:
+ <synopsis>TRANSLATE [criteria operator] CRITERIA [ON (column list)] [WITH (mapping list)]</synopsis>
+ </para>
+ <para>If there is no user criteria, then the translated criteria is always treated as TRUE.</para>
+ <itemizedlist>
+ <para>Syntax Rules</para>
+ <listitem>
+ <para>The criteria operator, can be one of =, <, >, <=, >=, <>, LIKE, IS NULL, or IN.
+ </para>
+ </listitem>
+ <listitem>
+ <para>If the ON clause is present, TRANSLATE CRITERIA will only form criteria using the specified columns.
+ </para>
+ </listitem>
+ <listitem>
+ <para>The columns in a TRANSLATE CRITERIA ON clause always refer to view columns.
+ </para>
+ </listitem>
+ <listitem>
+ <para>The WITH clause always has items with form <elem> = <expression> where the left hand side must refer to a view column.
+ </para>
+ </listitem>
+ <listitem>
+ <para>If the WITH clause or a specific mapping is not specified, then a mapping is created based on the SELECT clause of the SELECT transformation (the view column gets mapped to expression in SELECT clause at same position).
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>Some samples of TRANSLATE CRITERIA:</para>
+ <informaltable>
+ <tgroup cols="2">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>SQL</entry>
+ <entry>Result</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><code>TRANSLATE CRITERIA</code></entry>
+ <entry>Translates any user criteria using the default mappings.</entry>
+ </row>
+ <row>
+ <entry>TRANSLATE CRITERIA WITH (column1 = 'A', column2 = INPUTS.column2 + 2)</entry>
+ <entry>Translates any criteria with some additional mappings: column1 is always mapped to 'A' and column2 is mapped to the incoming column2 value + 2.</entry>
+ </row>
+ <row>
+ <entry><code>TRANSLATE = CRITERIA ON (column1)</code></entry>
+ <entry>Translates only criteria that have = comparison operator and involve column1.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <note><para>If a specific predicate type or column set is specified by TRANSALATE CRITERIA, but the user criteria has predicates that do not match, then an exception will be thrown.</para></note>
+ </section>
+ </section>
+ </section>
</section>
</chapter>
\ No newline at end of file
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/updatable_views.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/updatable_views.xml 2010-12-06 18:06:30 UTC (rev 2760)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/updatable_views.xml 2010-12-07 02:13:52 UTC (rev 2761)
@@ -13,7 +13,7 @@
<itemizedlist>
<listitem>
- <para>A set operation (INTERSECT, EXCEPT, UNION, UNION ALL)</para>
+ <para>A set operation (INTERSECT, EXCEPT, UNION).</para>
</listitem>
<listitem>
<para>SELECT DISTINCT</para>
@@ -26,6 +26,9 @@
</listitem>
</itemizedlist>
+ <para>A UNION ALL can define an inherently updatable view only if each of the UNION branches is itself inherently updatable.
+ A view defined by a UNION ALL though does not support inherent INSERTs.</para>
+
<para>Any view column that is not mapped directly to a column is not updatable and cannot be targeted by an UPDATE set
clause or be an INSERT column.</para>
14 years
teiid SVN: r2760 - in trunk/engine/src: main/java/org/teiid/query/processor/proc and 5 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-06 13:06:30 -0500 (Mon, 06 Dec 2010)
New Revision: 2760
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java
trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/DeleteResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
Log:
TEIID-1267 adding support for compensating updates/deletes with non-pushdown logic as a procedure
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -79,6 +79,7 @@
import org.teiid.query.sql.lang.CacheHint;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.lang.Delete;
import org.teiid.query.sql.lang.From;
import org.teiid.query.sql.lang.FromClause;
import org.teiid.query.sql.lang.GroupBy;
@@ -97,7 +98,9 @@
import org.teiid.query.sql.lang.SubqueryContainer;
import org.teiid.query.sql.lang.SubqueryFromClause;
import org.teiid.query.sql.lang.TableFunctionReference;
+import org.teiid.query.sql.lang.TranslatableProcedureContainer;
import org.teiid.query.sql.lang.UnaryFromClause;
+import org.teiid.query.sql.lang.Update;
import org.teiid.query.sql.lang.WithQueryCommand;
import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
import org.teiid.query.sql.proc.CreateUpdateProcedureCommand;
@@ -586,9 +589,21 @@
//skip the rewrite here, we'll do that in the optimizer
//so that we know what the determinism level is.
addNestedCommand(sourceNode, container.getGroup(), container, c, false);
- } else if (!(container instanceof Insert) && !container.getGroup().isTempGroupSymbol() &&
+ } else if (container instanceof TranslatableProcedureContainer && !container.getGroup().isTempGroupSymbol() &&
!CriteriaCapabilityValidatorVisitor.canPushLanguageObject(container, metadata.getModelID(container.getGroup().getMetadataID()), metadata, capFinder, analysisRecord)) {
- throw new QueryPlannerException(QueryPlugin.Util.getString("RelationalPlanner.nonpushdown_command", container)); //$NON-NLS-1$
+ if (metadata.getUniqueKeysInGroup(container.getGroup().getMetadataID()).isEmpty()
+ || !CapabilitiesUtil.supports(Capability.CRITERIA_COMPARE_EQ, metadata.getModelID(container.getGroup().getMetadataID()), metadata, capFinder)) {
+ throw new QueryPlannerException(QueryPlugin.Util.getString("RelationalPlanner.nonpushdown_command", container)); //$NON-NLS-1$
+ }
+
+ //treat this as an update procedure
+ if (container instanceof Update) {
+ c = QueryRewriter.createUpdateProcedure((Update)container, metadata, context);
+ } else {
+ c = QueryRewriter.createDeleteProcedure((Delete)container, metadata, context);
+ }
+ addNestedCommand(sourceNode, container.getGroup(), container, c, false);
+ return false;
}
//plan any subqueries in criteria/parameters/values
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -156,5 +156,10 @@
this.queryProcessor = null;
this.tupleSource = null;
}
+
+ @Override
+ public boolean requiresTransaction(boolean transactionalReads) {
+ return true;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -300,11 +300,13 @@
}
public static void resolveSubqueries(Command command,
- TempMetadataAdapter metadata, AnalysisRecord analysis)
+ TempMetadataAdapter metadata, AnalysisRecord analysis, Collection<GroupSymbol> externalGroups)
throws QueryResolverException, TeiidComponentException {
for (SubqueryContainer container : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(command)) {
QueryResolver.setChildMetadata(container.getCommand(), command);
-
+ if (externalGroups != null) {
+ container.getCommand().pushNewResolvingContext(externalGroups);
+ }
QueryResolver.resolveCommand(container.getCommand(), Collections.EMPTY_MAP, metadata.getMetadata(), analysis);
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/DeleteResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/DeleteResolver.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/DeleteResolver.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -58,8 +58,8 @@
Set<GroupSymbol> groups = new HashSet<GroupSymbol>();
groups.add(delete.getGroup());
+ QueryResolver.resolveSubqueries(command, metadata, analysis, groups);
ResolverVisitor.resolveLanguageObject(delete, groups, delete.getExternalGroupContexts(), metadata);
- QueryResolver.resolveSubqueries(command, metadata, analysis);
}
/**
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -75,7 +75,7 @@
Insert insert = (Insert) command;
if (insert.getValues() != null) {
- QueryResolver.resolveSubqueries(command, metadata, analysis);
+ QueryResolver.resolveSubqueries(command, metadata, analysis, null);
//variables and values must be resolved separately to account for implicitly defined temp groups
resolveList(insert.getValues(), metadata, insert.getExternalGroupContexts(), null);
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -103,6 +103,8 @@
break;
}
}
+ } else if (!metadata.isVirtualGroup(virtualGroup.getMetadataID())) {
+ return;
}
// If still haven't found virtual group, the external metadata is bad
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -73,8 +73,8 @@
for (SetClause clause : update.getChangeList().getClauses()) {
ResolverVisitor.resolveLanguageObject(clause.getSymbol(), groups, null, metadata);
}
+ QueryResolver.resolveSubqueries(command, metadata, analysis, groups);
ResolverVisitor.resolveLanguageObject(update, groups, update.getExternalGroupContexts(), metadata);
- QueryResolver.resolveSubqueries(command, metadata, analysis);
}
/**
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -2560,12 +2560,12 @@
if (!info.getUnionBranches().isEmpty()) {
List<Command> batchedUpdates = new ArrayList<Command>(info.getUnionBranches().size() + 1);
for (UpdateInfo branchInfo : info.getUnionBranches()) {
- batchedUpdates.add(createInherentUpdateProc((Update)update.clone(), branchInfo));
+ batchedUpdates.add(rewriteInherentUpdate((Update)update.clone(), branchInfo));
}
- batchedUpdates.add(0, createInherentUpdateProc(update, info));
+ batchedUpdates.add(0, rewriteInherentUpdate(update, info));
return new BatchedUpdateCommand(batchedUpdates);
}
- return createInherentUpdateProc(update, info);
+ return rewriteInherentUpdate(update, info);
}
if (commandType == Command.TYPE_UPDATE && variables != null) {
@@ -2594,7 +2594,7 @@
return update;
}
- private Command createInherentUpdateProc(Update update, UpdateInfo info)
+ private Command rewriteInherentUpdate(Update update, UpdateInfo info)
throws QueryValidatorException, QueryMetadataException,
TeiidComponentException, QueryResolverException,
TeiidProcessingException {
@@ -2621,6 +2621,24 @@
query.setOrderBy(null);
SymbolMap expressionMapping = SymbolMap.createSymbolMap(update.getGroup(), query.getProjectedSymbols(), metadata);
+ ArrayList<SingleElementSymbol> selectSymbols = mapChangeList(update, symbolMap);
+ query.setSelect(new Select(selectSymbols));
+ ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
+ PostOrderNavigator.doVisit(query.getSelect(), emv);
+
+ Criteria crit = update.getCriteria();
+ if (crit != null) {
+ PostOrderNavigator.doVisit(crit, emv);
+ query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
+ }
+ GroupSymbol group = mapping.getGroup();
+ String correlationName = mapping.getCorrelatedName().getName();
+
+ return createUpdateProcedure(update, query, group, correlationName);
+ }
+
+ private ArrayList<SingleElementSymbol> mapChangeList(Update update,
+ Map<ElementSymbol, ElementSymbol> symbolMap) {
ArrayList<SingleElementSymbol> selectSymbols = new ArrayList<SingleElementSymbol>(update.getChangeList().getClauses().size());
int i = 0;
for (SetClause clause : update.getChangeList().getClauses()) {
@@ -2635,29 +2653,30 @@
selectSymbols.add(new AliasSymbol("s_" +i, selectSymbol)); //$NON-NLS-1$
ex = new ElementSymbol("s_" +i); //$NON-NLS-1$
}
- clause.setSymbol(symbolMap.get(clause.getSymbol()));
+ if (symbolMap != null) {
+ clause.setSymbol(symbolMap.get(clause.getSymbol()));
+ }
i++;
}
- query.setSelect(new Select(selectSymbols));
- ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
- PostOrderNavigator.doVisit(query.getSelect(), emv);
-
- Criteria crit = update.getCriteria();
- if (crit != null) {
- PostOrderNavigator.doVisit(crit, emv);
- query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
- }
-
+ return selectSymbols;
+ }
+
+ private Command createUpdateProcedure(Update update, Query query,
+ GroupSymbol group, String correlationName)
+ throws TeiidComponentException, QueryMetadataException,
+ QueryResolverException, TeiidProcessingException {
Update newUpdate = new Update();
newUpdate.setChangeList(update.getChangeList());
- newUpdate.setGroup(mapping.getGroup().clone());
-
- List<Criteria> pkCriteria = createPkCriteria(mapping, query, i);
- newUpdate.setCriteria(Criteria.combineCriteria(newUpdate.getCriteria(), new CompoundCriteria(pkCriteria)));
- return createUpdateProcedure(update, query, newUpdate);
+ newUpdate.setGroup(group.clone());
+ List<Criteria> pkCriteria = createPkCriteria(group, correlationName, query);
+ newUpdate.setCriteria(new CompoundCriteria(pkCriteria));
+ return asLoopProcedure(update.getGroup(), query, newUpdate);
}
- private Command createUpdateProcedure(ProcedureContainer update, Query query,
+ /**
+ * rewrite as loop on (query) as X begin newupdate; rows_updated = rows_updated + 1;
+ */
+ private Command asLoopProcedure(GroupSymbol group, Query query,
ProcedureContainer newUpdate) throws QueryResolverException,
TeiidComponentException, TeiidProcessingException {
Block b = new Block();
@@ -2672,23 +2691,23 @@
as.setExpression(new Function("+", new Expression[] {rowsUpdate, new Constant(1)})); //$NON-NLS-1$
b.addStatement(as);
cupc.setBlock(parent);
- cupc.setVirtualGroup(update.getGroup());
+ cupc.setVirtualGroup(group);
QueryResolver.resolveCommand(cupc, metadata);
return rewrite(cupc, metadata, context);
}
- private List<Criteria> createPkCriteria(UpdateMapping mapping, Query query,
- int i) throws TeiidComponentException, QueryMetadataException {
- Object pk = metadata.getPrimaryKey(mapping.getGroup().getMetadataID());
+ private List<Criteria> createPkCriteria(GroupSymbol group, String correlationName, Query query) throws TeiidComponentException, QueryMetadataException {
+ Object pk = metadata.getPrimaryKey(group.getMetadataID());
if (pk == null) {
- pk = metadata.getUniqueKeysInGroup(mapping.getGroup().getMetadataID()).iterator().next();
+ pk = metadata.getUniqueKeysInGroup(group.getMetadataID()).iterator().next();
}
+ int i = query.getSelect().getSymbols().size();
List<Object> ids = metadata.getElementIDsInKey(pk);
List<Criteria> pkCriteria = new ArrayList<Criteria>(ids.size());
for (Object object : ids) {
- ElementSymbol es = new ElementSymbol(mapping.getCorrelatedName().getName() + ElementSymbol.SEPARATOR + SingleElementSymbol.getShortName(metadata.getFullName(object)));
+ ElementSymbol es = new ElementSymbol(correlationName + ElementSymbol.SEPARATOR + SingleElementSymbol.getShortName(metadata.getFullName(object)));
query.getSelect().addSymbol(new AliasSymbol("s_" +i, es)); //$NON-NLS-1$
- es = new ElementSymbol(mapping.getGroup().getName() + ElementSymbol.SEPARATOR + SingleElementSymbol.getShortName(metadata.getFullName(object)));
+ es = new ElementSymbol(group.getName() + ElementSymbol.SEPARATOR + SingleElementSymbol.getShortName(metadata.getFullName(object)));
pkCriteria.add(new CompareCriteria(es, CompareCriteria.EQ, new ElementSymbol("X.s_" + i))); //$NON-NLS-1$
i++;
}
@@ -2733,12 +2752,12 @@
if (!info.getUnionBranches().isEmpty()) {
List<Command> batchedUpdates = new ArrayList<Command>(info.getUnionBranches().size() + 1);
for (UpdateInfo branchInfo : info.getUnionBranches()) {
- batchedUpdates.add(createInherentDeleteProc((Delete)delete.clone(), branchInfo));
+ batchedUpdates.add(rewriteInherentDelete((Delete)delete.clone(), branchInfo));
}
- batchedUpdates.add(0, createInherentDeleteProc(delete, info));
+ batchedUpdates.add(0, rewriteInherentDelete(delete, info));
return new BatchedUpdateCommand(batchedUpdates);
}
- return createInherentDeleteProc(delete, info);
+ return rewriteInherentDelete(delete, info);
}
// Rewrite criteria
Criteria crit = delete.getCriteria();
@@ -2749,7 +2768,7 @@
return delete;
}
- private Command createInherentDeleteProc(Delete delete, UpdateInfo info)
+ private Command rewriteInherentDelete(Delete delete, UpdateInfo info)
throws QueryMetadataException, TeiidComponentException,
QueryResolverException, TeiidProcessingException {
UpdateMapping mapping = info.getDeleteTarget();
@@ -2770,20 +2789,41 @@
query.setSelect(new Select());
ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
- PostOrderNavigator.doVisit(query.getSelect(), emv);
Criteria crit = delete.getCriteria();
if (crit != null) {
PostOrderNavigator.doVisit(crit, emv);
query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
}
-
+ GroupSymbol group = mapping.getGroup();
+ String correlationName = mapping.getCorrelatedName().getName();
+ return createDeleteProcedure(delete, query, group, correlationName);
+ }
+
+ public static Command createDeleteProcedure(Delete delete, QueryMetadataInterface metadata, CommandContext context) throws QueryResolverException, QueryMetadataException, TeiidComponentException, TeiidProcessingException {
+ QueryRewriter rewriter = new QueryRewriter(metadata, context, null);
+ Criteria crit = delete.getCriteria();
+ Query query = new Query(new Select(), new From(Arrays.asList(new UnaryFromClause(delete.getGroup()))), crit, null, null);
+ return rewriter.createDeleteProcedure(delete, query, delete.getGroup(), delete.getGroup().getName());
+ }
+
+ public static Command createUpdateProcedure(Update update, QueryMetadataInterface metadata, CommandContext context) throws QueryResolverException, QueryMetadataException, TeiidComponentException, TeiidProcessingException {
+ QueryRewriter rewriter = new QueryRewriter(metadata, context, null);
+ Criteria crit = update.getCriteria();
+ ArrayList<SingleElementSymbol> selectSymbols = rewriter.mapChangeList(update, null);
+ Query query = new Query(new Select(selectSymbols), new From(Arrays.asList(new UnaryFromClause(update.getGroup()))), crit, null, null);
+ return rewriter.createUpdateProcedure(update, query, update.getGroup(), update.getGroup().getName());
+ }
+
+ private Command createDeleteProcedure(Delete delete, Query query,
+ GroupSymbol group, String correlationName)
+ throws TeiidComponentException, QueryMetadataException,
+ QueryResolverException, TeiidProcessingException {
Delete newUpdate = new Delete();
- newUpdate.setGroup(mapping.getGroup().clone());
-
- List<Criteria> pkCriteria = createPkCriteria(mapping, query, 0);
- newUpdate.setCriteria(Criteria.combineCriteria(newUpdate.getCriteria(), new CompoundCriteria(pkCriteria)));
- return createUpdateProcedure(delete, query, newUpdate);
+ newUpdate.setGroup(group.clone());
+ List<Criteria> pkCriteria = createPkCriteria(group, correlationName, query);
+ newUpdate.setCriteria(new CompoundCriteria(pkCriteria));
+ return asLoopProcedure(delete.getGroup(), query, newUpdate);
}
private Limit rewriteLimitClause(Limit limit) throws TeiidComponentException, TeiidProcessingException{
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-06 18:06:30 UTC (rev 2760)
@@ -886,6 +886,6 @@
failed_to_unwrap_connection=Failed to unwrap the source connection.
connection_factory_not_found=Failed to the Connection Factory with JNDI name {0}. Please check the name for spelling or deploy the Connection Factory with specified name.
-RelationalPlanner.nonpushdown_command=Source command "{0}" contains non-pushdown constructs.
+RelationalPlanner.nonpushdown_command=Source UPDATE or DELETE command "{0}" contains non-pushdown constructs and no compensating action can be taken as the table lacks a unique key or the source does not support equality predicates .
Translate.error=Cannot translate criteria "{0}", it is not matched by selector "{1}"
\ No newline at end of file
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2010-12-06 16:56:22 UTC (rev 2759)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2010-12-06 18:06:30 UTC (rev 2760)
@@ -7596,5 +7596,35 @@
helpProcess(plan, dataManager, expected);
}
+ @Test public void testDeleteCompensation() {
+ String sql = "delete from pm1.g1 where e1 = 'a' and e2 in (select e2 from pm1.g2)"; //$NON-NLS-1$
+
+ List[] expected = new List[] {
+ Arrays.asList(3),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(sql, FakeMetadataFactory.example4(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Test public void testUpdateCompensation() {
+ String sql = "update pm1.g1 set e4 = null where e1 = 'a' and exists (select 1 from pm1.g2 where e2 = pm1.g1.e2)"; //$NON-NLS-1$
+
+ List[] expected = new List[] {
+ Arrays.asList(3),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(sql, FakeMetadataFactory.example4(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
private static final boolean DEBUG = false;
}
14 years
teiid SVN: r2759 - in trunk: documentation/caching-guide/src/main/docbook/en-US/content and 6 other directories.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-12-06 11:56:22 -0500 (Mon, 06 Dec 2010)
New Revision: 2759
Modified:
trunk/build/kits/jboss-container/teiid-releasenotes.html
trunk/documentation/caching-guide/src/main/docbook/en-US/content/hint-option.xml
trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/CacheHint.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java
trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java
Log:
TEIID-1253: Adding cache scope to the Cache Hint. The added scopes are "session|user|vdb". If the scope hint is provided, it will override the computed scope from query.
Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-12-06 16:56:22 UTC (rev 2759)
@@ -28,7 +28,7 @@
<UL>
<LI><B>Subquery Optimization</B> - added rewrite to INNER JOIN for applicable WHERE clause subqueries. Also added cost based SEMI and ANTI-SEMI join handling for applicable non-pushed WHERE and HAVING subqueries.
<LI><B>Updatable Views</B> - added support to perform simple pass-through and more complicated updates through views by default.
- <LI><B>UDF</B> - new API objects added to teiid-api to support user defined functions that are capable of pushdown to source.
+ <LI><B>UDF</B> - new API objects added to teiid-api to support user defined functions that are capable of pushdown to source.
</UL>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
@@ -49,6 +49,7 @@
<li>By default the "ENV" system function is now turned off. To enable it, edit the teiid-jboss-beans.xml configuration file.
<li>The use of VARIABLES.ROWCOUNT is now reserved.
<li>Exec statements of the form "var = EXEC foo()" are only valid if the procedure foo has a return parameter.
+ <li>Cache hint now supports "scope" definition. For ex: /* cache(scope:user) */ select * from T1; This hint will override the computed scope based on the query.
</ul>
<h4>from 7.0</h4>
<ul>
Modified: trunk/documentation/caching-guide/src/main/docbook/en-US/content/hint-option.xml
===================================================================
--- trunk/documentation/caching-guide/src/main/docbook/en-US/content/hint-option.xml 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/documentation/caching-guide/src/main/docbook/en-US/content/hint-option.xml 2010-12-06 16:56:22 UTC (rev 2759)
@@ -15,7 +15,7 @@
<listitem><para>Indicate that a virtual procedure should be cachable and set the cache entry memory preference or time to live.
</para></listitem>
</itemizedlist>
- <para><synopsis>/*+ cache[([pref_mem] [ttl:n] [updatable])] */ sql ...</synopsis>
+ <para><synopsis>/*+ cache[([pref_mem] [ttl:n] [updatable])] [scope:(session|user|vdb)] */ sql ...</synopsis>
<itemizedlist>
<listitem><para>The cache hint should appear at the beginning of the SQL. It will not have any affect on INSERT/UPDATE/DELETE statements or virtual update procedure definitions.</para></listitem>
<listitem><para><emphasis>pref_mem</emphasis> - if present indicates that the cached results should prefer to remain in memory. They are not however required to be memory only.
@@ -24,6 +24,10 @@
</para></listitem>
<listitem><para><emphasis>updatable</emphasis> - if present indicates that the cached results can be updated. This is currently only applicable to materialized views.
</para></listitem>
+ <listitem><para><emphasis>scope</emphasis> - if present indicates the override scope of query results. Using this flag, user can override the computed scope, to improve or force the results to cache.
+ There are three different cache scopes, session - cached only for current session, user - cached for any session by the current user, vdb - cached for any user connected to the same vdb.
+ </para></listitem>
+
</itemizedlist>
</para>
<section>
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java 2010-12-06 16:56:22 UTC (rev 2759)
@@ -38,6 +38,7 @@
import org.teiid.dqp.internal.process.SessionAwareCache.CacheID;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.QueryPlugin;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.metadata.QueryMetadataInterface;
@@ -140,7 +141,14 @@
// Defect 13751: Clone the plan in its current state (i.e. before processing) so that it can be used for later queries
prepPlan.setPlan(processPlan.clone());
prepPlan.setAnalysisRecord(analysisRecord);
- this.prepPlanCache.put(id, this.context.getDeterminismLevel(), prepPlan, userCommand.getCacheHint() != null?userCommand.getCacheHint().getTtl():null);
+
+ Determinism hintDeterminismLevel = null;
+ if (userCommand.getCacheHint() != null && userCommand.getCacheHint().getDeterminism() != null) {
+ hintDeterminismLevel = userCommand.getCacheHint().getDeterminism();
+ LogManager.logTrace(LogConstants.CTX_DQP, new Object[] { "Cache hint modified the query determinism from ",this.context.getDeterminismLevel(), " to ", hintDeterminismLevel }); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ this.prepPlanCache.put(id, hintDeterminismLevel!= null?hintDeterminismLevel:this.context.getDeterminismLevel(), prepPlan, userCommand.getCacheHint() != null?userCommand.getCacheHint().getTtl():null);
}
} else {
ProcessorPlan cachedPlan = prepPlan.getPlan();
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-12-06 16:56:22 UTC (rev 2759)
@@ -390,6 +390,12 @@
cr.setCommand(originalCommand);
cr.setAnalysisRecord(analysisRecord);
cr.setResults(resultsBuffer);
+
+ if (originalCommand.getCacheHint() != null && originalCommand.getCacheHint().getDeterminism() != null) {
+ determinismLevel = originalCommand.getCacheHint().getDeterminism();
+ LogManager.logTrace(LogConstants.CTX_DQP, new Object[] { "Cache hint modified the query determinism from ",processor.getContext().getDeterminismLevel(), " to ", determinismLevel }); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
if (determinismLevel.isRestrictiveThan(Determinism.SESSION_DETERMINISTIC)) {
LogManager.logInfo(LogConstants.CTX_DQP, QueryPlugin.Util.getString("RequestWorkItem.cache_nondeterministic", originalCommand)); //$NON-NLS-1$
}
Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2010-12-06 16:56:22 UTC (rev 2759)
@@ -178,7 +178,7 @@
return hint;
}
- private static Pattern CACHE_HINT = Pattern.compile("/\\*\\+?\\s*cache(\\(\\s*(pref_mem)?\\s*(ttl:\\d{1,19})?\\s*(updatable)?[^\\)]*\\))?[^\\*]*\\*\\/.*", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
+ private static Pattern CACHE_HINT = Pattern.compile("/\\*\\+?\\s*cache(\\(\\s*(pref_mem)?\\s*(ttl:\\d{1,19})?\\s*(updatable)?\\s*(scope:(session|vdb|user))?[^\\)]*\\))?[^\\*]*\\*\\/.*", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
static CacheHint getQueryCacheOption(String query) {
Matcher match = CACHE_HINT.matcher(query);
@@ -194,6 +194,11 @@
if (match.group(4) != null) {
hint.setUpdatable(true);
}
+ String scope = match.group(5);
+ if (scope != null) {
+ scope = scope.substring(6);
+ hint.setScope(scope);
+ }
return hint;
}
return null;
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/CacheHint.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/CacheHint.java 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/CacheHint.java 2010-12-06 16:56:22 UTC (rev 2759)
@@ -25,6 +25,7 @@
import java.io.Serializable;
import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.sql.visitor.SQLStringVisitor;
public class CacheHint implements Serializable {
@@ -35,10 +36,16 @@
public static final String TTL = "ttl:"; //$NON-NLS-1$
public static final String UPDATABLE = "updatable"; //$NON-NLS-1$
public static final String CACHE = "cache"; //$NON-NLS-1$
+ public static final String SCOPE = "scope:"; //$NON-NLS-1$
+ private static final String SESSION = "session"; //$NON-NLS-1$
+ private static final String VDB = "vdb"; //$NON-NLS-1$
+ private static final String USER = "user"; //$NON-NLS-1$
+
private boolean prefersMemory;
private boolean updatable;
private Long ttl;
+ private String scope;
public CacheHint() {
}
@@ -79,6 +86,31 @@
this.updatable = updatable;
}
+ public Determinism getDeterminism() {
+ if (this.scope == null) {
+ return null;
+ }
+
+ if (scope.equals(SESSION)) {
+ return Determinism.SESSION_DETERMINISTIC;
+ }
+ else if (this.scope.equals(VDB)) {
+ return Determinism.VDB_DETERMINISTIC;
+ }
+ else if (this.scope.equals(USER)) {
+ return Determinism.USER_DETERMINISTIC;
+ }
+ return null;
+ }
+
+ public String getScope() {
+ return this.scope;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+
@Override
public boolean equals(Object obj) {
if (obj == this) {
@@ -90,7 +122,8 @@
CacheHint other = (CacheHint)obj;
return this.prefersMemory == other.prefersMemory
&& EquivalenceUtil.areEqual(this.ttl, other.ttl)
- && this.updatable == other.updatable;
+ && this.updatable == other.updatable
+ && EquivalenceUtil.areEqual(this.scope, other.scope);
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-12-06 16:56:22 UTC (rev 2759)
@@ -585,7 +585,7 @@
outputDisplayName((String)iter.next());
if (iter.hasNext()) {
- append(", ");
+ append(", ");//$NON-NLS-1$
}
}
}
@@ -602,7 +602,7 @@
outputDisplayName((String)iter.next());
if (iter.hasNext()) {
- append(", ");
+ append(", ");//$NON-NLS-1$
}
}
}
@@ -619,7 +619,7 @@
outputDisplayName((String)iter.next());
if (iter.hasNext()) {
- append(", ");
+ append(", ");//$NON-NLS-1$
}
}
} else if (obj.isNoCache()) {
@@ -1011,6 +1011,16 @@
}
append(CacheHint.UPDATABLE);
}
+ if (obj.getScope() != null) {
+ if (!addParens) {
+ append(Tokens.LPAREN);
+ addParens = true;
+ } else {
+ append(SPACE);
+ }
+ append(CacheHint.SCOPE);
+ append(obj.getScope());
+ }
if (addParens) {
append(Tokens.RPAREN);
}
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java 2010-12-06 16:56:22 UTC (rev 2759)
@@ -285,7 +285,12 @@
CachedResults cr = new CachedResults();
cr.setResults(tb);
cr.setHint(hint);
- cache.put(cid, context.getDeterminismLevel(), cr, hint != null?hint.getTtl():null);
+ Determinism hintDeterminismLevel = null;
+ if (hint != null && hint.getDeterminism() != null) {
+ hintDeterminismLevel = hint.getDeterminism();
+ LogManager.logTrace(LogConstants.CTX_DQP, new Object[] { "Cache hint modified the query determinism from ",determinismLevel, " to ", hintDeterminismLevel }); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ cache.put(cid, hintDeterminismLevel != null?hintDeterminismLevel:context.getDeterminismLevel(), cr, hint != null?hint.getTtl():null);
context.setDeterminismLevel(determinismLevel);
return tb.createIndexedTupleSource();
}
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java 2010-12-06 14:40:09 UTC (rev 2758)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java 2010-12-06 16:56:22 UTC (rev 2759)
@@ -22,7 +22,7 @@
package org.teiid.query.parser;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
@@ -1053,6 +1053,25 @@
TestParser.helpTest(sql, "/*+ cache */ SELECT * FROM t1", query); //$NON-NLS-1$
}
+ @Test public void testCacheScope() {
+ String sql = "/*+ cache(pref_mem scope:session) */ SELECT * FROM t1"; //$NON-NLS-1$
+
+ Query query = new Query();
+ Select select = new Select();
+ select.addSymbol(new AllSymbol());
+ query.setSelect(select);
+ From from = new From();
+ UnaryFromClause ufc = new UnaryFromClause();
+ from.addClause(ufc);
+ ufc.setGroup(new GroupSymbol("t1")); //$NON-NLS-1$
+ query.setFrom(from);
+ CacheHint hint = new CacheHint();
+ hint.setScope("session");
+ hint.setPrefersMemory(true);
+ query.setCacheHint(hint);
+ TestParser.helpTest(sql, "/*+ cache(pref_mem scope:session) */ SELECT * FROM t1", query); //$NON-NLS-1$
+ }
+
@Test public void testCache1() {
String sql = "/*+ cache */ execute foo()"; //$NON-NLS-1$
14 years
teiid SVN: r2758 - in trunk/engine/src: main/java/org/teiid/query/validator and 3 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-06 09:40:09 -0500 (Mon, 06 Dec 2010)
New Revision: 2758
Modified:
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/processor/TestInherintlyUpdatableViews.java
trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java
Log:
TEIID-1351 adding union all support inherently updatable views
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-03 20:41:42 UTC (rev 2757)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-06 14:40:09 UTC (rev 2758)
@@ -2557,63 +2557,15 @@
private Command rewriteUpdate(Update update) throws TeiidComponentException, TeiidProcessingException{
UpdateInfo info = update.getUpdateInfo();
if (info != null && info.isInherentUpdate()) {
- UpdateMapping mapping = info.findUpdateMapping(update.getChangeList().getClauseMap().keySet(), false);
- if (mapping == null) {
- throw new QueryValidatorException(QueryPlugin.Util.getString("ValidationVisitor.nonUpdatable", update.getChangeList().getClauseMap().keySet())); //$NON-NLS-1$
- }
- Map<ElementSymbol, ElementSymbol> symbolMap = mapping.getUpdatableViewSymbols();
- if (info.isSimple()) {
- update.setGroup(mapping.getGroup().clone());
- for (SetClause clause : update.getChangeList().getClauses()) {
- clause.setSymbol(symbolMap.get(clause.getSymbol()));
+ if (!info.getUnionBranches().isEmpty()) {
+ List<Command> batchedUpdates = new ArrayList<Command>(info.getUnionBranches().size() + 1);
+ for (UpdateInfo branchInfo : info.getUnionBranches()) {
+ batchedUpdates.add(createInherentUpdateProc((Update)update.clone(), branchInfo));
}
- //TODO: properly handle correlated references
- DeepPostOrderNavigator.doVisit(update, new ExpressionMappingVisitor(symbolMap, true));
- if (info.getViewDefinition().getCriteria() != null) {
- update.setCriteria(Criteria.combineCriteria(update.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
- }
- //resolve
- update.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(update.getGroup(), metadata));
- return rewriteUpdate(update);
- }
- Query query = (Query)info.getViewDefinition().clone();
- query.setOrderBy(null);
- SymbolMap expressionMapping = SymbolMap.createSymbolMap(update.getGroup(), query.getProjectedSymbols(), metadata);
-
- ArrayList<SingleElementSymbol> selectSymbols = new ArrayList<SingleElementSymbol>(update.getChangeList().getClauses().size());
- int i = 0;
- for (SetClause clause : update.getChangeList().getClauses()) {
- Expression ex = clause.getValue();
- SingleElementSymbol selectSymbol = null;
- if (!EvaluatableVisitor.willBecomeConstant(ex)) {
- if (!(ex instanceof SingleElementSymbol)) {
- selectSymbol = new ExpressionSymbol("expr", ex); //$NON-NLS-1$
- } else {
- selectSymbol = (SingleElementSymbol)ex;
- }
- selectSymbols.add(new AliasSymbol("s_" +i, selectSymbol)); //$NON-NLS-1$
- ex = new ElementSymbol("s_" +i); //$NON-NLS-1$
- }
- clause.setSymbol(symbolMap.get(clause.getSymbol()));
- i++;
+ batchedUpdates.add(0, createInherentUpdateProc(update, info));
+ return new BatchedUpdateCommand(batchedUpdates);
}
- query.setSelect(new Select(selectSymbols));
- ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
- PostOrderNavigator.doVisit(query.getSelect(), emv);
-
- Criteria crit = update.getCriteria();
- if (crit != null) {
- PostOrderNavigator.doVisit(crit, emv);
- query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
- }
-
- Update newUpdate = new Update();
- newUpdate.setChangeList(update.getChangeList());
- newUpdate.setGroup(mapping.getGroup().clone());
-
- List<Criteria> pkCriteria = createPkCriteria(mapping, query, i);
- newUpdate.setCriteria(Criteria.combineCriteria(newUpdate.getCriteria(), new CompoundCriteria(pkCriteria)));
- return createUpdateProcedure(update, query, newUpdate);
+ return createInherentUpdateProc(update, info);
}
if (commandType == Command.TYPE_UPDATE && variables != null) {
@@ -2642,6 +2594,69 @@
return update;
}
+ private Command createInherentUpdateProc(Update update, UpdateInfo info)
+ throws QueryValidatorException, QueryMetadataException,
+ TeiidComponentException, QueryResolverException,
+ TeiidProcessingException {
+ UpdateMapping mapping = info.findUpdateMapping(update.getChangeList().getClauseMap().keySet(), false);
+ if (mapping == null) {
+ throw new QueryValidatorException(QueryPlugin.Util.getString("ValidationVisitor.nonUpdatable", update.getChangeList().getClauseMap().keySet())); //$NON-NLS-1$
+ }
+ Map<ElementSymbol, ElementSymbol> symbolMap = mapping.getUpdatableViewSymbols();
+ if (info.isSimple()) {
+ update.setGroup(mapping.getGroup().clone());
+ for (SetClause clause : update.getChangeList().getClauses()) {
+ clause.setSymbol(symbolMap.get(clause.getSymbol()));
+ }
+ //TODO: properly handle correlated references
+ DeepPostOrderNavigator.doVisit(update, new ExpressionMappingVisitor(symbolMap, true));
+ if (info.getViewDefinition().getCriteria() != null) {
+ update.setCriteria(Criteria.combineCriteria(update.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
+ }
+ //resolve
+ update.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(update.getGroup(), metadata));
+ return rewriteUpdate(update);
+ }
+ Query query = (Query)info.getViewDefinition().clone();
+ query.setOrderBy(null);
+ SymbolMap expressionMapping = SymbolMap.createSymbolMap(update.getGroup(), query.getProjectedSymbols(), metadata);
+
+ ArrayList<SingleElementSymbol> selectSymbols = new ArrayList<SingleElementSymbol>(update.getChangeList().getClauses().size());
+ int i = 0;
+ for (SetClause clause : update.getChangeList().getClauses()) {
+ Expression ex = clause.getValue();
+ SingleElementSymbol selectSymbol = null;
+ if (!EvaluatableVisitor.willBecomeConstant(ex)) {
+ if (!(ex instanceof SingleElementSymbol)) {
+ selectSymbol = new ExpressionSymbol("expr", ex); //$NON-NLS-1$
+ } else {
+ selectSymbol = (SingleElementSymbol)ex;
+ }
+ selectSymbols.add(new AliasSymbol("s_" +i, selectSymbol)); //$NON-NLS-1$
+ ex = new ElementSymbol("s_" +i); //$NON-NLS-1$
+ }
+ clause.setSymbol(symbolMap.get(clause.getSymbol()));
+ i++;
+ }
+ query.setSelect(new Select(selectSymbols));
+ ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
+ PostOrderNavigator.doVisit(query.getSelect(), emv);
+
+ Criteria crit = update.getCriteria();
+ if (crit != null) {
+ PostOrderNavigator.doVisit(crit, emv);
+ query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
+ }
+
+ Update newUpdate = new Update();
+ newUpdate.setChangeList(update.getChangeList());
+ newUpdate.setGroup(mapping.getGroup().clone());
+
+ List<Criteria> pkCriteria = createPkCriteria(mapping, query, i);
+ newUpdate.setCriteria(Criteria.combineCriteria(newUpdate.getCriteria(), new CompoundCriteria(pkCriteria)));
+ return createUpdateProcedure(update, query, newUpdate);
+ }
+
private Command createUpdateProcedure(ProcedureContainer update, Query query,
ProcedureContainer newUpdate) throws QueryResolverException,
TeiidComponentException, TeiidProcessingException {
@@ -2715,38 +2730,15 @@
private Command rewriteDelete(Delete delete) throws TeiidComponentException, TeiidProcessingException{
UpdateInfo info = delete.getUpdateInfo();
if (info != null && info.isInherentDelete()) {
- UpdateMapping mapping = info.getDeleteTarget();
- if (info.isSimple()) {
- delete.setGroup(mapping.getGroup().clone());
- //TODO: properly handle correlated references
- DeepPostOrderNavigator.doVisit(delete, new ExpressionMappingVisitor(mapping.getUpdatableViewSymbols(), true));
- delete.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(delete.getGroup(), metadata));
- if (info.getViewDefinition().getCriteria() != null) {
- delete.setCriteria(Criteria.combineCriteria(delete.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
+ if (!info.getUnionBranches().isEmpty()) {
+ List<Command> batchedUpdates = new ArrayList<Command>(info.getUnionBranches().size() + 1);
+ for (UpdateInfo branchInfo : info.getUnionBranches()) {
+ batchedUpdates.add(createInherentDeleteProc((Delete)delete.clone(), branchInfo));
}
- return rewriteDelete(delete);
+ batchedUpdates.add(0, createInherentDeleteProc(delete, info));
+ return new BatchedUpdateCommand(batchedUpdates);
}
-
- Query query = (Query)info.getViewDefinition().clone();
- query.setOrderBy(null);
- SymbolMap expressionMapping = SymbolMap.createSymbolMap(delete.getGroup(), query.getProjectedSymbols(), metadata);
-
- query.setSelect(new Select());
- ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
- PostOrderNavigator.doVisit(query.getSelect(), emv);
-
- Criteria crit = delete.getCriteria();
- if (crit != null) {
- PostOrderNavigator.doVisit(crit, emv);
- query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
- }
-
- Delete newUpdate = new Delete();
- newUpdate.setGroup(mapping.getGroup().clone());
-
- List<Criteria> pkCriteria = createPkCriteria(mapping, query, 0);
- newUpdate.setCriteria(Criteria.combineCriteria(newUpdate.getCriteria(), new CompoundCriteria(pkCriteria)));
- return createUpdateProcedure(delete, query, newUpdate);
+ return createInherentDeleteProc(delete, info);
}
// Rewrite criteria
Criteria crit = delete.getCriteria();
@@ -2756,6 +2748,43 @@
return delete;
}
+
+ private Command createInherentDeleteProc(Delete delete, UpdateInfo info)
+ throws QueryMetadataException, TeiidComponentException,
+ QueryResolverException, TeiidProcessingException {
+ UpdateMapping mapping = info.getDeleteTarget();
+ if (info.isSimple()) {
+ delete.setGroup(mapping.getGroup().clone());
+ //TODO: properly handle correlated references
+ DeepPostOrderNavigator.doVisit(delete, new ExpressionMappingVisitor(mapping.getUpdatableViewSymbols(), true));
+ delete.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(delete.getGroup(), metadata));
+ if (info.getViewDefinition().getCriteria() != null) {
+ delete.setCriteria(Criteria.combineCriteria(delete.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
+ }
+ return rewriteDelete(delete);
+ }
+
+ Query query = (Query)info.getViewDefinition().clone();
+ query.setOrderBy(null);
+ SymbolMap expressionMapping = SymbolMap.createSymbolMap(delete.getGroup(), query.getProjectedSymbols(), metadata);
+
+ query.setSelect(new Select());
+ ExpressionMappingVisitor emv = new ExpressionMappingVisitor(expressionMapping.asMap(), true);
+ PostOrderNavigator.doVisit(query.getSelect(), emv);
+
+ Criteria crit = delete.getCriteria();
+ if (crit != null) {
+ PostOrderNavigator.doVisit(crit, emv);
+ query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
+ }
+
+ Delete newUpdate = new Delete();
+ newUpdate.setGroup(mapping.getGroup().clone());
+
+ List<Criteria> pkCriteria = createPkCriteria(mapping, query, 0);
+ newUpdate.setCriteria(Criteria.combineCriteria(newUpdate.getCriteria(), new CompoundCriteria(pkCriteria)));
+ return createUpdateProcedure(delete, query, newUpdate);
+ }
private Limit rewriteLimitClause(Limit limit) throws TeiidComponentException, TeiidProcessingException{
if (limit.getOffset() != null) {
Modified: trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java 2010-12-03 20:41:42 UTC (rev 2757)
+++ trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java 2010-12-06 14:40:09 UTC (rev 2758)
@@ -25,6 +25,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -38,6 +39,7 @@
import org.teiid.query.resolver.util.ResolverUtil;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.SetQuery;
import org.teiid.query.sql.lang.UnaryFromClause;
import org.teiid.query.sql.lang.SetQuery.Operation;
@@ -109,6 +111,7 @@
private UpdateType insertType;
private boolean insertValidationError;
private Query view;
+ private List<UpdateInfo> unionBranches = new LinkedList<UpdateInfo>();
public boolean isSimple() {
return isSimple;
@@ -118,10 +121,6 @@
return deleteTarget;
}
- public Map<String, UpdateMapping> getUpdatableGroups() {
- return updatableGroups;
- }
-
public boolean isInherentDelete() {
return deleteType == UpdateType.INHERENT;
}
@@ -142,8 +141,20 @@
return deleteType;
}
+ public boolean hasValidUpdateMapping(Collection<ElementSymbol> updateCols) {
+ if (findUpdateMapping(updateCols, false) == null) {
+ return false;
+ }
+ for (UpdateInfo info : this.unionBranches) {
+ if (info.findUpdateMapping(updateCols, false) == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public UpdateMapping findUpdateMapping(Collection<ElementSymbol> updateCols, boolean insert) {
- for (UpdateMapping entry : getUpdatableGroups().values()) {
+ for (UpdateMapping entry : this.updatableGroups.values()) {
if (((insert && entry.insertAllowed) || (!insert && entry.updateAllowed)) && entry.updatableViewSymbols.keySet().containsAll(updateCols)) {
return entry;
}
@@ -167,6 +178,10 @@
return updateValidationError;
}
+ public List<UpdateInfo> getUnionBranches() {
+ return unionBranches;
+ }
+
}
private QueryMetadataInterface metadata;
@@ -218,12 +233,9 @@
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001"), true, true, true); //$NON-NLS-1$
return;
}
- //TOOD each branch should return it's own info?
- /*this.validate(setQuery.getLeftQuery(), viewSymbols);
- this.validate(setQuery.getRightQuery(), viewSymbols);
- if (!this.updateInfo.insertValidationError) {
- handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0018"), false, true, false); //$NON-NLS-1$
- }*/
+ validateBranch(viewSymbols, setQuery.getLeftQuery());
+ validateBranch(viewSymbols, setQuery.getRightQuery());
+ return;
}
if (!(command instanceof Query)) {
@@ -351,6 +363,35 @@
}
}
}
+
+ private void validateBranch(List<ElementSymbol> viewSymbols,
+ QueryCommand query) throws QueryMetadataException,
+ TeiidComponentException {
+ if (!this.updateInfo.insertValidationError) {
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0018"), false, true, false); //$NON-NLS-1$
+ }
+ if (!this.updateInfo.isInherentDelete() && !this.updateInfo.isInherentUpdate()) {
+ return; //don't bother
+ }
+ UpdateValidator uv = this;
+ if (this.updateInfo.view != null) {
+ uv = new UpdateValidator(metadata, null, null, null);
+ uv.updateInfo.deleteType = this.updateInfo.deleteType;
+ uv.updateInfo.insertType = this.updateInfo.insertType;
+ uv.updateInfo.updateType = this.updateInfo.updateType;
+ }
+ uv.validate(query, viewSymbols);
+ if (uv != this) {
+ UpdateInfo info = uv.getUpdateInfo();
+ this.updateInfo.deleteValidationError |= info.deleteValidationError;
+ this.updateInfo.updateValidationError |= info.updateValidationError;
+ if (info.view != null) {
+ this.updateInfo.unionBranches.add(info);
+ } else {
+ this.updateInfo.unionBranches.addAll(info.unionBranches);
+ }
+ }
+ }
private void setUpdateFlags(GroupSymbol groupSymbol) throws QueryMetadataException, TeiidComponentException {
UpdateMapping info = updateInfo.updatableGroups.get(groupSymbol.getCanonicalName());
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-12-03 20:41:42 UTC (rev 2757)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-12-06 14:40:09 UTC (rev 2758)
@@ -949,7 +949,7 @@
}
if (info != null && info.isInherentUpdate()) {
Set<ElementSymbol> updateCols = update.getChangeList().getClauseMap().keySet();
- if (info.findUpdateMapping(updateCols, false) == null) {
+ if (!info.hasValidUpdateMapping(updateCols)) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.nonUpdatable", updateCols), update); //$NON-NLS-1$
}
}
@@ -1473,7 +1473,7 @@
validateSubquery(obj);
}
- //TODO: it may be simplier to catch this in the parser
+ //TODO: it may be simpler to catch this in the parser
private void validateSubquery(SubqueryContainer subQuery) {
if (subQuery.getCommand() instanceof Query && ((Query)subQuery.getCommand()).getInto() != null) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.subquery_insert"), subQuery.getCommand()); //$NON-NLS-1$
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-03 20:41:42 UTC (rev 2757)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-06 14:40:09 UTC (rev 2758)
@@ -165,7 +165,7 @@
# util (011)
# validator (012)
-ERR.015.012.0001 = The query defining an updatable view must be a simple query with a FROM clause.
+ERR.015.012.0001 = The query defining an updatable view must be a simple query or a UNION ALL of simple queries.
ERR.015.012.0002 = The query defining an updatable view has a WITH clause, pass-through processing will not be used for UPDATE/DELETE operations.
ERR.015.012.0003 = The query defining an updatable view projects a column from a non-updatable group {0}.
ERR.015.012.0004 = The query defining an updatable view has a non key preserving join group {0}, which cannot be targeted by UPDATE/DELETE operations.
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestInherintlyUpdatableViews.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestInherintlyUpdatableViews.java 2010-12-03 20:41:42 UTC (rev 2757)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestInherintlyUpdatableViews.java 2010-12-06 14:40:09 UTC (rev 2758)
@@ -22,6 +22,7 @@
package org.teiid.query.processor;
+import static org.junit.Assert.*;
import static org.teiid.query.processor.TestProcessor.*;
import java.util.Arrays;
@@ -33,6 +34,7 @@
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder;
import org.teiid.query.rewriter.TestQueryRewriter;
+import org.teiid.query.sql.lang.BatchedUpdateCommand;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.util.CommandContext;
import org.teiid.query.validator.TestUpdateValidator;
@@ -48,7 +50,7 @@
helpTest(userSql, viewSql, expectedSql, null);
}
- private void helpTest(String userSql, String viewSql, String expectedSql, ProcessorDataManager dm)
+ private Command helpTest(String userSql, String viewSql, String expectedSql, ProcessorDataManager dm)
throws Exception {
TransformationMetadata metadata = TestUpdateValidator.example1();
TestUpdateValidator.createView(viewSql, metadata, "gx");
@@ -62,6 +64,8 @@
List[] expected = new List[] {Arrays.asList(1)};
helpProcess(plan, context, dm, expected);
}
+
+ return command;
}
@Test public void testUpdatePassThroughWithAlias() throws Exception {
@@ -85,6 +89,14 @@
helpTest(userSql, viewSql, expectedSql, null);
}
+ @Test public void testDeleteUnion() throws Exception {
+ String userSql = "delete from vm1.gx where e4 is null"; //$NON-NLS-1$
+ String viewSql = "select * from pm1.g1 where e3 < 5 union all select * from pm1.g2 where e1 > 1";
+ String expectedSql = "BatchedUpdate{D,D}";
+ BatchedUpdateCommand buc = (BatchedUpdateCommand)helpTest(userSql, viewSql, expectedSql, null);
+ assertEquals("DELETE FROM pm1.g2 WHERE (pm1.g2.e4 IS NULL) AND (e1 > '1')", buc.getUpdateCommands().get(1).toString());
+ }
+
/**
* Here we should be able to figure out that we can pass through the join
* @throws Exception
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java 2010-12-03 20:41:42 UTC (rev 2757)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java 2010-12-06 14:40:09 UTC (rev 2758)
@@ -55,8 +55,12 @@
@SuppressWarnings("nls")
public class TestUpdateValidator {
+
+ private UpdateValidator helpTest(String sql, TransformationMetadata md, boolean shouldFail) {
+ return helpTest(sql, md, shouldFail, shouldFail, shouldFail);
+ }
- private UpdateValidator helpTest(String sql, TransformationMetadata md, boolean shouldFail) {
+ private UpdateValidator helpTest(String sql, TransformationMetadata md, boolean failInsert, boolean failUpdate, boolean failDelete) {
try {
String vGroup = "gx";
Command command = createView(sql, md, vGroup);
@@ -66,10 +70,9 @@
ResolverUtil.resolveGroup(gs, md);
uv.validate(command, ResolverUtil.resolveElementsInGroup(gs, md));
UpdateInfo info = uv.getUpdateInfo();
- boolean failed = info.isDeleteValidationError() || info.isInsertValidationError() || info.isUpdateValidationError();
- if (!failed && shouldFail) {
- fail("expeceted failures, but got none: " + uv.getReport());
- }
+ assertEquals(uv.getReport().getFailureMessage(), failInsert, info.isInsertValidationError());
+ assertEquals(uv.getReport().getFailureMessage(), failUpdate, info.isUpdateValidationError());
+ assertEquals(uv.getReport().getFailureMessage(), failDelete, info.isDeleteValidationError());
return uv;
} catch (TeiidException e) {
throw new RuntimeException(e);
@@ -288,37 +291,31 @@
example1(), true);
}
- // Check that e3 is not required (it has a default value)
@Test public void testRequiredElements1() {
helpTest("SELECT e1, e2 FROM pm1.g3",
example1(), false); //$NON-NLS-1$
}
- // Check that e2 is not required (it is auto-incremented)
@Test public void testRequiredElements2() {
helpTest("SELECT e1, e3 FROM pm1.g3",
example1(), false); //$NON-NLS-1$
}
- // Check that e1 is required (it is not-nullable, not auto-incrementable, and has no default value)
@Test public void testRequiredElements3() {
helpTest("SELECT e2, e3 FROM pm1.g3",
- example1(), true);
+ example1(), true, false, false);
}
- // Verify that elements that are not updateable are exlcluded from update and delete procedures
@Test public void testNonUpdateableElements() {
helpTest("select e1 as a, e2 from pm1.g1 where e4 > 5",
example1(false), false); //$NON-NLS-1$
}
- // Verify that elements that are not updateable are exlcluded from update and delete procedures
@Test public void testNonUpdateableElements2() {
helpTest("SELECT e1, e2 FROM pm1.g1",
example1(false), false); //$NON-NLS-1$
}
- // Verify that elements that are not updateable are exlcluded from update and delete procedures
@Test public void testSelectDistinct() {
helpTest("SELECT distinct e1, e2 FROM pm1.g1",
example1(), true); //$NON-NLS-1$
@@ -333,6 +330,11 @@
helpTest("SELECT g1.e1, x.e2 FROM pm1.g2 x inner join pm1.g1 on (x.e1 = g1.e1)",
example1(), false); //$NON-NLS-1$
}
+
+ @Test public void testUnionAll() {
+ helpTest("SELECT g1.e1, x.e2 FROM pm1.g2 x inner join pm1.g1 on (x.e1 = g1.e1) union all select pm1.g2.e1, pm1.g2.e2 from pm1.g2",
+ example1(), true, false, false); //$NON-NLS-1$
+ }
}
14 years
teiid SVN: r2757 - trunk/build/kits/jboss-container.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-12-03 15:41:42 -0500 (Fri, 03 Dec 2010)
New Revision: 2757
Modified:
trunk/build/kits/jboss-container/teiid-releasenotes.html
Log:
TEIID-231
Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-12-03 20:32:45 UTC (rev 2756)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-12-03 20:41:42 UTC (rev 2757)
@@ -28,6 +28,7 @@
<UL>
<LI><B>Subquery Optimization</B> - added rewrite to INNER JOIN for applicable WHERE clause subqueries. Also added cost based SEMI and ANTI-SEMI join handling for applicable non-pushed WHERE and HAVING subqueries.
<LI><B>Updatable Views</B> - added support to perform simple pass-through and more complicated updates through views by default.
+ <LI><B>UDF</B> - new API objects added to teiid-api to support user defined functions that are capable of pushdown to source.
</UL>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
14 years, 1 month
teiid SVN: r2756 - in trunk/engine/src: main/java/org/teiid/query/validator and 3 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-03 15:32:45 -0500 (Fri, 03 Dec 2010)
New Revision: 2756
Modified:
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java
Log:
TEIID-1351 differentiating between update procedures and trigger actions
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2010-12-03 18:49:01 UTC (rev 2755)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2010-12-03 20:32:45 UTC (rev 2756)
@@ -249,24 +249,23 @@
}
public static UpdateInfo getUpdateInfo(GroupSymbol group, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException, QueryResolverException {
- //if this is not inherently updatable, just return null
- if(group.isTempGroupSymbol() || !metadata.isVirtualGroup(group.getMetadataID()) || (
- metadata.getUpdatePlan(group.getMetadataID()) != null &&
- metadata.getDeletePlan(group.getMetadataID()) != null &&
- metadata.getInsertPlan(group.getMetadataID()) != null)) {
+ //if this is not a view, just return null
+ if(group.isTempGroupSymbol() || !metadata.isVirtualGroup(group.getMetadataID())) {
return null;
}
+ String updatePlan = metadata.getUpdatePlan(group.getMetadataID());
+ String deletePlan = metadata.getDeletePlan(group.getMetadataID());
+ String insertPlan = metadata.getInsertPlan(group.getMetadataID());
+
+
UpdateInfo info = (UpdateInfo)metadata.getFromMetadataCache(group.getMetadataID(), "UpdateInfo"); //$NON-NLS-1$
if (info == null) {
-
List<ElementSymbol> elements = ResolverUtil.resolveElementsInGroup(group, metadata);
-
- UpdateValidator validator = new UpdateValidator(metadata,
- metadata.getUpdatePlan(group.getMetadataID()) == null,
- metadata.getDeletePlan(group.getMetadataID()) == null,
- metadata.getInsertPlan(group.getMetadataID()) == null);
- validator.validate(UpdateProcedureResolver.getQueryTransformCmd(group, metadata), elements);
+ UpdateValidator validator = new UpdateValidator(metadata, updatePlan, deletePlan, insertPlan);
info = validator.getUpdateInfo();
+ if (info.isInherentDelete() || info.isInherentInsert() || info.isInherentUpdate()) {
+ validator.validate(UpdateProcedureResolver.getQueryTransformCmd(group, metadata), elements);
+ }
metadata.addToMetadataCache(group.getMetadataID(), "UpdateInfo", info); //$NON-NLS-1$
}
return info;
Modified: trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java 2010-12-03 18:49:01 UTC (rev 2755)
+++ trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java 2010-12-03 20:32:45 UTC (rev 2756)
@@ -30,13 +30,17 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.util.StringUtil;
+import org.teiid.language.SQLConstants;
import org.teiid.query.QueryPlugin;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.SupportConstants;
import org.teiid.query.resolver.util.ResolverUtil;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.SetQuery;
import org.teiid.query.sql.lang.UnaryFromClause;
+import org.teiid.query.sql.lang.SetQuery.Operation;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.GroupSymbol;
@@ -51,6 +55,21 @@
*/
public class UpdateValidator {
+ public enum UpdateType {
+ /**
+ * The default handling should be used
+ */
+ INHERENT,
+ /**
+ * A procedure handler has been defined
+ */
+ UPDATE_PROCEDURE,
+ /**
+ * An instead of trigger (TriggerAction) has been defined
+ */
+ INSTEAD_OF
+ }
+
public static class UpdateMapping {
private GroupSymbol group;
private GroupSymbol correlatedName;
@@ -83,11 +102,11 @@
private Map<String, UpdateMapping> updatableGroups = new HashMap<String, UpdateMapping>();
private boolean isSimple = true;
private UpdateMapping deleteTarget;
- private boolean inherentUpdate;
+ private UpdateType updateType;
private boolean updateValidationError;
- private boolean inherentDelete;
+ private UpdateType deleteType;
private boolean deleteValidationError;
- private boolean inherentInsert;
+ private UpdateType insertType;
private boolean insertValidationError;
private Query view;
@@ -104,17 +123,25 @@
}
public boolean isInherentDelete() {
- return inherentDelete;
+ return deleteType == UpdateType.INHERENT;
}
public boolean isInherentInsert() {
- return inherentInsert;
+ return insertType == UpdateType.INHERENT;
}
public boolean isInherentUpdate() {
- return inherentUpdate;
+ return updateType == UpdateType.INHERENT;
}
+ public UpdateType getUpdateType() {
+ return updateType;
+ }
+
+ public UpdateType getDeleteType() {
+ return deleteType;
+ }
+
public UpdateMapping findUpdateMapping(Collection<ElementSymbol> updateCols, boolean insert) {
for (UpdateMapping entry : getUpdatableGroups().values()) {
if (((insert && entry.insertAllowed) || (!insert && entry.updateAllowed)) && entry.updatableViewSymbols.keySet().containsAll(updateCols)) {
@@ -146,12 +173,24 @@
private ValidatorReport report = new ValidatorReport();
private UpdateInfo updateInfo = new UpdateInfo();
- public UpdateValidator(QueryMetadataInterface qmi, boolean inherentUpdate, boolean inherentDelete, boolean inherentInsert) {
+ public UpdateValidator(QueryMetadataInterface qmi, String updatePlan, String deletePlan, String insertPlan) {
this.metadata = qmi;
- this.updateInfo.inherentDelete = inherentDelete;
- this.updateInfo.inherentInsert = inherentInsert;
- this.updateInfo.inherentUpdate = inherentUpdate;
+ this.updateInfo.deleteType = determineType(deletePlan);
+ this.updateInfo.insertType = determineType(insertPlan);
+ this.updateInfo.updateType = determineType(updatePlan);
}
+
+ private UpdateType determineType(String plan) {
+ UpdateType type = UpdateType.INHERENT;
+ if (plan != null) {
+ if (StringUtil.startsWithIgnoreCase(plan, SQLConstants.Reserved.CREATE)) {
+ type = UpdateType.UPDATE_PROCEDURE;
+ } else {
+ type = UpdateType.INSTEAD_OF;
+ }
+ }
+ return type;
+ }
public UpdateInfo getUpdateInfo() {
return updateInfo;
@@ -169,6 +208,24 @@
}
public void validate(Command command, List<ElementSymbol> viewSymbols) throws QueryMetadataException, TeiidComponentException {
+ if (command instanceof SetQuery) {
+ SetQuery setQuery = (SetQuery)command;
+ if (setQuery.getLimit() != null) {
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0013"), true, true, true); //$NON-NLS-1$
+ return;
+ }
+ if (setQuery.getOperation() != Operation.UNION || !setQuery.isAll()) {
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001"), true, true, true); //$NON-NLS-1$
+ return;
+ }
+ //TOOD each branch should return it's own info?
+ /*this.validate(setQuery.getLeftQuery(), viewSymbols);
+ this.validate(setQuery.getRightQuery(), viewSymbols);
+ if (!this.updateInfo.insertValidationError) {
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0018"), false, true, false); //$NON-NLS-1$
+ }*/
+ }
+
if (!(command instanceof Query)) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001"), true, true, true); //$NON-NLS-1$
return;
@@ -191,8 +248,6 @@
return;
}
- updateInfo.view = query;
-
if (query.getLimit() != null) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0013"), true, true, true); //$NON-NLS-1$
return;
@@ -203,6 +258,8 @@
return;
}
+ updateInfo.view = query;
+
List<SingleElementSymbol> projectedSymbols = query.getSelect().getProjectedSymbols();
for (int i = 0; i < projectedSymbols.size(); i++) {
@@ -256,7 +313,7 @@
if (!allGroups.isEmpty()) {
setUpdateFlags(allGroups.iterator().next());
}
- } else if (this.updateInfo.inherentUpdate || this.updateInfo.inherentDelete) {
+ } else if (this.updateInfo.updateType == UpdateType.INHERENT || this.updateInfo.deleteType == UpdateType.INHERENT) {
for (GroupSymbol groupSymbol : allGroups) {
UpdateMapping info = updateInfo.updatableGroups.get(groupSymbol.getCanonicalName());
if (info == null) {
@@ -280,13 +337,13 @@
updatable |= info.updateAllowed;
insertable |= info.insertAllowed;
}
- if ((this.updateInfo.inherentInsert && !insertable)) {
+ if ((this.updateInfo.insertType == UpdateType.INHERENT && !insertable)) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0015"), false, true, false); //$NON-NLS-1$
}
- if (this.updateInfo.inherentUpdate && !updatable) {
+ if (this.updateInfo.updateType == UpdateType.INHERENT && !updatable) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0005"), true, false, true); //$NON-NLS-1$
}
- if (this.updateInfo.inherentDelete && this.updateInfo.deleteTarget == null) {
+ if (this.updateInfo.deleteType == UpdateType.INHERENT && this.updateInfo.deleteTarget == null) {
if (this.updateInfo.isSimple) {
this.updateInfo.deleteTarget = this.updateInfo.updatableGroups.values().iterator().next();
} else {
@@ -330,7 +387,7 @@
|| metadata.elementSupports(element.getMetadataID(), SupportConstants.Element.AUTO_INCREMENT)) {
return true;
}
- if (this.updateInfo.inherentInsert) {
+ if (this.updateInfo.insertType == UpdateType.INHERENT) {
report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0010", element, element.getGroupSymbol())); //$NON-NLS-1$
}
return false;
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-12-03 18:49:01 UTC (rev 2755)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-12-03 20:32:45 UTC (rev 2756)
@@ -76,6 +76,7 @@
import org.teiid.query.sql.lang.Option;
import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.lang.OrderByItem;
+import org.teiid.query.sql.lang.ProcedureContainer;
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.SPParameter;
@@ -137,6 +138,7 @@
import org.teiid.query.sql.visitor.SQLStringVisitor;
import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
import org.teiid.query.validator.UpdateValidator.UpdateInfo;
+import org.teiid.query.validator.UpdateValidator.UpdateType;
import org.teiid.query.xquery.saxon.SaxonXQueryExpression;
import org.teiid.translator.SourceSystemFunctions;
@@ -201,24 +203,20 @@
validateNoXMLUpdates(obj);
GroupSymbol group = obj.getGroup();
validateGroupSupportsUpdate(group);
- if (obj.getUpdateInfo() == null || !obj.getUpdateInfo().isInherentDelete()) {
- Criteria crit = obj.getCriteria();
- validateVirtualUpdate(group, crit);
- }
+ Criteria crit = obj.getCriteria();
+ validateVirtualUpdate(obj, crit);
}
- private void validateVirtualUpdate(GroupSymbol group,
+ private void validateVirtualUpdate(ProcedureContainer container,
Criteria crit) {
- if (crit == null) {
- return;
+ if (crit == null || container.getUpdateInfo() == null) {
+ return;
}
- try {
- if (getMetadata().isVirtualGroup(group.getMetadataID()) &&
- !ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(crit).isEmpty()) {
+ if ((container.getType() == Command.TYPE_UPDATE && container.getUpdateInfo().getUpdateType() == UpdateType.UPDATE_PROCEDURE)
+ || (container.getType() == Command.TYPE_DELETE && container.getUpdateInfo().getDeleteType() == UpdateType.UPDATE_PROCEDURE)) {
+ if (!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(crit).isEmpty()) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.virtual_update_subquery"), crit); //$NON-NLS-1$
}
- } catch (TeiidException e) {
- handleException(e);
}
}
@@ -335,9 +333,7 @@
validateNoXMLUpdates(obj);
validateGroupSupportsUpdate(obj.getGroup());
validateUpdate(obj);
- if (obj.getUpdateInfo() == null || !obj.getUpdateInfo().isInherentUpdate()) {
- validateVirtualUpdate(obj.getGroup(), obj.getCriteria());
- }
+ validateVirtualUpdate(obj, obj.getCriteria());
}
public void visit(Into obj) {
@@ -911,7 +907,6 @@
protected void validateUpdate(Update update) {
try {
UpdateInfo info = update.getUpdateInfo();
- boolean updatableView = info != null && info.isInherentUpdate();
// list of elements that are being updated
for (SetClause entry : update.getChangeList().getClauses()) {
@@ -942,7 +937,7 @@
if(((Constant)value).isNull() && ! getMetadata().elementSupports(elementID.getMetadataID(), SupportConstants.Element.NULL)) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0060", SQLStringVisitor.getSQLString(elementID)), elementID); //$NON-NLS-1$
}// end of if
- } else if (!updatableView && getMetadata().isVirtualGroup(update.getGroup().getMetadataID()) && !EvaluatableVisitor.willBecomeConstant(value)) {
+ } else if (info != null && info.getUpdateType() == UpdateType.UPDATE_PROCEDURE && getMetadata().isVirtualGroup(update.getGroup().getMetadataID()) && !EvaluatableVisitor.willBecomeConstant(value)) {
// If this is an update on a virtual group, verify that no elements are in the right side
Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(value, false);
for (ElementSymbol element : elements) {
@@ -952,7 +947,7 @@
}
}
}
- if (updatableView) {
+ if (info != null && info.isInherentUpdate()) {
Set<ElementSymbol> updateCols = update.getChangeList().getClauseMap().keySet();
if (info.findUpdateMapping(updateCols, false) == null) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.nonUpdatable", updateCols), update); //$NON-NLS-1$
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-03 18:49:01 UTC (rev 2755)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-03 20:32:45 UTC (rev 2756)
@@ -182,6 +182,7 @@
ERR.015.012.0015 = The query defining an updatable view has no valid target for INSERTs.
ERR.015.012.0016 = Variable {0} not assigned any value in this procedure.
ERR.015.012.0017 = Variables declared the procedure''s DeclareStatement cannot be one of the special variables: {0}, {1} and {2}.
+ERR.015.012.0018 = Inherent INSERT is not possible on a view defined by a UNION.
ERR.015.012.0019 = TranslateCriteria cannot be used in on an if or while statement.
ERR.015.012.0020 = Elements used on the criteria of an if or while statement should be variables declared in the procedure, virtual group elements can be used in the HAS Criteria
ERR.015.012.0021 = Element being translated in the WITH clause not among the elements on the ON clause of the TranslateCriteria.
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java 2010-12-03 18:49:01 UTC (rev 2755)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java 2010-12-03 20:32:45 UTC (rev 2756)
@@ -120,5 +120,26 @@
helpProcess(plan, context, dm, expected);
assertEquals("UPDATE pm1.g1 SET e2 = 5 WHERE e2 = 2", dm.getQueries().get(0));
}
+
+ @Test public void testUpdateWithNonConstant() throws Exception {
+ TransformationMetadata metadata = TestUpdateValidator.example1();
+ TestUpdateValidator.createView("select 1 as x, 2 as y", metadata, "gx");
+ Table t = metadata.getMetadataStore().getSchemas().get("vm1").getTables().get("gx");
+ t.setDeletePlan("");
+ t.setUpdatePlan("FOR EACH ROW BEGIN update pm1.g1 set e2 = new.y where e2 = old.y; END");
+ t.setInsertPlan("");
+
+ String sql = "update gx set y = x";
+
+ FakeDataManager dm = new FakeDataManager();
+ FakeDataStore.addTable("pm1.g1", dm, metadata);
+
+ CommandContext context = createCommandContext();
+ BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+ ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata, null), metadata, new DefaultCapabilitiesFinder(caps), context);
+ List[] expected = new List[] {Arrays.asList(1)};
+ helpProcess(plan, context, dm, expected);
+ assertEquals("UPDATE pm1.g1 SET e2 = 1 WHERE e2 = 2", dm.getQueries().get(0));
+ }
}
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java 2010-12-03 18:49:01 UTC (rev 2755)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java 2010-12-03 20:32:45 UTC (rev 2756)
@@ -61,7 +61,7 @@
String vGroup = "gx";
Command command = createView(sql, md, vGroup);
- UpdateValidator uv = new UpdateValidator(md, true, true, true);
+ UpdateValidator uv = new UpdateValidator(md, null, null, null);
GroupSymbol gs = new GroupSymbol(vGroup);
ResolverUtil.resolveGroup(gs, md);
uv.validate(command, ResolverUtil.resolveElementsInGroup(gs, md));
14 years, 1 month
teiid SVN: r2755 - trunk/connectors.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-12-03 13:49:01 -0500 (Fri, 03 Dec 2010)
New Revision: 2755
Removed:
trunk/connectors/translator-portfolioview/
Log:
invalid commit - deleting
14 years, 1 month
teiid SVN: r2754 - in trunk: api/src/main/java/org/teiid/translator and 55 other directories.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-12-03 13:46:01 -0500 (Fri, 03 Dec 2010)
New Revision: 2754
Added:
trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java
trunk/api/src/main/java/org/teiid/metadata/FunctionParameter.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleSpatialFunctions.java
trunk/connectors/translator-portfolioview/
trunk/connectors/translator-portfolioview/.classpath
trunk/connectors/translator-portfolioview/.project
trunk/connectors/translator-portfolioview/.settings/
trunk/connectors/translator-portfolioview/.settings/org.eclipse.jdt.core.prefs
trunk/connectors/translator-portfolioview/.settings/org.maven.ide.eclipse.prefs
trunk/connectors/translator-portfolioview/pom.xml
trunk/connectors/translator-portfolioview/src/
trunk/connectors/translator-portfolioview/src/main/
trunk/connectors/translator-portfolioview/src/main/java/
trunk/connectors/translator-portfolioview/src/main/java/com/
trunk/connectors/translator-portfolioview/src/main/java/com/citi/
trunk/connectors/translator-portfolioview/src/main/java/com/citi/translator/
trunk/connectors/translator-portfolioview/src/main/java/com/citi/translator/dap/
trunk/connectors/translator-portfolioview/src/main/java/com/citi/translator/dap/PortfolioViewExecutionFactory.java
trunk/connectors/translator-portfolioview/src/main/resources/
trunk/connectors/translator-portfolioview/src/main/resources/META-INF/
trunk/connectors/translator-portfolioview/src/main/resources/META-INF/jboss-beans.xml
trunk/connectors/translator-portfolioview/target/
trunk/connectors/translator-portfolioview/target/classes/
trunk/connectors/translator-portfolioview/target/classes/META-INF/
trunk/connectors/translator-portfolioview/target/classes/META-INF/jboss-beans.xml
trunk/connectors/translator-portfolioview/target/classes/com/
trunk/connectors/translator-portfolioview/target/classes/com/citi/
trunk/connectors/translator-portfolioview/target/classes/com/citi/translator/
trunk/connectors/translator-portfolioview/target/classes/com/citi/translator/dap/
trunk/connectors/translator-portfolioview/target/classes/com/citi/translator/dap/PortfolioViewExecutionFactory.class
trunk/connectors/translator-portfolioview/target/test-classes/
trunk/runtime/src/test/java/org/teiid/deployers/TestCompositeVDB.java
Removed:
trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionParameter.java
Modified:
trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java
trunk/api/src/main/java/org/teiid/metadata/Schema.java
trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/modeshape/ModeShapeExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/resources/JCRFunctions.xmi
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TranslationHelper.java
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForceExecutionFactory.java
trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorManager.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/QueryProcessorFactoryImpl.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/SessionAwareCache.java
trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java
trunk/engine/src/main/java/org/teiid/query/function/FunctionForm.java
trunk/engine/src/main/java/org/teiid/query/function/FunctionLibrary.java
trunk/engine/src/main/java/org/teiid/query/function/FunctionMetadataSource.java
trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java
trunk/engine/src/main/java/org/teiid/query/function/UDFSource.java
trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMetadataReader.java
trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMetadataValidator.java
trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMethod.java
trunk/engine/src/main/java/org/teiid/query/function/metadata/InvalidFunctionItem.java
trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java
trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/JoinRegion.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/EvaluatableVisitor.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java
trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestConnectorCapabilitiesFinder.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedPlanCache.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestSessionAwareCache.java
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionDescriptorImpl.java
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMetadataReader.java
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionTree.java
trunk/engine/src/test/java/org/teiid/query/function/metadata/TestFunctionMetadataValidator.java
trunk/engine/src/test/java/org/teiid/query/function/metadata/TestFunctionMethod.java
trunk/engine/src/test/java/org/teiid/query/metadata/TestTransformationMetadata.java
trunk/engine/src/test/java/org/teiid/query/optimizer/FakeFunctionMetadataSource.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
trunk/metadata/src/test/java/org/teiid/cdk/api/TranslationUtility.java
trunk/metadata/src/test/java/org/teiid/metadata/index/VDBMetadataFactory.java
trunk/runtime/src/main/java/org/teiid/deployers/CompositeVDB.java
trunk/runtime/src/main/java/org/teiid/deployers/UDFMetaData.java
trunk/runtime/src/main/java/org/teiid/deployers/VDBDeployer.java
Log:
TEIID-231: Adding function support for Dynamic VDB based schema stores and Translators. Functions added through these mechanism will be automatically added to the FunctionLibrary, thus do not need to be added to separately as currently being done with UDF models. This change also adds additional API classes into Teiid API to support functions.
Added: trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java (rev 0)
+++ trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,484 @@
+/*
+ * 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.metadata;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.teiid.core.util.HashCodeUtil;
+
+
+/**
+ * <p>This class represents information about a particular function signature.
+ * Function signatures are unique with respect to their name, # of arguments,
+ * and type of arguments. Return type and argument names are not uniqueness
+ * factors. This class makes no attempt to validate the data put into it,
+ * particularly with respect to null values. The
+ * {@link FunctionMetadataValidator} can be used to validate this object.</p>
+ *
+ * Attributes:
+ * <UL>
+ * <LI>name - Name of the function</LI>
+ * <LI>description - Description of the function</LI>
+ * <LI>category - Function category containing this function</LI>
+ * <LI>pushdown - Determine whether this function can, cannot, or must be pushed down to a source</LI>
+ * <LI>invocationClass - Class containing method implementing this function</LI>
+ * <LI>invocationMethod - Method implementing this function</LI>
+ * <LI>inputParameters - 0 or more input parameters</LI>
+ * <LI>outputParameter - 1 output parameter</LI>
+ * <LI>determinism - specifies whether the function is deterministic or not. Various levels are provided
+ * <LI>nullOnNull - Specifies whether the function is called if any of the input arguments is null. The result is the null value.
+ * </UL>
+ *
+ * @see FunctionParameter
+ */
+public class FunctionMethod extends AbstractMetadataRecord implements Serializable {
+ private static final long serialVersionUID = -8039086494296455152L;
+
+ private static final String NOT_ALLOWED = "NOT_ALLOWED"; //$NON-NLS-1$
+ private static final String ALLOWED = "ALLOWED"; //$NON-NLS-1$
+ private static final String REQUIRED = "REQUIRED"; //$NON-NLS-1$
+
+ /**
+ * Function Pushdown
+ * CAN_PUSHDOWN = If the source supports the function, then it will be pushed down. Must supply the Java impl
+ * CANNOT_PUSHDOWN = It will not be pushed down, evaluated in Teiid. Must supply the Java impl
+ * MUST_PUSHDOWN = Function must be pushed to source, no need to supply Java impl.
+ * SYNTHETIC = system functions?
+ */
+ public enum PushDown {CAN_PUSHDOWN, CANNOT_PUSHDOWN, MUST_PUSHDOWN, SYNTHETIC};
+
+ /**
+ * DETERMINISTIC -> normal deterministic functions
+ * vdb -> lookup (however lookup values can be flushed at any time), current_database
+ * session -> env, user
+ * command -> command payload
+ * never -> rand, etc.
+ *
+ * Anything at a session level and above is treated as deterministic.
+ * This is not quite correct for lookup or env. Only in extremely rare
+ * circumstances would that be a problem.
+ *
+ * For now the commandPayload function is treated as a special case, like lookup, in
+ * that it is considered deterministic, but will be delayed in its evaluation until
+ * processing time.
+ */
+ public enum Determinism{
+ DETERMINISTIC(0),VDB_DETERMINISTIC(1),USER_DETERMINISTIC(2),SESSION_DETERMINISTIC(3),COMMAND_DETERMINISTIC(4),NONDETERMINISTIC(5);
+ private int value;
+
+ Determinism(int value){
+ this.value = value;
+ }
+
+ public boolean isRestrictiveThan(Determinism that) {
+ return this.value > that.value;
+ }
+
+ public boolean isRestrictiveThanOrEqual(Determinism that) {
+ return this.value >= that.value;
+ }
+
+ public static Determinism restrictiveOf(Determinism scopeOne, Determinism scopeTwo) {
+ return (scopeOne.value > scopeTwo.value)?scopeOne:scopeTwo;
+ }
+ }
+
+
+ private String description;
+ private String category;
+ private PushDown pushdown = PushDown.CAN_PUSHDOWN;
+ private String invocationClass;
+ private String invocationMethod;
+ private boolean nullDependent;
+
+ private Determinism determinism = Determinism.DETERMINISTIC;
+
+ private FunctionParameter[] inputParameters;
+ private FunctionParameter outputParameter;
+
+ protected FunctionMethod() {
+ }
+
+ public FunctionMethod(String name, String description, String category, FunctionParameter[] inputParams, FunctionParameter outputParam) {
+ this(name, description, category, PushDown.MUST_PUSHDOWN, null, null, inputParams, outputParam, true, Determinism.DETERMINISTIC);
+ }
+
+ public FunctionMethod(String name,
+ String description,
+ String category,
+ PushDown pushdown,
+ String invocationClass,
+ String invocationMethod,
+ FunctionParameter[] inputParams,
+ FunctionParameter outputParam,
+ boolean nullOnNull,
+ Determinism deterministic) {
+
+ setName(name);
+ setDescription(description);
+ setCategory(category);
+ setPushdown(pushdown);
+ setInvocationClass(invocationClass);
+ setInvocationMethod(invocationMethod);
+ setInputParameters(inputParams);
+ setOutputParameter(outputParam);
+ setNullOnNull(nullOnNull);
+ setDeterminism(deterministic);
+ }
+
+ /**
+ * Return name of method
+ * @return Name
+ */
+ @XmlAttribute
+ public String getName() {
+ return super.getName();
+ }
+
+ /**
+ * Set name of method
+ * @param name Name
+ */
+ public void setName(String name) {
+ super.setName(name);
+ }
+
+ @Override
+ public String getFullName() {
+ if (this.category != null) {
+ return this.category + NAME_DELIM_CHAR + getName();
+ }
+ return getName();
+ }
+
+
+ /**
+ * Get description of method
+ * @return Description
+ */
+ @XmlAttribute
+ public String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * Set description of method
+ * @param description Description
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Get category of method
+ * @return Category
+ * @see FunctionCategoryConstants
+ */
+ @XmlAttribute
+ public String getCategory() {
+ return this.category;
+ }
+
+ /**
+ * Set category of method
+ * @param category Category
+ * @see FunctionCategoryConstants
+ */
+ public void setCategory(String category) {
+ this.category = category;
+ }
+
+ /**
+ * Get pushdown property of method
+ * @return One of the FunctionMethod constants for pushdown
+ */
+ public PushDown getPushdown() {
+ return pushdown;
+ }
+
+ /**
+ * Set pushdown property of method
+ * @param pushdown One of the FunctionMethod constants for pushdown
+ */
+ public void setPushdown(PushDown pushdown) {
+ this.pushdown = pushdown;
+ }
+
+ @XmlAttribute
+ public void setPushDown(String pushdown) {
+ if (pushdown != null) {
+ if (pushdown.equals(REQUIRED)) {
+ this.pushdown = PushDown.MUST_PUSHDOWN;
+ } else if (pushdown.equals(ALLOWED)) {
+ this.pushdown = PushDown.CAN_PUSHDOWN;
+ } else if (pushdown.equals(NOT_ALLOWED)) {
+ this.pushdown = PushDown.CANNOT_PUSHDOWN;
+ }
+ } else {
+ this.pushdown = PushDown.CAN_PUSHDOWN;
+ }
+ }
+
+ /**
+ * Get invocation class name
+ * @return Invocation class name
+ */
+ @XmlAttribute
+ public String getInvocationClass() {
+ return this.invocationClass;
+ }
+
+ /**
+ * Set invocation class name
+ * @param invocationClass Invocation class name
+ */
+ public void setInvocationClass(String invocationClass) {
+ this.invocationClass = invocationClass;
+ }
+
+ /**
+ * Get invocation method name
+ * @return Invocation method name
+ */
+ @XmlAttribute
+ public String getInvocationMethod() {
+ return this.invocationMethod;
+ }
+
+ /**
+ * Set invocation method name
+ * @param invocationMethod Invocation method name
+ */
+ public void setInvocationMethod(String invocationMethod) {
+ this.invocationMethod = invocationMethod;
+ }
+
+ /**
+ * Get a count of the input parameters.
+ * @return Number of input parameters
+ */
+ public int getInputParameterCount() {
+ if(this.inputParameters == null) {
+ return 0;
+ }
+ return this.inputParameters.length;
+ }
+
+ /**
+ * Get input parameters
+ * @return Array of input parameters, may be null if 0 parameters
+ */
+ @XmlElement
+ public FunctionParameter[] getInputParameters() {
+ return this.inputParameters;
+ }
+
+ /**
+ * Set input parameters.
+ * @param params Input parameters
+ */
+ public void setInputParameters(FunctionParameter[] params) {
+ this.inputParameters = params;
+ }
+
+ /**
+ * Get ouput parameter.
+ * @return Output parameter or return argument
+ */
+ @XmlElement(name="returnParameter")
+ public FunctionParameter getOutputParameter() {
+ return this.outputParameter;
+ }
+
+ /**
+ * Set ouput parameter.
+ * @param param Output Parameter
+ */
+ public void setOutputParameter(FunctionParameter param) {
+ if (param != null) {
+ param.setName(FunctionParameter.OUTPUT_PARAMETER_NAME);
+ }
+ this.outputParameter = param;
+ }
+
+ /**
+ * Get hash code for this object. The hash code is based on the name
+ * and input parameters. <B>WARNING: Changing the name or input parameters
+ * will change the hash code.</B> If this occurs after the object has been
+ * placed in a HashSet or HashMap, the object will be lost!!!! In that
+ * case, the object must be added to the hashed collection again.
+ * @return Hash code, based on name and input parameters
+ */
+ public int hashCode() {
+ int hash = HashCodeUtil.hashCode(0, super.getName());
+ if(inputParameters != null) {
+ hash = HashCodeUtil.hashCode(hash, Arrays.hashCode(inputParameters));
+ }
+ return hash;
+ }
+
+ /**
+ * Compare other object for equality. This object is equal to another
+ * FunctionMethod if 1) Name of function matches (case-insensitive),
+ * 2) number of input parameters matches and 3) types of input parameters
+ * match.
+ * @return True if object equals this object according to conditions
+ */
+ public boolean equals(Object obj) {
+ if(obj == this) {
+ return true;
+ }
+ if(obj instanceof FunctionMethod) {
+ FunctionMethod other = (FunctionMethod) obj;
+
+ // Compare # of parameters - do this first as it is much faster than name compare
+ if(getInputParameterCount() != other.getInputParameterCount()) {
+ return false;
+ }
+
+ // Compare function names - case insensitive
+ if(other.getName() == null || this.getName() == null) {
+ return false;
+ }
+ if(! other.getName().equalsIgnoreCase(this.getName()) ) {
+ return false;
+ }
+
+ // Compare types of parameters
+ FunctionParameter[] thisInputs = this.getInputParameters();
+ if(thisInputs != null && thisInputs.length > 0) {
+ // If thisInputs is not null and >0 and other parameter
+ // count matched this parameter count, otherInputs MUST be
+ // non null to have more than one parameter - so we don't
+ // need to check it here.
+ FunctionParameter[] otherInputs = other.getInputParameters();
+
+ for(int i=0; i<thisInputs.length; i++) {
+ boolean paramMatch = compareWithNull(thisInputs[i], otherInputs[i]);
+ if(! paramMatch) {
+ return false;
+ }
+ }
+ }
+
+ // Found no discrepancies, must be equal
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Compare two objects that may or may not be null and consider null==null
+ * as true.
+ * @param o1 Object 1
+ * @param o2 Object 2
+ * @return True if o1 and o2 are null or if they both aren't and they are equal
+ */
+ private boolean compareWithNull(Object o1, Object o2) {
+ if(o1 == null) {
+ if(o2 == null) {
+ return true;
+ }
+ return false;
+ }
+ if(o2 == null) {
+ return false;
+ }
+ return o1.equals(o2);
+ }
+
+ /**
+ * Return string version for debugging purposes
+ * @return String representation of function method
+ */
+ public String toString() {
+ StringBuffer str = new StringBuffer();
+ if(getName() != null) {
+ str.append(getName());
+ } else {
+ str.append("<unknown>"); //$NON-NLS-1$
+ }
+
+ // Print parameters
+ str.append("("); //$NON-NLS-1$
+ if(inputParameters != null) {
+ for(int i=0; i<inputParameters.length; i++) {
+ if(inputParameters[i] != null) {
+ str.append(inputParameters[i].toString());
+ } else {
+ str.append("<unknown>"); //$NON-NLS-1$
+ }
+
+ if(i < (inputParameters.length-1)) {
+ str.append(", "); //$NON-NLS-1$
+ }
+ }
+ }
+ str.append(") : "); //$NON-NLS-1$
+
+ // Print return type
+ if(outputParameter != null) {
+ str.append(outputParameter.toString());
+ } else {
+ str.append("<unknown>"); //$NON-NLS-1$
+ }
+
+ return str.toString();
+ }
+
+ /**
+ * Returns true if the function can produce a non-null output from a null parameter
+ */
+ public boolean isNullOnNull() {
+ return this.nullDependent;
+ }
+
+ public void setNullOnNull(boolean nullSafe) {
+ this.nullDependent = nullSafe;
+ }
+
+ public Determinism getDeterminism() {
+ return this.determinism;
+ }
+
+ @XmlAttribute(name="deterministic")
+ public void setDeterministicBoolean(boolean deterministic) {
+ this.determinism = deterministic ? Determinism.DETERMINISTIC : Determinism.NONDETERMINISTIC;
+ }
+
+ public void setDeterminism(Determinism determinism) {
+ this.determinism = determinism;
+ }
+
+ public boolean isVarArgs() {
+ if (this.inputParameters != null && this.inputParameters.length > 0) {
+ return inputParameters[inputParameters.length - 1].isVarArg();
+ }
+ return false;
+ }
+
+}
Property changes on: trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/api/src/main/java/org/teiid/metadata/FunctionParameter.java (from rev 2683, trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionParameter.java)
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/FunctionParameter.java (rev 0)
+++ trunk/api/src/main/java/org/teiid/metadata/FunctionParameter.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,186 @@
+/*
+ * 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.metadata;
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+
+/**
+ * A function parameter defines the name and description of an input or output
+ * parameter for a function. The name should not be null, but that is not
+ * verified by this class. Validation of this object can be done with the
+ * {@link FunctionMetadataValidator}. The type string used in the function
+ * parameter should be one of the standard type names defined in
+ * {@link org.teiid.core.types.DataTypeManager.DefaultDataTypes}.
+ */
+public class FunctionParameter implements Serializable {
+ private static final long serialVersionUID = -4696050948395485266L;
+
+ public static final String OUTPUT_PARAMETER_NAME = "result"; //$NON-NLS-1$
+
+ private String name;
+ private String type;
+ private String description;
+ private boolean isVarArg;
+
+ /**
+ * Construct a function parameter with no attributes.
+ */
+ public FunctionParameter() {
+ }
+
+ /**
+ * Construct a function parameter with no description.
+ * @param name Name
+ * @param type Type from standard set of types
+ */
+ public FunctionParameter(String name, String type) {
+ this(name, type, null);
+ }
+
+ /**
+ * Construct a function parameter with all attributes.
+ * @param name Name
+ * @param type Type from standard set of types
+ * @param description Description
+ */
+ public FunctionParameter(String name, String type, String description) {
+ this(name, type, description, false);
+ }
+
+ public FunctionParameter(String name, String type, String description, boolean vararg) {
+ setName(name);
+ setType(type);
+ setDescription(description);
+ this.isVarArg = vararg;
+ }
+
+ /**
+ * Return name of parameter.
+ * @return Name
+ */
+ @XmlAttribute
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Set name
+ * @param name Name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Get description of parameter
+ * @return Description
+ */
+ @XmlAttribute
+ public String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * Set description of parameter
+ * @param description Description
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Get type of parameter
+ * @return Type name
+ * @see org.teiid.core.types.DataTypeManager.DefaultDataTypes
+ */
+ @XmlAttribute
+ public String getType() {
+ return this.type;
+ }
+
+ /**
+ * Set type of parameter
+ * @param type Type of parameter
+ * @see org.teiid.core.types.DataTypeManager.DefaultDataTypes
+ */
+ public void setType(String type) {
+ if(type == null) {
+ this.type = null;
+ } else {
+ this.type = type.toLowerCase();
+ }
+ }
+
+ /**
+ * Return hash code for this parameter. The hash code is based only
+ * on the type of the parameter. Changing the type of the parameter
+ * after placing this object in a hashed collection will likely cause
+ * the object to be lost.
+ * @return Hash code
+ */
+ public int hashCode() {
+ if(this.type == null) {
+ return 0;
+ }
+ return this.type.hashCode();
+ }
+
+ /**
+ * Compare with other object for equality. Equality is based on whether
+ * the type is the same as the other parameter.
+ * @return True if equal to obj
+ */
+ public boolean equals(Object obj) {
+ if(obj == this) {
+ return true;
+ }
+ if(!(obj instanceof FunctionParameter)) {
+ return false;
+ }
+ FunctionParameter other = (FunctionParameter) obj;
+ if(other.getType() == null) {
+ return (this.getType() == null);
+ }
+ return other.getType().equals(this.getType()) && this.isVarArg == other.isVarArg;
+ }
+
+ /**
+ * Return string version for debugging purposes
+ * @return String representation of function parameter
+ */
+ public String toString() {
+ return type + (isVarArg?"... ":" ") + name; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void setVarArg(boolean isVarArg) {
+ this.isVarArg = isVarArg;
+ }
+
+ public boolean isVarArg() {
+ return isVarArg;
+ }
+
+}
Modified: trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -276,4 +276,18 @@
}
}
}
+
+ /**
+ * Add a function with the given name to the model.
+ * @param name
+ * @return
+ * @throws TranslatorException
+ */
+ public FunctionMethod addFunction(String name) throws TranslatorException {
+ FunctionMethod function = new FunctionMethod();
+ function.setName(name);
+ setUUID(function);
+ this.schema.addFunction(function);
+ return function;
+ }
}
Modified: trunk/api/src/main/java/org/teiid/metadata/Schema.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/Schema.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/api/src/main/java/org/teiid/metadata/Schema.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -35,6 +35,7 @@
private Map<String, Table> tables = new LinkedHashMap<String, Table>();
private Map<String, Procedure> procedures = new LinkedHashMap<String, Procedure>();
+ private Map<String, FunctionMethod> functions = new LinkedHashMap<String, FunctionMethod>();
public void addTable(Table table) {
table.setParent(this);
@@ -45,6 +46,10 @@
procedure.setParent(this);
this.procedures.put(procedure.getName().toLowerCase(), procedure);
}
+
+ public void addFunction(FunctionMethod function) {
+ this.functions.put(function.getName().toLowerCase(), function);
+ }
/**
* Get the tables defined in this schema
@@ -62,6 +67,14 @@
return procedures;
}
+ /**
+ * Get the functions defined in this schema
+ * @return
+ */
+ public Map<String, FunctionMethod> getFunctions() {
+ return functions;
+ }
+
public String getPrimaryMetamodelUri() {
return primaryMetamodelUri;
}
Modified: trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -23,6 +23,7 @@
package org.teiid.translator;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -41,6 +42,7 @@
import org.teiid.language.SetQuery;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.RuntimeMetadata;
@@ -647,6 +649,10 @@
return null;
}
+ public List<FunctionMethod> getPushDownFunctions(){
+ return Collections.EMPTY_LIST;
+ }
+
/**
* Get the integer value representing the number of values allowed in an IN criteria
* in the WHERE clause of a query
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/modeshape/ModeShapeExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/modeshape/ModeShapeExecutionFactory.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/modeshape/ModeShapeExecutionFactory.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -29,6 +29,7 @@
import java.util.Arrays;
import java.util.List;
+import org.teiid.core.types.DataTypeManager;
import org.teiid.language.Comparison;
import org.teiid.language.Function;
import org.teiid.language.LanguageObject;
@@ -37,6 +38,8 @@
import org.teiid.language.Comparison.Operator;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.SourceSystemFunctions;
import org.teiid.translator.Translator;
@@ -51,6 +54,13 @@
@Translator(name="modeshape", description="A translator for the open source Modeshape JCR Repository")
public class ModeShapeExecutionFactory extends JDBCExecutionFactory {
+ private static final String JCR = "JCR"; //$NON-NLS-1$
+ private static final String JCR_REFERENCE = "JCR_REFERENCE";//$NON-NLS-1$
+ private static final String JCR_CONTAINS = "JCR_CONTAINS";//$NON-NLS-1$
+ private static final String JCR_ISSAMENODE = "JCR_ISSAMENODE";//$NON-NLS-1$
+ private static final String JCR_ISDESCENDANTNODE = "JCR_ISDESCENDANTNODE";//$NON-NLS-1$
+ private static final String JCR_ISCHILDNODE = "JCR_ISCHILDNODE";//$NON-NLS-1$
+
public ModeShapeExecutionFactory() {
setDatabaseVersion("2.0"); //$NON-NLS-1$
setUseBindVariables(false);
@@ -63,11 +73,11 @@
registerFunctionModifier(SourceSystemFunctions.UCASE, new AliasModifier("UpperCase")); //$NON-NLS-1$
registerFunctionModifier(SourceSystemFunctions.LCASE,new AliasModifier("LowerCase")); //$NON-NLS-1$
- registerFunctionModifier("JCR_ISCHILDNODE", new IdentifierFunctionModifier()); //$NON-NLS-1$
- registerFunctionModifier("JCR_ISDESCENDANTNODE", new IdentifierFunctionModifier()); //$NON-NLS-1$
- registerFunctionModifier("JCR_ISSAMENODE", new IdentifierFunctionModifier()); //$NON-NLS-1$
- registerFunctionModifier("JCR_REFERENCE", new IdentifierFunctionModifier()); //$NON-NLS-1$
- registerFunctionModifier("JCR_CONTAINS", new IdentifierFunctionModifier()); //$NON-NLS-1$
+ registerFunctionModifier(JCR_ISCHILDNODE, new IdentifierFunctionModifier());
+ registerFunctionModifier(JCR_ISDESCENDANTNODE, new IdentifierFunctionModifier());
+ registerFunctionModifier(JCR_ISSAMENODE, new IdentifierFunctionModifier());
+ registerFunctionModifier(JCR_REFERENCE, new IdentifierFunctionModifier());
+ registerFunctionModifier(JCR_CONTAINS, new IdentifierFunctionModifier());
LogManager.logTrace(LogConstants.CTX_CONNECTOR, "ModeShape Translator Started"); //$NON-NLS-1$
}
@@ -99,15 +109,45 @@
supportedFunctions.add(SourceSystemFunctions.UCASE);
supportedFunctions.add(SourceSystemFunctions.LCASE);
supportedFunctions.add(SourceSystemFunctions.LENGTH);
- supportedFunctions.add("JCR_ISCHILDNODE"); //$NON-NLS-1$
- supportedFunctions.add("JCR_ISDESCENDANTNODE"); //$NON-NLS-1$
- supportedFunctions.add("JCR_ISSAMENODE"); //$NON-NLS-1$
- supportedFunctions.add("JCR_REFERENCE"); //$NON-NLS-1$
- supportedFunctions.add("JCR_CONTAINS"); //$NON-NLS-1$
return supportedFunctions;
}
+
@Override
+ public List<FunctionMethod> getPushDownFunctions(){
+ List<FunctionMethod> pushdownFunctions = new ArrayList<FunctionMethod>();
+ pushdownFunctions.add(new FunctionMethod(JCR_ISCHILDNODE, JCR_ISCHILDNODE, JCR,
+ new FunctionParameter[] {
+ new FunctionParameter("path1", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("path2", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ pushdownFunctions.add(new FunctionMethod(JCR_ISDESCENDANTNODE, JCR_ISDESCENDANTNODE, JCR,
+ new FunctionParameter[] {
+ new FunctionParameter("path1", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("path2", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ pushdownFunctions.add(new FunctionMethod(JCR_ISSAMENODE, JCR_ISSAMENODE, JCR,
+ new FunctionParameter[] {
+ new FunctionParameter("path1", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("path2", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ pushdownFunctions.add(new FunctionMethod(JCR_CONTAINS, JCR_CONTAINS, JCR,
+ new FunctionParameter[] {
+ new FunctionParameter("selectorOrProperty", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("searchExpr", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ pushdownFunctions.add(new FunctionMethod(JCR_REFERENCE, JCR_REFERENCE, JCR,
+ new FunctionParameter[] {
+ new FunctionParameter("selectorOrProperty", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ return pushdownFunctions;
+ }
+
+ @Override
public List<?> translate(LanguageObject obj, ExecutionContext context) {
if (obj instanceof Comparison) {
Comparison compare = (Comparison)obj;
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -49,6 +49,7 @@
import org.teiid.language.SetQuery.Operation;
import org.teiid.language.visitor.CollectorVisitor;
import org.teiid.metadata.Column;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.SourceSystemFunctions;
import org.teiid.translator.Translator;
@@ -65,25 +66,17 @@
@Translator(name="oracle", description="A translator for Oracle 9i Database or later")
public class OracleExecutionFactory extends JDBCExecutionFactory {
+
private static final String TIME_FORMAT = "HH24:MI:SS"; //$NON-NLS-1$
private static final String DATE_FORMAT = "YYYY-MM-DD"; //$NON-NLS-1$
private static final String DATETIME_FORMAT = DATE_FORMAT + " " + TIME_FORMAT; //$NON-NLS-1$
private static final String TIMESTAMP_FORMAT = DATETIME_FORMAT + ".FF"; //$NON-NLS-1$
- /*
- * Spatial Functions
- */
- public static final String RELATE = "sdo_relate"; //$NON-NLS-1$
- public static final String NEAREST_NEIGHBOR = "sdo_nn"; //$NON-NLS-1$
- public static final String FILTER = "sdo_filter"; //$NON-NLS-1$
- public static final String WITHIN_DISTANCE = "sdo_within_distance"; //$NON-NLS-1$
- public static final String NEAREST_NEIGHBOR_DISTANCE = "sdo_nn_distance"; //$NON-NLS-1$
-
public final static String HINT_PREFIX = "/*+"; //$NON-NLS-1$
public final static String DUAL = "DUAL"; //$NON-NLS-1$
public final static String ROWNUM = "ROWNUM"; //$NON-NLS-1$
public final static String SEQUENCE = ":SEQUENCE="; //$NON-NLS-1$
-
+
public void start() throws TranslatorException {
super.start();
@@ -120,10 +113,10 @@
});
//spatial functions
- registerFunctionModifier(RELATE, new OracleSpatialFunctionModifier());
- registerFunctionModifier(NEAREST_NEIGHBOR, new OracleSpatialFunctionModifier());
- registerFunctionModifier(FILTER, new OracleSpatialFunctionModifier());
- registerFunctionModifier(WITHIN_DISTANCE, new OracleSpatialFunctionModifier());
+ registerFunctionModifier(OracleSpatialFunctions.RELATE, new OracleSpatialFunctionModifier());
+ registerFunctionModifier(OracleSpatialFunctions.NEAREST_NEIGHBOR, new OracleSpatialFunctionModifier());
+ registerFunctionModifier(OracleSpatialFunctions.FILTER, new OracleSpatialFunctionModifier());
+ registerFunctionModifier(OracleSpatialFunctions.WITHIN_DISTANCE, new OracleSpatialFunctionModifier());
//add in type conversion
ConvertModifier convertModifier = new ConvertModifier();
@@ -335,7 +328,7 @@
// If so, the ORDERED hint is added, if not, it isn't
Collection<Function> col = CollectorVisitor.collectObjects(Function.class, command);
for (Function func : col) {
- if (func.getName().equalsIgnoreCase(RELATE)) {
+ if (func.getName().equalsIgnoreCase(OracleSpatialFunctions.RELATE)) {
return comment + "/*+ ORDERED */ "; //$NON-NLS-1$
}
}
@@ -465,15 +458,15 @@
supportedFunctions.add("NVL"); //$NON-NLS-1$
supportedFunctions.add("COALESCE"); //$NON-NLS-1$
- supportedFunctions.add(OracleExecutionFactory.RELATE);
- supportedFunctions.add(OracleExecutionFactory.NEAREST_NEIGHBOR);
- supportedFunctions.add(OracleExecutionFactory.FILTER);
- supportedFunctions.add(OracleExecutionFactory.NEAREST_NEIGHBOR_DISTANCE);
- supportedFunctions.add(OracleExecutionFactory.WITHIN_DISTANCE);
return supportedFunctions;
}
@Override
+ public List<FunctionMethod> getPushDownFunctions(){
+ return OracleSpatialFunctions.getOracleSpatialFunctions();
+ }
+
+ @Override
public String translateLiteralTimestamp(Timestamp timestampValue) {
if (timestampValue.getNanos() == 0) {
String val = formatDateValue(timestampValue);
Added: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleSpatialFunctions.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleSpatialFunctions.java (rev 0)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleSpatialFunctions.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,149 @@
+/*
+ * 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.translator.jdbc.oracle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
+
+public class OracleSpatialFunctions {
+
+ /*
+ * Spatial Functions
+ */
+ public static final String RELATE = "sdo_relate"; //$NON-NLS-1$
+ public static final String NEAREST_NEIGHBOR = "sdo_nn"; //$NON-NLS-1$
+ public static final String FILTER = "sdo_filter"; //$NON-NLS-1$
+ public static final String WITHIN_DISTANCE = "sdo_within_distance"; //$NON-NLS-1$
+ public static final String NEAREST_NEIGHBOR_DISTANCE = "sdo_nn_distance"; //$NON-NLS-1$
+ private static final String ORACLE_SDO = "Oracle-SDO"; //$NON-NLS-1$
+
+
+ public static List<FunctionMethod> getOracleSpatialFunctions(){
+
+ List<FunctionMethod> spatialFuncs = new ArrayList<FunctionMethod>();
+
+ spatialFuncs.add(new FunctionMethod(RELATE, RELATE, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(RELATE, RELATE, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(RELATE, RELATE, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(RELATE, RELATE, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(NEAREST_NEIGHBOR, NEAREST_NEIGHBOR, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("NUMBER", DataTypeManager.DefaultDataTypes.INTEGER, "") }, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(NEAREST_NEIGHBOR, NEAREST_NEIGHBOR, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("NUMBER", DataTypeManager.DefaultDataTypes.INTEGER, "") }, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(NEAREST_NEIGHBOR, NEAREST_NEIGHBOR, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("NUMBER", DataTypeManager.DefaultDataTypes.INTEGER, "") }, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(NEAREST_NEIGHBOR_DISTANCE, NEAREST_NEIGHBOR_DISTANCE, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("NUMBER", DataTypeManager.DefaultDataTypes.INTEGER, "") }, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.INTEGER, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(WITHIN_DISTANCE, WITHIN_DISTANCE, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(WITHIN_DISTANCE, WITHIN_DISTANCE, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(WITHIN_DISTANCE, WITHIN_DISTANCE, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(FILTER, FILTER, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(FILTER, FILTER, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ spatialFuncs.add(new FunctionMethod(FILTER, FILTER, ORACLE_SDO,
+ new FunctionParameter[] {
+ new FunctionParameter("GEOM1", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("GEOM2", DataTypeManager.DefaultDataTypes.OBJECT, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("PARAMS", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ return spatialFuncs;
+ }
+}
Property changes on: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleSpatialFunctions.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/connectors/translator-jdbc/src/main/resources/JCRFunctions.xmi
===================================================================
--- trunk/connectors/translator-jdbc/src/main/resources/JCRFunctions.xmi 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-jdbc/src/main/resources/JCRFunctions.xmi 2010-12-03 18:46:01 UTC (rev 2754)
@@ -12,18 +12,18 @@
</diagram:DiagramContainer>
<mmcore:AnnotationContainer xmi:uuid="mmuuid:c3c82dbf-1339-4354-b23d-7135aa430b21"/>
<mmfunction:ScalarFunction xmi:uuid="mmuuid:ecf2b4a4-40fe-4cab-b84a-93a26c0560c7" name="JCR_ISCHILDNODE" category="JCR" pushDown="REQUIRED">
- <inputParameters xmi:uuid="mmuuid:23fd3fce-de13-4b11-957d-a44c2ac6da43" name="path" type="string"/>
- <inputParameters xmi:uuid="mmuuid:68bafab4-98f7-472d-81cb-38e6bf2aa096" name="path" type="string"/>
+ <inputParameters xmi:uuid="mmuuid:23fd3fce-de13-4b11-957d-a44c2ac6da43" name="path1" type="string"/>
+ <inputParameters xmi:uuid="mmuuid:68bafab4-98f7-472d-81cb-38e6bf2aa096" name="path2" type="string"/>
<returnParameter xmi:uuid="mmuuid:151394ed-8654-4e9a-a081-f3bf02b71b2d" type="boolean"/>
</mmfunction:ScalarFunction>
<mmfunction:ScalarFunction xmi:uuid="mmuuid:6387763f-0397-4abc-a2ca-46c9c0f793bd" name="JCR_ISDESCENDANTNODE" category="JCR" pushDown="REQUIRED">
- <inputParameters xmi:uuid="mmuuid:c3a1f10b-58a5-4c5b-a94f-bac009b31284" name="path" type="string"/>
- <inputParameters xmi:uuid="mmuuid:403500a9-f48b-4603-8d92-2011944baa9d" name="path" type="string"/>
+ <inputParameters xmi:uuid="mmuuid:c3a1f10b-58a5-4c5b-a94f-bac009b31284" name="path1" type="string"/>
+ <inputParameters xmi:uuid="mmuuid:403500a9-f48b-4603-8d92-2011944baa9d" name="path2" type="string"/>
<returnParameter xmi:uuid="mmuuid:ae90df19-106a-481d-b905-68a9c2493316" type="boolean"/>
</mmfunction:ScalarFunction>
<mmfunction:ScalarFunction xmi:uuid="mmuuid:4ecc9ba6-a383-4196-a261-1860cc3ee88c" name="JCR_ISSAMENODE" category="JCR" pushDown="REQUIRED">
- <inputParameters xmi:uuid="mmuuid:94a8a68c-4744-4cdb-9ad8-23417e5aff56" name="path" type="string"/>
- <inputParameters xmi:uuid="mmuuid:004473ae-2199-43d0-b4bd-fd996fa18b7b" name="path" type="string"/>
+ <inputParameters xmi:uuid="mmuuid:94a8a68c-4744-4cdb-9ad8-23417e5aff56" name="path1" type="string"/>
+ <inputParameters xmi:uuid="mmuuid:004473ae-2199-43d0-b4bd-fd996fa18b7b" name="path2" type="string"/>
<returnParameter xmi:uuid="mmuuid:8ab20d78-fd6a-400a-9e03-70be996b4cc6" type="boolean"/>
</mmfunction:ScalarFunction>
<mmfunction:ScalarFunction xmi:uuid="mmuuid:a84444b6-79b4-45bc-97bf-745503dabc03" name="JCR_CONTAINS" category="JCR" pushDown="REQUIRED">
Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TranslationHelper.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TranslationHelper.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TranslationHelper.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -36,8 +36,8 @@
import org.teiid.cdk.unittest.FakeTranslationFactory;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.language.Command;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.query.function.metadata.FunctionMetadataReader;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.ExecutionContext;
Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -722,7 +722,7 @@
RealMetadataFactory.createElements(dual, new String[] {"something"}, new String[] {DataTypeManager.DefaultDataTypes.STRING}); //$NON-NLS-1$
CompositeMetadataStore store = new CompositeMetadataStore(metadataStore);
- return new TransformationMetadata(null, store, null, null, FakeMetadataFactory.SFM.getSystemFunctions());
+ return new TransformationMetadata(null, store, null, FakeMetadataFactory.SFM.getSystemFunctions(), null);
}
public void helpTestVisitor(String vdb, String input, String expectedOutput) throws TranslatorException {
Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -160,7 +160,7 @@
obj.setNativeType("uniqueidentifier"); //$NON-NLS-1$
CompositeMetadataStore store = new CompositeMetadataStore(metadataStore);
- QueryMetadataInterface metadata = new TransformationMetadata(null, store, null, null, FakeMetadataFactory.SFM.getSystemFunctions());
+ QueryMetadataInterface metadata = new TransformationMetadata(null, store, null, FakeMetadataFactory.SFM.getSystemFunctions(), null);
TranslationUtility tu = new TranslationUtility(metadata);
Command command = tu.parseCommand("select max(x) from bar"); //$NON-NLS-1$
Modified: trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
===================================================================
--- trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -304,7 +304,7 @@
}
// Create the facade from the store
- return new TransformationMetadata(null, new CompositeMetadataStore(metadataStore), null, null, FakeMetadataFactory.SFM.getSystemFunctions());
+ return new TransformationMetadata(null, new CompositeMetadataStore(metadataStore), null, FakeMetadataFactory.SFM.getSystemFunctions(), null);
}
}
Added: trunk/connectors/translator-portfolioview/.classpath
===================================================================
--- trunk/connectors/translator-portfolioview/.classpath (rev 0)
+++ trunk/connectors/translator-portfolioview/.classpath 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
Property changes on: trunk/connectors/translator-portfolioview/.classpath
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-portfolioview/.project
===================================================================
--- trunk/connectors/translator-portfolioview/.project (rev 0)
+++ trunk/connectors/translator-portfolioview/.project 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>translator-portfolioview</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ </natures>
+</projectDescription>
Property changes on: trunk/connectors/translator-portfolioview/.project
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-portfolioview/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- trunk/connectors/translator-portfolioview/.settings/org.eclipse.jdt.core.prefs (rev 0)
+++ trunk/connectors/translator-portfolioview/.settings/org.eclipse.jdt.core.prefs 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,6 @@
+#Tue Nov 16 14:11:58 EST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
Property changes on: trunk/connectors/translator-portfolioview/.settings/org.eclipse.jdt.core.prefs
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-portfolioview/.settings/org.maven.ide.eclipse.prefs
===================================================================
--- trunk/connectors/translator-portfolioview/.settings/org.maven.ide.eclipse.prefs (rev 0)
+++ trunk/connectors/translator-portfolioview/.settings/org.maven.ide.eclipse.prefs 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,9 @@
+#Tue Nov 16 14:11:30 EST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
Property changes on: trunk/connectors/translator-portfolioview/.settings/org.maven.ide.eclipse.prefs
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-portfolioview/pom.xml
===================================================================
--- trunk/connectors/translator-portfolioview/pom.xml (rev 0)
+++ trunk/connectors/translator-portfolioview/pom.xml 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>connectors</artifactId>
+ <groupId>org.jboss.teiid</groupId>
+ <version>7.2.0.CR1-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>translator-portfolioview</artifactId>
+ <groupId>org.jboss.teiid.connectors</groupId>
+ <name>Portfolio View Generator Translator</name>
+ <description>This translator injects portfolio views into Teiid VDB</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>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.resource</groupId>
+ <artifactId>connector-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <outputDirectory>target/classes</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*.xml</include>
+ <include>**/*.properties</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>false</filtering>
+ <excludes>
+ <exclude>**/*.xml</exclude>
+ <exclude>**/*.properties</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+
+</project>
Property changes on: trunk/connectors/translator-portfolioview/pom.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-portfolioview/src/main/java/com/citi/translator/dap/PortfolioViewExecutionFactory.java
===================================================================
--- trunk/connectors/translator-portfolioview/src/main/java/com/citi/translator/dap/PortfolioViewExecutionFactory.java (rev 0)
+++ trunk/connectors/translator-portfolioview/src/main/java/com/citi/translator/dap/PortfolioViewExecutionFactory.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,90 @@
+/*
+ * 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 com.citi.translator.dap;
+
+import java.sql.Connection;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.resource.cci.ConnectionFactory;
+
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.language.Call;
+import org.teiid.metadata.MetadataFactory;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.metadata.Table;
+import org.teiid.metadata.Table.Type;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ExecutionFactory;
+import org.teiid.translator.ProcedureExecution;
+import org.teiid.translator.Translator;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TranslatorProperty;
+
+@Translator(name="portfolioview", description="A translator for creating a portfolio view")
+public class PortfolioViewExecutionFactory extends ExecutionFactory<ConnectionFactory, Connection> {
+
+ private String portfolioName;
+
+ @TranslatorProperty(display="portfolio name", description="Portfolio View name")
+ public String getPortfolioName() {
+ return this.portfolioName;
+ }
+
+ public void setPortfolioName(String portfolio) {
+ this.portfolioName = portfolio;
+ }
+
+ @Override
+ public ProcedureExecution createProcedureExecution(Call command, ExecutionContext executionContext, RuntimeMetadata metadata, Connection connection)
+ throws TranslatorException {
+ throw new TranslatorException("This is view model, no executions allowed"); //$NON-NLS-1$
+ }
+
+ @Override
+ public final List getSupportedFunctions() {
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public void getMetadata(MetadataFactory metadataFactory, Connection conn) throws TranslatorException {
+ Table t = createView(metadataFactory, "pg_attribute"); //$NON-NLS-1$
+
+ metadataFactory.addColumn("oid", DataTypeManager.DefaultDataTypes.INTEGER, t); //$NON-NLS-1$
+
+ metadataFactory.addPrimaryKey("pk_pg_attr", Arrays.asList("oid"), t); //$NON-NLS-1$ //$NON-NLS-2$
+
+ String transformation = "select * from foo"; //$NON-NLS-1$
+ t.setSelectTransformation(transformation);
+ }
+
+
+ private Table createView(MetadataFactory metadataFactory, String name) throws TranslatorException {
+ Table t = metadataFactory.addTable(name);
+ t.setSupportsUpdate(false);
+ t.setVirtual(true);
+ t.setTableType(Type.Table);
+ return t;
+ }
+}
Property changes on: trunk/connectors/translator-portfolioview/src/main/java/com/citi/translator/dap/PortfolioViewExecutionFactory.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-portfolioview/src/main/resources/META-INF/jboss-beans.xml
===================================================================
--- trunk/connectors/translator-portfolioview/src/main/resources/META-INF/jboss-beans.xml (rev 0)
+++ trunk/connectors/translator-portfolioview/src/main/resources/META-INF/jboss-beans.xml 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="translator-citi-dap" class="org.teiid.templates.TranslatorDeploymentTemplate">
+ <property name="info"><inject bean="translator-citi-dap"/></property>
+ <property name="managedObjectFactory"><inject bean="ManagedObjectFactory"/></property>
+ </bean>
+
+ <bean name="translator-citi-dap" 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">com.citi.translator.dap.DAPExecutionFactory</parameter>
+ <parameter class="java.lang.String">translator-citi-dap</parameter>
+ <parameter class="java.lang.String">citi-dap</parameter>
+ </constructor>
+ </bean>
+
+</deployment>
Property changes on: trunk/connectors/translator-portfolioview/src/main/resources/META-INF/jboss-beans.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-portfolioview/target/classes/META-INF/jboss-beans.xml
===================================================================
--- trunk/connectors/translator-portfolioview/target/classes/META-INF/jboss-beans.xml (rev 0)
+++ trunk/connectors/translator-portfolioview/target/classes/META-INF/jboss-beans.xml 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="translator-citi-dap" class="org.teiid.templates.TranslatorDeploymentTemplate">
+ <property name="info"><inject bean="translator-citi-dap"/></property>
+ <property name="managedObjectFactory"><inject bean="ManagedObjectFactory"/></property>
+ </bean>
+
+ <bean name="translator-citi-dap" 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">com.citi.translator.dap.DAPExecutionFactory</parameter>
+ <parameter class="java.lang.String">translator-citi-dap</parameter>
+ <parameter class="java.lang.String">citi-dap</parameter>
+ </constructor>
+ </bean>
+
+</deployment>
Property changes on: trunk/connectors/translator-portfolioview/target/classes/META-INF/jboss-beans.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/translator-portfolioview/target/classes/com/citi/translator/dap/PortfolioViewExecutionFactory.class
===================================================================
(Binary files differ)
Property changes on: trunk/connectors/translator-portfolioview/target/classes/com/citi/translator/dap/PortfolioViewExecutionFactory.class
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForceExecutionFactory.java
===================================================================
--- trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForceExecutionFactory.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/SalesForceExecutionFactory.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -23,15 +23,19 @@
package org.teiid.translator.salesforce;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import javax.resource.cci.ConnectionFactory;
+import org.teiid.core.types.DataTypeManager;
import org.teiid.language.Call;
import org.teiid.language.Command;
import org.teiid.language.QueryExpression;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.RuntimeMetadata;
import org.teiid.translator.ExecutionContext;
@@ -51,6 +55,9 @@
@Translator(name="salesforce", description="A translator for Salesforce")
public class SalesForceExecutionFactory extends ExecutionFactory<ConnectionFactory, SalesforceConnection> {
+ private static final String SALESFORCE = "salesforce"; //$NON-NLS-1$
+ private static final String EXCLUDES = "excludes";//$NON-NLS-1$
+ private static final String INCLUDES = "includes";//$NON-NLS-1$
private String connectorStateClass;
private boolean auditModelFields = false;
@@ -123,11 +130,25 @@
@Override
public List getSupportedFunctions() {
- List<String> supportedFunctions = new ArrayList<String>();
- supportedFunctions.add("includes"); //$NON-NLS-1$
- supportedFunctions.add("excludes"); //$NON-NLS-1$
- return supportedFunctions;
+ return Collections.EMPTY_LIST;
}
+
+ @Override
+ public List<FunctionMethod> getPushDownFunctions(){
+ List<FunctionMethod> pushdownFunctions = new ArrayList<FunctionMethod>();
+ pushdownFunctions.add(new FunctionMethod(INCLUDES, INCLUDES, SALESFORCE,
+ new FunctionParameter[] {
+ new FunctionParameter("columnName", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("param", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ pushdownFunctions.add(new FunctionMethod(EXCLUDES, EXCLUDES, SALESFORCE,
+ new FunctionParameter[] {
+ new FunctionParameter("columnName", DataTypeManager.DefaultDataTypes.STRING, ""), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("param", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ return pushdownFunctions;
+ }
@Override
public boolean supportsCompareCriteriaEquals() {
Modified: trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java
===================================================================
--- trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -96,7 +96,7 @@
Column obj = contactCols.get(i);
obj.setNameInSource(contactNameInSource[i]);
}
- return new TransformationMetadata(null, new CompositeMetadataStore(store), null, null, FakeMetadataFactory.SFM.getSystemFunctions());
+ return new TransformationMetadata(null, new CompositeMetadataStore(store), null, FakeMetadataFactory.SFM.getSystemFunctions(), null);
}
private static TranslationUtility translationUtility = new TranslationUtility(exampleSalesforce());
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -25,6 +25,7 @@
import java.util.Iterator;
import java.util.List;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.SourceCapabilities;
import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
@@ -106,6 +107,12 @@
tgtCaps.setFunctionSupport(func.toLowerCase(), true);
}
}
+ List<FunctionMethod> pushDowns = srcCaps.getPushDownFunctions();
+ if(pushDowns != null && pushDowns.size() > 0) {
+ for(FunctionMethod func:pushDowns) {
+ tgtCaps.setFunctionSupport(func.getName().toLowerCase(), true);
+ }
+ }
tgtCaps.setSourceProperty(Capability.MAX_IN_CRITERIA_SIZE, new Integer(srcCaps.getMaxInCriteriaSize()));
tgtCaps.setSourceProperty(Capability.CONNECTOR_ID, connectorID);
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorManager.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorManager.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorManager.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -27,6 +27,7 @@
package org.teiid.dqp.internal.datamgr;
import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
@@ -45,6 +46,7 @@
import org.teiid.logging.MessageLevel;
import org.teiid.logging.CommandLogMessage.Event;
import org.teiid.metadata.Datatype;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.MetadataStore;
import org.teiid.query.QueryPlugin;
@@ -68,6 +70,7 @@
private String translatorName;
private String connectionName;
+ private String modelName;
// known requests
private ConcurrentHashMap<AtomicRequestID, ConnectorWorkItem> requestStates = new ConcurrentHashMap<AtomicRequestID, ConnectorWorkItem>();
@@ -129,6 +132,10 @@
return factory.getMetadataStore();
}
+ public List<FunctionMethod> getPushDownFunctions(){
+ return getExecutionFactory().getPushDownFunctions();
+ }
+
public SourceCapabilities getCapabilities() throws TeiidComponentException {
if (cachedCapabilities != null) {
return cachedCapabilities;
@@ -275,4 +282,12 @@
public String getConnectionName() {
return this.connectionName;
}
+
+ public void setModelName(String modelName) {
+ this.modelName = modelName;
+ }
+
+ public String getModelName() {
+ return this.modelName;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/QueryProcessorFactoryImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/QueryProcessorFactoryImpl.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/QueryProcessorFactoryImpl.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -29,6 +29,7 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.id.IDGenerator;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.QueryOptimizer;
@@ -82,7 +83,7 @@
AbstractValidationVisitor visitor = new ValidationVisitor();
Request.validateWithVisitor(visitor, metadata, newCommand);
- int determinismLevel = copy.resetDeterminismLevel();
+ Determinism determinismLevel = copy.resetDeterminismLevel();
newCommand = QueryRewriter.rewrite(newCommand, metadata, copy);
AnalysisRecord record = new AnalysisRecord(false, false);
ProcessorPlan plan = QueryOptimizer.optimizePlan(newCommand, metadata, idGenerator, finder, record, copy);
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -57,10 +57,10 @@
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.logging.MessageLevel;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.eval.SecurityFunctionEvaluator;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempCapabilitiesFinder;
import org.teiid.query.metadata.TempMetadataAdapter;
@@ -383,7 +383,7 @@
Collection<GroupSymbol> groups = GroupCollectorVisitor.getGroups(command, true);
for (GroupSymbol groupSymbol : groups) {
if (groupSymbol.isTempTable()) {
- this.context.setDeterminismLevel(FunctionMethod.SESSION_DETERMINISTIC);
+ this.context.setDeterminismLevel(Determinism.SESSION_DETERMINISTIC);
break;
}
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -56,9 +56,9 @@
import org.teiid.logging.LogManager;
import org.teiid.logging.MessageLevel;
import org.teiid.logging.CommandLogMessage.Event;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.parser.ParseInfo;
import org.teiid.query.parser.QueryParser;
import org.teiid.query.processor.BatchCollector;
@@ -385,12 +385,12 @@
doneProducingBatches();
}
if (doneProducingBatches && cid != null) {
- int determinismLevel = processor.getContext().getDeterminismLevel();
+ Determinism determinismLevel = processor.getContext().getDeterminismLevel();
CachedResults cr = new CachedResults();
cr.setCommand(originalCommand);
cr.setAnalysisRecord(analysisRecord);
cr.setResults(resultsBuffer);
- if (determinismLevel > FunctionMethod.SESSION_DETERMINISTIC) {
+ if (determinismLevel.isRestrictiveThan(Determinism.SESSION_DETERMINISTIC)) {
LogManager.logInfo(LogConstants.CTX_DQP, QueryPlugin.Util.getString("RequestWorkItem.cache_nondeterministic", originalCommand)); //$NON-NLS-1$
}
dqpCore.getRsCache().put(cid, determinismLevel, cr, originalCommand.getCacheHint() != null?originalCommand.getCacheHint().getTtl():null);
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/SessionAwareCache.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/SessionAwareCache.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/SessionAwareCache.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -41,7 +41,7 @@
import org.teiid.core.util.HashCodeUtil;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.parser.ParseInfo;
import org.teiid.vdb.runtime.VDBKey;
@@ -142,8 +142,8 @@
return localCache.size() + distributedCache.size();
}
- public void put(CacheID id, int determinismLevel, T t, Long ttl){
- if (determinismLevel >= FunctionMethod.SESSION_DETERMINISTIC) {
+ public void put(CacheID id, Determinism determinismLevel, T t, Long ttl){
+ if (determinismLevel.isRestrictiveThanOrEqual(Determinism.SESSION_DETERMINISTIC)) {
id.setSessionId(id.originalSessionId);
LogManager.logTrace(LogConstants.CTX_DQP, "Adding to session/local cache", id); //$NON-NLS-1$
this.localCache.put(id, t, ttl);
@@ -154,7 +154,7 @@
id.setSessionId(null);
- if (determinismLevel == FunctionMethod.USER_DETERMINISTIC) {
+ if (determinismLevel == Determinism.USER_DETERMINISTIC) {
id.setUserName(id.originalUserName);
}
else {
Modified: trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -63,10 +63,10 @@
import org.teiid.core.types.XMLType.Type;
import org.teiid.core.types.basic.StringToSQLXMLTransform;
import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.FunctionDescriptor;
import org.teiid.query.function.FunctionLibrary;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.function.source.XMLSystemFunctions;
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.sql.LanguageObject;
@@ -963,7 +963,7 @@
}
// Check for function we can't evaluate
- if(fd.getPushdown() == FunctionMethod.MUST_PUSHDOWN) {
+ if(fd.getPushdown() == PushDown.MUST_PUSHDOWN) {
throw new TeiidComponentException(QueryPlugin.Util.getString("ExpressionEvaluator.Must_push", fd.getName())); //$NON-NLS-1$
}
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -34,8 +34,9 @@
import org.teiid.core.util.Assertion;
import org.teiid.core.util.HashCodeUtil;
import org.teiid.core.util.PropertiesUtils;
+import org.teiid.metadata.FunctionMethod.PushDown;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.QueryPlugin;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.util.CommandContext;
@@ -50,13 +51,13 @@
private static final boolean ALLOW_NAN_INFINITY = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.allowNanInfinity", false); //$NON-NLS-1$
private String name;
- private int pushdown;
+ private PushDown pushdown = PushDown.CAN_PUSHDOWN;
private Class[] types;
private Class returnType;
private int hash;
private boolean requiresContext;
private boolean nullDependent;
- private int deterministic;
+ private Determinism deterministic = Determinism.DETERMINISTIC;
// This is transient as it would be useless to invoke this method in
// a different VM. This function descriptor can be used to look up
@@ -74,7 +75,7 @@
* @param invocationMethod Reflection method used to invoke the function
* @param requiresContext during execution requires command context to be pushed into method as first argument
*/
- FunctionDescriptor(String name, int pushdown, Class[] types, Class returnType, Method invocationMethod, boolean requiresContext, boolean nullDependent, int deterministic) {
+ FunctionDescriptor(String name, PushDown pushdown, Class[] types, Class returnType, Method invocationMethod, boolean requiresContext, boolean nullDependent, Determinism deterministic) {
Assertion.isNotNull(name);
Assertion.isNotNull(types);
Assertion.isNotNull(returnType);
@@ -99,11 +100,11 @@
return this.name;
}
- public int getPushdown() {
+ public PushDown getPushdown() {
return this.pushdown;
}
- void setPushdown(int pushdown) {
+ void setPushdown(PushDown pushdown) {
this.pushdown = pushdown;
}
@@ -192,11 +193,11 @@
return nullDependent;
}
- public int getDeterministic() {
+ public Determinism getDeterministic() {
return deterministic;
}
- void setDeterministic(int deterministic) {
+ void setDeterministic(Determinism deterministic) {
this.deterministic = deterministic;
}
@@ -238,7 +239,7 @@
throw new FunctionExecutionException("ERR.015.001.0002", QueryPlugin.Util.getString("ERR.015.001.0002", getName())); //$NON-NLS-1$ //$NON-NLS-2$
}
- if (getDeterministic() >= FunctionMethod.USER_DETERMINISTIC && values.length > 0 && values[0] instanceof CommandContext) {
+ if (getDeterministic().isRestrictiveThanOrEqual(Determinism.USER_DETERMINISTIC) && values.length > 0 && values[0] instanceof CommandContext) {
CommandContext cc = (CommandContext)values[0];
cc.setDeterminismLevel(getDeterministic());
}
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionForm.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionForm.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionForm.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -30,8 +30,8 @@
import org.teiid.core.util.Assertion;
import org.teiid.core.util.HashCodeUtil;
import org.teiid.language.SQLConstants.Reserved;
-import org.teiid.query.function.metadata.FunctionMethod;
-import org.teiid.query.function.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
/**
@@ -41,8 +41,9 @@
* function name and the names of the arguments.
*/
public class FunctionForm implements Serializable, Comparable {
-
- private String name;
+ private static final long serialVersionUID = 2411783099304320334L;
+
+ private String name;
private String description;
private String category;
private List inputParamNames;
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionLibrary.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionLibrary.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionLibrary.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -32,8 +32,8 @@
import org.teiid.api.exception.query.InvalidFunctionException;
import org.teiid.api.exception.query.QueryResolverException;
import org.teiid.core.types.DataTypeManager;
-import org.teiid.query.function.metadata.FunctionMethod;
-import org.teiid.query.function.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.Function;
@@ -93,13 +93,13 @@
private FunctionTree systemFunctions;
// Function tree for user-defined functions
- private FunctionTree userFunctions;
+ private FunctionTree[] userFunctions;
/**
* Construct the function library. This should be called only once by the
* FunctionLibraryManager.
*/
- public FunctionLibrary(FunctionTree systemFuncs, FunctionTree userFuncs) {
+ public FunctionLibrary(FunctionTree systemFuncs, FunctionTree... userFuncs) {
systemFunctions = systemFuncs;
userFunctions = userFuncs;
}
@@ -111,8 +111,12 @@
public List getFunctionCategories() {
// Remove category duplicates
HashSet categories = new HashSet();
- categories.addAll( systemFunctions.getCategories() );
- categories.addAll( userFunctions.getCategories() );
+ categories.addAll( systemFunctions.getCategories() );
+ if (this.userFunctions != null) {
+ for (FunctionTree tree: this.userFunctions) {
+ categories.addAll(tree.getCategories());
+ }
+ }
// Sort alphabetically
ArrayList categoryList = new ArrayList(categories);
@@ -127,8 +131,12 @@
*/
public List getFunctionForms(String category) {
List forms = new ArrayList();
- forms.addAll(systemFunctions.getFunctionForms(category));
- forms.addAll(userFunctions.getFunctionForms(category));
+ forms.addAll(systemFunctions.getFunctionForms(category));
+ if (this.userFunctions != null) {
+ for (FunctionTree tree: this.userFunctions) {
+ forms.addAll(tree.getFunctionForms(category));
+ }
+ }
// Sort alphabetically
Collections.sort(forms);
@@ -143,8 +151,13 @@
*/
public FunctionForm findFunctionForm(String name, int numArgs) {
FunctionForm form = systemFunctions.findFunctionForm(name, numArgs);
- if(form == null) {
- form = userFunctions.findFunctionForm(name, numArgs);
+ if(form == null && this.userFunctions != null) {
+ for (FunctionTree tree: this.userFunctions) {
+ form = tree.findFunctionForm(name, numArgs);
+ if (form != null) {
+ break;
+ }
+ }
}
return form;
}
@@ -162,8 +175,13 @@
FunctionDescriptor descriptor = systemFunctions.getFunction(name, types);
// If that fails, check the user defined functions
- if(descriptor == null) {
- descriptor = userFunctions.getFunction(name, types);
+ if(descriptor == null && this.userFunctions != null) {
+ for (FunctionTree tree: this.userFunctions) {
+ descriptor = tree.getFunction(name, types);
+ if (descriptor != null) {
+ break;
+ }
+ }
}
return descriptor;
@@ -195,8 +213,12 @@
//First find existing functions with same name and same number of parameters
final Collection<FunctionMethod> functionMethods = new LinkedList<FunctionMethod>();
- functionMethods.addAll( this.systemFunctions.findFunctionMethods(name , types.length) );
- functionMethods.addAll( this.userFunctions.findFunctionMethods(name , types.length) );
+ functionMethods.addAll( this.systemFunctions.findFunctionMethods(name, types.length) );
+ if (this.userFunctions != null) {
+ for (FunctionTree tree: this.userFunctions) {
+ functionMethods.addAll( tree.findFunctionMethods(name, types.length) );
+ }
+ }
//Score each match, reject any where types can not be converted implicitly
//Score of current method (lower score means better match with less converts
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionMetadataSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionMetadataSource.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionMetadataSource.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -24,7 +24,7 @@
import java.util.Collection;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionMethod;
/**
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -41,10 +41,12 @@
import org.teiid.core.util.ReflectionHelper;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
+import org.teiid.metadata.AbstractMetadataRecord;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.metadata.FunctionCategoryConstants;
-import org.teiid.query.function.metadata.FunctionMethod;
-import org.teiid.query.function.metadata.FunctionParameter;
import org.teiid.query.util.CommandContext;
@@ -152,7 +154,7 @@
}
categoryKey = categoryKey.toUpperCase();
String nameKey = method.getName().toUpperCase();
-
+
// Look up function map (create if necessary)
Set<String> functions = categories.get(categoryKey);
if (functions == null) {
@@ -160,16 +162,28 @@
categories.put(categoryKey, functions);
}
- // Look up function in function map
- functions.add(nameKey);
-
- // Add method to list by function name
- List<FunctionMethod> knownMethods = functionsByName.get(nameKey);
- if(knownMethods == null) {
- knownMethods = new ArrayList<FunctionMethod>();
- functionsByName.put(nameKey, knownMethods);
- }
- knownMethods.add(method);
+ int index = -1;
+ while (true){
+ // Look up function in function map
+ functions.add(nameKey);
+
+ // Add method to list by function name
+ List<FunctionMethod> knownMethods = functionsByName.get(nameKey);
+ if(knownMethods == null) {
+ knownMethods = new ArrayList<FunctionMethod>();
+ functionsByName.put(nameKey, knownMethods);
+ }
+ knownMethods.add(method);
+
+ // if the function is "." delimited, then add all possible forms
+ index = nameKey.indexOf(AbstractMetadataRecord.NAME_DELIM_CHAR, index+1);
+ if (index != -1) {
+ nameKey = nameKey.substring(index+1);
+ }
+ else {
+ break;
+ }
+ }
allFunctions.add(method);
}
@@ -273,7 +287,7 @@
Method invocationMethod = null;
boolean requiresContext = false;
// Defect 20007 - Ignore the invocation method if pushdown is not required.
- if (method.getPushdown() == FunctionMethod.CAN_PUSHDOWN || method.getPushdown() == FunctionMethod.CANNOT_PUSHDOWN) {
+ if (method.getPushdown() == PushDown.CAN_PUSHDOWN || method.getPushdown() == PushDown.CANNOT_PUSHDOWN) {
try {
Class<?> methodClass = source.getInvocationClass(method.getInvocationClass());
ReflectionHelper helper = new ReflectionHelper(methodClass);
@@ -315,28 +329,38 @@
inputTypes.add(0, CommandContext.class);
}
- FunctionDescriptor descriptor = new FunctionDescriptor(method.getName(), method.getPushdown(), types, outputType, invocationMethod, requiresContext, method.isNullDependent(), method.getDeterministic());
+ FunctionDescriptor descriptor = new FunctionDescriptor(method.getName(), method.getPushdown(), types, outputType, invocationMethod, requiresContext, method.isNullOnNull(), method.getDeterminism());
// Store this path in the function tree
- Map node = treeRoot;
- Object[] path = buildPath(methodName, types);
- for(int pathIndex = 0; pathIndex < path.length; pathIndex++) {
- Object pathPart = path[pathIndex];
- Map children = (Map) node.get(pathPart);
- if(children == null) {
- children = new HashMap();
- node.put(pathPart, children);
- }
- if (method.isVarArgs() && pathIndex == path.length - 1) {
- node.put(DESCRIPTOR_KEY, descriptor);
- }
- node = children;
+
+ int index = -1;
+ while(true) {
+ Map node = treeRoot;
+ Object[] path = buildPath(methodName, types);
+ for(int pathIndex = 0; pathIndex < path.length; pathIndex++) {
+ Object pathPart = path[pathIndex];
+ Map children = (Map) node.get(pathPart);
+ if(children == null) {
+ children = new HashMap();
+ node.put(pathPart, children);
+ }
+ if (method.isVarArgs() && pathIndex == path.length - 1) {
+ node.put(DESCRIPTOR_KEY, descriptor);
+ }
+ node = children;
+ }
+
+ if (method.isVarArgs()) {
+ node.put(types[types.length - 1], node);
+ }
+ // Store the leaf descriptor in the tree
+ node.put(DESCRIPTOR_KEY, descriptor);
+
+ index = methodName.indexOf(AbstractMetadataRecord.NAME_DELIM_CHAR, index+1);
+ if (index == -1) {
+ break;
+ }
+ methodName = methodName.substring(index+1);
}
-
- if (method.isVarArgs()) {
- node.put(types[types.length - 1], node);
- }
- // Store the leaf descriptor in the tree
- node.put(DESCRIPTOR_KEY, descriptor);
}
/**
Modified: trunk/engine/src/main/java/org/teiid/query/function/UDFSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/UDFSource.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/UDFSource.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -24,7 +24,7 @@
import java.util.Collection;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionMethod;
Modified: trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMetadataReader.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMetadataReader.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMetadataReader.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -11,6 +11,8 @@
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
+import org.teiid.metadata.FunctionMethod;
+
@XmlType
@XmlRootElement(namespace="http://www.omg.org/XMI", name="XMI")
public class FunctionMetadataReader {
Modified: trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMetadataValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMetadataValidator.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMetadataValidator.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -27,6 +27,9 @@
import org.teiid.api.exception.query.FunctionMetadataException;
import org.teiid.core.types.DataTypeManager;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.QueryPlugin;
import org.teiid.query.report.ActivityReport;
@@ -209,8 +212,8 @@
* @param invocationMethod Invocation method to validate
* @throws FunctionMetadataException Thrown if invocation method is not valid in some way
*/
- public static final void validateInvocationMethod(String invocationClass, String invocationMethod, int pushdown) throws FunctionMetadataException {
- if (pushdown == FunctionMethod.CAN_PUSHDOWN || pushdown == FunctionMethod.CANNOT_PUSHDOWN) {
+ public static final void validateInvocationMethod(String invocationClass, String invocationMethod, PushDown pushdown) throws FunctionMetadataException {
+ if (pushdown == PushDown.CAN_PUSHDOWN || pushdown == PushDown.CANNOT_PUSHDOWN) {
validateIsNotNull(invocationClass, "Invocation class"); //$NON-NLS-1$
validateIsNotNull(invocationMethod, "Invocation method"); //$NON-NLS-1$
validateJavaIdentifier(invocationClass, "Invocation class", true); //$NON-NLS-1$
Modified: trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMethod.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMethod.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMethod.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -22,94 +22,17 @@
package org.teiid.query.function.metadata;
-import java.io.Serializable;
-import java.util.Arrays;
+import org.teiid.metadata.FunctionParameter;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import org.teiid.core.util.HashCodeUtil;
-
-
/**
- * <p>This class represents information about a particular function signature.
- * Function signatures are unique with respect to their name, # of arguments,
- * and type of arguments. Return type and argument names are not uniqueness
- * factors. This class makes no attempt to validate the data put into it,
- * particularly with respect to null values. The
- * {@link FunctionMetadataValidator} can be used to validate this object.</p>
- *
- * Attributes:
- * <UL>
- * <LI>name - Name of the function</LI>
- * <LI>description - Description of the function</LI>
- * <LI>category - Function category containing this function</LI>
- * <LI>pushdown - Determine whether this function can, cannot, or must be pushed down to a source</LI>
- * <LI>invocationClass - Class containing method implementing this function</LI>
- * <LI>invocationMethod - Method implementing this function</LI>
- * <LI>inputParameters - 0 or more input parameters</LI>
- * <LI>outputParameter - 1 output parameter</LI>
- * </UL>
- *
- * @see FunctionParameter
* @see FunctionMetadataValidator
* @see FunctionCategoryConstants
*/
-public class FunctionMethod implements Serializable {
- private static final long serialVersionUID = -8039086494296455152L;
+public class FunctionMethod extends org.teiid.metadata.FunctionMethod {
+ private static final long serialVersionUID = -2380536393719646754L;
- private static final String NOT_ALLOWED = "NOT_ALLOWED"; //$NON-NLS-1$
- private static final String ALLOWED = "ALLOWED"; //$NON-NLS-1$
- private static final String REQUIRED = "REQUIRED"; //$NON-NLS-1$
-
- public static final int CAN_PUSHDOWN = 0;
- public static final int CANNOT_PUSHDOWN = 1;
- public static final int MUST_PUSHDOWN = 2;
- public static final int SYNTHETIC = 3;
-
- /*
- * always -> normal deterministic functions
- * vdb -> lookup (however lookup values can be flushed at any time), current_database
- * session -> env, user
- * command -> command payload
- * never -> rand, etc.
- *
- * Anything at a session level and above is treated as deterministic.
- * This is not quite correct for lookup or env. Only in extremely rare
- * circumstances would that be a problem.
- *
- * For now the commandPayload function is treated as a special case, like lookup, in
- * that it is considered deterministic, but will be delayed in its evaluation until
- * processing time.
- */
- public static final int DETERMINISTIC = 0;
- public static final int VDB_DETERMINISTIC = 1;
- public static final int USER_DETERMINISTIC = 2;
- public static final int SESSION_DETERMINISTIC = 3;
- public static final int COMMAND_DETERMINISTIC = 4;
- public static final int NONDETERMINISTIC = 5;
-
-
- private String name;
- private String description;
- private String category;
- private int pushdown = CAN_PUSHDOWN;
- private String invocationClass;
- private String invocationMethod;
- private boolean nullDependent;
-
- private int deterministic = DETERMINISTIC;
-
- private FunctionParameter[] inputParameters;
- private FunctionParameter outputParameter;
-
- /**
- * Construct a new empty function method.
- */
- public FunctionMethod() {
- }
-
- /**
+ /**
* Construct a function method with default pushdown and null dependent attributes.
* @param name Function name
* @param description Function description
@@ -122,8 +45,7 @@
public FunctionMethod(String name, String description, String category,
String invocationClass, String invocationMethod,
FunctionParameter[] inputParams, FunctionParameter outputParam) {
-
- this(name, description, category, invocationClass, invocationMethod, inputParams, outputParam, DETERMINISTIC);
+ this(name, description, category, invocationClass, invocationMethod, inputParams, outputParam, Determinism.DETERMINISTIC);
}
/**
@@ -138,9 +60,8 @@
*/
public FunctionMethod(String name, String description, String category,
String invocationClass, String invocationMethod,
- FunctionParameter[] inputParams, FunctionParameter outputParam, int deterministic) {
-
- this(name, description, category, CAN_PUSHDOWN, invocationClass, invocationMethod, inputParams, outputParam, false, deterministic);
+ FunctionParameter[] inputParams, FunctionParameter outputParam, Determinism deterministic) {
+ super(name, description, category, PushDown.CAN_PUSHDOWN, invocationClass, invocationMethod, inputParams, outputParam, false, deterministic);
}
/**
@@ -154,365 +75,25 @@
* @param outputParam Output parameter (return parameter)
*/
public FunctionMethod(String name, String description, String category,
- int pushdown, String invocationClass, String invocationMethod,
+ PushDown pushdown, String invocationClass, String invocationMethod,
FunctionParameter[] inputParams, FunctionParameter outputParam) {
-
- this(name, description, category, pushdown, invocationClass, invocationMethod, inputParams, outputParam, true, NONDETERMINISTIC);
+ super(name, description, category, pushdown, invocationClass, invocationMethod, inputParams, outputParam, true,Determinism.NONDETERMINISTIC);
}
- /**
- * Construct a function method with all parameters.
- * @param name Function name
- * @param description Function description
- * @param category Function category
- * @param invocationClass Invocation class
- * @param invocationMethod Invocation method
- * @param inputParams Input parameters
- * @param outputParam Output parameter (return parameter)
- */
+ public FunctionMethod(String name, String description, String category, FunctionParameter[] inputParams, FunctionParameter outputParam) {
+ super(name, description, category, PushDown.MUST_PUSHDOWN, null, null, inputParams, outputParam, false, Determinism.DETERMINISTIC);
+ }
+
public FunctionMethod(String name,
- String description,
- String category,
- int pushdown,
- String invocationClass,
- String invocationMethod,
- FunctionParameter[] inputParams,
- FunctionParameter outputParam,
- boolean nullDependent,
- int deterministic) {
-
- setName(name);
- setDescription(description);
- setCategory(category);
- setPushdown(pushdown);
- setInvocationClass(invocationClass);
- setInvocationMethod(invocationMethod);
- setInputParameters(inputParams);
- setOutputParameter(outputParam);
- setNullDependent(nullDependent);
- setDeterministic(deterministic);
+ String description,
+ String category,
+ PushDown pushdown,
+ String invocationClass,
+ String invocationMethod,
+ FunctionParameter[] inputParams,
+ FunctionParameter outputParam,
+ boolean nullDependent,
+ Determinism deterministic) {
+ super(name, description, category, pushdown, invocationClass, invocationMethod, inputParams, outputParam, nullDependent, deterministic);
}
-
- /**
- * Return name of method
- * @return Name
- */
- @XmlAttribute
- public String getName() {
- return this.name;
- }
-
- /**
- * Set name of method
- * @param name Name
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * Get description of method
- * @return Description
- */
- @XmlAttribute
- public String getDescription() {
- return this.description;
- }
-
- /**
- * Set description of method
- * @param description Description
- */
- public void setDescription(String description) {
- this.description = description;
- }
-
- /**
- * Get category of method
- * @return Category
- * @see FunctionCategoryConstants
- */
- @XmlAttribute
- public String getCategory() {
- return this.category;
- }
-
- /**
- * Set category of method
- * @param category Category
- * @see FunctionCategoryConstants
- */
- public void setCategory(String category) {
- this.category = category;
- }
-
- /**
- * Get pushdown property of method
- * @return One of the FunctionMethod constants for pushdown
- */
- public int getPushdown() {
- return pushdown;
- }
-
- /**
- * Set pushdown property of method
- * @param pushdown One of the FunctionMethod constants for pushdown
- */
- public void setPushdown(int pushdown) {
- this.pushdown = pushdown;
- }
-
- @XmlAttribute
- public void setPushDown(String pushdown) {
- if (pushdown != null) {
- if (pushdown.equals(REQUIRED)) {
- this.pushdown = FunctionMethod.MUST_PUSHDOWN;
- } else if (pushdown.equals(ALLOWED)) {
- this.pushdown = FunctionMethod.CAN_PUSHDOWN;
- } else if (pushdown.equals(NOT_ALLOWED)) {
- this.pushdown = FunctionMethod.CANNOT_PUSHDOWN;
- }
- } else {
- this.pushdown = FunctionMethod.CAN_PUSHDOWN;
- }
- }
-
- /**
- * Get invocation class name
- * @return Invocation class name
- */
- @XmlAttribute
- public String getInvocationClass() {
- return this.invocationClass;
- }
-
- /**
- * Set invocation class name
- * @param invocationClass Invocation class name
- */
- public void setInvocationClass(String invocationClass) {
- this.invocationClass = invocationClass;
- }
-
- /**
- * Get invocation method name
- * @return Invocation method name
- */
- @XmlAttribute
- public String getInvocationMethod() {
- return this.invocationMethod;
- }
-
- /**
- * Set invocation method name
- * @param invocationMethod Invocation method name
- */
- public void setInvocationMethod(String invocationMethod) {
- this.invocationMethod = invocationMethod;
- }
-
- /**
- * Get a count of the input parameters.
- * @return Number of input parameters
- */
- public int getInputParameterCount() {
- if(this.inputParameters == null) {
- return 0;
- }
- return this.inputParameters.length;
- }
-
- /**
- * Get input parameters
- * @return Array of input parameters, may be null if 0 parameters
- */
- @XmlElement
- public FunctionParameter[] getInputParameters() {
- return this.inputParameters;
- }
-
- /**
- * Set input parameters.
- * @param params Input parameters
- */
- public void setInputParameters(FunctionParameter[] params) {
- this.inputParameters = params;
- }
-
- /**
- * Get ouput parameter.
- * @return Output parameter or return argument
- */
- @XmlElement(name="returnParameter")
- public FunctionParameter getOutputParameter() {
- return this.outputParameter;
- }
-
- /**
- * Set ouput parameter.
- * @param param Output Parameter
- */
- public void setOutputParameter(FunctionParameter param) {
- if (param != null) {
- param.setName(FunctionParameter.OUTPUT_PARAMETER_NAME);
- }
- this.outputParameter = param;
- }
-
- /**
- * Get hash code for this object. The hash code is based on the name
- * and input parameters. <B>WARNING: Changing the name or input parameters
- * will change the hash code.</B> If this occurs after the object has been
- * placed in a HashSet or HashMap, the object will be lost!!!! In that
- * case, the object must be added to the hashed collection again.
- * @return Hash code, based on name and input parameters
- */
- public int hashCode() {
- int hash = HashCodeUtil.hashCode(0, name);
- if(inputParameters != null) {
- hash = HashCodeUtil.hashCode(hash, Arrays.hashCode(inputParameters));
- }
- return hash;
- }
-
- /**
- * Compare other object for equality. This object is equal to another
- * FunctionMethod if 1) Name of function matches (case-insensitive),
- * 2) number of input parameters matches and 3) types of input parameters
- * match.
- * @return True if object equals this object according to conditions
- */
- public boolean equals(Object obj) {
- if(obj == this) {
- return true;
- }
- if(obj instanceof FunctionMethod) {
- FunctionMethod other = (FunctionMethod) obj;
-
- // Compare # of parameters - do this first as it is much faster than name compare
- if(getInputParameterCount() != other.getInputParameterCount()) {
- return false;
- }
-
- // Compare function names - case insensitive
- if(other.getName() == null || this.getName() == null) {
- return false;
- }
- if(! other.getName().equalsIgnoreCase(this.getName()) ) {
- return false;
- }
-
- // Compare types of parameters
- FunctionParameter[] thisInputs = this.getInputParameters();
- if(thisInputs != null && thisInputs.length > 0) {
- // If thisInputs is not null and >0 and other parameter
- // count matched this parameter count, otherInputs MUST be
- // non null to have more than one parameter - so we don't
- // need to check it here.
- FunctionParameter[] otherInputs = other.getInputParameters();
-
- for(int i=0; i<thisInputs.length; i++) {
- boolean paramMatch = compareWithNull(thisInputs[i], otherInputs[i]);
- if(! paramMatch) {
- return false;
- }
- }
- }
-
- // Found no discrepancies, must be equal
- return true;
- }
- return false;
- }
-
- /**
- * Compare two objects that may or may not be null and consider null==null
- * as true.
- * @param o1 Object 1
- * @param o2 Object 2
- * @return True if o1 and o2 are null or if they both aren't and they are equal
- */
- private boolean compareWithNull(Object o1, Object o2) {
- if(o1 == null) {
- if(o2 == null) {
- return true;
- }
- return false;
- }
- if(o2 == null) {
- return false;
- }
- return o1.equals(o2);
- }
-
- /**
- * Return string version for debugging purposes
- * @return String representation of function method
- */
- public String toString() {
- StringBuffer str = new StringBuffer();
- if(name != null) {
- str.append(name);
- } else {
- str.append("<unknown>"); //$NON-NLS-1$
- }
-
- // Print parameters
- str.append("("); //$NON-NLS-1$
- if(inputParameters != null) {
- for(int i=0; i<inputParameters.length; i++) {
- if(inputParameters[i] != null) {
- str.append(inputParameters[i].toString());
- } else {
- str.append("<unknown>"); //$NON-NLS-1$
- }
-
- if(i < (inputParameters.length-1)) {
- str.append(", "); //$NON-NLS-1$
- }
- }
- }
- str.append(") : "); //$NON-NLS-1$
-
- // Print return type
- if(outputParameter != null) {
- str.append(outputParameter.toString());
- } else {
- str.append("<unknown>"); //$NON-NLS-1$
- }
-
- return str.toString();
- }
-
- /**
- * Returns true if the function can produce a non-null output from a null parameter
- */
- public boolean isNullDependent() {
- return this.nullDependent;
- }
-
- public void setNullDependent(boolean nullSafe) {
- this.nullDependent = nullSafe;
- }
-
- public int getDeterministic() {
- return this.deterministic;
- }
-
- @XmlAttribute(name="deterministic")
- public void setDeterministicBoolean(boolean deterministic) {
- this.deterministic = deterministic ? FunctionMethod.DETERMINISTIC : FunctionMethod.NONDETERMINISTIC;
- }
-
- public void setDeterministic(int deterministic) {
- this.deterministic = deterministic;
- }
-
- public boolean isVarArgs() {
- if (this.inputParameters != null && this.inputParameters.length > 0) {
- return inputParameters[inputParameters.length - 1].isVarArg();
- }
- return false;
- }
-
}
Deleted: trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionParameter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionParameter.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionParameter.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -1,183 +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.query.function.metadata;
-
-import java.io.Serializable;
-
-import javax.xml.bind.annotation.XmlAttribute;
-
-/**
- * A function parameter defines the name and description of an input or output
- * parameter for a function. The name should not be null, but that is not
- * verified by this class. Validation of this object can be done with the
- * {@link FunctionMetadataValidator}. The type string used in the function
- * parameter should be one of the standard type names defined in
- * {@link org.teiid.core.types.DataTypeManager.DefaultDataTypes}.
- */
-public class FunctionParameter implements Serializable {
- public static final String OUTPUT_PARAMETER_NAME = "result"; //$NON-NLS-1$
-
- private String name;
- private String type;
- private String description;
- private boolean isVarArg;
-
- /**
- * Construct a function parameter with no attributes.
- */
- public FunctionParameter() {
- }
-
- /**
- * Construct a function parameter with no description.
- * @param name Name
- * @param type Type from standard set of types
- */
- public FunctionParameter(String name, String type) {
- this(name, type, null);
- }
-
- /**
- * Construct a function parameter with all attributes.
- * @param name Name
- * @param type Type from standard set of types
- * @param description Description
- */
- public FunctionParameter(String name, String type, String description) {
- this(name, type, description, false);
- }
-
- public FunctionParameter(String name, String type, String description, boolean vararg) {
- setName(name);
- setType(type);
- setDescription(description);
- this.isVarArg = vararg;
- }
-
- /**
- * Return name of parameter.
- * @return Name
- */
- @XmlAttribute
- public String getName() {
- return this.name;
- }
-
- /**
- * Set name
- * @param name Name
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * Get description of parameter
- * @return Description
- */
- @XmlAttribute
- public String getDescription() {
- return this.description;
- }
-
- /**
- * Set description of parameter
- * @param description Description
- */
- public void setDescription(String description) {
- this.description = description;
- }
-
- /**
- * Get type of parameter
- * @return Type name
- * @see org.teiid.core.types.DataTypeManager.DefaultDataTypes
- */
- @XmlAttribute
- public String getType() {
- return this.type;
- }
-
- /**
- * Set type of parameter
- * @param type Type of parameter
- * @see org.teiid.core.types.DataTypeManager.DefaultDataTypes
- */
- public void setType(String type) {
- if(type == null) {
- this.type = null;
- } else {
- this.type = type.toLowerCase();
- }
- }
-
- /**
- * Return hash code for this parameter. The hash code is based only
- * on the type of the parameter. Changing the type of the parameter
- * after placing this object in a hashed collection will likely cause
- * the object to be lost.
- * @return Hash code
- */
- public int hashCode() {
- if(this.type == null) {
- return 0;
- }
- return this.type.hashCode();
- }
-
- /**
- * Compare with other object for equality. Equality is based on whether
- * the type is the same as the other parameter.
- * @return True if equal to obj
- */
- public boolean equals(Object obj) {
- if(obj == this) {
- return true;
- }
- if(!(obj instanceof FunctionParameter)) {
- return false;
- }
- FunctionParameter other = (FunctionParameter) obj;
- if(other.getType() == null) {
- return (this.getType() == null);
- }
- return other.getType().equals(this.getType()) && this.isVarArg == other.isVarArg;
- }
-
- /**
- * Return string version for debugging purposes
- * @return String representation of function parameter
- */
- public String toString() {
- return type + (isVarArg?"... ":" ") + name; //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- public void setVarArg(boolean isVarArg) {
- this.isVarArg = isVarArg;
- }
-
- public boolean isVarArg() {
- return isVarArg;
- }
-
-}
Modified: trunk/engine/src/main/java/org/teiid/query/function/metadata/InvalidFunctionItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/metadata/InvalidFunctionItem.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/metadata/InvalidFunctionItem.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -22,6 +22,7 @@
package org.teiid.query.function.metadata;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.query.report.ReportItem;
/**
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-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -28,13 +28,15 @@
import java.util.List;
import org.teiid.core.types.DataTypeManager;
+import org.teiid.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod.PushDown;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.FunctionLibrary;
import org.teiid.query.function.FunctionMetadataSource;
import org.teiid.query.function.FunctionMethods;
import org.teiid.query.function.metadata.FunctionCategoryConstants;
import org.teiid.query.function.metadata.FunctionMethod;
-import org.teiid.query.function.metadata.FunctionParameter;
import org.teiid.translator.SourceSystemFunctions;
@@ -50,7 +52,7 @@
private static final String SECURITY_FUNCTION_CLASS = SecuritySystemFunctions.class.getName();
/** Cached list of system function metadata, created in constructor */
- private List<FunctionMethod> functions = new ArrayList<FunctionMethod>();
+ private List<org.teiid.metadata.FunctionMethod> functions = new ArrayList<org.teiid.metadata.FunctionMethod>();
/**
* Construct a source of system metadata.
@@ -192,16 +194,16 @@
}
private void addSecurityFunctions() {
- functions.add(new FunctionMethod("hasRole", QueryPlugin.Util.getString("SystemSource.hasRole_description"), SECURITY, FunctionMethod.CANNOT_PUSHDOWN, SECURITY_FUNCTION_CLASS, "hasRole", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ functions.add(new FunctionMethod("hasRole", QueryPlugin.Util.getString("SystemSource.hasRole_description"), SECURITY, PushDown.CANNOT_PUSHDOWN, SECURITY_FUNCTION_CLASS, "hasRole", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {
new FunctionParameter("roleType", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.hasRole_param1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("roleName", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.hasRole_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, QueryPlugin.Util.getString("SystemSource.hasRole_result")), false, FunctionMethod.USER_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, QueryPlugin.Util.getString("SystemSource.hasRole_result")), false, Determinism.USER_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
- functions.add(new FunctionMethod("hasRole", QueryPlugin.Util.getString("SystemSource.hasRole_description"), SECURITY, FunctionMethod.CANNOT_PUSHDOWN, SECURITY_FUNCTION_CLASS, "hasRole", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ functions.add(new FunctionMethod("hasRole", QueryPlugin.Util.getString("SystemSource.hasRole_description"), SECURITY, PushDown.CANNOT_PUSHDOWN, SECURITY_FUNCTION_CLASS, "hasRole", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {
new FunctionParameter("roleName", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.hasRole_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, QueryPlugin.Util.getString("SystemSource.hasRole_result")), false, FunctionMethod.USER_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.BOOLEAN, QueryPlugin.Util.getString("SystemSource.hasRole_result")), false, Determinism.USER_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addFormatNumberFunctions() {
@@ -261,13 +263,13 @@
// With Seed
FunctionMethod rand = new FunctionMethod(SourceSystemFunctions.RAND, QueryPlugin.Util.getString("SystemSource.Rand_desc"), NUMERIC, FUNCTION_CLASS, "rand", //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter[] {new FunctionParameter("seed", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Rand_arg")) }, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DOUBLE, QueryPlugin.Util.getString("SystemSource.Rand_result_desc")), FunctionMethod.NONDETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
- rand.setNullDependent(true);
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DOUBLE, QueryPlugin.Util.getString("SystemSource.Rand_result_desc")), Determinism.NONDETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
+ rand.setNullOnNull(true);
functions.add(rand);
// Without Seed
functions.add( new FunctionMethod(SourceSystemFunctions.RAND, QueryPlugin.Util.getString("SystemSource.Rand_desc"), NUMERIC, FUNCTION_CLASS, "rand", //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter[] {},
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DOUBLE, QueryPlugin.Util.getString("SystemSource.Rand_result_desc")), FunctionMethod.NONDETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DOUBLE, QueryPlugin.Util.getString("SystemSource.Rand_result_desc")), Determinism.NONDETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addDoubleFunction(String name, String description) {
@@ -375,7 +377,7 @@
functions.add(
new FunctionMethod(name, description, DATETIME, FUNCTION_CLASS, methodName,
new FunctionParameter[] {},
- new FunctionParameter("result", returnType, description), FunctionMethod.COMMAND_DETERMINISTIC ) ); //$NON-NLS-1$
+ new FunctionParameter("result", returnType, description), Determinism.COMMAND_DETERMINISTIC ) ); //$NON-NLS-1$
}
private void addDateFunction(String name, String methodName, String dateDesc, String timestampDesc, String returnType) {
@@ -406,14 +408,14 @@
private void addTimestampAddFunction() {
functions.add(
- new FunctionMethod(SourceSystemFunctions.TIMESTAMPADD, QueryPlugin.Util.getString("SystemSource.Timestampadd_d_desc"), DATETIME, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(SourceSystemFunctions.TIMESTAMPADD, QueryPlugin.Util.getString("SystemSource.Timestampadd_d_desc"), DATETIME, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("interval", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Timestampadd_d_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("count", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Timestampadd_d_arg2")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("timestamp", DataTypeManager.DefaultDataTypes.DATE, QueryPlugin.Util.getString("SystemSource.Timestampadd_d_arg3"))}, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DATE, QueryPlugin.Util.getString("SystemSource.Timestampadd_d_result_desc")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
functions.add(
- new FunctionMethod(SourceSystemFunctions.TIMESTAMPADD, QueryPlugin.Util.getString("SystemSource.Timestampadd_t_desc"), DATETIME, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(SourceSystemFunctions.TIMESTAMPADD, QueryPlugin.Util.getString("SystemSource.Timestampadd_t_desc"), DATETIME, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("interval", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Timestampadd_t_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("count", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Timestampadd_t_arg2")), //$NON-NLS-1$ //$NON-NLS-2$
@@ -470,10 +472,10 @@
private void addClobFunction(String name, String description, String methodName, String returnType) {
functions.add(
- new FunctionMethod(name, description, STRING, FunctionMethod.MUST_PUSHDOWN, FUNCTION_CLASS, methodName,
+ new FunctionMethod(name, description, STRING, PushDown.MUST_PUSHDOWN, FUNCTION_CLASS, methodName,
new FunctionParameter[] {
new FunctionParameter("clob", DataTypeManager.DefaultDataTypes.CLOB, QueryPlugin.Util.getString("SystemSource.Clobfunc_arg1")) }, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", returnType, description), false, FunctionMethod.DETERMINISTIC ) ); //$NON-NLS-1$
+ new FunctionParameter("result", returnType, description), false, Determinism.DETERMINISTIC ) ); //$NON-NLS-1$
}
private void addConcatFunction() {
@@ -490,11 +492,11 @@
new FunctionParameter("string2", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concatop_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concatop_result_desc")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
- FunctionMethod concat2 = new FunctionMethod("concat2", QueryPlugin.Util.getString("SystemSource.Concat_desc"), STRING, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$ //$NON-NLS-2$
+ FunctionMethod concat2 = new FunctionMethod("concat2", QueryPlugin.Util.getString("SystemSource.Concat_desc"), STRING, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter[] {
new FunctionParameter("string1", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("string2", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_result_desc")), true, FunctionMethod.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_result_desc")), true, Determinism.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
functions.add(concat2);
}
@@ -537,7 +539,7 @@
new FunctionParameter("string", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Locate_arg2")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("index", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Locate_arg3")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Locate_result")) ); //$NON-NLS-1$ //$NON-NLS-2$
- func.setNullDependent(true);
+ func.setNullOnNull(true);
functions.add(func);
functions.add(
new FunctionMethod(SourceSystemFunctions.LOCATE, QueryPlugin.Util.getString("SystemSource.Locate2_desc"), STRING, FUNCTION_CLASS, "locate", //$NON-NLS-1$ //$NON-NLS-2$
@@ -568,7 +570,7 @@
private void addSpaceFunction() {
functions.add(
- new FunctionMethod(FunctionLibrary.SPACE, QueryPlugin.Util.getString("SystemSource.Space_desc"), STRING, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(FunctionLibrary.SPACE, QueryPlugin.Util.getString("SystemSource.Space_desc"), STRING, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("count", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Space_arg1"))}, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Space_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
@@ -740,14 +742,14 @@
private void addDecodeFunction(String functionName, String resultType) {
functions.add(
- new FunctionMethod(functionName, QueryPlugin.Util.getString("SystemSource.Decode1_desc"), MISCELLANEOUS, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(functionName, QueryPlugin.Util.getString("SystemSource.Decode1_desc"), MISCELLANEOUS, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("input", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Decode1_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("decodeString", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Decode1_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", resultType, QueryPlugin.Util.getString("SystemSource.Decode1_result") ) ) ); //$NON-NLS-1$ //$NON-NLS-2$
functions.add(
- new FunctionMethod(functionName, QueryPlugin.Util.getString("SystemSource.Decode2_desc"), MISCELLANEOUS, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(functionName, QueryPlugin.Util.getString("SystemSource.Decode2_desc"), MISCELLANEOUS, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("input", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Decode2_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("decodeString", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Decode2_arg2")), //$NON-NLS-1$ //$NON-NLS-2$
@@ -759,55 +761,55 @@
private void addLookupFunctions() {
for (String keyValueType : DataTypeManager.getAllDataTypeNames()) {
functions.add(
- new FunctionMethod("lookup", QueryPlugin.Util.getString("SystemSource.Lookup_desc"), MISCELLANEOUS, FunctionMethod.CANNOT_PUSHDOWN, FUNCTION_CLASS, "lookup", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionMethod("lookup", QueryPlugin.Util.getString("SystemSource.Lookup_desc"), MISCELLANEOUS, PushDown.CANNOT_PUSHDOWN, FUNCTION_CLASS, "lookup", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {
new FunctionParameter("codetable", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Lookup_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("returnelement", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Lookup_arg2")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("keyelement", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Lookup_arg3")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("keyvalue", keyValueType, QueryPlugin.Util.getString("SystemSource.Lookup_arg4")), //$NON-NLS-1$ //$NON-NLS-2$
},
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.OBJECT, QueryPlugin.Util.getString("SystemSource.Lookup_result")), true, FunctionMethod.VDB_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.OBJECT, QueryPlugin.Util.getString("SystemSource.Lookup_result")), true, Determinism.VDB_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
}
private void addUserFunction() {
functions.add(
- new FunctionMethod("user", QueryPlugin.Util.getString("SystemSource.User_desc"), MISCELLANEOUS, FunctionMethod.CANNOT_PUSHDOWN, FUNCTION_CLASS, "user", null, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.User_result")), false, FunctionMethod.USER_DETERMINISTIC) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionMethod("user", QueryPlugin.Util.getString("SystemSource.User_desc"), MISCELLANEOUS, PushDown.CANNOT_PUSHDOWN, FUNCTION_CLASS, "user", null, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.User_result")), false, Determinism.USER_DETERMINISTIC) ); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addCurrentDatabaseFunction() {
functions.add(
- new FunctionMethod("current_database", QueryPlugin.Util.getString("SystemSource.current_database_desc"), MISCELLANEOUS, FunctionMethod.CANNOT_PUSHDOWN, FUNCTION_CLASS, "current_database", null, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("current_database_result")), false, FunctionMethod.VDB_DETERMINISTIC) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionMethod("current_database", QueryPlugin.Util.getString("SystemSource.current_database_desc"), MISCELLANEOUS, PushDown.CANNOT_PUSHDOWN, FUNCTION_CLASS, "current_database", null, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("current_database_result")), false, Determinism.VDB_DETERMINISTIC) ); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addEnvFunction() {
functions.add(
- new FunctionMethod("env", QueryPlugin.Util.getString("SystemSource.Env_desc"), MISCELLANEOUS, FunctionMethod.CANNOT_PUSHDOWN, FUNCTION_CLASS, "env", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionMethod("env", QueryPlugin.Util.getString("SystemSource.Env_desc"), MISCELLANEOUS, PushDown.CANNOT_PUSHDOWN, FUNCTION_CLASS, "env", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {
new FunctionParameter("variablename", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Env_varname")) //$NON-NLS-1$ //$NON-NLS-2$
},
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Env_result")), false, FunctionMethod.SESSION_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Env_result")), false, Determinism.SESSION_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addSessionIdFunction() {
functions.add(
- new FunctionMethod(FunctionLibrary.SESSION_ID, QueryPlugin.Util.getString("SystemSource.session_id_desc"), MISCELLANEOUS, FunctionMethod.CANNOT_PUSHDOWN, FUNCTION_CLASS, "session_id", null, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.session_id_result")), false, FunctionMethod.SESSION_DETERMINISTIC) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionMethod(FunctionLibrary.SESSION_ID, QueryPlugin.Util.getString("SystemSource.session_id_desc"), MISCELLANEOUS, PushDown.CANNOT_PUSHDOWN, FUNCTION_CLASS, "session_id", null, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.session_id_result")), false, Determinism.SESSION_DETERMINISTIC) ); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addCommandPayloadFunctions() {
functions.add(
- new FunctionMethod("commandpayload", QueryPlugin.Util.getString("SystemSource.CommandPayload_desc0"), MISCELLANEOUS, FunctionMethod.CANNOT_PUSHDOWN, FUNCTION_CLASS, "commandPayload", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionMethod("commandpayload", QueryPlugin.Util.getString("SystemSource.CommandPayload_desc0"), MISCELLANEOUS, PushDown.CANNOT_PUSHDOWN, FUNCTION_CLASS, "commandPayload", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {},
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.CommandPayload_result")), false, FunctionMethod.COMMAND_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.CommandPayload_result")), false, Determinism.COMMAND_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
functions.add(
- new FunctionMethod("commandpayload", QueryPlugin.Util.getString("SystemSource.CommandPayload_desc1"), MISCELLANEOUS, FunctionMethod.CANNOT_PUSHDOWN, FUNCTION_CLASS, "commandPayload", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionMethod("commandpayload", QueryPlugin.Util.getString("SystemSource.CommandPayload_desc1"), MISCELLANEOUS, PushDown.CANNOT_PUSHDOWN, FUNCTION_CLASS, "commandPayload", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {
new FunctionParameter("property", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.CommandPayload_property")) //$NON-NLS-1$ //$NON-NLS-2$
},
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.CommandPayload_result")), false, FunctionMethod.COMMAND_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.CommandPayload_result")), false, Determinism.COMMAND_DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addIfNullFunctions() {
@@ -824,7 +826,7 @@
new FunctionParameter("value", valueType, QueryPlugin.Util.getString("SystemSource.Nvl_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("valueIfNull", valueType, QueryPlugin.Util.getString("SystemSource.Nvl_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", valueType, QueryPlugin.Util.getString("SystemSource.Nvl_result")) ); //$NON-NLS-1$ //$NON-NLS-2$
- nvl.setNullDependent(true);
+ nvl.setNullOnNull(true);
functions.add(nvl);
}
@@ -835,7 +837,7 @@
new FunctionParameter("value", valueType, QueryPlugin.Util.getString("SystemSource.Ifnull_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("valueIfNull", valueType, QueryPlugin.Util.getString("SystemSource.Ifnull_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", valueType, QueryPlugin.Util.getString("SystemSource.Ifnull_result")) ); //$NON-NLS-1$ //$NON-NLS-2$
- nvl.setNullDependent(true);
+ nvl.setNullOnNull(true);
functions.add(nvl);
}
@@ -847,13 +849,13 @@
new FunctionParameter("format", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Formattimestamp_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Formattimestamp_result_desc")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
functions.add(
- new FunctionMethod(FunctionLibrary.FORMATDATE, QueryPlugin.Util.getString("SystemSource.Formatdate_desc"),CONVERSION, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(FunctionLibrary.FORMATDATE, QueryPlugin.Util.getString("SystemSource.Formatdate_desc"),CONVERSION, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("date", DataTypeManager.DefaultDataTypes.DATE, QueryPlugin.Util.getString("SystemSource.Formatdate_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("format", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Formatdate_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Formatdate_result_desc")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
functions.add(
- new FunctionMethod(FunctionLibrary.FORMATTIME, QueryPlugin.Util.getString("SystemSource.Formattime_desc"),CONVERSION, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(FunctionLibrary.FORMATTIME, QueryPlugin.Util.getString("SystemSource.Formattime_desc"),CONVERSION, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("time", DataTypeManager.DefaultDataTypes.TIME, QueryPlugin.Util.getString("SystemSource.Formattime_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("format", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Formattime_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
@@ -868,13 +870,13 @@
new FunctionParameter("format", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Parsetimestamp_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.TIMESTAMP, QueryPlugin.Util.getString("SystemSource.Parsetimestamp_result_desc")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
functions.add(
- new FunctionMethod(FunctionLibrary.PARSETIME, QueryPlugin.Util.getString("SystemSource.Parsetime_desc"),CONVERSION, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(FunctionLibrary.PARSETIME, QueryPlugin.Util.getString("SystemSource.Parsetime_desc"),CONVERSION, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("time", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Parsetime_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("format", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Parsetime_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("result", DataTypeManager.DefaultDataTypes.TIME, QueryPlugin.Util.getString("SystemSource.Parsetime_result_desc")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
functions.add(
- new FunctionMethod(FunctionLibrary.PARSEDATE, QueryPlugin.Util.getString("SystemSource.Parsedate_desc"),CONVERSION, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(FunctionLibrary.PARSEDATE, QueryPlugin.Util.getString("SystemSource.Parsedate_desc"),CONVERSION, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("date", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Parsedate_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("format", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Parsedate_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
@@ -985,11 +987,11 @@
}
private void addXmlConcat() {
- functions.add(new FunctionMethod(SourceSystemFunctions.XMLCONCAT, QueryPlugin.Util.getString("SystemSource.xmlconcat_description"), XML, FunctionMethod.CAN_PUSHDOWN, XML_FUNCTION_CLASS, "xmlConcat", //$NON-NLS-1$ //$NON-NLS-2$
+ functions.add(new FunctionMethod(SourceSystemFunctions.XMLCONCAT, QueryPlugin.Util.getString("SystemSource.xmlconcat_description"), XML, PushDown.CAN_PUSHDOWN, XML_FUNCTION_CLASS, "xmlConcat", //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter[] {
new FunctionParameter("param1", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xmlconcat_param1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("param2", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xmlconcat_param2"), true)}, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xmlconcat_result")), true, FunctionMethod.DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xmlconcat_result")), true, Determinism.DETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addTimeZoneFunctions() {
@@ -1009,37 +1011,37 @@
}
private void addUnixTimeFunctions() {
- functions.add(new FunctionMethod(FunctionLibrary.FROM_UNIXTIME, QueryPlugin.Util.getString("SystemSource.from_unixtime_description"), DATETIME, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ functions.add(new FunctionMethod(FunctionLibrary.FROM_UNIXTIME, QueryPlugin.Util.getString("SystemSource.from_unixtime_description"), DATETIME, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("unix_timestamp", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.from_unixtime_param1")) //$NON-NLS-1$ //$NON-NLS-2$
},
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.TIMESTAMP, QueryPlugin.Util.getString("SystemSource.from_unixtime_result")), false, FunctionMethod.DETERMINISTIC )); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.TIMESTAMP, QueryPlugin.Util.getString("SystemSource.from_unixtime_result")), false, Determinism.DETERMINISTIC )); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addTypedNullIfFunction(String type) {
functions.add(
- new FunctionMethod(FunctionLibrary.NULLIF, QueryPlugin.Util.getString("SystemSource.nullif_description"), MISCELLANEOUS, FunctionMethod.SYNTHETIC, null, null, //$NON-NLS-1$
+ new FunctionMethod(FunctionLibrary.NULLIF, QueryPlugin.Util.getString("SystemSource.nullif_description"), MISCELLANEOUS, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$
new FunctionParameter[] {
new FunctionParameter("op1", type, QueryPlugin.Util.getString("SystemSource.nullif_param1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("op2", type, QueryPlugin.Util.getString("SystemSource.nullif_param1")) }, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", type, QueryPlugin.Util.getString("SystemSource.nullif_result")), true, FunctionMethod.DETERMINISTIC)); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", type, QueryPlugin.Util.getString("SystemSource.nullif_result")), true, Determinism.DETERMINISTIC)); //$NON-NLS-1$ //$NON-NLS-2$
}
private void addTypedCoalesceFunction(String type) {
functions.add(
- new FunctionMethod(FunctionLibrary.COALESCE, QueryPlugin.Util.getString("SystemSource.coalesce_description"), MISCELLANEOUS, FunctionMethod.CAN_PUSHDOWN, FUNCTION_CLASS, "coalesce", //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionMethod(FunctionLibrary.COALESCE, QueryPlugin.Util.getString("SystemSource.coalesce_description"), MISCELLANEOUS, PushDown.CAN_PUSHDOWN, FUNCTION_CLASS, "coalesce", //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter[] {
new FunctionParameter("op1", type, QueryPlugin.Util.getString("SystemSource.coalesce_param1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("op2", type, QueryPlugin.Util.getString("SystemSource.coalesce_param1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("op3", type, QueryPlugin.Util.getString("SystemSource.coalesce_param1"), true) }, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", type, QueryPlugin.Util.getString("SystemSource.coalesce_result")), true, FunctionMethod.DETERMINISTIC)); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", type, QueryPlugin.Util.getString("SystemSource.coalesce_result")), true, Determinism.DETERMINISTIC)); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Get all function signatures for this metadata source.
* @return Unordered collection of {@link FunctionMethod}s
*/
- public Collection<FunctionMethod> getFunctionMethods() {
+ public Collection<org.teiid.metadata.FunctionMethod> getFunctionMethods() {
return this.functions;
}
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -65,8 +65,6 @@
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.FunctionLibrary;
import org.teiid.query.function.FunctionTree;
-import org.teiid.query.function.UDFSource;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.mapping.relational.QueryNode;
import org.teiid.query.mapping.xml.MappingDocument;
import org.teiid.query.mapping.xml.MappingLoader;
@@ -144,7 +142,7 @@
* TransformationMetadata constructor
* @param context Object containing the info needed to lookup metadta.
*/
- public TransformationMetadata(VDBMetaData vdbMetadata, final CompositeMetadataStore store, Map<String, Resource> vdbEntries, Collection <FunctionMethod> udfMethods, FunctionTree systemFunctions) {
+ public TransformationMetadata(VDBMetaData vdbMetadata, final CompositeMetadataStore store, Map<String, Resource> vdbEntries, FunctionTree systemFunctions, FunctionTree... udfFunctions) {
ArgCheck.isNotNull(store);
this.vdbMetaData = vdbMetadata;
this.store = store;
@@ -153,10 +151,7 @@
} else {
this.vdbEntries = vdbEntries;
}
- if (udfMethods == null) {
- udfMethods = Collections.emptyList();
- }
- this.functionLibrary = new FunctionLibrary(systemFunctions, new FunctionTree(new UDFSource(udfMethods), true));
+ this.functionLibrary = new FunctionLibrary(systemFunctions, udfFunctions);
}
//==================================================================================
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -34,6 +34,7 @@
import org.teiid.core.id.IDGenerator;
import org.teiid.core.id.IntegerIDFactory;
import org.teiid.dqp.internal.process.PreparedPlan;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempCapabilitiesFinder;
@@ -111,7 +112,7 @@
String fullName = metadata.getFullName(cupc.getVirtualGroup().getMetadataID());
PreparedPlan pp = context.getPlan(fullName);
if (pp == null) {
- int determinismLevel = context.resetDeterminismLevel();
+ Determinism determinismLevel = context.resetDeterminismLevel();
ProcessorPlan plan = planProcedure(command, metadata, idGenerator, capFinder, analysisRecord, context);
//note that this is not a full prepared plan. It is not usable by user queries.
pp = new PreparedPlan();
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -27,9 +27,9 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.SupportConstants;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -228,7 +228,7 @@
if (EvaluatableVisitor.willBecomeConstant(obj, true)) {
return;
}
- if(obj.getFunctionDescriptor().getPushdown() == FunctionMethod.CANNOT_PUSHDOWN) {
+ if(obj.getFunctionDescriptor().getPushdown() == PushDown.CANNOT_PUSHDOWN) {
markInvalid(obj, "Function metadata indicates it cannot be pusheddown."); //$NON-NLS-1$
return;
}
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/JoinRegion.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/JoinRegion.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/JoinRegion.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -35,7 +35,7 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.core.TeiidComponentException;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.relational.RelationalPlanner;
import org.teiid.query.optimizer.relational.plantree.NodeConstants;
@@ -473,7 +473,7 @@
Iterator functions = FunctionCollectorVisitor.getFunctions(expression, true).iterator();
while (functions.hasNext()) {
Function function = (Function)functions.next();
- if (function.getFunctionDescriptor().getPushdown() == FunctionMethod.CANNOT_PUSHDOWN) {
+ if (function.getFunctionDescriptor().getPushdown() == PushDown.CANNOT_PUSHDOWN) {
return true;
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -32,8 +32,8 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryPlannerException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.analysis.AnalysisRecord;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
import org.teiid.query.optimizer.relational.OptimizerRule;
@@ -350,7 +350,7 @@
// TEIID-16: We do not want to merge a non-deterministic scalar function
Collection<Function> functions = FunctionCollectorVisitor.getFunctions(symbol, true, true);
for (Function function : functions) {
- if ( function.getFunctionDescriptor().getDeterministic() >= FunctionMethod.NONDETERMINISTIC ) {
+ if ( function.getFunctionDescriptor().getDeterministic().isRestrictiveThanOrEqual(Determinism.NONDETERMINISTIC )) {
return false;
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -102,17 +102,6 @@
return sb.toString();
}
- String validateFunctionName(String id) throws ParseException {
- int length = id.length();
- for(int i=0; i<length; i++) {
- char c = id.charAt(i);
- if(! (c == '_' || StringUtil.isLetterOrDigit(c))) {
- throw new ParseException(QueryPlugin.Util.getString("SQLParser.Invalid_func", id)); //$NON-NLS-1$
- }
- }
- return id;
- }
-
/**
* Check if this is a valid string literal
* @param id Possible string literal
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/EvaluatableVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/EvaluatableVisitor.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/EvaluatableVisitor.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -27,8 +27,9 @@
import java.util.TreeSet;
+import org.teiid.metadata.FunctionMethod.PushDown;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.function.FunctionLibrary;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
@@ -63,16 +64,16 @@
private TreeSet<EvaluationLevel> levels = new TreeSet<EvaluationLevel>();
private EvaluationLevel targetLevel;
- private int determinismLevel;
+ private Determinism determinismLevel = Determinism.DETERMINISTIC;
private boolean hasCorrelatedReferences;
public void visit(Function obj) {
this.setDeterminismLevel(obj.getFunctionDescriptor().getDeterministic());
- if (obj.getFunctionDescriptor().getPushdown() == FunctionMethod.MUST_PUSHDOWN) {
+ if (obj.getFunctionDescriptor().getPushdown() == PushDown.MUST_PUSHDOWN) {
evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
} else if (obj.getName().equalsIgnoreCase(FunctionLibrary.LOOKUP)
//TODO: if we had the context here we could plan better for non-prepared requests
- || obj.getFunctionDescriptor().getDeterministic() >= FunctionMethod.COMMAND_DETERMINISTIC) {
+ || obj.getFunctionDescriptor().getDeterministic().isRestrictiveThanOrEqual(Determinism.COMMAND_DETERMINISTIC)) {
evaluationNotPossible(EvaluationLevel.PROCESSING);
}
}
@@ -84,8 +85,8 @@
}
}
- private void setDeterminismLevel(int value) {
- determinismLevel = Math.max(determinismLevel, value);
+ private void setDeterminismLevel(Determinism value) {
+ determinismLevel = Determinism.restrictiveOf(determinismLevel, value);
}
private void evaluationNotPossible(EvaluationLevel newLevel) {
@@ -196,7 +197,7 @@
EvaluatableVisitor visitor = new EvaluatableVisitor();
visitor.targetLevel = EvaluationLevel.PROCESSING;
PreOrderNavigator.doVisit(obj, visitor);
- if (pushdown && (visitor.hasCorrelatedReferences || visitor.determinismLevel >= FunctionMethod.NONDETERMINISTIC)) {
+ if (pushdown && (visitor.hasCorrelatedReferences || visitor.determinismLevel.isRestrictiveThanOrEqual(Determinism.NONDETERMINISTIC))) {
return false;
}
return visitor.isEvaluationPossible();
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -57,10 +57,10 @@
import org.teiid.language.SQLConstants.Reserved;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.eval.Evaluator;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.mapping.relational.QueryNode;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempMetadataID;
@@ -277,7 +277,7 @@
option.setNoCache(true);
option.addNoCacheGroup(fullName);
proc.setOption(option);
- int determinismLevel = context.resetDeterminismLevel();
+ Determinism determinismLevel = context.resetDeterminismLevel();
QueryProcessor qp = context.getQueryProcessorFactory().createQueryProcessor(proc.toString(), fullName.toUpperCase(), context);
qp.setNonBlocking(true);
BatchCollector bc = qp.createBatchCollector();
@@ -505,7 +505,7 @@
TupleBuffer tb = bc.collectTuples();
cr.setResults(tb);
touchTable(context, fullName, true);
- this.distributedCache.put(cid, FunctionMethod.VDB_DETERMINISTIC, cr, info.getTtl());
+ this.distributedCache.put(cid, Determinism.VDB_DETERMINISTIC, cr, info.getTtl());
ts = tb.createIndexedTupleSource();
} else {
ts = new BatchCollector.BatchProducerTupleSource(qp);
Modified: trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -36,9 +36,9 @@
import org.teiid.dqp.internal.process.PreparedPlan;
import org.teiid.dqp.internal.process.SessionAwareCache;
import org.teiid.dqp.internal.process.SessionAwareCache.CacheID;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.QueryPlugin;
import org.teiid.query.eval.SecurityFunctionEvaluator;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.relational.PlanToProcessConverter;
import org.teiid.query.parser.ParseInfo;
@@ -90,7 +90,7 @@
private QueryProcessor.ProcessorFactory queryProcessorFactory;
- private int determinismLevel;
+ private Determinism determinismLevel = Determinism.DETERMINISTIC;
private Set<String> groups;
@@ -152,18 +152,18 @@
this.globalState = state;
}
- public int getDeterminismLevel() {
+ public Determinism getDeterminismLevel() {
return globalState.determinismLevel;
}
- public int resetDeterminismLevel() {
- int result = globalState.determinismLevel;
- globalState.determinismLevel = 0;
+ public Determinism resetDeterminismLevel() {
+ Determinism result = globalState.determinismLevel;
+ globalState.determinismLevel = Determinism.DETERMINISTIC;
return result;
}
- public void setDeterminismLevel(int level) {
- globalState.determinismLevel = Math.max(globalState.determinismLevel, level);
+ public void setDeterminismLevel(Determinism level) {
+ globalState.determinismLevel = Determinism.restrictiveOf(globalState.determinismLevel, level);
}
/**
@@ -485,16 +485,16 @@
PreparedPlan pp = this.globalState.planCache.get(id);
if (pp != null) {
if (id.getSessionId() != null) {
- setDeterminismLevel(FunctionMethod.USER_DETERMINISTIC);
+ setDeterminismLevel(Determinism.USER_DETERMINISTIC);
} else if (id.getUserName() != null) {
- setDeterminismLevel(FunctionMethod.SESSION_DETERMINISTIC);
+ setDeterminismLevel(Determinism.SESSION_DETERMINISTIC);
}
return pp;
}
return null;
}
- public void putPlan(String key, PreparedPlan plan, int determinismLevel) {
+ public void putPlan(String key, PreparedPlan plan, Determinism determinismLevel) {
if (this.globalState.planCache == null) {
return;
}
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-12-03 18:46:01 UTC (rev 2754)
@@ -3539,9 +3539,6 @@
}
|
( funcName = id()
- {
- funcName = validateFunctionName(funcName);
- }
<LPAREN>
[
expression = expression(info)
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestConnectorCapabilitiesFinder.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestConnectorCapabilitiesFinder.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestConnectorCapabilitiesFinder.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -23,16 +23,22 @@
package org.teiid.dqp.internal.process;
import java.util.ArrayList;
+import java.util.List;
import junit.framework.TestCase;
import org.mockito.Mockito;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.dqp.internal.datamgr.CapabilitiesConverter;
import org.teiid.dqp.internal.datamgr.ConnectorManager;
import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.SourceCapabilities;
+import org.teiid.translator.ExecutionFactory;
/**
@@ -77,4 +83,20 @@
assertEquals("Did not get expected capabilities", true, actual.supportsFunction(functionName)); //$NON-NLS-1$
}
+
+ public void testPushdownFunctionSupport() throws Exception {
+ ExecutionFactory<Object, Object> ef = new ExecutionFactory<Object, Object>(){
+ public List<FunctionMethod> getPushDownFunctions(){
+ ArrayList<FunctionMethod> list = new ArrayList<FunctionMethod>();
+ list.add(new FunctionMethod("ns.func", "function", "misc", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter[] {
+ new FunctionParameter("param", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "" ) )); //$NON-NLS-1$ //$NON-NLS-2$
+ return list;
+ }
+ };
+
+ BasicSourceCapabilities bsc = CapabilitiesConverter.convertCapabilities(ef, "conn"); //$NON-NLS-1$
+ assertEquals("Did not get expected capabilities", true, bsc.supportsFunction("ns.func")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
}
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedPlanCache.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedPlanCache.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedPlanCache.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -22,7 +22,10 @@
package org.teiid.dqp.internal.process;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
@@ -30,8 +33,8 @@
import org.junit.Test;
import org.teiid.api.exception.query.QueryParserException;
import org.teiid.dqp.internal.process.SessionAwareCache.CacheID;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.analysis.AnalysisRecord;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.parser.ParseInfo;
import org.teiid.query.parser.QueryParser;
import org.teiid.query.processor.relational.ProjectNode;
@@ -62,7 +65,7 @@
//No PreparedPlan at the begining
assertNull(cache.get(id));
//create one
- cache.put(id, FunctionMethod.SESSION_DETERMINISTIC, new PreparedPlan(), null);
+ cache.put(id, Determinism.SESSION_DETERMINISTIC, new PreparedPlan(), null);
//should have one now
assertNotNull("Unable to get prepared plan from cache", cache.get(id)); //$NON-NLS-1$
}
@@ -149,7 +152,7 @@
CacheID id = new CacheID(session, pi, dummy.toString());
PreparedPlan pPlan = new PreparedPlan();
- cache.put(id, FunctionMethod.SESSION_DETERMINISTIC, pPlan, null);
+ cache.put(id, Determinism.SESSION_DETERMINISTIC, pPlan, null);
pPlan.setCommand(dummy);
pPlan.setPlan(new RelationalPlan(new ProjectNode(i)));
AnalysisRecord analysisRecord = new AnalysisRecord(true, false);
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestSessionAwareCache.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestSessionAwareCache.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestSessionAwareCache.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -21,6 +21,11 @@
*/
package org.teiid.dqp.internal.process;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.times;
+
import org.junit.Test;
import org.mockito.Mockito;
import org.teiid.adminapi.impl.SessionMetadata;
@@ -28,10 +33,8 @@
import org.teiid.cache.Cache;
import org.teiid.common.buffer.BufferManager;
import org.teiid.dqp.internal.process.SessionAwareCache.CacheID;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.parser.ParseInfo;
-import static org.mockito.Mockito.*;
-import static org.junit.Assert.*;
@SuppressWarnings("nls")
@@ -47,7 +50,7 @@
Cachable result = Mockito.mock(Cachable.class);
id = new CacheID(buildWorkContext(), new ParseInfo(), "SELECT * FROM FOO");
- cache.put(id, FunctionMethod.SESSION_DETERMINISTIC, result, null);
+ cache.put(id, Determinism.SESSION_DETERMINISTIC, result, null);
// make sure that in the case of session specific; we do not call prepare
// as session is local only call for distributed
@@ -71,7 +74,7 @@
Mockito.stub(result.prepare((Cache)anyObject(), (BufferManager)anyObject())).toReturn(true);
Mockito.stub(result.restore((Cache)anyObject(), (BufferManager)anyObject())).toReturn(true);
- cache.put(id, FunctionMethod.USER_DETERMINISTIC, result, null);
+ cache.put(id, Determinism.USER_DETERMINISTIC, result, null);
// make sure that in the case of session specific; we do not call prepare
// as session is local only call for distributed
@@ -97,7 +100,7 @@
Mockito.stub(result.prepare((Cache)anyObject(), (BufferManager)anyObject())).toReturn(true);
Mockito.stub(result.restore((Cache)anyObject(), (BufferManager)anyObject())).toReturn(true);
- cache.put(id, FunctionMethod.VDB_DETERMINISTIC, result, null);
+ cache.put(id, Determinism.VDB_DETERMINISTIC, result, null);
// make sure that in the case of session specific; we do not call prepare
// as session is local only call for distributed
@@ -124,7 +127,7 @@
Mockito.stub(result.restore((Cache)anyObject(), (BufferManager)anyObject())).toReturn(true);
id = new CacheID(buildWorkContext(), new ParseInfo(), "SELECT * FROM FOO");
- cache.put(id, FunctionMethod.VDB_DETERMINISTIC, result, null);
+ cache.put(id, Determinism.VDB_DETERMINISTIC, result, null);
Object c = cache.get(id);
Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionDescriptorImpl.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionDescriptorImpl.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionDescriptorImpl.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -28,7 +28,8 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.UnitTestUtil;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionMethod.Determinism;
+import org.teiid.metadata.FunctionMethod.PushDown;
public class TestFunctionDescriptorImpl extends TestCase {
@@ -74,39 +75,39 @@
}
public void test1() throws Exception {
- FunctionDescriptor f1 = new FunctionDescriptor("+", FunctionMethod.CAN_PUSHDOWN, //$NON-NLS-1$
+ FunctionDescriptor f1 = new FunctionDescriptor("+", PushDown.CAN_PUSHDOWN, //$NON-NLS-1$
new Class[] { DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.INTEGER },
DataTypeManager.DefaultDataClasses.INTEGER,
- lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2) , false, true, FunctionMethod.DETERMINISTIC); //$NON-NLS-1$ //$NON-NLS-2$
+ lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2) , false, true, Determinism.DETERMINISTIC); //$NON-NLS-1$ //$NON-NLS-2$
UnitTestUtil.helpTestEquivalence(0, f1, f1);
}
public void test2() throws Exception {
- FunctionDescriptor f1 = new FunctionDescriptor("+", FunctionMethod.CAN_PUSHDOWN,//$NON-NLS-1$
+ FunctionDescriptor f1 = new FunctionDescriptor("+", PushDown.CAN_PUSHDOWN,//$NON-NLS-1$
new Class[] { DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.INTEGER },
DataTypeManager.DefaultDataClasses.INTEGER,
- lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2), false, true, FunctionMethod.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
+ lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2), false, true, Determinism.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
- FunctionDescriptor f2 = new FunctionDescriptor("+", FunctionMethod.CAN_PUSHDOWN,//$NON-NLS-1$
+ FunctionDescriptor f2 = new FunctionDescriptor("+", PushDown.CAN_PUSHDOWN,//$NON-NLS-1$
new Class[] { DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.INTEGER },
DataTypeManager.DefaultDataClasses.INTEGER,
- lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2), false, true, FunctionMethod.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
+ lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2), false, true, Determinism.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
UnitTestUtil.helpTestEquivalence(0, f1, f2);
}
public void test3() throws Exception {
- FunctionDescriptor f1 = new FunctionDescriptor("+", FunctionMethod.CAN_PUSHDOWN,//$NON-NLS-1$
+ FunctionDescriptor f1 = new FunctionDescriptor("+", PushDown.CAN_PUSHDOWN,//$NON-NLS-1$
new Class[] { DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.INTEGER },
DataTypeManager.DefaultDataClasses.INTEGER,
- lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2), false, false, FunctionMethod.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
+ lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2), false, false, Determinism.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
- FunctionDescriptor f2 = new FunctionDescriptor("+", FunctionMethod.CAN_PUSHDOWN,//$NON-NLS-1$
+ FunctionDescriptor f2 = new FunctionDescriptor("+", PushDown.CAN_PUSHDOWN,//$NON-NLS-1$
new Class[] { DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.INTEGER },
DataTypeManager.DefaultDataClasses.INTEGER,
- lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2), false, true, FunctionMethod.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
+ lookupMethod("com.metamatrix.query.function.FunctionMethods", "plus", 2), false, true, Determinism.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
assertNotSame("objects should not be equal", f1, f2); //$NON-NLS-1$
}
Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -22,7 +22,12 @@
package org.teiid.query.function;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -56,7 +61,7 @@
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.TimestampWithTimezone;
import org.teiid.language.SQLConstants.NonReserved;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.unittest.FakeMetadataFactory;
import org.teiid.query.unittest.TimestampUtil;
import org.teiid.query.util.CommandContext;
@@ -98,8 +103,8 @@
public String getName() {
return fname;
}
- public int getPushdown() {
- return FunctionMethod.CAN_PUSHDOWN;
+ public PushDown getPushdown() {
+ return PushDown.CAN_PUSHDOWN;
}
public Class[] getTypes() {
return ftypes;
Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMetadataReader.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMetadataReader.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMetadataReader.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -29,10 +29,13 @@
import junit.framework.TestCase;
import org.teiid.core.util.UnitTestUtil;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod.PushDown;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.function.metadata.FunctionMetadataReader;
-import org.teiid.query.function.metadata.FunctionMethod;
-import org.teiid.query.function.metadata.FunctionParameter;
+@SuppressWarnings("nls")
public class TestFunctionMetadataReader extends TestCase {
public void testLoadFunctionMethods() throws Exception {
@@ -46,8 +49,8 @@
assertEquals("MyFunctions", m.getCategory());
assertEquals("com.metamatrix.dqp.embedded.udf.MyFunctions", m.getInvocationClass());
assertEquals("getProperty", m.getInvocationMethod());
- assertEquals(FunctionMethod.CAN_PUSHDOWN, m.getPushdown());
- assertEquals(FunctionMethod.DETERMINISTIC, m.getDeterministic());
+ assertEquals(PushDown.CAN_PUSHDOWN, m.getPushdown());
+ assertEquals(Determinism.DETERMINISTIC, m.getDeterminism());
assertNull(m.getDescription());
assertEquals(1, m.getInputParameterCount());
@@ -65,8 +68,8 @@
assertEquals("MyFunctions", m.getCategory());
assertEquals("com.metamatrix.dqp.embedded.udf.MyFunctions", m.getInvocationClass());
assertEquals("getPropertyNoArgs", m.getInvocationMethod());
- assertEquals(FunctionMethod.CANNOT_PUSHDOWN, m.getPushdown());
- assertEquals(FunctionMethod.DETERMINISTIC, m.getDeterministic());
+ assertEquals(PushDown.CANNOT_PUSHDOWN, m.getPushdown());
+ assertEquals(Determinism.DETERMINISTIC, m.getDeterminism());
assertNull(m.getDescription());
assertEquals(0, m.getInputParameterCount());
@@ -79,8 +82,8 @@
assertEquals("MyFunctions", m.getCategory());
assertEquals("com.metamatrix.dqp.embedded.udf.MyFunctions", m.getInvocationClass());
assertEquals("getPropertyNoArgs", m.getInvocationMethod());
- assertEquals(FunctionMethod.CAN_PUSHDOWN, m.getPushdown());
- assertEquals(FunctionMethod.NONDETERMINISTIC, m.getDeterministic());
+ assertEquals(PushDown.CAN_PUSHDOWN, m.getPushdown());
+ assertEquals(Determinism.NONDETERMINISTIC, m.getDeterminism());
assertNull(m.getDescription());
assertEquals(0, m.getInputParameterCount());
Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionTree.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionTree.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionTree.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -33,9 +33,11 @@
import org.mockito.Mockito;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.DataTypeManager;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod.PushDown;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.function.metadata.FunctionCategoryConstants;
-import org.teiid.query.function.metadata.FunctionMethod;
-import org.teiid.query.function.metadata.FunctionParameter;
import org.teiid.query.function.source.SystemSource;
import org.teiid.query.unittest.FakeMetadataFactory;
@@ -71,9 +73,9 @@
@Test public void testLoadErrors() {
FunctionMethod method = new FunctionMethod(
- "dummy", null, null, FunctionMethod.CAN_PUSHDOWN, "nonexistentClass", "noMethod", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ "dummy", null, null, PushDown.CAN_PUSHDOWN, "nonexistentClass", "noMethod", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[0],
- new FunctionParameter("output", DataTypeManager.DefaultDataTypes.STRING)); //$NON-NLS-1$
+ new FunctionParameter("output", DataTypeManager.DefaultDataTypes.STRING), false, Determinism.DETERMINISTIC); //$NON-NLS-1$
//allowed, since we're not validating the class
new FunctionLibrary(FakeMetadataFactory.SFM.getSystemFunctions(), new FunctionTree(new UDFSource(Arrays.asList(method))));
@@ -133,12 +135,15 @@
}
@Test public void testNullCategory() {
+ FunctionMethod method = new FunctionMethod(
+ "dummy", null, null, PushDown.MUST_PUSHDOWN, "nonexistentClass", "noMethod", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter[0],
+ new FunctionParameter("output", DataTypeManager.DefaultDataTypes.STRING), //$NON-NLS-1$
+ false, Determinism.DETERMINISTIC);
+
+ Collection<org.teiid.metadata.FunctionMethod> list = Arrays.asList(method);
FunctionMetadataSource fms = Mockito.mock(FunctionMetadataSource.class);
- Mockito.stub(fms.getFunctionMethods()).toReturn(Arrays.asList(new FunctionMethod(
- "dummy", null, null, FunctionMethod.MUST_PUSHDOWN, "nonexistentClass", "noMethod", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- new FunctionParameter[0],
- new FunctionParameter("output", DataTypeManager.DefaultDataTypes.STRING) //$NON-NLS-1$
- )));
+ Mockito.stub(fms.getFunctionMethods()).toReturn(list);
FunctionTree ft = new FunctionTree(fms);
assertEquals(1, ft.getFunctionForms(FunctionCategoryConstants.MISCELLANEOUS).size());
}
Modified: trunk/engine/src/test/java/org/teiid/query/function/metadata/TestFunctionMetadataValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/metadata/TestFunctionMetadataValidator.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/function/metadata/TestFunctionMetadataValidator.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -22,13 +22,12 @@
package org.teiid.query.function.metadata;
-import org.teiid.api.exception.query.FunctionMetadataException;
-import org.teiid.query.function.metadata.FunctionMetadataValidator;
-import org.teiid.query.function.metadata.FunctionMethod;
-
import junit.framework.TestCase;
+import org.teiid.api.exception.query.FunctionMetadataException;
+import org.teiid.metadata.FunctionMethod.PushDown;
+
public class TestFunctionMetadataValidator extends TestCase {
// ################################## FRAMEWORK ################################
@@ -55,7 +54,7 @@
}
}
- public void helpTestValidateFunction(String className, String methodName, int pushdown) {
+ public void helpTestValidateFunction(String className, String methodName, PushDown pushdown) {
try {
FunctionMetadataValidator.validateInvocationMethod(className, methodName, pushdown);
} catch(FunctionMetadataException e) {
@@ -63,7 +62,7 @@
}
}
- public void helpTestValidateFunctionFail(String className, String methodName, int pushdown) {
+ public void helpTestValidateFunctionFail(String className, String methodName, PushDown pushdown) {
try {
FunctionMetadataValidator.validateInvocationMethod(className, methodName, pushdown);
fail("Expected exception but did not get one"); //$NON-NLS-1$
@@ -102,63 +101,63 @@
}
public void testValidateFunction1() {
- helpTestValidateFunction("a", "b", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunction("a", "b", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunction2() {
- helpTestValidateFunction("a.b", "b", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunction("a.b", "b", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunction3() {
- helpTestValidateFunction("a.b.c", "b", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunction("a.b.c", "b", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunction4() {
- helpTestValidateFunction("a$1", "b", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunction("a$1", "b", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunction5() {
- helpTestValidateFunction(null, null, FunctionMethod.MUST_PUSHDOWN);
+ helpTestValidateFunction(null, null, PushDown.MUST_PUSHDOWN);
}
public void testValidateFunctionFail1() {
- helpTestValidateFunctionFail(null, null, FunctionMethod.CAN_PUSHDOWN);
+ helpTestValidateFunctionFail(null, null, PushDown.CAN_PUSHDOWN);
}
public void testValidateFunctionFail2() {
- helpTestValidateFunctionFail(null, "a", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$
+ helpTestValidateFunctionFail(null, "a", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$
}
public void testValidateFunctionFail3() {
- helpTestValidateFunctionFail("a", null, FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$
+ helpTestValidateFunctionFail("a", null, PushDown.CAN_PUSHDOWN); //$NON-NLS-1$
}
public void testValidateFunctionFail4() {
- helpTestValidateFunctionFail("1", "b", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunctionFail("1", "b", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunctionFail5() {
- helpTestValidateFunctionFail("a", "2", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunctionFail("a", "2", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunctionFail6() {
- helpTestValidateFunctionFail("a@(", "b", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunctionFail("a@(", "b", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunctionFail7() {
- helpTestValidateFunctionFail("a.b.", "b", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunctionFail("a.b.", "b", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunctionFail8() {
- helpTestValidateFunctionFail("a", "b.c", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunctionFail("a", "b.c", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunctionFail9() {
- helpTestValidateFunctionFail("a", "b@", FunctionMethod.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
+ helpTestValidateFunctionFail("a", "b@", PushDown.CAN_PUSHDOWN); //$NON-NLS-1$ //$NON-NLS-2$
}
public void testValidateFunctionFail10() {
- helpTestValidateFunctionFail(null, null, FunctionMethod.CAN_PUSHDOWN);
- helpTestValidateFunctionFail(null, null, FunctionMethod.CANNOT_PUSHDOWN);
+ helpTestValidateFunctionFail(null, null, PushDown.CAN_PUSHDOWN);
+ helpTestValidateFunctionFail(null, null, PushDown.CANNOT_PUSHDOWN);
}
}
Modified: trunk/engine/src/test/java/org/teiid/query/function/metadata/TestFunctionMethod.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/metadata/TestFunctionMethod.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/function/metadata/TestFunctionMethod.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -22,14 +22,12 @@
package org.teiid.query.function.metadata;
-import org.teiid.core.util.UnitTestUtil;
-import org.teiid.query.function.metadata.FunctionCategoryConstants;
-import org.teiid.query.function.metadata.FunctionMethod;
-import org.teiid.query.function.metadata.FunctionParameter;
-
import junit.framework.TestCase;
+import org.teiid.core.util.UnitTestUtil;
+import org.teiid.metadata.FunctionParameter;
+
public class TestFunctionMethod extends TestCase {
public TestFunctionMethod(String name) {
Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestTransformationMetadata.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/metadata/TestTransformationMetadata.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestTransformationMetadata.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -92,7 +92,7 @@
vdb.addModel(buildModel("x1"));
vdb.addModel(buildModel("y"));
- return new TransformationMetadata(vdb, cms, resources, null, FakeMetadataFactory.SFM.getSystemFunctions());
+ return new TransformationMetadata(vdb, cms, resources, FakeMetadataFactory.SFM.getSystemFunctions(), null);
}
ModelMetaData buildModel(String name) {
@@ -125,7 +125,7 @@
model2.setVisible(true);
vdb.addModel(model2);
- TransformationMetadata tm = new TransformationMetadata(vdb, cms, null, null, FakeMetadataFactory.SFM.getSystemFunctions());
+ TransformationMetadata tm = new TransformationMetadata(vdb, cms, null, FakeMetadataFactory.SFM.getSystemFunctions(), null);
Collection result = tm.getGroupsForPartialName("y"); //$NON-NLS-1$
assertEquals(2, result.size());
@@ -133,7 +133,7 @@
model.setVisible(false);
- tm = new TransformationMetadata(vdb, cms, null, null, FakeMetadataFactory.SFM.getSystemFunctions());
+ tm = new TransformationMetadata(vdb, cms, null, FakeMetadataFactory.SFM.getSystemFunctions(), null);
result = tm.getGroupsForPartialName("y"); //$NON-NLS-1$
assertEquals(1, result.size());
}
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/FakeFunctionMetadataSource.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/FakeFunctionMetadataSource.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/FakeFunctionMetadataSource.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -26,25 +26,32 @@
import java.util.Collection;
import java.util.List;
+import org.teiid.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.function.FunctionMetadataSource;
import org.teiid.query.function.metadata.FunctionMethod;
-import org.teiid.query.function.metadata.FunctionParameter;
public class FakeFunctionMetadataSource implements FunctionMetadataSource {
public Collection getFunctionMethods() {
List methods = new ArrayList();
- methods.add(new FunctionMethod("xyz", "", "misc", FunctionMethod.MUST_PUSHDOWN, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ methods.add(new FunctionMethod("xyz", "", "misc", PushDown.MUST_PUSHDOWN, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
FakeFunctionMetadataSource.class.getName(), "xyz", //$NON-NLS-1$
new FunctionParameter[0],
new FunctionParameter("out", "integer"))); //$NON-NLS-1$ //$NON-NLS-2$
FunctionParameter p1 = new FunctionParameter("astring", "string"); //$NON-NLS-1$ //$NON-NLS-2$
FunctionParameter result = new FunctionParameter("trimstring", "string"); //$NON-NLS-1$ //$NON-NLS-2$
+
FunctionMethod method = new FunctionMethod("MYRTRIM", "", "", FakeFunctionMetadataSource.class.getName(), "myrtrim", new FunctionParameter[] {p1}, result); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- method.setPushdown(FunctionMethod.CAN_PUSHDOWN);
+ method.setPushdown(PushDown.CAN_PUSHDOWN);
methods.add(method);
+
+ FunctionMethod method2 = new FunctionMethod("misc.namespace.func", "", "", null, null, new FunctionParameter[] {p1}, result); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ method2.setPushdown(PushDown.MUST_PUSHDOWN);
+ methods.add(method2);
+
return methods;
}
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -6572,10 +6572,17 @@
helpException(sql, "Parsing error: Invalid alias format: [a.x]"); //$NON-NLS-1$
}
- @Test public void testBadFunctionName() {
+ @Test public void testNameSpacedFunctionName() {
String sql = "select a.x()"; //$NON-NLS-1$
- helpException(sql, "Parsing error: Invalid function name: [a.x]"); //$NON-NLS-1$
+ Query query = new Query();
+ Select select = new Select();
+ Function func1 = new Function("a.x", new Expression[] { }); //$NON-NLS-1$
+ ExpressionSymbol exprSymbol = new ExpressionSymbol("expr", func1); //$NON-NLS-1$
+ select.addSymbol(exprSymbol);
+ query.setSelect(select);
+
+ helpTest(sql, "SELECT a.x()", query); //$NON-NLS-1$
}
@Test public void testUnionJoin() {
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -22,7 +22,8 @@
package org.teiid.query.processor;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collection;
@@ -36,7 +37,7 @@
import org.teiid.core.TeiidProcessingException;
import org.teiid.dqp.internal.process.CachedResults;
import org.teiid.dqp.internal.process.SessionAwareCache;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.metadata.TempMetadataAdapter;
import org.teiid.query.tempdata.TempTableDataManager;
import org.teiid.query.tempdata.TempTableStore;
@@ -58,7 +59,7 @@
CommandContext cc = TestProcessor.createCommandContext();
cc.setTempTableStore(tempStore);
TestProcessor.doProcess(processorPlan, dataManager, expectedResults, cc);
- assertTrue(cc.getDeterminismLevel() <= FunctionMethod.SESSION_DETERMINISTIC);
+ assertTrue(Determinism.SESSION_DETERMINISTIC.isRestrictiveThanOrEqual(cc.getDeterminismLevel()));
}
@Before public void setUp() {
Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -56,10 +56,13 @@
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.function.FunctionDescriptor;
import org.teiid.query.function.FunctionLibrary;
+import org.teiid.query.function.FunctionTree;
+import org.teiid.query.function.UDFSource;
import org.teiid.query.mapping.relational.QueryNode;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.metadata.TempMetadataStore;
+import org.teiid.query.optimizer.FakeFunctionMetadataSource;
import org.teiid.query.parser.QueryParser;
import org.teiid.query.resolver.util.BindVariableVisitor;
import org.teiid.query.sql.LanguageObject;
@@ -1581,6 +1584,20 @@
}
}
+ @Test public void testNamespacedFunction() throws Exception {
+ String sql = "SELECT namespace.func('e1') FROM vm1.g1 "; //$NON-NLS-1$
+
+ FunctionLibrary funcLibrary = new FunctionLibrary(FakeMetadataFactory.SFM.getSystemFunctions(), new FunctionTree(new UDFSource(new FakeFunctionMetadataSource().getFunctionMethods())));
+ FakeMetadataFacade metadata = new FakeMetadataFacade(FakeMetadataFactory.example1Cached().getStore(), funcLibrary);
+
+ Query command = (Query) helpParse(sql);
+ QueryResolver.resolveCommand(command, metadata);
+
+ command = (Query) helpParse("SELECT func('e1') FROM vm1.g1 ");
+ QueryResolver.resolveCommand(command, metadata);
+
+ }
+
// special test for both sides are String
@Test public void testSetCriteriaCastFromExpression_9657() {
// parse
@@ -3078,5 +3095,4 @@
helpResolveUpdateProcedure(procedure, userQuery);
}
-
}
\ No newline at end of file
Modified: trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -32,6 +32,8 @@
import org.teiid.metadata.Column;
import org.teiid.metadata.ColumnSet;
import org.teiid.metadata.ForeignKey;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
import org.teiid.metadata.KeyRecord;
import org.teiid.metadata.MetadataStore;
import org.teiid.metadata.Procedure;
@@ -41,6 +43,8 @@
import org.teiid.metadata.BaseColumn.NullType;
import org.teiid.metadata.Column.SearchType;
import org.teiid.metadata.ProcedureParameter.Type;
+import org.teiid.query.function.FunctionTree;
+import org.teiid.query.function.UDFSource;
import org.teiid.query.mapping.relational.QueryNode;
import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
@@ -57,8 +61,7 @@
public static TransformationMetadata exampleBQTCached() {
return CACHED_BQT;
}
-
- public static TransformationMetadata exampleBQT() {
+ public static MetadataStore exampleBQTStore() {
MetadataStore metadataStore = new MetadataStore();
Schema bqt1 = createPhysicalModel("BQT1", metadataStore); //$NON-NLS-1$
@@ -264,21 +267,32 @@
Procedure vsp7 = createVirtualProcedure("TEIIDSP7", mmspTest1, Arrays.asList(vsp7p1), vspqn7); //$NON-NLS-1$
vsp7.setResultSet(vsprs7);
- return createTransformationMetadata(metadataStore, "bqt");
+ // this is for the source added function
+ bqt1.addFunction(new FunctionMethod("reverse", "reverse", "misc", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter[] {new FunctionParameter("columnName", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ return metadataStore;
}
+
+ public static TransformationMetadata exampleBQT() {
+ return createTransformationMetadata(exampleBQTStore(), "bqt");
+ }
+
- public static TransformationMetadata createTransformationMetadata(
- MetadataStore metadataStore, String vdbName) {
+ public static TransformationMetadata createTransformationMetadata(MetadataStore metadataStore, String vdbName) {
CompositeMetadataStore store = new CompositeMetadataStore(metadataStore);
VDBMetaData vdbMetaData = new VDBMetaData();
vdbMetaData.setName(vdbName); //$NON-NLS-1$
vdbMetaData.setVersion(1);
+ List<FunctionTree> udfs = new ArrayList<FunctionTree>();
for (Schema schema : metadataStore.getSchemas().values()) {
vdbMetaData.addModel(FakeMetadataFactory.createModel(schema.getName(), schema.isPhysical()));
+ udfs.add(new FunctionTree(new UDFSource(schema.getFunctions().values()), true));
}
- return new TransformationMetadata(vdbMetaData, store, null, null, FakeMetadataFactory.SFM.getSystemFunctions());
+ return new TransformationMetadata(vdbMetaData, store, null, FakeMetadataFactory.SFM.getSystemFunctions(), udfs.toArray(new FunctionTree[udfs.size()]));
}
-
+
/**
* Metadata for Materialized Views
* @return
Modified: trunk/metadata/src/test/java/org/teiid/cdk/api/TranslationUtility.java
===================================================================
--- trunk/metadata/src/test/java/org/teiid/cdk/api/TranslationUtility.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/metadata/src/test/java/org/teiid/cdk/api/TranslationUtility.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -29,13 +29,13 @@
import org.teiid.cdk.CommandBuilder;
import org.teiid.dqp.internal.datamgr.RuntimeMetadataImpl;
import org.teiid.language.Command;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.metadata.RuntimeMetadata;
import org.teiid.metadata.index.VDBMetadataFactory;
import org.teiid.query.function.FunctionLibrary;
import org.teiid.query.function.FunctionTree;
import org.teiid.query.function.SystemFunctionManager;
import org.teiid.query.function.UDFSource;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.metadata.BasicQueryMetadataWrapper;
import org.teiid.query.metadata.QueryMetadataInterface;
Modified: trunk/metadata/src/test/java/org/teiid/metadata/index/VDBMetadataFactory.java
===================================================================
--- trunk/metadata/src/test/java/org/teiid/metadata/index/VDBMetadataFactory.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/metadata/src/test/java/org/teiid/metadata/index/VDBMetadataFactory.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -38,10 +38,12 @@
import org.teiid.core.util.FileUtils;
import org.teiid.core.util.LRUCache;
import org.teiid.core.util.UnitTestUtil;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.metadata.MetadataStore;
+import org.teiid.query.function.FunctionTree;
import org.teiid.query.function.SystemFunctionManager;
+import org.teiid.query.function.UDFSource;
import org.teiid.query.function.metadata.FunctionMetadataReader;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.TransformationMetadata;
@@ -85,7 +87,7 @@
methods = FunctionMetadataReader.loadFunctionMethods(udfFile.openStream());
}
SystemFunctionManager sfm = new SystemFunctionManager();
- vdbmetadata = new TransformationMetadata(null, new CompositeMetadataStore(Arrays.asList(getSystem(), imf.getMetadataStore(getSystem().getDatatypes()))), imf.getEntriesPlusVisibilities(), methods, sfm.getSystemFunctions());
+ vdbmetadata = new TransformationMetadata(null, new CompositeMetadataStore(Arrays.asList(getSystem(), imf.getMetadataStore(getSystem().getDatatypes()))), imf.getEntriesPlusVisibilities(), sfm.getSystemFunctions(), new FunctionTree(new UDFSource(methods), true));
VDB_CACHE.put(vdbURL, vdbmetadata);
return vdbmetadata;
} catch (URISyntaxException e) {
Modified: trunk/runtime/src/main/java/org/teiid/deployers/CompositeVDB.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/deployers/CompositeVDB.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/runtime/src/main/java/org/teiid/deployers/CompositeVDB.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -21,18 +21,24 @@
*/
package org.teiid.deployers;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
+import java.util.List;
import org.teiid.adminapi.DataPolicy;
import org.teiid.adminapi.Model;
import org.teiid.adminapi.impl.DataPolicyMetadata;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.dqp.internal.datamgr.ConnectorManager;
import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository;
+import org.teiid.metadata.AbstractMetadataRecord;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.metadata.MetadataStore;
+import org.teiid.metadata.Schema;
import org.teiid.query.function.FunctionTree;
-import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.query.function.UDFSource;
import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TransformationMetadata;
@@ -92,9 +98,11 @@
}
private TransformationMetadata buildTransformationMetaData(VDBMetaData vdb, LinkedHashMap<String, Resource> visibilityMap, MetadataStoreGroup stores, UDFMetaData udf, FunctionTree systemFunctions) {
- Collection <FunctionMethod> methods = null;
- if (udf != null) {
- methods = udf.getFunctions();
+ Collection <FunctionTree> udfs = new ArrayList<FunctionTree>();
+ if (udf != null) {
+ for (Collection<FunctionMethod> methods:udf.getFunctions()) {
+ udfs.add(new FunctionTree(new UDFSource(methods), true));
+ }
}
CompositeMetadataStore compositeStore = new CompositeMetadataStore(stores.getStores());
@@ -102,7 +110,7 @@
compositeStore.addMetadataStore(s);
}
- TransformationMetadata metadata = new TransformationMetadata(vdb, compositeStore, visibilityMap, methods, systemFunctions);
+ TransformationMetadata metadata = new TransformationMetadata(vdb, compositeStore, visibilityMap, systemFunctions, udfs.toArray(new FunctionTree[udfs.size()]));
return metadata;
}
@@ -148,20 +156,40 @@
}
private UDFMetaData getUDF() {
- if (this.children == null || this.children.isEmpty()) {
- return this.udf;
- }
-
UDFMetaData mergedUDF = new UDFMetaData();
if (this.udf != null) {
- mergedUDF.addFunctions(this.udf.getFunctions());
+ mergedUDF.addFunctions(this.udf);
}
- for (CompositeVDB child:this.children.values()) {
- UDFMetaData funcs = child.getUDF();
- if (funcs != null) {
- mergedUDF.addFunctions(funcs.getFunctions());
+ if (this.stores != null) {
+ for(MetadataStore store:this.stores.getStores()) {
+ for (Schema schema:store.getSchemas().values()) {
+ Collection<FunctionMethod> funcs = schema.getFunctions().values();
+ for(FunctionMethod func:funcs) {
+ func.setNameInSource(func.getName());
+ func.setName(schema.getName() + AbstractMetadataRecord.NAME_DELIM_CHAR + func.getName());
+ }
+ mergedUDF.addFunctions(funcs);
+ }
}
- }
+ }
+ if (this.cmr != null) {
+ for (ConnectorManager cm:this.cmr.getConnectorManagers().values()) {
+ List<FunctionMethod> funcs = cm.getPushDownFunctions();
+ for(FunctionMethod func:funcs) {
+ func.setNameInSource(cm.getTranslatorName()+ AbstractMetadataRecord.NAME_DELIM_CHAR + func.getName());
+ func.setName(cm.getModelName() + AbstractMetadataRecord.NAME_DELIM_CHAR + func.getName());
+ }
+ mergedUDF.addFunctions(funcs);
+ }
+ }
+ if (this.children != null) {
+ for (CompositeVDB child:this.children.values()) {
+ UDFMetaData funcs = child.getUDF();
+ if (funcs != null) {
+ mergedUDF.addFunctions(funcs);
+ }
+ }
+ }
return mergedUDF;
}
Modified: trunk/runtime/src/main/java/org/teiid/deployers/UDFMetaData.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/deployers/UDFMetaData.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/runtime/src/main/java/org/teiid/deployers/UDFMetaData.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -30,14 +30,14 @@
import org.jboss.managed.api.annotation.ManagementObject;
import org.jboss.virtual.VirtualFile;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.query.function.metadata.FunctionMetadataReader;
-import org.teiid.query.function.metadata.FunctionMethod;
import org.teiid.runtime.RuntimePlugin;
@ManagementObject
public class UDFMetaData {
- private Collection <FunctionMethod> methods = new ArrayList<FunctionMethod>();
+ private Collection<Collection <FunctionMethod>> methods = new ArrayList<Collection<FunctionMethod>>();
private HashMap<String, VirtualFile> files = new HashMap<String, VirtualFile>();
@@ -55,18 +55,22 @@
}
VirtualFile file =this.files.get(name);
if (file != null) {
- this.methods.addAll(FunctionMetadataReader.loadFunctionMethods(file.openStream()));
+ this.methods.add(FunctionMetadataReader.loadFunctionMethods(file.openStream()));
}
else {
throw new IOException(RuntimePlugin.Util.getString("udf_model_not_found", name)); //$NON-NLS-1$
}
}
- public Collection <FunctionMethod> getFunctions(){
+ public Collection<Collection <FunctionMethod>> getFunctions(){
return this.methods;
}
public void addFunctions(Collection <FunctionMethod> funcs){
- this.methods.addAll(funcs);
+ this.methods.add(funcs);
}
+
+ public void addFunctions(UDFMetaData funcs){
+ this.methods.addAll(funcs.getFunctions());
+ }
}
Modified: trunk/runtime/src/main/java/org/teiid/deployers/VDBDeployer.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/deployers/VDBDeployer.java 2010-12-03 17:14:37 UTC (rev 2753)
+++ trunk/runtime/src/main/java/org/teiid/deployers/VDBDeployer.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -193,6 +193,7 @@
ConnectorManager cm = new ConnectorManager(name, model.getSourceConnectionJndiName(source));
cm.setExecutionFactory(ef);
+ cm.setModelName(model.getName());
cmr.addConnectorManager(source, cm);
}
}
Added: trunk/runtime/src/test/java/org/teiid/deployers/TestCompositeVDB.java
===================================================================
--- trunk/runtime/src/test/java/org/teiid/deployers/TestCompositeVDB.java (rev 0)
+++ trunk/runtime/src/test/java/org/teiid/deployers/TestCompositeVDB.java 2010-12-03 18:46:01 UTC (rev 2754)
@@ -0,0 +1,142 @@
+/*
+ * 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.deployers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.dqp.internal.datamgr.ConnectorManager;
+import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository;
+import org.teiid.metadata.FunctionMethod;
+import org.teiid.metadata.FunctionParameter;
+import org.teiid.metadata.MetadataStore;
+import org.teiid.metadata.Schema;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.parser.QueryParser;
+import org.teiid.query.resolver.QueryResolver;
+import org.teiid.query.sql.lang.Command;
+import org.teiid.query.unittest.FakeMetadataFactory;
+import org.teiid.query.unittest.RealMetadataFactory;
+import org.teiid.translator.ExecutionFactory;
+
+@SuppressWarnings("nls")
+public class TestCompositeVDB {
+
+ public static TransformationMetadata createTransformationMetadata(MetadataStore metadataStore, String vdbName) throws Exception {
+ VDBMetaData vdbMetaData = new VDBMetaData();
+ vdbMetaData.setName(vdbName); //$NON-NLS-1$
+ vdbMetaData.setVersion(1);
+ for (Schema schema : metadataStore.getSchemas().values()) {
+ vdbMetaData.addModel(FakeMetadataFactory.createModel(schema.getName(), schema.isPhysical()));
+ }
+ MetadataStoreGroup metaGroup = new MetadataStoreGroup();
+ metaGroup.addStore(metadataStore);
+
+ ConnectorManagerRepository cmr = new ConnectorManagerRepository();
+ cmr.addConnectorManager("source", getConnectorManager("bqt1", "FakeTranslator", "FakeConnection", getFuncsOne()));
+ cmr.addConnectorManager("source2", getConnectorManager("bqt2", "FakeTranslator2", "FakeConnection2", getFuncsTwo()));
+
+ CompositeVDB cvdb = new CompositeVDB(vdbMetaData, metaGroup, null, null, FakeMetadataFactory.SFM.getSystemFunctions(),cmr);
+ VDBMetaData vdb = cvdb.getVDB();
+ return vdb.getAttachment(TransformationMetadata.class);
+ }
+
+ private static ConnectorManager getConnectorManager(String modelName, String translatorName, String connectionName, List<FunctionMethod> funcs) {
+ final ExecutionFactory<Object, Object> ef = Mockito.mock(ExecutionFactory.class);
+
+ Mockito.stub(ef.getPushDownFunctions()).toReturn(funcs);
+
+ ConnectorManager cm = new ConnectorManager(translatorName,connectionName) {
+ protected ExecutionFactory getExecutionFactory() {
+ return ef;
+ }
+ };
+ cm.setModelName(modelName);
+ cm.start();
+ return cm;
+ }
+
+ private static List<FunctionMethod> getFuncsOne() {
+ List<FunctionMethod> funcs = new ArrayList<FunctionMethod>();
+ funcs.add(new FunctionMethod("echo", "echo", "misc", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter[] {new FunctionParameter("columnName", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ funcs.add(new FunctionMethod("duplicate_func", "duplicate", "misc", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter[] {new FunctionParameter("columnName", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ return funcs;
+ }
+
+ private static List<FunctionMethod> getFuncsTwo() {
+ List<FunctionMethod> funcs = new ArrayList<FunctionMethod>();
+ funcs.add(new FunctionMethod("duplicate_func", "duplicate", "misc", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter[] {new FunctionParameter("columnName", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ funcs.add(new FunctionMethod("duplicate_func", "duplicate", "misc", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ new FunctionParameter[] {new FunctionParameter("c1", DataTypeManager.DefaultDataTypes.INTEGER, ""),
+ new FunctionParameter("c2", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, "") ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ return funcs;
+ }
+
+
+ private void helpResolve(String sql) throws Exception {
+ TransformationMetadata metadata = createTransformationMetadata(RealMetadataFactory.exampleBQTStore(), "bqt");
+ Command command = QueryParser.getQueryParser().parseCommand(sql);
+ QueryResolver.resolveCommand(command, metadata);
+ }
+
+ @Test
+ public void testSourceMetadataStoreFunction() throws Exception {
+ helpResolve("SELECT bqt1.reverse(BQT1.SmallA.INTKEY) FROM BQT1.SmallA");
+ }
+
+ @Test
+ public void testTranslatorDefinedFunction() throws Exception {
+ helpResolve("SELECT bqt1.echo(BQT1.SmallA.INTKEY) FROM BQT1.SmallA");
+ }
+
+ @Test
+ public void testPartialUDFName() throws Exception {
+ helpResolve("SELECT echo(BQT1.SmallA.STRINGKEY) FROM BQT1.SmallA");
+ }
+
+ @Test
+ public void testFullyQualifiedDuplicate() throws Exception {
+ helpResolve("SELECT bqt1.duplicate_func(BQT1.SmallA.STRINGKEY) FROM BQT1.SmallA");
+ }
+
+ @Test
+ public void testNonQualifiedDuplicateWithDifferentSignature() throws Exception {
+ helpResolve("SELECT duplicate_func(BQT1.SmallA.INTKEY, BQT1.SmallA.STRINGKEY) FROM BQT1.SmallA");
+ }
+
+ @Test
+ public void testNonQualifiedDuplicate() throws Exception {
+ helpResolve("SELECT duplicate_func(BQT1.SmallA.INTKEY) FROM BQT1.SmallA");
+ }
+
+}
Property changes on: trunk/runtime/src/test/java/org/teiid/deployers/TestCompositeVDB.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
14 years, 1 month
teiid SVN: r2753 - in trunk/engine/src: main/java/org/teiid/query/validator and 3 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-03 12:14:37 -0500 (Fri, 03 Dec 2010)
New Revision: 2753
Removed:
trunk/engine/src/main/java/org/teiid/query/validator/ValidatorWarning.java
Modified:
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidatorReport.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java
Log:
TEIID-1351 ensuring that validation is performed only based update type
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2010-12-02 21:53:52 UTC (rev 2752)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2010-12-03 17:14:37 UTC (rev 2753)
@@ -23,7 +23,6 @@
package org.teiid.query.resolver;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -41,7 +40,6 @@
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.metadata.TempMetadataID.Type;
import org.teiid.query.parser.QueryParser;
-import org.teiid.query.report.ReportItem;
import org.teiid.query.resolver.command.UpdateProcedureResolver;
import org.teiid.query.resolver.util.ResolverUtil;
import org.teiid.query.sql.ProcedureReservedWords;
@@ -56,7 +54,6 @@
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.validator.UpdateValidator;
-import org.teiid.query.validator.ValidatorFailure;
import org.teiid.query.validator.UpdateValidator.UpdateInfo;
@@ -236,7 +233,17 @@
throws TeiidComponentException, QueryMetadataException,
QueryResolverException {
if(!procCommand.getGroup().isTempGroupSymbol() && metadata.isVirtualGroup(procCommand.getGroup().getMetadataID())) {
- return getPlan(metadata, procCommand.getGroup());
+ String plan = getPlan(metadata, procCommand.getGroup());
+ if (plan == null && !metadata.isProcedure(procCommand.getGroup().getMetadataID())) {
+ UpdateInfo info = getUpdateInfo(procCommand.getGroup(), metadata);
+ int type = procCommand.getType();
+ if ((info.isDeleteValidationError() && type == Command.TYPE_DELETE)
+ || (info.isUpdateValidationError() && type == Command.TYPE_UPDATE)
+ || (info.isInsertValidationError() && type == Command.TYPE_INSERT)) {
+ throw new QueryResolverException("ERR.015.008.0009", QueryPlugin.Util.getString("ERR.015.008.0009", procCommand.getGroup(), procCommand.getClass().getSimpleName())); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ return plan;
}
return null;
}
@@ -260,17 +267,8 @@
metadata.getInsertPlan(group.getMetadataID()) == null);
validator.validate(UpdateProcedureResolver.getQueryTransformCmd(group, metadata), elements);
info = validator.getUpdateInfo();
- for (ReportItem item : (Collection<ReportItem>)validator.getReport().getItems()) {
- if (item instanceof ValidatorFailure) {
- info.setValidationError(item.getMessage());
- break;
- }
- }
metadata.addToMetadataCache(group.getMetadataID(), "UpdateInfo", info); //$NON-NLS-1$
}
- if (info.getValidationError() != null) {
- throw new QueryResolverException(info.getValidationError());
- }
return info;
}
Modified: trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java 2010-12-02 21:53:52 UTC (rev 2752)
+++ trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java 2010-12-03 17:14:37 UTC (rev 2753)
@@ -83,10 +83,12 @@
private Map<String, UpdateMapping> updatableGroups = new HashMap<String, UpdateMapping>();
private boolean isSimple = true;
private UpdateMapping deleteTarget;
- private String validationError;
private boolean inherentUpdate;
+ private boolean updateValidationError;
private boolean inherentDelete;
+ private boolean deleteValidationError;
private boolean inherentInsert;
+ private boolean insertValidationError;
private Query view;
public boolean isSimple() {
@@ -101,14 +103,6 @@
return updatableGroups;
}
- public String getValidationError() {
- return validationError;
- }
-
- public void setValidationError(String validationError) {
- this.validationError = validationError;
- }
-
public boolean isInherentDelete() {
return inherentDelete;
}
@@ -134,6 +128,18 @@
return view;
}
+ public boolean isDeleteValidationError() {
+ return deleteValidationError;
+ }
+
+ public boolean isInsertValidationError() {
+ return insertValidationError;
+ }
+
+ public boolean isUpdateValidationError() {
+ return updateValidationError;
+ }
+
}
private QueryMetadataInterface metadata;
@@ -155,38 +161,45 @@
return report;
}
+ private void handleValidationError(String error, boolean update, boolean insert, boolean delete) {
+ report.handleValidationError(error);
+ updateInfo.updateValidationError |= update;
+ updateInfo.insertValidationError |= insert;
+ updateInfo.deleteValidationError |= delete;
+ }
+
public void validate(Command command, List<ElementSymbol> viewSymbols) throws QueryMetadataException, TeiidComponentException {
if (!(command instanceof Query)) {
- report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001"), true, true, true); //$NON-NLS-1$
return;
}
Query query = (Query)command;
if (query.getFrom() == null || query.getInto() != null) {
- report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001"), true, true, true); //$NON-NLS-1$
return;
}
if (query.getWith() != null) {
- report.handleValidationWarning(QueryPlugin.Util.getString("ERR.015.012.0002")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0002"), true, true, true); //$NON-NLS-1$
updateInfo.isSimple = false;
}
if (query.hasAggregates()) {
- report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0006")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0006"), true, true, true); //$NON-NLS-1$
return;
}
updateInfo.view = query;
if (query.getLimit() != null) {
- report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0013")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0013"), true, true, true); //$NON-NLS-1$
return;
}
if (query.getSelect().isDistinct()) {
- report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0008")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0008"), true, true, true); //$NON-NLS-1$
return;
}
@@ -221,12 +234,12 @@
} else {
//TODO: look for reversable widening conversions
- report.handleValidationWarning(QueryPlugin.Util.getString("ERR.015.012.0007", viewSymbols.get(i), symbol)); //$NON-NLS-1$
+ report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0007", viewSymbols.get(i), symbol)); //$NON-NLS-1$
}
}
if (query.getFrom().getClauses().size() > 1 || (!(query.getFrom().getClauses().get(0) instanceof UnaryFromClause))) {
- report.handleValidationWarning(QueryPlugin.Util.getString("ERR.015.012.0009", query.getFrom())); //$NON-NLS-1$
+ report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0009", query.getFrom())); //$NON-NLS-1$
updateInfo.isSimple = false;
}
List<GroupSymbol> allGroups = query.getFrom().getGroups();
@@ -249,7 +262,7 @@
if (info == null) {
continue; // not projected
}
- report.handleValidationWarning(QueryPlugin.Util.getString("ERR.015.012.0004", groupSymbol)); //$NON-NLS-1$
+ report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0004", groupSymbol)); //$NON-NLS-1$
}
}
@@ -268,16 +281,16 @@
insertable |= info.insertAllowed;
}
if ((this.updateInfo.inherentInsert && !insertable)) {
- report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0015")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0015"), false, true, false); //$NON-NLS-1$
}
if (this.updateInfo.inherentUpdate && !updatable) {
- report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0005")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0005"), true, false, true); //$NON-NLS-1$
}
if (this.updateInfo.inherentDelete && this.updateInfo.deleteTarget == null) {
if (this.updateInfo.isSimple) {
this.updateInfo.deleteTarget = this.updateInfo.updatableGroups.values().iterator().next();
} else {
- report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0014")); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0014"), false, false, true); //$NON-NLS-1$
}
}
}
@@ -290,7 +303,7 @@
}
if (!metadata.groupSupports(groupSymbol.getMetadataID(), SupportConstants.Group.UPDATE)) {
- report.handleValidationWarning(QueryPlugin.Util.getString("ERR.015.012.0003", groupSymbol)); //$NON-NLS-1$
+ report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0003", groupSymbol)); //$NON-NLS-1$
return;
}
@@ -318,7 +331,7 @@
return true;
}
if (this.updateInfo.inherentInsert) {
- report.handleValidationWarning(QueryPlugin.Util.getString("ERR.015.012.0010", element, element.getGroupSymbol())); //$NON-NLS-1$
+ report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0010", element, element.getGroupSymbol())); //$NON-NLS-1$
}
return false;
}
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidatorReport.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidatorReport.java 2010-12-02 21:53:52 UTC (rev 2752)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidatorReport.java 2010-12-03 17:14:37 UTC (rev 2753)
@@ -87,8 +87,4 @@
this.addItem(new ValidatorFailure(message, invalidObjs));
}
- public void handleValidationWarning(String message) {
- this.addItem(new ValidatorWarning(message));
- }
-
}
Deleted: trunk/engine/src/main/java/org/teiid/query/validator/ValidatorWarning.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidatorWarning.java 2010-12-02 21:53:52 UTC (rev 2752)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidatorWarning.java 2010-12-03 17:14:37 UTC (rev 2753)
@@ -1,84 +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.query.validator;
-
-import java.util.*;
-
-import org.teiid.query.report.ReportItem;
-import org.teiid.query.sql.LanguageObject;
-
-public class ValidatorWarning extends ReportItem {
-
- private static final long serialVersionUID = 3991298598581344564L;
-
- public static final String VALIDATOR_WARNING = "ValidatorWarning"; //$NON-NLS-1$
-
- // Don't want to pass this around, so make it transient
- private transient Collection invalidObjects;
-
- public ValidatorWarning(String description) {
- super(VALIDATOR_WARNING);
- setMessage(description);
- }
-
- public ValidatorWarning(String description, LanguageObject object) {
- super(VALIDATOR_WARNING);
- setMessage(description);
- this.invalidObjects = new ArrayList(1);
- this.invalidObjects.add(object);
- }
-
- public ValidatorWarning(String description, Collection objects) {
- super(VALIDATOR_WARNING);
- setMessage(description);
- this.invalidObjects = new ArrayList(objects);
- }
-
- /**
- * Get count of invalid objects.
- * @return Count of invalid objects
- */
- public int getInvalidObjectCount() {
- if(this.invalidObjects == null) {
- return 0;
- }
- return this.invalidObjects.size();
- }
-
- /**
- * Get the objects that failed validation. The collection may be null.
- * @return Invalid objects, may be null
- */
- public Collection getInvalidObjects() {
- return this.invalidObjects;
- }
-
- /**
- * Return description
- * @return Description of failure
- */
- public String toString() {
- return getMessage();
- }
-
-}
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-02 21:53:52 UTC (rev 2752)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-03 17:14:37 UTC (rev 2753)
@@ -94,7 +94,7 @@
# resolver (008)
ERR.015.008.0003= Only one XML document may be specified in the FROM clause of a query.
ERR.015.008.0007= Incorrect number of parameters specified on the stored procedure {2} - expected {0} but got {1}
-ERR.015.008.0009= {1} is not allowed on the virtual group {0}: no {1} procedure was defined.
+ERR.015.008.0009= {1} is not allowed on the view {0}: a procedure must be defined to handle the {1}.
ERR.015.008.0010= INSERT statement must have the same number of elements and values specified. This statement has {0} elements and {1} values.
ERR.015.008.0011= Error parsing query plan transformation for {0}
ERR.015.008.0012= Unable to resolve update procedure as the virtual group context is ambiguous.
Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java 2010-12-02 21:53:52 UTC (rev 2752)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java 2010-12-03 17:14:37 UTC (rev 2753)
@@ -2572,6 +2572,24 @@
helpResolveException(sql);
}
+
+ @Test public void testUpdateError() {
+ String userUpdateStr = "UPDATE vm1.g2 SET e1='x'"; //$NON-NLS-1$
+
+ helpResolveException(userUpdateStr, metadata, "Error Code:ERR.015.008.0009 Message:Update is not allowed on the view vm1.g2: a procedure must be defined to handle the Update."); //$NON-NLS-1$
+ }
+
+ @Test public void testInsertError() {
+ String userUpdateStr = "INSERT into vm1.g2 (e1) values ('x')"; //$NON-NLS-1$
+
+ helpResolveException(userUpdateStr, metadata, "Error Code:ERR.015.008.0009 Message:Insert is not allowed on the view vm1.g2: a procedure must be defined to handle the Insert."); //$NON-NLS-1$
+ }
+
+ @Test public void testDeleteError() {
+ String userUpdateStr = "DELETE from vm1.g2 where e1='x'"; //$NON-NLS-1$
+
+ helpResolveException(userUpdateStr, metadata, "Error Code:ERR.015.008.0009 Message:Delete is not allowed on the view vm1.g2: a procedure must be defined to handle the Delete."); //$NON-NLS-1$
+ }
@Test public void testResolveXMLSelect() {
String procedure = "CREATE VIRTUAL PROCEDURE "; //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java 2010-12-02 21:53:52 UTC (rev 2752)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java 2010-12-03 17:14:37 UTC (rev 2753)
@@ -24,7 +24,6 @@
import static org.junit.Assert.*;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -46,13 +45,13 @@
import org.teiid.query.mapping.relational.QueryNode;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.parser.QueryParser;
-import org.teiid.query.report.ReportItem;
import org.teiid.query.resolver.QueryResolver;
import org.teiid.query.resolver.util.ResolverUtil;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.unittest.RealMetadataFactory;
+import org.teiid.query.validator.UpdateValidator.UpdateInfo;
@SuppressWarnings("nls")
public class TestUpdateValidator {
@@ -66,15 +65,8 @@
GroupSymbol gs = new GroupSymbol(vGroup);
ResolverUtil.resolveGroup(gs, md);
uv.validate(command, ResolverUtil.resolveElementsInGroup(gs, md));
- boolean failed = false;
- for (ReportItem item : (Collection<ReportItem>)uv.getReport().getItems()) {
- if (item instanceof ValidatorFailure) {
- failed = true;
- if (!shouldFail) {
- fail(item.toString());
- }
- }
- }
+ UpdateInfo info = uv.getUpdateInfo();
+ boolean failed = info.isDeleteValidationError() || info.isInsertValidationError() || info.isUpdateValidationError();
if (!failed && shouldFail) {
fail("expeceted failures, but got none: " + uv.getReport());
}
14 years, 1 month
teiid SVN: r2752 - in trunk/engine/src: main/java/org/teiid/query/optimizer/relational and 13 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-02 16:53:52 -0500 (Thu, 02 Dec 2010)
New Revision: 2752
Added:
trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/TriggerAction.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseJoinStrategy.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java
trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/VariableResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateUpdateProcedureCommand.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/test/java/org/teiid/query/processor/FakeDataStore.java
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
Log:
TEIID-1351 initial check-in of for each row instead of trigger handling. still need to fix validation and combine with earlier rewrite based logic
Added: trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -0,0 +1,136 @@
+/*
+ * 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.optimizer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.teiid.api.exception.query.QueryMetadataException;
+import org.teiid.api.exception.query.QueryResolverException;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.id.IDGenerator;
+import org.teiid.language.SQLConstants;
+import org.teiid.query.analysis.AnalysisRecord;
+import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
+import org.teiid.query.optimizer.relational.rules.RuleChooseJoinStrategy;
+import org.teiid.query.processor.ProcessorPlan;
+import org.teiid.query.processor.proc.ForEachRowPlan;
+import org.teiid.query.processor.proc.ProcedurePlan;
+import org.teiid.query.processor.relational.RelationalNode;
+import org.teiid.query.resolver.QueryResolver;
+import org.teiid.query.resolver.util.ResolverUtil;
+import org.teiid.query.rewriter.QueryRewriter;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.ProcedureReservedWords;
+import org.teiid.query.sql.lang.Delete;
+import org.teiid.query.sql.lang.From;
+import org.teiid.query.sql.lang.Insert;
+import org.teiid.query.sql.lang.ProcedureContainer;
+import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.QueryCommand;
+import org.teiid.query.sql.lang.Select;
+import org.teiid.query.sql.lang.TranslatableProcedureContainer;
+import org.teiid.query.sql.lang.UnaryFromClause;
+import org.teiid.query.sql.lang.Update;
+import org.teiid.query.sql.proc.CreateUpdateProcedureCommand;
+import org.teiid.query.sql.proc.TriggerAction;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.ExpressionSymbol;
+import org.teiid.query.sql.symbol.SelectSymbol;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.util.CommandContext;
+
+
+public final class TriggerActionPlanner {
+
+ public ProcessorPlan optimize(ProcedureContainer userCommand, TriggerAction ta, IDGenerator idGenerator, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context)
+ throws QueryMetadataException, TeiidComponentException, QueryResolverException, TeiidProcessingException {
+ //TODO consider caching the plans without using the changing vars
+ QueryRewriter.rewrite(ta, null, metadata, context, QueryResolver.getVariableValues(userCommand, true, metadata), userCommand.getType());
+
+ QueryCommand query = null;
+ Map<ElementSymbol, Expression> params = new HashMap<ElementSymbol, Expression>();
+
+ if (userCommand instanceof Insert) {
+ Insert insert = (Insert)userCommand;
+ if (insert.getQueryExpression() != null) {
+ query = insert.getQueryExpression();
+ } else {
+ query = new Query();
+ ((Query)query).setSelect(new Select(RuleChooseJoinStrategy.createExpressionSymbols(insert.getValues())));
+ }
+ } else if (userCommand instanceof Delete) {
+ query = createOldQuery(userCommand, ta, metadata, params);
+ } else if (userCommand instanceof Update) {
+ query = createOldQuery(userCommand, ta, metadata, params);
+ } else {
+ throw new AssertionError();
+ }
+
+ for (Map.Entry<String, Expression> entry : QueryResolver.getVariableValues(userCommand, false, metadata).entrySet()) {
+ if (entry.getKey().startsWith(ProcedureReservedWords.INPUTS)) {
+ Expression value = entry.getValue() instanceof SingleElementSymbol ? entry.getValue() : new ExpressionSymbol("x", entry.getValue()); //$NON-NLS-1$
+ params.put(new ElementSymbol(SQLConstants.Reserved.NEW + ElementSymbol.SEPARATOR + SingleElementSymbol.getShortName(entry.getKey())), value);
+ if (userCommand instanceof Update) {
+ ((Query)query).getSelect().addSymbol((SelectSymbol) value);
+ }
+ } else {
+ params.put(new ElementSymbol(entry.getKey()), entry.getValue());
+ }
+ }
+ ForEachRowPlan result = new ForEachRowPlan();
+ result.setParams(params);
+ ProcessorPlan queryPlan = QueryOptimizer.optimizePlan(query, metadata, idGenerator, capFinder, analysisRecord, context);
+ result.setQueryPlan(queryPlan);
+ result.setLookupMap(RelationalNode.createLookupMap(query.getProjectedSymbols()));
+ ProcedurePlan rowProcedure = (ProcedurePlan)QueryOptimizer.optimizePlan(new CreateUpdateProcedureCommand(ta.getBlock()), metadata, idGenerator, capFinder, analysisRecord, context);
+ result.setRowProcedure(rowProcedure);
+ return result;
+ }
+
+ private QueryCommand createOldQuery(ProcedureContainer userCommand,
+ TriggerAction ta, QueryMetadataInterface metadata,
+ Map<ElementSymbol, Expression> params)
+ throws QueryMetadataException, TeiidComponentException {
+ QueryCommand query;
+ ArrayList<SelectSymbol> selectSymbols = new ArrayList<SelectSymbol>();
+ List<ElementSymbol> allSymbols = ResolverUtil.resolveElementsInGroup(ta.getView(), metadata);
+ for (ElementSymbol elementSymbol : allSymbols) {
+ params.put(new ElementSymbol(SQLConstants.Reserved.OLD + ElementSymbol.SEPARATOR + elementSymbol.getShortName()), elementSymbol);
+ if (userCommand instanceof Update) {
+ //default to old
+ params.put(new ElementSymbol(SQLConstants.Reserved.NEW + ElementSymbol.SEPARATOR + elementSymbol.getShortName()), elementSymbol);
+ }
+ }
+ selectSymbols.addAll(LanguageObject.Util.deepClone(allSymbols, ElementSymbol.class));
+ query = new Query(new Select(selectSymbols), new From(Arrays.asList(new UnaryFromClause(ta.getView()))), ((TranslatableProcedureContainer)userCommand).getCriteria(), null, null);
+ return query;
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/optimizer/TriggerActionPlanner.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -52,6 +52,7 @@
import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.optimizer.QueryOptimizer;
+import org.teiid.query.optimizer.TriggerActionPlanner;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
import org.teiid.query.optimizer.relational.plantree.NodeConstants;
@@ -100,6 +101,7 @@
import org.teiid.query.sql.lang.WithQueryCommand;
import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
import org.teiid.query.sql.proc.CreateUpdateProcedureCommand;
+import org.teiid.query.sql.proc.TriggerAction;
import org.teiid.query.sql.symbol.AllSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.Reference;
@@ -518,16 +520,17 @@
PlanNode sourceNode = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
sourceNode.setProperty(NodeConstants.Info.ATOMIC_REQUEST, command);
sourceNode.setProperty(NodeConstants.Info.VIRTUAL_COMMAND, command);
+ boolean usingTriggerAction = false;
if (command instanceof ProcedureContainer) {
ProcedureContainer container = (ProcedureContainer)command;
- addNestedProcedure(sourceNode, container);
+ usingTriggerAction = addNestedProcedure(sourceNode, container);
}
sourceNode.addGroups(groups);
attachLast(projectNode, sourceNode);
//for INTO query, attach source and project nodes
- if(command instanceof Insert){
+ if(!usingTriggerAction && command instanceof Insert){
Insert insert = (Insert)command;
if (insert.getQueryExpression() != null) {
PlanNode plan = generatePlan(insert.getQueryExpression());
@@ -540,7 +543,7 @@
return projectNode;
}
- private void addNestedProcedure(PlanNode sourceNode,
+ private boolean addNestedProcedure(PlanNode sourceNode,
ProcedureContainer container) throws TeiidComponentException,
QueryMetadataException, TeiidProcessingException {
String cacheString = "transformation/" + container.getClass().getSimpleName(); //$NON-NLS-1$
@@ -558,6 +561,12 @@
}
}
if (c != null) {
+ if (c instanceof TriggerAction) {
+ TriggerAction ta = (TriggerAction)c;
+ ProcessorPlan plan = new TriggerActionPlanner().optimize(container, ta, idGenerator, metadata, capFinder, analysisRecord, context);
+ sourceNode.setProperty(NodeConstants.Info.PROCESSOR_PLAN, plan);
+ return true;
+ }
if (c.getCacheHint() != null) {
if (container instanceof StoredProcedure) {
boolean noCache = isNoCacheGroup(metadata, ((StoredProcedure) container).getProcedureID(), option);
@@ -566,7 +575,7 @@
container.getGroup().setGlobalTable(true);
container.setCacheHint(c.getCacheHint());
recordAnnotation(analysisRecord, Annotation.CACHED_PROCEDURE, Priority.LOW, "SimpleQueryResolver.procedure_cache_used", container.getGroup()); //$NON-NLS-1$
- return;
+ return false;
}
recordAnnotation(analysisRecord, Annotation.CACHED_PROCEDURE, Priority.MEDIUM, "SimpleQueryResolver.procedure_cache_not_usable", container.getGroup()); //$NON-NLS-1$
} else {
@@ -577,7 +586,11 @@
//skip the rewrite here, we'll do that in the optimizer
//so that we know what the determinism level is.
addNestedCommand(sourceNode, container.getGroup(), container, c, false);
+ } else if (!(container instanceof Insert) && !container.getGroup().isTempGroupSymbol() &&
+ !CriteriaCapabilityValidatorVisitor.canPushLanguageObject(container, metadata.getModelID(container.getGroup().getMetadataID()), metadata, capFinder, analysisRecord)) {
+ throw new QueryPlannerException(QueryPlugin.Util.getString("RelationalPlanner.nonpushdown_command", container)); //$NON-NLS-1$
}
+
//plan any subqueries in criteria/parameters/values
for (SubqueryContainer subqueryContainer : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(container)) {
ProcessorPlan plan = QueryOptimizer.optimizePlan(subqueryContainer.getCommand(), metadata, null, capFinder, analysisRecord, context);
@@ -587,11 +600,7 @@
RuleCollapseSource.replaceCorrelatedReferences(subqueryContainer);
}
}
-
- if (c == null && !(container instanceof Insert) && !container.getGroup().isTempGroupSymbol() &&
- !CriteriaCapabilityValidatorVisitor.canPushLanguageObject(container, metadata.getModelID(container.getGroup().getMetadataID()), metadata, capFinder, analysisRecord)) {
- throw new QueryPlannerException(QueryPlugin.Util.getString("RelationalPlanner.nonpushdown_command", container)); //$NON-NLS-1$
- }
+ return false;
}
PlanNode createStoredProcedurePlan(StoredProcedure storedProc) throws QueryMetadataException, TeiidComponentException, TeiidProcessingException {
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseJoinStrategy.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseJoinStrategy.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseJoinStrategy.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -168,7 +168,7 @@
private static AtomicInteger EXPRESSION_INDEX = new AtomicInteger(0);
- static List<SingleElementSymbol> createExpressionSymbols(List<Expression> expressions) {
+ public static List<SingleElementSymbol> createExpressionSymbols(List<Expression> expressions) {
HashMap<Expression, ExpressionSymbol> uniqueExpressions = new HashMap<Expression, ExpressionSymbol>();
List<SingleElementSymbol> result = new ArrayList<SingleElementSymbol>();
for (Expression expression : expressions) {
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -70,7 +70,6 @@
import org.teiid.query.sql.navigator.DeepPostOrderNavigator;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.GroupSymbol;
-import org.teiid.query.sql.symbol.Reference;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.sql.visitor.ExpressionMappingVisitor;
@@ -366,20 +365,7 @@
Command command = child.getCommand();
final SymbolMap map = container.getCommand().getCorrelatedReferences();
if (map != null) {
- ExpressionMappingVisitor visitor = new ExpressionMappingVisitor(null) {
- @Override
- public Expression replaceExpression(
- Expression element) {
- if (element instanceof Reference) {
- Reference ref = (Reference)element;
- Expression replacement = map.getMappedExpression(ref.getExpression());
- if (replacement != null) {
- return replacement;
- }
- }
- return element;
- }
- };
+ ExpressionMappingVisitor visitor = new RuleMergeCriteria.ReferenceReplacementVisitor(map);
DeepPostOrderNavigator.doVisit(command, visitor);
}
command.setProcessorPlan(container.getCommand().getProcessorPlan());
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -87,12 +87,12 @@
/**
* Used to replace correlated references
*/
- private final class ReferenceReplacementVisitor extends
+ protected static final class ReferenceReplacementVisitor extends
ExpressionMappingVisitor {
private final SymbolMap refs;
private boolean replacedAny;
- private ReferenceReplacementVisitor(SymbolMap refs) {
+ ReferenceReplacementVisitor(SymbolMap refs) {
super(null);
this.refs = refs;
}
Modified: trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -93,6 +93,18 @@
return parseCommand(sql, new ParseInfo());
}
+ public Command parseUpdateProcedure(String sql) throws QueryParserException {
+ try{
+ Command result = getSqlParser(sql).updateProcedure(new ParseInfo());
+ result.setCacheHint(SQLParserUtil.getQueryCacheOption(sql));
+ return result;
+ } catch(ParseException pe) {
+ throw convertParserException(pe);
+ } catch(TokenMgrError tme) {
+ throw handleTokenMgrError(tme);
+ }
+ }
+
/**
* Takes a SQL string representing a Command and returns the object
* representation.
@@ -120,7 +132,7 @@
if(sql.startsWith(XML_OPEN_BRACKET) || sql.startsWith(XQUERY_DECLARE)) {
throw new QueryParserException(tme, QueryPlugin.Util.getString("QueryParser.xqueryCompilation", sql)); //$NON-NLS-1$
}
- handleTokenMgrError(tme);
+ throw handleTokenMgrError(tme);
}
return result;
}
@@ -155,7 +167,7 @@
throw convertParserException(pe);
} catch(TokenMgrError tme) {
- handleTokenMgrError(tme);
+ throw handleTokenMgrError(tme);
}
return result;
}
@@ -187,46 +199,37 @@
throw convertParserException(pe);
} catch(TokenMgrError tme) {
- handleTokenMgrError(tme);
+ throw handleTokenMgrError(tme);
}
return result;
}
- private void handleTokenMgrError(TokenMgrError tme) throws QueryParserException{
+ private QueryParserException handleTokenMgrError(TokenMgrError tme) {
// LogManager.logError( LogConstants.CTX_QUERY_PARSER, tme, new Object[] {"Exception parsing: ", sql} );
- try {
- // From TokenMgrError, here is format of lexical error:
- //
- // "Lexical error at line " + errorLine + ", column " + errorColumn +
- // ". Encountered: " + (EOFSeen ? "<EOF> " : ("\"" +
- // addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
- // "after : \"" + addEscapes(errorAfter) + "\""
+ // From TokenMgrError, here is format of lexical error:
+ //
+ // "Lexical error at line " + errorLine + ", column " + errorColumn +
+ // ". Encountered: " + (EOFSeen ? "<EOF> " : ("\"" +
+ // addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+ // "after : \"" + addEscapes(errorAfter) + "\""
- String msg = tme.getMessage();
- int index = msg.indexOf(LINE_MARKER);
+ String msg = tme.getMessage();
+ int index = msg.indexOf(LINE_MARKER);
+ if(index > 0) {
+ index += LINE_MARKER.length();
+ int lastIndex = msg.indexOf(",", index); //$NON-NLS-1$
+
+ index = msg.indexOf(COL_MARKER, lastIndex);
if(index > 0) {
- index += LINE_MARKER.length();
- int lastIndex = msg.indexOf(",", index); //$NON-NLS-1$
+ index += COL_MARKER.length();
+ lastIndex = msg.indexOf(".", index); //$NON-NLS-1$
- index = msg.indexOf(COL_MARKER, lastIndex);
- if(index > 0) {
- index += COL_MARKER.length();
- lastIndex = msg.indexOf(".", index); //$NON-NLS-1$
-
- QueryParserException qpe = new QueryParserException(QueryPlugin.Util.getString("QueryParser.lexicalError", tme.getMessage())); //$NON-NLS-1$
- throw qpe;
- }
-
+ return new QueryParserException(QueryPlugin.Util.getString("QueryParser.lexicalError", tme.getMessage())); //$NON-NLS-1$
}
- } catch(QueryParserException e) {
- throw e;
- } catch(Throwable e) {
- throw new QueryParserException(e, e.getMessage());
}
-
- throw new QueryParserException(QueryPlugin.Util.getString("QueryParser.parsingError", tme.getMessage())); //$NON-NLS-1$
+ return new QueryParserException(QueryPlugin.Util.getString("QueryParser.parsingError", tme.getMessage())); //$NON-NLS-1$
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ExecDynamicSqlInstruction.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -168,7 +168,7 @@
// create a new set of variables including vars
Map nameValueMap = createVariableValuesMap(localContext);
- nameValueMap.putAll(QueryResolver.getVariableValues(parentProcCommand.getUserCommand(), metadata));
+ nameValueMap.putAll(QueryResolver.getVariableValues(parentProcCommand.getUserCommand(), false, metadata));
ValidationVisitor visitor = new ValidationVisitor();
visitor.setUpdateProc(parentProcCommand);
Request.validateWithVisitor(visitor, metadata, command);
Added: trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -0,0 +1,160 @@
+/*
+ * 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.processor.proc;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.teiid.common.buffer.BlockedException;
+import org.teiid.common.buffer.BufferManager;
+import org.teiid.common.buffer.TupleBatch;
+import org.teiid.common.buffer.TupleSource;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.processor.BatchCollector;
+import org.teiid.query.processor.ProcessorDataManager;
+import org.teiid.query.processor.ProcessorPlan;
+import org.teiid.query.processor.QueryProcessor;
+import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.util.CommandContext;
+
+public class ForEachRowPlan extends ProcessorPlan {
+
+ private ProcessorPlan queryPlan;
+ private ProcedurePlan rowProcedure;
+ private Map<ElementSymbol, Expression> params;
+ private Map lookupMap;
+
+ private ProcessorDataManager dataMgr;
+ private BufferManager bufferMgr;
+
+ private QueryProcessor queryProcessor;
+ private TupleSource tupleSource;
+ private QueryProcessor rowProcessor;
+ private List<?> currentTuple;
+ private int updateCount;
+
+ @Override
+ public ProcessorPlan clone() {
+ ForEachRowPlan clone = new ForEachRowPlan();
+ clone.setQueryPlan(queryPlan.clone());
+ clone.setRowProcedure((ProcedurePlan) rowProcedure.clone());
+ clone.setParams(params);
+ clone.setLookupMap(lookupMap);
+ return clone;
+ }
+
+ @Override
+ public void close() throws TeiidComponentException {
+ if (this.queryProcessor != null) {
+ this.queryProcessor.closeProcessing();
+ if (this.rowProcessor != null) {
+ this.rowProcessor.closeProcessing();
+ }
+ }
+ }
+
+ @Override
+ public List<SingleElementSymbol> getOutputElements() {
+ return Command.getUpdateCommandSymbol();
+ }
+
+ @Override
+ public void initialize(CommandContext context,
+ ProcessorDataManager dataMgr, BufferManager bufferMgr) {
+ setContext(context);
+ this.dataMgr = dataMgr;
+ this.bufferMgr = bufferMgr;
+ }
+
+ @Override
+ public TupleBatch nextBatch() throws BlockedException,
+ TeiidComponentException, TeiidProcessingException {
+ while (true) {
+ if (currentTuple == null) {
+ currentTuple = tupleSource.nextTuple();
+ if (currentTuple == null) {
+ TupleBatch result = new TupleBatch(1, new List[] {Arrays.asList(updateCount)});
+ result.setTerminationFlag(true);
+ return result;
+ }
+ }
+ if (this.rowProcessor == null) {
+ rowProcedure.reset();
+ this.rowProcessor = new QueryProcessor(rowProcedure, getContext(), this.bufferMgr, this.dataMgr);
+ for (Map.Entry<ElementSymbol, Expression> entry : this.params.entrySet()) {
+ Integer index = (Integer)this.lookupMap.get(entry.getValue());
+ if (index != null) {
+ rowProcedure.getCurrentVariableContext().setValue(entry.getKey(), this.currentTuple.get(index));
+ } else {
+ rowProcedure.getCurrentVariableContext().setValue(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ //just getting the next batch is enough
+ this.rowProcessor.nextBatch();
+ this.rowProcessor.closeProcessing();
+ this.rowProcessor = null;
+ this.currentTuple = null;
+ this.updateCount++;
+ }
+ }
+
+ @Override
+ public void open() throws TeiidComponentException, TeiidProcessingException {
+ queryProcessor = new QueryProcessor(queryPlan, getContext(), this.bufferMgr, this.dataMgr);
+ tupleSource = new BatchCollector.BatchProducerTupleSource(queryProcessor);
+ }
+
+ public void setQueryPlan(ProcessorPlan queryPlan) {
+ this.queryPlan = queryPlan;
+ }
+
+ public void setRowProcedure(ProcedurePlan rowProcedure) {
+ this.rowProcedure = rowProcedure;
+ }
+
+ public void setParams(Map<ElementSymbol, Expression> params) {
+ this.params = params;
+ }
+
+ public void setLookupMap(Map symbolMap) {
+ this.lookupMap = symbolMap;
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ this.queryPlan.reset();
+ this.updateCount = 0;
+ this.currentTuple = null;
+ this.rowProcessor = null;
+ this.queryProcessor = null;
+ this.tupleSource = null;
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/processor/proc/ForEachRowPlan.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -32,6 +32,7 @@
import org.teiid.api.exception.query.QueryResolverException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.types.DataTypeManager;
+import org.teiid.language.SQLConstants;
import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
@@ -45,9 +46,13 @@
import org.teiid.query.resolver.util.ResolverUtil;
import org.teiid.query.sql.ProcedureReservedWords;
import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.Delete;
import org.teiid.query.sql.lang.GroupContext;
+import org.teiid.query.sql.lang.Insert;
import org.teiid.query.sql.lang.ProcedureContainer;
+import org.teiid.query.sql.lang.Update;
import org.teiid.query.sql.proc.CreateUpdateProcedureCommand;
+import org.teiid.query.sql.proc.TriggerAction;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.validator.UpdateValidator;
@@ -92,7 +97,7 @@
QueryParser parser = QueryParser.getQueryParser();
try {
- subCommand = parser.parseCommand(plan);
+ subCommand = parser.parseUpdateProcedure(plan);
} catch(QueryParserException e) {
throw new QueryResolverException(e, "ERR.015.008.0045", QueryPlugin.Util.getString("ERR.015.008.0045", group)); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -107,7 +112,26 @@
cupCommand.setVirtualGroup(procCommand.getGroup());
cupCommand.setUserCommand(procCommand);
- }
+ } else if (subCommand instanceof TriggerAction) {
+ TriggerAction ta = (TriggerAction)subCommand;
+ ta.setView(procCommand.getGroup());
+ TempMetadataAdapter tma = new TempMetadataAdapter(metadata, new TempMetadataStore());
+ ta.setTemporaryMetadata(tma.getMetadataStore().getData());
+ GroupContext externalGroups = procCommand.getExternalGroupContexts();
+
+ List<ElementSymbol> viewElements = ResolverUtil.resolveElementsInGroup(ta.getView(), metadata);
+ if (procCommand instanceof Update || procCommand instanceof Insert) {
+ addChanging(tma.getMetadataStore(), externalGroups, viewElements);
+ ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.NEW, tma.getMetadataStore(), externalGroups, viewElements);
+ }
+ if (procCommand instanceof Update || procCommand instanceof Delete) {
+ ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.OLD, tma.getMetadataStore(), externalGroups, viewElements);
+ }
+
+ new UpdateProcedureResolver().resolveBlock(new CreateUpdateProcedureCommand(), ta.getBlock(), externalGroups, tma, analysis);
+
+ return subCommand;
+ }
//find the childMetadata using a clean metadata store
TempMetadataStore childMetadata = new TempMetadataStore();
@@ -176,7 +200,13 @@
addScalarGroup(ProcedureReservedWords.INPUTS, discoveredMetadata, externalGroups, inputElments);
// Switch type to be boolean for all CHANGING variables
- List<ElementSymbol> changingElements = new ArrayList<ElementSymbol>(elements.size());
+ addChanging(discoveredMetadata, externalGroups, elements);
+ return externalGroups;
+ }
+
+ private static void addChanging(TempMetadataStore discoveredMetadata,
+ GroupContext externalGroups, List<ElementSymbol> elements) {
+ List<ElementSymbol> changingElements = new ArrayList<ElementSymbol>(elements.size());
for(int i=0; i<elements.size(); i++) {
ElementSymbol virtualElmnt = elements.get(i);
ElementSymbol changeElement = (ElementSymbol)virtualElmnt.clone();
@@ -185,7 +215,6 @@
}
addScalarGroup(ProcedureReservedWords.CHANGING, discoveredMetadata, externalGroups, changingElements);
- return externalGroups;
}
/**
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -60,6 +60,7 @@
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.SubqueryContainer;
import org.teiid.query.sql.lang.UnaryFromClause;
+import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
@@ -287,12 +288,12 @@
subCommand.setExternalGroupContexts(parentContext);
}
- public static Map getVariableValues(Command command, QueryMetadataInterface metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException {
+ public static Map<String, Expression> getVariableValues(Command command, boolean changingOnly, QueryMetadataInterface metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException {
CommandResolver resolver = chooseResolver(command, metadata);
if (resolver instanceof VariableResolver) {
- return ((VariableResolver)resolver).getVariableValues(command, metadata);
+ return ((VariableResolver)resolver).getVariableValues(command, changingOnly, metadata);
}
return Collections.EMPTY_MAP;
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/VariableResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/VariableResolver.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/VariableResolver.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -29,10 +29,11 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.symbol.Expression;
public interface VariableResolver {
- Map getVariableValues(Command command, QueryMetadataInterface metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException;
+ Map<String, Expression> getVariableValues(Command command, boolean changingOnly, QueryMetadataInterface metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException;
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/InsertResolver.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -243,16 +243,21 @@
* @throws QueryMetadataException
* @see org.teiid.query.resolver.CommandResolver#getVariableValues(org.teiid.query.sql.lang.Command, org.teiid.query.metadata.QueryMetadataInterface)
*/
- public Map getVariableValues(Command command,
+ public Map<String, Expression> getVariableValues(Command command, boolean changingOnly,
QueryMetadataInterface metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException {
Insert insert = (Insert) command;
- Map result = new HashMap();
+ Map<String, Expression> result = new HashMap<String, Expression>();
// iterate over the variables and values they should be the same number
Iterator varIter = insert.getVariables().iterator();
- Iterator valIter = insert.getValues().iterator();
+ Iterator valIter = null;
+ if (insert.getQueryExpression() != null) {
+ valIter = insert.getQueryExpression().getProjectedSymbols().iterator();
+ } else {
+ valIter = insert.getValues().iterator();
+ }
while (varIter.hasNext()) {
ElementSymbol varSymbol = (ElementSymbol) varIter.next();
@@ -260,8 +265,10 @@
String changingKey = ProcedureReservedWords.CHANGING + ElementSymbol.SEPARATOR + varName;
String inputsKey = ProcedureReservedWords.INPUTS + ElementSymbol.SEPARATOR + varName;
result.put(changingKey, new Constant(Boolean.TRUE));
- Object value = valIter.next();
- result.put(inputsKey, value);
+ if (!changingOnly) {
+ Object value = valIter.next();
+ result.put(inputsKey, (Expression)value);
+ }
}
Collection insertElmnts = ResolverUtil.resolveElementsInGroup(insert.getGroup(), metadata);
@@ -278,7 +285,9 @@
String changingKey = ProcedureReservedWords.CHANGING + ElementSymbol.SEPARATOR + varName;
String inputsKey = ProcedureReservedWords.INPUTS + ElementSymbol.SEPARATOR + varName;
result.put(changingKey, new Constant(Boolean.FALSE));
- result.put(inputsKey, value);
+ if (!changingOnly) {
+ result.put(inputsKey, value);
+ }
}
return result;
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -172,11 +172,11 @@
symbols.add(updateCount);
ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES, metadata.getMetadataStore(), externalGroups, symbols);
- resolveBlock(procCommand, procCommand.getBlock(), externalGroups, metadata, procCommand.isUpdateProcedure(), analysis);
+ resolveBlock(procCommand, procCommand.getBlock(), externalGroups, metadata, analysis);
}
- private void resolveBlock(CreateUpdateProcedureCommand command, Block block, GroupContext externalGroups,
- TempMetadataAdapter metadata, boolean isUpdateProcedure, AnalysisRecord analysis)
+ public void resolveBlock(CreateUpdateProcedureCommand command, Block block, GroupContext externalGroups,
+ TempMetadataAdapter metadata, AnalysisRecord analysis)
throws QueryResolverException, QueryMetadataException, TeiidComponentException {
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_QUERY_RESOLVER, new Object[]{"Resolving block", block}); //$NON-NLS-1$
@@ -190,11 +190,11 @@
Iterator stmtIter = block.getStatements().iterator();
while(stmtIter.hasNext()) {
- resolveStatement(command, (Statement)stmtIter.next(), externalGroups, variables, metadata, isUpdateProcedure, analysis);
+ resolveStatement(command, (Statement)stmtIter.next(), externalGroups, variables, metadata, analysis);
}
}
- private void resolveStatement(CreateUpdateProcedureCommand command, Statement statement, GroupContext externalGroups, GroupSymbol variables, TempMetadataAdapter metadata, boolean isUpdateProcedure, AnalysisRecord analysis)
+ private void resolveStatement(CreateUpdateProcedureCommand command, Statement statement, GroupContext externalGroups, GroupSymbol variables, TempMetadataAdapter metadata, AnalysisRecord analysis)
throws QueryResolverException, QueryMetadataException, TeiidComponentException {
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_QUERY_RESOLVER, new Object[]{"Resolving statement", statement}); //$NON-NLS-1$
@@ -206,9 +206,9 @@
resolveEmbeddedCommand(metadata, externalGroups, container.getCommand(), analysis);
}
ResolverVisitor.resolveLanguageObject(ifCrit, null, externalGroups, metadata);
- resolveBlock(command, ifStmt.getIfBlock(), externalGroups, metadata, isUpdateProcedure, analysis);
+ resolveBlock(command, ifStmt.getIfBlock(), externalGroups, metadata, analysis);
if(ifStmt.hasElseBlock()) {
- resolveBlock(command, ifStmt.getElseBlock(), externalGroups, metadata, isUpdateProcedure, analysis);
+ resolveBlock(command, ifStmt.getElseBlock(), externalGroups, metadata, analysis);
}
break;
case Statement.TYPE_COMMAND:
@@ -308,7 +308,7 @@
resolveEmbeddedCommand(metadata, externalGroups, container.getCommand(), analysis);
}
ResolverVisitor.resolveLanguageObject(whileCrit, null, externalGroups, metadata);
- resolveBlock(command, whileStmt.getBlock(), externalGroups, metadata, isUpdateProcedure, analysis);
+ resolveBlock(command, whileStmt.getBlock(), externalGroups, metadata, analysis);
break;
case Statement.TYPE_LOOP:
LoopStatement loopStmt = (LoopStatement) statement;
@@ -334,7 +334,7 @@
ProcedureContainerResolver.addScalarGroup(groupName, store, externalGroups, symbols);
- resolveBlock(command, loopStmt.getBlock(), externalGroups, metadata, isUpdateProcedure, analysis);
+ resolveBlock(command, loopStmt.getBlock(), externalGroups, metadata, analysis);
break;
case Statement.TYPE_BREAK:
case Statement.TYPE_CONTINUE:
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateResolver.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -93,9 +93,8 @@
/**
* @see org.teiid.query.resolver.VariableResolver#getVariableValues(org.teiid.query.sql.lang.Command, org.teiid.query.metadata.QueryMetadataInterface)
*/
- public Map getVariableValues(Command command,
+ public Map<String, Expression> getVariableValues(Command command, boolean changingOnly,
QueryMetadataInterface metadata) throws QueryMetadataException,
- QueryResolverException,
TeiidComponentException {
Map result = new HashMap();
@@ -110,7 +109,9 @@
String changingKey = ProcedureReservedWords.CHANGING + ElementSymbol.SEPARATOR + varName;
String inputsKey = ProcedureReservedWords.INPUTS + ElementSymbol.SEPARATOR + varName;
result.put(changingKey, new Constant(Boolean.TRUE));
- result.put(inputsKey, entry.getValue());
+ if (!changingOnly) {
+ result.put(inputsKey, entry.getValue());
+ }
updateVars.add(leftSymbol);
}
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -133,6 +133,7 @@
import org.teiid.query.sql.proc.LoopStatement;
import org.teiid.query.sql.proc.Statement;
import org.teiid.query.sql.proc.TranslateCriteria;
+import org.teiid.query.sql.proc.TriggerAction;
import org.teiid.query.sql.proc.WhileStatement;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.AliasSymbol;
@@ -285,7 +286,10 @@
subCommands.set(i, subCommand);
}
break;
-
+ case Command.TYPE_TRIGGER_ACTION:
+ TriggerAction ta = (TriggerAction)command;
+ ta.setBlock(rewriteBlock(ta.getBlock()));
+ break;
}
this.metadata = oldMetadata;
@@ -297,7 +301,7 @@
throws TeiidComponentException, TeiidProcessingException{
Map oldVariables = variables;
if (command.getUserCommand() != null) {
- variables = QueryResolver.getVariableValues(command.getUserCommand(), metadata);
+ variables = QueryResolver.getVariableValues(command.getUserCommand(), false, metadata);
commandType = command.getUserCommand().getType();
}
@@ -2641,12 +2645,12 @@
private Command createUpdateProcedure(ProcedureContainer update, Query query,
ProcedureContainer newUpdate) throws QueryResolverException,
TeiidComponentException, TeiidProcessingException {
+ Block b = new Block();
+ b.addStatement(new CommandStatement(newUpdate));
CreateUpdateProcedureCommand cupc = new CreateUpdateProcedureCommand();
Block parent = new Block();
- Block b = new Block();
LoopStatement ls = new LoopStatement(b, query, "X"); //$NON-NLS-1$
parent.addStatement(ls);
- b.addStatement(new CommandStatement(newUpdate));
AssignmentStatement as = new AssignmentStatement();
ElementSymbol rowsUpdate = new ElementSymbol(ProcedureReservedWords.VARIABLES+ElementSymbol.SEPARATOR+ProcedureReservedWords.ROWS_UPDATED);
as.setVariable(rowsUpdate);
@@ -2655,7 +2659,7 @@
cupc.setBlock(parent);
cupc.setVirtualGroup(update.getGroup());
QueryResolver.resolveCommand(cupc, metadata);
- return rewriteUpdateProcedure(cupc);
+ return rewrite(cupc, metadata, context);
}
private List<Criteria> createPkCriteria(UpdateMapping mapping, Query query,
Modified: trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -138,4 +138,5 @@
public void visit(XMLParse obj) {}
public void visit(ExpressionCriteria obj) {}
public void visit(WithQueryCommand obj) {}
+ public void visit(TriggerAction obj) {}
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Command.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -101,6 +101,8 @@
public static final int TYPE_CREATE = 11;
public static final int TYPE_DROP = 12;
+
+ public static final int TYPE_TRIGGER_ACTION = 13;
private static List<SingleElementSymbol> updateCommandSymbol;
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -34,7 +34,6 @@
import org.teiid.client.metadata.ParameterInfo;
import org.teiid.query.QueryPlugin;
-import org.teiid.query.metadata.StoredProcedureInfo;
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
@@ -63,9 +62,6 @@
private Object modelID;
private String callableName;
- //whether return a scalar value
- private boolean returnsScalarValue;
-
//stored procedure is treated as a group
private GroupSymbol group;
Modified: trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -23,7 +23,6 @@
package org.teiid.query.sql.navigator;
import java.util.Collection;
-import java.util.Iterator;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
@@ -80,6 +79,7 @@
import org.teiid.query.sql.proc.LoopStatement;
import org.teiid.query.sql.proc.RaiseErrorStatement;
import org.teiid.query.sql.proc.TranslateCriteria;
+import org.teiid.query.sql.proc.TriggerAction;
import org.teiid.query.sql.proc.WhileStatement;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.AliasSymbol;
@@ -448,10 +448,9 @@
public void visit(StoredProcedure obj) {
preVisitVisitor(obj);
- Collection params = obj.getParameters();
+ Collection<SPParameter> params = obj.getParameters();
if(params != null && !params.isEmpty()) {
- for(final Iterator iter = params.iterator(); iter.hasNext();) {
- SPParameter parameter = (SPParameter) iter.next();
+ for (SPParameter parameter : params) {
Expression expression = parameter.getExpression();
visitNode(expression);
}
@@ -652,6 +651,13 @@
postVisitVisitor(obj);
}
+ @Override
+ public void visit(TriggerAction obj) {
+ preVisitVisitor(obj);
+ visitNode(obj.getBlock());
+ postVisitVisitor(obj);
+ }
+
public static void doVisit(LanguageObject object, LanguageVisitor visitor, boolean order) {
doVisit(object, visitor, order, false);
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateUpdateProcedureCommand.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateUpdateProcedureCommand.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/CreateUpdateProcedureCommand.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -154,7 +154,7 @@
//Clone this class state
if (this.block != null) {
- copy.setBlock((Block)this.block.clone());
+ copy.setBlock(this.block.clone());
}
if (this.getSymbolMap() != null) {
copy.setSymbolMap(new HashMap(this.getSymbolMap()));
@@ -164,7 +164,7 @@
copy.setProjectedSymbols(new ArrayList(this.projectedSymbols));
}
if (this.virtualGroup != null) {
- copy.virtualGroup = (GroupSymbol)this.virtualGroup.clone();
+ copy.virtualGroup = this.virtualGroup.clone();
}
this.copyMetadataState(copy);
return copy;
Added: trunk/engine/src/main/java/org/teiid/query/sql/proc/TriggerAction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/proc/TriggerAction.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/sql/proc/TriggerAction.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -0,0 +1,109 @@
+/*
+ * 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.sql.proc;
+
+import java.util.List;
+
+import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.sql.visitor.SQLStringVisitor;
+
+public class TriggerAction extends Command {
+
+ private GroupSymbol view;
+ private Block block;
+
+ public TriggerAction(Block b) {
+ this.block = b;
+ }
+
+ public Block getBlock() {
+ return block;
+ }
+
+ public void setBlock(Block block) {
+ this.block = block;
+ }
+
+ public GroupSymbol getView() {
+ return view;
+ }
+
+ public void setView(GroupSymbol view) {
+ this.view = view;
+ }
+
+ @Override
+ public int hashCode() {
+ return block.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof TriggerAction)) {
+ return false;
+ }
+ TriggerAction other = (TriggerAction) obj;
+ return block.equals(other.block);
+ }
+
+ @Override
+ public String toString() {
+ return SQLStringVisitor.getSQLString(this);
+ }
+
+ @Override
+ public void acceptVisitor(LanguageVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public TriggerAction clone() {
+ TriggerAction clone = new TriggerAction(this.block.clone());
+ if (this.view != null) {
+ clone.setView(view.clone());
+ }
+ return clone;
+ }
+
+ @Override
+ public boolean areResultsCachable() {
+ return false;
+ }
+
+ @Override
+ public List<SingleElementSymbol> getProjectedSymbols() {
+ return Command.getUpdateCommandSymbol();
+ }
+
+ @Override
+ public int getType() {
+ return Command.TYPE_TRIGGER_ACTION;
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/sql/proc/TriggerAction.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -97,6 +97,7 @@
import org.teiid.query.sql.proc.RaiseErrorStatement;
import org.teiid.query.sql.proc.Statement;
import org.teiid.query.sql.proc.TranslateCriteria;
+import org.teiid.query.sql.proc.TriggerAction;
import org.teiid.query.sql.proc.WhileStatement;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.AliasSymbol;
@@ -789,7 +790,7 @@
}
private void addWithClause(QueryCommand obj) {
- if (obj.getWith() != null && !obj.getWith().isEmpty()) {
+ if (obj.getWith() != null) {
append(WITH);
append(SPACE);
registerNodes(obj.getWith(), 0);
@@ -1871,6 +1872,18 @@
public void visit( ExpressionCriteria obj ) {
visitNode(obj.getExpression());
}
+
+ @Override
+ public void visit(TriggerAction obj) {
+ append(FOR);
+ append(SPACE);
+ append(EACH);
+ append(SPACE);
+ append(ROW);
+ append("\n"); //$NON-NLS-1$
+ addTabs(0);
+ visitNode(obj.getBlock());
+ }
public static String escapeSinglePart( String part ) {
if (isReservedWord(part)) {
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-12-02 21:53:52 UTC (rev 2752)
@@ -452,6 +452,31 @@
}
}
+Command updateProcedure(ParseInfo info) :
+{
+ Command command = null;
+}
+{
+ (command = createUpdateProcedure(info) |
+ command = triggerAction(info))
+ <EOF>
+ {
+ return command;
+ }
+}
+
+TriggerAction triggerAction(ParseInfo info) :
+{
+ Block b = null;
+}
+{
+ <FOR> <EACH> <ROW>
+ b = block(info)
+ {
+ return new TriggerAction(b);
+ }
+}
+
Command userCommand(ParseInfo info) :
{
Command command = null;
Modified: trunk/engine/src/test/java/org/teiid/query/processor/FakeDataStore.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/FakeDataStore.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/test/java/org/teiid/query/processor/FakeDataStore.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -30,6 +30,7 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.client.metadata.ParameterInfo;
import org.teiid.core.TeiidComponentException;
+import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.StoredProcedureInfo;
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.sql.lang.SPParameter;
@@ -43,6 +44,7 @@
/**
* This is sample data go along with FakeMetaDataFactory and FakeDataManager
*/
+@SuppressWarnings("nls")
public class FakeDataStore {
// Helper to create a list of elements - used in creating sample data
@@ -55,8 +57,19 @@
}
return elements;
- }
+ }
+ public static List createElements(List elementIDs, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException {
+ List elements = new ArrayList();
+ for(int i=0; i<elementIDs.size(); i++) {
+ Object elementID = elementIDs.get(i);
+ ElementSymbol element = new ElementSymbol(metadata.getFullName(elementID));
+ elements.add(element);
+ }
+
+ return elements;
+ }
+
private static List getProcResultSetSymbols(List params){
List result = new ArrayList();
Iterator iter = params.iterator();
@@ -76,139 +89,19 @@
return result;
}
- public static void sampleData1(FakeDataManager dataMgr) throws QueryMetadataException, TeiidComponentException {
- FakeMetadataFacade metadata = FakeMetadataFactory.example1Cached();
-
- // Group pm1.g1
- FakeMetadataObject groupID = (FakeMetadataObject) metadata.getGroupID("pm1.g1"); //$NON-NLS-1$
- List elementIDs = metadata.getElementIDsInGroupID(groupID);
- List elementSymbols = createElements(elementIDs);
-
- dataMgr.registerTuples(
- groupID,
- elementSymbols,
-
- new List[] {
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { null, new Integer(1), Boolean.FALSE, new Double(1.0) }),
- Arrays.asList(new Object[] { "a", new Integer(3), Boolean.TRUE, new Double(7.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "c", new Integer(1), Boolean.TRUE, null }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "b", new Integer(2), Boolean.FALSE, new Double(0.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
- } );
+ public static void sampleData1(FakeDataManager dataMgr, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException {
+ addTable("pm1.g1", dataMgr, metadata);
+ addTable("pm1.g2", dataMgr, metadata);
+ addTable("pm1.g3", dataMgr, metadata);
+ addTable("pm2.g1", dataMgr, metadata);
+ addTable("pm2.g2", dataMgr, metadata);
+ addTable("pm2.g3", dataMgr, metadata);
+ addTable("tm1.g1", dataMgr, metadata);
- // Group pm1.g2
- groupID = (FakeMetadataObject) metadata.getGroupID("pm1.g2"); //$NON-NLS-1$
- elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
-
- dataMgr.registerTuples(
- groupID,
- elementSymbols,
-
- new List[] {
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { null, new Integer(1), Boolean.FALSE, new Double(1.0) }),
- Arrays.asList(new Object[] { "a", new Integer(3), Boolean.TRUE, new Double(7.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "c", new Integer(1), Boolean.TRUE, null }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "b", new Integer(2), Boolean.FALSE, new Double(0.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
- } );
-
- // Group pm1.g3
- groupID = (FakeMetadataObject) metadata.getGroupID("pm1.g3"); //$NON-NLS-1$
- elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
-
- dataMgr.registerTuples(
- groupID,
- elementSymbols,
-
- new List[] {
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { null, new Integer(1), Boolean.FALSE, new Double(1.0) }),
- Arrays.asList(new Object[] { "a", new Integer(3), Boolean.TRUE, new Double(7.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "c", new Integer(1), Boolean.TRUE, null }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "b", new Integer(2), Boolean.FALSE, new Double(0.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
- } );
-
- // Group pm2.g1
- groupID = (FakeMetadataObject) metadata.getGroupID("pm2.g1"); //$NON-NLS-1$
- elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
-
- dataMgr.registerTuples(
- groupID,
- elementSymbols,
-
- new List[] {
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { null, new Integer(1), Boolean.FALSE, new Double(1.0) }),
- Arrays.asList(new Object[] { "a", new Integer(3), Boolean.TRUE, new Double(7.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "c", new Integer(1), Boolean.TRUE, null }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "b", new Integer(2), Boolean.FALSE, new Double(0.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
- } );
-
- // Group pm2.g2
- groupID = (FakeMetadataObject) metadata.getGroupID("pm2.g2"); //$NON-NLS-1$
- elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
-
- dataMgr.registerTuples(
- groupID,
- elementSymbols,
-
- new List[] {
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { null, new Integer(1), Boolean.FALSE, new Double(1.0) }),
- Arrays.asList(new Object[] { "a", new Integer(3), Boolean.TRUE, new Double(7.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "c", new Integer(1), Boolean.TRUE, null }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "b", new Integer(2), Boolean.FALSE, new Double(0.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
- } );
-
- // Group pm2.g3
- groupID = (FakeMetadataObject) metadata.getGroupID("pm2.g3"); //$NON-NLS-1$
- elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
-
- dataMgr.registerTuples(
- groupID,
- elementSymbols,
-
- new List[] {
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { null, new Integer(1), Boolean.FALSE, new Double(1.0) }),
- Arrays.asList(new Object[] { "a", new Integer(3), Boolean.TRUE, new Double(7.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "c", new Integer(1), Boolean.TRUE, null }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "b", new Integer(2), Boolean.FALSE, new Double(0.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
- } );
-
- // Group tm1.g1
- groupID = (FakeMetadataObject) metadata.getGroupID("tm1.g1"); //$NON-NLS-1$
- elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
-
- dataMgr.registerTuples(
- groupID,
- elementSymbols,
-
- new List[] {
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { null, new Integer(1), Boolean.FALSE, new Double(1.0) }),
- Arrays.asList(new Object[] { "a", new Integer(3), Boolean.TRUE, new Double(7.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "c", new Integer(1), Boolean.TRUE, null }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "b", new Integer(2), Boolean.FALSE, new Double(0.0) }), //$NON-NLS-1$
- Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
- } );
-
//stored procedure pm1.sp1
TempMetadataStore tempStore = new TempMetadataStore();
StoredProcedureInfo procInfo = metadata.getStoredProcedureInfoForProcedure("pm1.sp1"); //$NON-NLS-1$
- elementSymbols = getProcResultSetSymbols(procInfo.getParameters());
+ List elementSymbols = getProcResultSetSymbols(procInfo.getParameters());
tempStore.addTempGroup("pm1.sp1", elementSymbols); //$NON-NLS-1$
Object procID = tempStore.getTempGroupID("pm1.sp1"); //$NON-NLS-1$
dataMgr.registerTuples(
@@ -225,6 +118,27 @@
} );
}
+ public static void addTable(String name, FakeDataManager dataMgr,
+ QueryMetadataInterface metadata) throws TeiidComponentException,
+ QueryMetadataException {
+ Object groupID = metadata.getGroupID(name);
+ List elementIDs = metadata.getElementIDsInGroupID(groupID);
+ List elementSymbols = createElements(elementIDs, metadata);
+
+ dataMgr.registerTuples(
+ groupID,
+ elementSymbols,
+
+ new List[] {
+ Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { null, new Integer(1), Boolean.FALSE, new Double(1.0) }),
+ Arrays.asList(new Object[] { "a", new Integer(3), Boolean.TRUE, new Double(7.0) }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "c", new Integer(1), Boolean.TRUE, null }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "b", new Integer(2), Boolean.FALSE, new Double(0.0) }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "a", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
+ } );
+ }
+
public static void sampleData2(FakeDataManager dataMgr) throws QueryMetadataException, TeiidComponentException {
FakeMetadataFacade metadata = FakeMetadataFactory.example1Cached();
@@ -232,7 +146,7 @@
FakeMetadataObject groupID = (FakeMetadataObject) metadata
.getGroupID("pm1.g1"); //$NON-NLS-1$
List elementIDs = metadata.getElementIDsInGroupID(groupID);
- List elementSymbols = createElements(elementIDs);
+ List elementSymbols = createElements(elementIDs, metadata);
dataMgr.registerTuples(groupID, elementSymbols,
@@ -248,7 +162,7 @@
// Group pm1.g2
groupID = (FakeMetadataObject) metadata.getGroupID("pm1.g2"); //$NON-NLS-1$
elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
+ elementSymbols = createElements(elementIDs, metadata);
dataMgr.registerTuples(groupID, elementSymbols,
@@ -268,7 +182,7 @@
// Group pm2.g1
groupID = (FakeMetadataObject) metadata.getGroupID("pm2.g1"); //$NON-NLS-1$
elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
+ elementSymbols = createElements(elementIDs, metadata);
dataMgr.registerTuples(groupID, elementSymbols,
@@ -284,7 +198,7 @@
// Group pm2.g2
groupID = (FakeMetadataObject) metadata.getGroupID("pm2.g2"); //$NON-NLS-1$
elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
+ elementSymbols = createElements(elementIDs, metadata);
dataMgr.registerTuples(groupID, elementSymbols,
@@ -304,7 +218,7 @@
// Group pm1.table1
groupID = (FakeMetadataObject) metadata.getGroupID("pm1.table1"); //$NON-NLS-1$
elementIDs = metadata.getElementIDsInGroupID(groupID);
- elementSymbols = createElements(elementIDs);
+ elementSymbols = createElements(elementIDs, metadata);
dataMgr.registerTuples(groupID, elementSymbols,
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2010-12-02 15:32:06 UTC (rev 2751)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -353,7 +353,7 @@
public static void sampleData1(FakeDataManager dataMgr) {
try {
- FakeDataStore.sampleData1(dataMgr);
+ FakeDataStore.sampleData1(dataMgr, FakeMetadataFactory.example1Cached());
} catch(Throwable e) {
throw new RuntimeException(e);
}
Added: trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java 2010-12-02 21:53:52 UTC (rev 2752)
@@ -0,0 +1,124 @@
+/*
+ * 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.processor;
+
+import static org.junit.Assert.*;
+import static org.teiid.query.processor.TestProcessor.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.teiid.metadata.Table;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.optimizer.TestOptimizer;
+import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
+import org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder;
+import org.teiid.query.resolver.TestResolver;
+import org.teiid.query.util.CommandContext;
+import org.teiid.query.validator.TestUpdateValidator;
+
+@SuppressWarnings("nls")
+public class TestTriggerActions {
+
+ @Test public void testInsert() throws Exception {
+ TransformationMetadata metadata = TestUpdateValidator.example1();
+ TestUpdateValidator.createView("select 1 as x, 2 as y", metadata, "gx");
+ Table t = metadata.getMetadataStore().getSchemas().get("vm1").getTables().get("gx");
+ t.setDeletePlan("");
+ t.setUpdatePlan("");
+ t.setInsertPlan("FOR EACH ROW BEGIN insert into pm1.g1 (e1) values (new.x); END");
+
+ String sql = "insert into gx (x, y) values (1, 2)";
+
+ FakeDataManager dm = new FakeDataManager();
+ FakeDataStore.addTable("pm1.g1", dm, metadata);
+
+ CommandContext context = createCommandContext();
+ BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+ ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata, null), metadata, new DefaultCapabilitiesFinder(caps), context);
+ List[] expected = new List[] {Arrays.asList(1)};
+ helpProcess(plan, context, dm, expected);
+ }
+
+ @Test public void testInsertWithQueryExpression() throws Exception {
+ TransformationMetadata metadata = TestUpdateValidator.example1();
+ TestUpdateValidator.createView("select '1' as x, 2 as y", metadata, "gx");
+ Table t = metadata.getMetadataStore().getSchemas().get("vm1").getTables().get("gx");
+ t.setDeletePlan("");
+ t.setUpdatePlan("");
+ t.setInsertPlan("FOR EACH ROW BEGIN insert into pm1.g1 (e1) values (new.x); END");
+
+ String sql = "insert into gx (x, y) select e1, e2 from pm1.g1";
+
+ FakeDataManager dm = new FakeDataManager();
+ FakeDataStore.addTable("pm1.g1", dm, metadata);
+ CommandContext context = createCommandContext();
+ BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+ ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata, null), metadata, new DefaultCapabilitiesFinder(caps), context);
+ List[] expected = new List[] {Arrays.asList(6)};
+ helpProcess(plan, context, dm, expected);
+ }
+
+ @Test public void testDelete() throws Exception {
+ TransformationMetadata metadata = TestUpdateValidator.example1();
+ TestUpdateValidator.createView("select 1 as x, 2 as y", metadata, "gx");
+ Table t = metadata.getMetadataStore().getSchemas().get("vm1").getTables().get("gx");
+ t.setDeletePlan("FOR EACH ROW BEGIN delete from pm1.g1 where e2 = old.x; END");
+ t.setUpdatePlan("");
+ t.setInsertPlan("");
+
+ String sql = "delete from gx where y = 2";
+
+ FakeDataManager dm = new FakeDataManager();
+ FakeDataStore.addTable("pm1.g1", dm, metadata);
+
+ CommandContext context = createCommandContext();
+ BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+ ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata, null), metadata, new DefaultCapabilitiesFinder(caps), context);
+ List[] expected = new List[] {Arrays.asList(1)};
+ helpProcess(plan, context, dm, expected);
+ }
+
+ @Test public void testUpdate() throws Exception {
+ TransformationMetadata metadata = TestUpdateValidator.example1();
+ TestUpdateValidator.createView("select 1 as x, 2 as y", metadata, "gx");
+ Table t = metadata.getMetadataStore().getSchemas().get("vm1").getTables().get("gx");
+ t.setDeletePlan("");
+ t.setUpdatePlan("FOR EACH ROW BEGIN update pm1.g1 set e2 = new.y where e2 = old.y; END");
+ t.setInsertPlan("");
+
+ String sql = "update gx set y = 5";
+
+ FakeDataManager dm = new FakeDataManager();
+ FakeDataStore.addTable("pm1.g1", dm, metadata);
+
+ CommandContext context = createCommandContext();
+ BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+ ProcessorPlan plan = TestProcessor.helpGetPlan(TestResolver.helpResolve(sql, metadata, null), metadata, new DefaultCapabilitiesFinder(caps), context);
+ List[] expected = new List[] {Arrays.asList(1)};
+ helpProcess(plan, context, dm, expected);
+ assertEquals("UPDATE pm1.g1 SET e2 = 5 WHERE e2 = 2", dm.getQueries().get(0));
+ }
+
+}
Property changes on: trunk/engine/src/test/java/org/teiid/query/processor/TestTriggerActions.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
14 years, 1 month