Author: shawkins
Date: 2012-05-05 19:32:41 -0400 (Sat, 05 May 2012)
New Revision: 4058
Modified:
trunk/api/src/main/java/org/teiid/metadata/Schema.java
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java
trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java
trunk/runtime/src/main/java/org/teiid/deployers/PgCatalogMetadataStore.java
Log:
TEIID-2031 allowing multiple functions of the same name
Modified: trunk/api/src/main/java/org/teiid/metadata/Schema.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/Schema.java 2012-05-04 18:29:47 UTC (rev
4057)
+++ trunk/api/src/main/java/org/teiid/metadata/Schema.java 2012-05-05 23:32:41 UTC (rev
4058)
@@ -23,7 +23,6 @@
package org.teiid.metadata;
import java.io.IOException;
-import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
@@ -56,13 +55,10 @@
}
public void addFunction(FunctionMethod function) {
- addFunction(function.getName(), function);
- }
-
- public void addFunction(String uniqueName, FunctionMethod function) {
function.setParent(this);
- if (this.functions.put(uniqueName, function) != null) {
- throw new DuplicateRecordException(DataPlugin.Util.gs(DataPlugin.Event.TEIID60015,
function.getName()));
+ //TODO: ensure that all uuids are unique
+ if (this.functions.put(function.getUUID(), function) != null) {
+ throw new DuplicateRecordException(DataPlugin.Util.gs(DataPlugin.Event.TEIID60015,
function.getUUID()));
}
}
@@ -91,13 +87,18 @@
}
/**
- * Get the functions defined in this schema
+ * Get the functions defined in this schema in a map of uuid to {@link FunctionMethod}
* @return
*/
public Map<String, FunctionMethod> getFunctions() {
return functions;
}
+ /**
+ * Get a funciton by uuid
+ * @param funcName
+ * @return
+ */
public FunctionMethod getFunction(String funcName) {
return functions.get(funcName);
}
@@ -139,7 +140,7 @@
throws IOException, ClassNotFoundException {
in.defaultReadObject();
if (this.functions == null) {
- this.functions = new LinkedHashMap<String, FunctionMethod>();
+ this.functions = new TreeMap<String,
FunctionMethod>(String.CASE_INSENSITIVE_ORDER);
}
}
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-05-04 18:29:47 UTC
(rev 4057)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-05-05 23:32:41 UTC
(rev 4058)
@@ -60,6 +60,11 @@
<li>allowCreateTemporaryTablesByDefault and allowFunctionCallsByDefault are now
set to false. When data roles are in use the user must explicitly grant these options to
the user on VDB
</ul>
+<h4>from 8.0</h4>
+<ul>
+ <li>org.teiid.metadata.Schema holds FunctionMethods by uuid rather than name to
accommodate overriden method signatures.
+<ul>
+
<h4>from 7.x</h4>
<ul>
<li>TRANSLATE/HAS CRITERIA has been removed. INSTEAD OF trigger actions should
be used instead. ROWS_UPDATED, INPUTS, and INPUT are no longer procedure reserved words.
Modified: trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java 2012-05-04 18:29:47
UTC (rev 4057)
+++ trunk/engine/src/main/java/org/teiid/query/parser/QueryParser.java 2012-05-05 23:32:41
UTC (rev 4058)
@@ -30,6 +30,9 @@
import java.util.List;
import org.teiid.api.exception.query.QueryParserException;
+import org.teiid.connector.DataPlugin;
+import org.teiid.metadata.DuplicateRecordException;
+import org.teiid.metadata.FunctionMethod;
import org.teiid.metadata.MetadataFactory;
import org.teiid.query.QueryPlugin;
import org.teiid.query.sql.lang.CacheHint;
@@ -347,7 +350,12 @@
public void parseDDL(MetadataFactory factory, String ddl) throws ParseException {
getSqlParser(ddl).parseMetadata(factory);
- SQLParserUtil.replaceProceduresWithFunctions(factory);
+ HashSet<FunctionMethod> functions = new HashSet<FunctionMethod>();
+ for (FunctionMethod functionMethod : factory.getFunctions().values()) {
+ if (!functions.add(functionMethod)) {
+ throw new DuplicateRecordException(DataPlugin.Util.gs(DataPlugin.Event.TEIID60015,
functionMethod.getName()));
+ }
+ }
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2012-05-04
18:29:47 UTC (rev 4057)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2012-05-05
23:32:41 UTC (rev 4058)
@@ -445,77 +445,63 @@
}
}
- static void replaceProceduresWithFunctions(MetadataFactory factory) throws
ParseException {
- ArrayList<String> procs = new ArrayList<String>();
-
- for (Procedure proc: factory.getProcedures().values()) {
- if (!proc.isFunction()) {
- continue;
- }
-
- procs.add(proc.getName());
-
- FunctionMethod method = new FunctionMethod();
- method.setName(proc.getName());
-
method.setPushdown(proc.isVirtual()?FunctionMethod.PushDown.CAN_PUSHDOWN:FunctionMethod.PushDown.MUST_PUSHDOWN);
-
- ArrayList<FunctionParameter> ins = new ArrayList<FunctionParameter>();
- for (ProcedureParameter pp:proc.getParameters()) {
- if (pp.getType() != ProcedureParameter.Type.In) {
- throw new ParseException("Functions can only support 'In'
parameters"); //$NON-NLS-1$
- }
-
- FunctionParameter fp = new FunctionParameter(pp.getName(),
pp.getDatatype().getName());
- fp.setVarArg(pp.isVarArg());
- ins.add(fp);
- }
- method.setInputParameters(ins);
-
- List<Column> returnCols = proc.getResultSet().getColumns();
- if (returnCols != null && !returnCols.isEmpty()) {
- if (returnCols.size() > 1) {
- throw new ParseException("Functions can only return single parameter");
//$NON-NLS-1$
- }
- Column c = returnCols.get(0);
- FunctionParameter fp = new FunctionParameter(c.getName(),
c.getDatatype().getName());
- method.setOutputParameter(fp);
- }
-
- method.setAnnotation(proc.getAnnotation());
- method.setNameInSource(proc.getNameInSource());
- method.setUUID(proc.getUUID());
-
- Map<String, String> props = proc.getProperties();
-
- String value = props.remove("CATEGORY"); //$NON-NLS-1$
- method.setCategory(value);
-
- value = props.remove("DETERMINISM"); //$NON-NLS-1$
- if (value != null) {
- method.setDeterminism(FunctionMethod.Determinism.valueOf(value.toUpperCase()));
+ static void replaceProcedureWithFunction(MetadataFactory factory,
+ Procedure proc) throws ParseException {
+ FunctionMethod method = new FunctionMethod();
+ method.setName(proc.getName());
+ method.setPushdown(proc.isVirtual()?FunctionMethod.PushDown.CAN_PUSHDOWN:FunctionMethod.PushDown.MUST_PUSHDOWN);
+
+ ArrayList<FunctionParameter> ins = new ArrayList<FunctionParameter>();
+ for (ProcedureParameter pp:proc.getParameters()) {
+ if (pp.getType() != ProcedureParameter.Type.In) {
+ throw new
ParseException(QueryPlugin.Util.getString("SQLParser.function_in",
proc.getName())); //$NON-NLS-1$
}
-
- value = props.remove("JAVA_CLASS"); //$NON-NLS-1$
- method.setInvocationClass(value);
- value = props.remove("JAVA_METHOD"); //$NON-NLS-1$
- method.setInvocationMethod(value);
-
- for (String key:props.keySet()) {
- value = props.get(key);
- method.setProperty(key, value);
- }
-
- FunctionMethod.convertExtensionMetadata(proc, method);
-
- factory.addFunction(method);
- }
-
- // remove the old procs
- for (String name:procs) {
- factory.getProcedures().remove(name);
- }
- }
+ FunctionParameter fp = new FunctionParameter(pp.getName(),
pp.getDatatype().getName());
+ fp.setVarArg(pp.isVarArg());
+ ins.add(fp);
+ }
+ method.setInputParameters(ins);
+
+ List<Column> returnCols = proc.getResultSet().getColumns();
+ if (returnCols != null && !returnCols.isEmpty()) {
+ if (returnCols.size() > 1) {
+ throw new
ParseException(QueryPlugin.Util.getString("SQLParser.function_return",
proc.getName())); //$NON-NLS-1$
+ }
+ Column c = returnCols.get(0);
+ FunctionParameter fp = new FunctionParameter(c.getName(), c.getDatatype().getName());
+ method.setOutputParameter(fp);
+ }
+
+ method.setAnnotation(proc.getAnnotation());
+ method.setNameInSource(proc.getNameInSource());
+ method.setUUID(proc.getUUID());
+
+ Map<String, String> props = proc.getProperties();
+
+ String value = props.remove("CATEGORY"); //$NON-NLS-1$
+ method.setCategory(value);
+
+ value = props.remove("DETERMINISM"); //$NON-NLS-1$
+ if (value != null) {
+ method.setDeterminism(FunctionMethod.Determinism.valueOf(value.toUpperCase()));
+ }
+
+ value = props.remove("JAVA_CLASS"); //$NON-NLS-1$
+ method.setInvocationClass(value);
+
+ value = props.remove("JAVA_METHOD"); //$NON-NLS-1$
+ method.setInvocationMethod(value);
+
+ for (String key:props.keySet()) {
+ value = props.get(key);
+ method.setProperty(key, value);
+ }
+
+ FunctionMethod.convertExtensionMetadata(proc, method);
+ factory.addFunction(method);
+ factory.getProcedures().remove(proc.getName());
+ }
void setProcedureOptions(Procedure proc) {
Map<String, String> props = proc.getProperties();
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-05-04 18:29:47
UTC (rev 4057)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-05-05 23:32:41
UTC (rev 4058)
@@ -4158,6 +4158,9 @@
if (returnDataType != null){
addProcReturnColumn(factory, proc, "return", returnDataType);
}
+ if (function) {
+ replaceProcedureWithFunction(factory, proc);
+ }
return procCmd;
}
}
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-05-04 18:29:47
UTC (rev 4057)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-05-05 23:32:41
UTC (rev 4058)
@@ -272,6 +272,8 @@
SQLParser.view_def=Virtual view {0} must be defined with a query expression.
SQLParser.pk_exists=Primary Key is already defined on {0}
SQLParser.no_column=Column name {0} not found on table {1}
+SQLParser.function_return=Function {0} is not valid. Functions can only return a single
parameter.
+SQLParser.function_in=Functions {0} is not valid. Functions can only support
'In' parameters.
SystemSource.array_length_desc=Get the length of the given array value
SystemSource.array_param1=Array
SystemSource.array_length_result=The array length
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java 2012-05-04
18:29:47 UTC (rev 4057)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java 2012-05-05
23:32:41 UTC (rev 4058)
@@ -390,25 +390,43 @@
@Test
public void testPushdownFunctionNoArgs() throws Exception {
- String ddl = "CREATE FUNCTION SourceFunc() RETURNS integer";
+ String ddl = "CREATE FUNCTION SourceFunc() RETURNS integer OPTIONS (UUID
'hello world')";
Schema s = helpParse(ddl, "model");
- FunctionMethod fm = s.getFunction("SourceFunc");
+ FunctionMethod fm = s.getFunction("hello world");
assertNotNull(fm);
assertEquals("integer", fm.getOutputParameter().getType());
assertEquals(FunctionMethod.PushDown.MUST_PUSHDOWN, fm.getPushdown());
}
+ @Test(expected=DuplicateRecordException.class)
+ public void testDuplicateFunctions() throws Exception {
+ String ddl = "CREATE FUNCTION SourceFunc() RETURNS integer; CREATE FUNCTION
SourceFunc() RETURNS string";
+ helpParse(ddl, "model");
+ }
+
+ @Test(expected=DuplicateRecordException.class)
+ public void testDuplicateFunctions1() throws Exception {
+ String ddl = "CREATE FUNCTION SourceFunc() RETURNS string OPTIONS (UUID
'a'); CREATE FUNCTION SourceFunc1() RETURNS string OPTIONS (UUID
'a')";
+ helpParse(ddl, "model");
+ }
+
+ @Test()
+ public void testDuplicateFunctions2() throws Exception {
+ String ddl = "CREATE FUNCTION SourceFunc() RETURNS string; CREATE FUNCTION
SourceFunc(param string) RETURNS string";
+ helpParse(ddl, "model");
+ }
+
@Test
public void testUDF() throws Exception {
String ddl = "CREATE VIRTUAL FUNCTION SourceFunc(flag boolean, msg varchar)
RETURNS varchar " +
"OPTIONS(CATEGORY 'misc', DETERMINISM 'DETERMINISTIC', " +
- "\"NULL-ON-NULL\" 'true', JAVA_CLASS 'foo',
JAVA_METHOD 'bar', RANDOM 'any')";
+ "\"NULL-ON-NULL\" 'true', JAVA_CLASS 'foo',
JAVA_METHOD 'bar', RANDOM 'any', UUID 'x')";
Schema s = helpParse(ddl, "model");
- FunctionMethod fm = s.getFunction("SourceFunc");
+ FunctionMethod fm = s.getFunction("x");
assertNotNull(fm);
assertEquals("string", fm.getOutputParameter().getType());
assertEquals(FunctionMethod.PushDown.CAN_PUSHDOWN, fm.getPushdown());
@@ -430,11 +448,11 @@
@Test
public void testUDAggregate() throws Exception {
String ddl = "CREATE VIRTUAL FUNCTION SourceFunc(flag boolean, msg varchar)
RETURNS varchar " +
- "OPTIONS(CATEGORY 'misc', AGGREGATE 'true',
\"allows-distinct\" 'true')";
+ "OPTIONS(CATEGORY 'misc', AGGREGATE 'true',
\"allows-distinct\" 'true', UUID 'y')";
Schema s = helpParse(ddl, "model");
- FunctionMethod fm = s.getFunction("SourceFunc");
+ FunctionMethod fm = s.getFunction("y");
assertNotNull(fm);
assertEquals("string", fm.getOutputParameter().getType());
assertEquals(FunctionMethod.PushDown.CAN_PUSHDOWN, fm.getPushdown());
@@ -453,11 +471,11 @@
@Test
public void testVarArgs() throws Exception {
- String ddl = "CREATE FUNCTION SourceFunc(flag boolean) RETURNS varchar options
(varargs 'true')";
+ String ddl = "CREATE FUNCTION SourceFunc(flag boolean) RETURNS varchar options
(varargs 'true', UUID 'z')";
Schema s = helpParse(ddl, "model");
- FunctionMethod fm = s.getFunction("SourceFunc");
+ FunctionMethod fm = s.getFunction("z");
assertTrue( fm.getInputParameters().get(0).isVarArg());
}
Modified: trunk/runtime/src/main/java/org/teiid/deployers/PgCatalogMetadataStore.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/deployers/PgCatalogMetadataStore.java 2012-05-04
18:29:47 UTC (rev 4057)
+++ trunk/runtime/src/main/java/org/teiid/deployers/PgCatalogMetadataStore.java 2012-05-05
23:32:41 UTC (rev 4058)
@@ -537,7 +537,7 @@
}
FunctionMethod func = FunctionMethod.createFunctionMethod(name, name, "pg",
returnType, paramTypes); //$NON-NLS-1$
setUUID(func);
- addFunction(javaFunction, func);
+ addFunction(func);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
func.setInvocationMethod(javaFunction);
func.setPushdown(PushDown.CANNOT_PUSHDOWN);