[teiid-commits] teiid SVN: r4418 - in trunk: api/src/main/java/org/teiid/metadata and 18 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Mon Sep 10 13:02:34 EDT 2012


Author: shawkins
Date: 2012-09-10 13:02:33 -0400 (Mon, 10 Sep 2012)
New Revision: 4418

Added:
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleSubstituteExpressions.java
   trunk/test-integration/common/src/test/resources/TestSystemVirtualModel/testDefect12064.expected
Modified:
   trunk/api/src/main/java/org/teiid/language/SQLConstants.java
   trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java
   trunk/api/src/main/java/org/teiid/metadata/Table.java
   trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/AccessInfo.java
   trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
   trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java
   trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java
   trunk/engine/src/main/java/org/teiid/query/metadata/DDLConstants.java
   trunk/engine/src/main/java/org/teiid/query/metadata/DDLStringVisitor.java
   trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java
   trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java
   trunk/engine/src/main/java/org/teiid/query/metadata/TempCapabilitiesFinder.java
   trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java
   trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanHints.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.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/RuleConstants.java
   trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
   trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
   trunk/engine/src/main/java/org/teiid/query/tempdata/GlobalTableStore.java
   trunk/engine/src/main/java/org/teiid/query/tempdata/GlobalTableStoreImpl.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/metadata/TestDDLStringVisitor.java
   trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java
   trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java
   trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java
   trunk/runtime/src/main/java/org/teiid/deployers/VDBRepository.java
   trunk/runtime/src/main/java/org/teiid/runtime/EmbeddedServer.java
   trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestSystemVirtualModel.java
Log:
TEIID-2195 adding support for internal mat view function based indexes

Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -125,6 +125,7 @@
 		public static final String EXCLUDING = "EXCLUDING"; //$NON-NLS-1$
 		public static final String XMLDECLARATION = "XMLDECLARATION"; //$NON-NLS-1$
 		public static final String VARIADIC = "VARIADIC"; //$NON-NLS-1$
+		public static final String INDEX = "INDEX"; //$NON-NLS-1$
 	}
 	
 	public interface Reserved {

Modified: trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -228,6 +228,54 @@
 		return index;
 	}
 	
+	/**
+	 * Adds a function based index on the given expressions.
+	 * @param name
+	 * @param expressions
+	 * @param nonColumnExpressions a Boolean list indicating when expressions are non-column expressions
+	 * @param table
+	 * @return
+	 * @throws TranslatorException
+	 */
+	public KeyRecord addFunctionBasedIndex(String name, List<String> expressions, List<Boolean> nonColumnExpressions, Table table) throws TranslatorException {
+		KeyRecord index = new KeyRecord(KeyRecord.Type.Index);
+		index.setParent(table);
+		index.setColumns(new ArrayList<Column>(expressions.size()));
+		index.setName(name);
+		setUUID(index);
+		boolean functionBased = false;
+		for (int i = 0; i < expressions.size(); i++) {
+			String expr = expressions.get(i);
+			if (nonColumnExpressions.get(i)) {
+				Column c = new Column();
+				//TODO: we could choose a derived name at this point, but we delay that to get a single unique name across all index expressions
+				c.setName(expr);
+				c.setNameInSource(expr);
+				setUUID(c);
+				c.setParent(index);
+				c.setPosition(i + 1); //position is temporarily relative to the index, but the validator changes this
+				index.getColumns().add(c);
+				functionBased = true;
+			} else {
+				assignColumn(table, index, expr);
+			}
+		}
+		if (!functionBased) {
+			table.getIndexes().add(index);
+		} else {
+			table.getFunctionBasedIndexes().add(index);
+		}
+		return index;
+	}
+
+	private void assignColumn(Table table, ColumnSet<?> columns, String columnName)
+			throws TranslatorException {
+		Column column = table.getColumnByName(columnName);
+		if (column == null) {
+			throw new TranslatorException(DataPlugin.Event.TEIID60011, DataPlugin.Util.gs(DataPlugin.Event.TEIID60011, columnName));				
+		}
+		columns.getColumns().add(column);
+	}
 	
 	/**
 	 * Adds a foreign key to the given table.  The referenced primary key must already exist.  The column names should be in key order.
@@ -332,11 +380,7 @@
 	private void assignColumns(List<String> columnNames, Table table,
 			ColumnSet<?> columns) throws TranslatorException {
 		for (String columnName : columnNames) {
-			Column column = table.getColumnByName(columnName);
-			if (column == null) {
-				throw new TranslatorException(DataPlugin.Event.TEIID60011, DataPlugin.Util.gs(DataPlugin.Event.TEIID60011, columnName));				
-			}
-			columns.getColumns().add(column);
+			assignColumn(table, columns, columnName);
 		}
 	}
 	

Modified: trunk/api/src/main/java/org/teiid/metadata/Table.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/Table.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/api/src/main/java/org/teiid/metadata/Table.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -22,6 +22,7 @@
 
 package org.teiid.metadata;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -60,6 +61,7 @@
     private boolean supportsUpdate;
     private List<ForeignKey> foriegnKeys = new ArrayList<ForeignKey>(2);
     private List<KeyRecord> indexes = new ArrayList<KeyRecord>(2);
+    private List<KeyRecord> functionBasedIndexes = new ArrayList<KeyRecord>(2);
     private List<KeyRecord> uniqueKeys = new ArrayList<KeyRecord>(2);
     private List<KeyRecord> accessPatterns = new ArrayList<KeyRecord>(2);
     private KeyRecord primaryKey;
@@ -218,6 +220,14 @@
 		this.indexes = indexes;
 	}
     
+    public List<KeyRecord> getFunctionBasedIndexes() {
+		return functionBasedIndexes;
+	}
+    
+    public void setFunctionBasedIndexes(List<KeyRecord> functionBasedIndexes) {
+		this.functionBasedIndexes = functionBasedIndexes;
+	}
+    
     public List<KeyRecord> getUniqueKeys() {
     	return this.uniqueKeys;
     }
@@ -398,6 +408,14 @@
       if (result == null)
          return null;
       return type.cast(result);      
-   }	
+   }
 	
+    private void readObject(java.io.ObjectInputStream in)
+    throws IOException, ClassNotFoundException {
+    	in.defaultReadObject();
+    	if (this.functionBasedIndexes == null) {
+    		this.functionBasedIndexes = new ArrayList<KeyRecord>(2);
+    	}
+    }
+	
 }
\ No newline at end of file

Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html	2012-09-10 17:02:33 UTC (rev 4418)
@@ -33,6 +33,8 @@
 	<li>TEIID-2163 <b>Binary XMLSERIALIZE</b> - XMLSERIALIZE now supports blob/varbinary and the encoding/version and XMLDECLARATION options.
 	<li>TEIID-2141 <b>OBJECTTABLE</b> - was added to extract values from objects using arbitrary scripts.  See the Reference for usage.
 	<li>TEIID-2111 <b>Vararg Procedures</b> - variable argument procedures and functions can be created through DDL using the VARIADIC parameter type.  See the Reference for usage.
+	<li>TEIID-2195 <b>Function Based Indexes</b> - DDL can be used to specify function based indexes.  When used on an internal mat view it will create
+	the corresponding function based index automatically.  In any other circumstance, the metadata is not currently used.
 </ul>
 
 <h2><a name="Compatibility">Compatibility Issues</a></h2>

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/AccessInfo.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/AccessInfo.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/AccessInfo.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -31,9 +31,8 @@
 import java.util.Set;
 
 import org.teiid.adminapi.impl.VDBMetaData;
-import org.teiid.api.exception.query.QueryResolverException;
-import org.teiid.api.exception.query.QueryValidatorException;
 import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
 import org.teiid.metadata.AbstractMetadataRecord;
 import org.teiid.metadata.Schema;
 import org.teiid.metadata.AbstractMetadataRecord.DataModifiable;
@@ -122,11 +121,10 @@
 	
 	/**
 	 * Restore reconnects to the live metadata objects
-	 * @throws QueryResolverException
-	 * @throws QueryValidatorException
 	 * @throws TeiidComponentException
+	 * @throws TeiidProcessingException 
 	 */
-	void restore() throws QueryResolverException, QueryValidatorException, TeiidComponentException {
+	void restore() throws TeiidComponentException, TeiidProcessingException {
 		if (this.objectsAccessed != null) {
 			return;
 		}

Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -528,6 +528,9 @@
     	TEIID31110, //invalid script
     	TEIID31111, //invalid teiid script
     	TEIID31112, //invalid vararg
-    	TEIID31113
+    	TEIID31113,
+    	TEIID31114,
+    	TEIID31115,
+    	TEIID31116,
 	}
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -25,6 +25,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -39,6 +40,7 @@
 import org.teiid.query.mapping.xml.MappingNode;
 import org.teiid.query.sql.lang.ObjectTable;
 import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.GroupSymbol;
 
 
@@ -548,4 +550,9 @@
 		return false;
 	}
 	
+	@Override
+	public Map<Expression, Integer> getFunctionBasedExpressions(Object metadataID) {
+		return null;
+	}
+	
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -24,6 +24,7 @@
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -35,6 +36,7 @@
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.mapping.xml.MappingNode;
+import org.teiid.query.sql.symbol.Expression;
 
 
 public class BasicQueryMetadataWrapper implements QueryMetadataInterface {
@@ -407,4 +409,9 @@
 		return actualMetadata.isVariadic(metadataID);
 	}
 	
+	@Override
+	public Map<Expression, Integer> getFunctionBasedExpressions(Object metadataID) {
+		return actualMetadata.getFunctionBasedExpressions(metadataID);
+	}
+	
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/DDLConstants.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/DDLConstants.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/DDLConstants.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -43,7 +43,6 @@
 	public static final String AUTO_INCREMENT = "AUTO_INCREMENT";//$NON-NLS-1$
 	public static final String NOT_NULL = "NOT NULL";//$NON-NLS-1$
 	public static final String FOREIGN_KEY = "FOREIGN KEY";//$NON-NLS-1$
-	public static final String INDEX = "INDEX";//$NON-NLS-1$
 	public static final String PRIMARY_KEY = "PRIMARY KEY";//$NON-NLS-1$
 	public static final String ACCESSPATTERN = "ACCESSPATTERN";//$NON-NLS-1$
 	public static final String NAMEINSOURCE = "NAMEINSOURCE";//$NON-NLS-1$

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/DDLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/DDLStringVisitor.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/DDLStringVisitor.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -42,6 +42,7 @@
 import org.teiid.metadata.BaseColumn.NullType;
 import org.teiid.metadata.FunctionMethod.Determinism;
 import org.teiid.metadata.ProcedureParameter.Type;
+import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.query.sql.visitor.SQLStringVisitor;
 
 public class DDLStringVisitor {
@@ -241,13 +242,14 @@
 
 		addConstraints(table.getUniqueKeys(), UNIQUE, UNIQUE);
 		addConstraints(table.getIndexes(), INDEX, INDEX);
+		addConstraints(table.getFunctionBasedIndexes(), INDEX, INDEX);
 
 		for (int i = 0; i < table.getForeignKeys().size(); i++) {
 			ForeignKey key = table.getForeignKeys().get(i);
 			addConstraint("FK" + i, FOREIGN_KEY, key, false); //$NON-NLS-1$
 			buffer.append(SPACE).append(REFERENCES);
 			if (key.getReferenceTableName() != null) {
-				buffer.append(SPACE).append(key.getReferenceTableName());
+				buffer.append(SPACE).append(new GroupSymbol(key.getReferenceTableName()).getName());
 			}
 			buffer.append(SPACE);
 			addNames(buffer, key.getReferenceColumns());
@@ -286,9 +288,14 @@
 			else {
 				builder.append(COMMA).append(SPACE);
 			}
-			appendColumn(builder, c, true, includeType);
 			if (includeType) {
+				appendColumn(builder, c, true, includeType);
 				appendColumnOptions(builder, c);
+			} else if (c.getParent() instanceof KeyRecord) {
+				//function based column
+				builder.append(c.getNameInSource());
+			} else {
+				builder.append(SQLStringVisitor.escapeSinglePart(c.getName()));
 			}
 		}
 		builder.append(RPAREN);
@@ -305,7 +312,7 @@
 				else {
 					builder.append(COMMA).append(SPACE);
 				}
-				builder.append(c);
+				builder.append(SQLStringVisitor.escapeSinglePart(c));
 			}
 			builder.append(RPAREN);
 		}

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -21,6 +21,7 @@
  */
 package org.teiid.query.metadata;
 
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -28,6 +29,7 @@
 import org.teiid.adminapi.impl.ModelMetaData;
 import org.teiid.adminapi.impl.VDBMetaData;
 import org.teiid.adminapi.impl.ModelMetaData.Message.Severity;
+import org.teiid.api.exception.query.QueryResolverException;
 import org.teiid.core.TeiidException;
 import org.teiid.core.types.DataTypeManager;
 import org.teiid.language.SQLConstants;
@@ -35,6 +37,7 @@
 import org.teiid.logging.LogManager;
 import org.teiid.logging.MessageLevel;
 import org.teiid.metadata.*;
+import org.teiid.metadata.FunctionMethod.Determinism;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.function.metadata.FunctionMetadataValidator;
 import org.teiid.query.mapping.relational.QueryNode;
@@ -43,11 +46,15 @@
 import org.teiid.query.report.ReportItem;
 import org.teiid.query.resolver.QueryResolver;
 import org.teiid.query.resolver.util.ResolverUtil;
+import org.teiid.query.resolver.util.ResolverVisitor;
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.QueryCommand;
+import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
 import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.query.sql.symbol.Symbol;
+import org.teiid.query.sql.visitor.EvaluatableVisitor;
+import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
 import org.teiid.query.validator.Validator;
 import org.teiid.query.validator.ValidatorFailure;
 import org.teiid.query.validator.ValidatorReport;
@@ -219,13 +226,15 @@
     		} else if (record instanceof Table) {
     			Table t = (Table)record;
     			
+    			GroupSymbol symbol = new GroupSymbol(t.getFullName());
+    			ResolverUtil.resolveGroup(symbol, metadata);
+    			MetadataFactory mf = t.removeAttachment(MetadataFactory.class);    			
     			if (t.isVirtual() && (t.getColumns() == null || t.getColumns().isEmpty())) {
     				QueryCommand command = (QueryCommand)QueryParser.getQueryParser().parseCommand(t.getSelectTransformation());
     				QueryResolver.resolveCommand(command, metadata);
     				resolverReport =  Validator.validate(command, metadata);
     				if(!resolverReport.hasItems()) {
     					List<Expression> symbols = command.getProjectedSymbols();
-    					MetadataFactory mf = t.removeAttachment(MetadataFactory.class);
     					for (Expression column:symbols) {
     						try {
 								addColumn(Symbol.getShortName(column), column.getType(), t, mf);
@@ -236,9 +245,36 @@
     				}
     			}
     			
-    			GroupSymbol symbol = new GroupSymbol(t.getFullName());
-    			ResolverUtil.resolveGroup(symbol, metadata);
-
+    			if (t.isMaterialized() && t.getMaterializedTable() == null) {
+	    			List<KeyRecord> fbis = t.getFunctionBasedIndexes();
+	    			List<GroupSymbol> groups = Arrays.asList(symbol);
+					if (fbis != null && !fbis.isEmpty()) {
+						for (KeyRecord fbi : fbis) {
+	    					for (int j = 0; j < fbi.getColumns().size(); j++) {
+	    						Column c = fbi.getColumns().get(j);
+	    						if (c.getParent() != fbi) {
+	    							continue;
+	    						}
+	    						String exprString = c.getNameInSource();
+	    						try {
+		    						Expression ex = QueryParser.getQueryParser().parseExpression(exprString);
+									ResolverVisitor.resolveLanguageObject(ex, groups, metadata);
+									if (!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(ex).isEmpty()) {
+										log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31114, exprString, fbi.getFullName()));
+									} 
+									EvaluatableVisitor ev = new EvaluatableVisitor();
+									PreOrPostOrderNavigator.doVisit(ex, ev, PreOrPostOrderNavigator.PRE_ORDER);
+									if (ev.getDeterminismLevel().compareTo(Determinism.VDB_DETERMINISTIC) < 0) {
+										log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31115, exprString, fbi.getFullName()));
+									}
+	    						} catch (QueryResolverException e) {
+	    							log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31116, exprString, fbi.getFullName(), e.getMessage()));
+	    						}
+							}
+						}
+					}
+    			}
+    			
     			// this seems to parse, resolve and validate.
     			QueryResolver.resolveView(symbol, new QueryNode(t.getSelectTransformation()), SQLConstants.Reserved.SELECT, metadata);
     		}

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -24,6 +24,7 @@
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -35,6 +36,7 @@
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.mapping.xml.MappingNode;
+import org.teiid.query.sql.symbol.Expression;
 
 
 /**
@@ -659,4 +661,6 @@
 	Set<String> getImportedModels();
 
 	boolean isVariadic(Object metadataID);
+
+	Map<Expression, Integer> getFunctionBasedExpressions(Object metadataID);
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempCapabilitiesFinder.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempCapabilitiesFinder.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempCapabilitiesFinder.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -30,7 +30,23 @@
 
 public class TempCapabilitiesFinder implements CapabilitiesFinder {
 
-	private static BasicSourceCapabilities tempCaps;
+	private final static BasicSourceCapabilities tempCaps;
+	static {
+		tempCaps = new BasicSourceCapabilities();
+		tempCaps.setCapabilitySupport(Capability.INSERT_WITH_ITERATOR, true);
+		tempCaps.setCapabilitySupport(Capability.QUERY_ORDERBY, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_IN, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_COMPARE_EQ, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_COMPARE_ORDERED, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_ONLY_LITERAL_COMPARE, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_ISNULL, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_LIKE, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_LIKE_ESCAPE, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_LIKE_REGEX, true);
+		tempCaps.setCapabilitySupport(Capability.CRITERIA_SIMILAR, true);
+		tempCaps.setCapabilitySupport(Capability.QUERY_AGGREGATES_COUNT_STAR, true);
+	}
+	
 	private final CapabilitiesFinder delegate;
 	
 	public TempCapabilitiesFinder(CapabilitiesFinder delegate) {
@@ -41,21 +57,6 @@
 	public SourceCapabilities findCapabilities(String modelName)
 			throws TeiidComponentException {
 		if (TempMetadataAdapter.TEMP_MODEL.getID().equals(modelName)) {
-    		if (tempCaps == null) {
-	    		tempCaps = new BasicSourceCapabilities();
-	    		tempCaps.setCapabilitySupport(Capability.INSERT_WITH_ITERATOR, true);
-	    		tempCaps.setCapabilitySupport(Capability.QUERY_ORDERBY, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_NOT, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_IN, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_COMPARE_EQ, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_COMPARE_ORDERED, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_ISNULL, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_LIKE, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_LIKE_ESCAPE, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_LIKE_REGEX, true);
-	    		tempCaps.setCapabilitySupport(Capability.CRITERIA_SIMILAR, true);
-	    		tempCaps.setCapabilitySupport(Capability.QUERY_AGGREGATES_COUNT_STAR, true);
-    		}
     		return tempCaps;
     	}
 		return delegate.findCapabilities(modelName);

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -38,6 +38,7 @@
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.mapping.xml.MappingNode;
 import org.teiid.query.metadata.TempMetadataID.Type;
+import org.teiid.query.sql.symbol.Expression;
 
 
 /**
@@ -429,7 +430,7 @@
     public Collection getIndexesInGroup(Object groupID)
         throws TeiidComponentException, QueryMetadataException {
         if(groupID instanceof TempMetadataID) {
-        	List<List<TempMetadataID>> result = ((TempMetadataID)groupID).getIndexes();
+        	List<TempMetadataID> result = ((TempMetadataID)groupID).getIndexes();
         	if (result == null) {
         		return Collections.emptyList();
         	}
@@ -479,6 +480,13 @@
     		return (List)keyID;
     	}
     	
+    	if (keyID instanceof TempMetadataID) {
+    		TempMetadataID id = (TempMetadataID)keyID;
+    		if (id.getMetadataType() == Type.INDEX) {
+    			return id.getElements();
+    		}
+    	}
+    	
         return this.actualMetadata.getElementIDsInKey(keyID);   
     }    
 
@@ -575,9 +583,6 @@
     public Properties getExtensionProperties(Object metadataID)
         throws TeiidComponentException, QueryMetadataException {
             
-        if(metadataID instanceof TempMetadataID) {
-            return null;
-        }
         return actualMetadata.getExtensionProperties(metadataID);
     }
 
@@ -734,5 +739,13 @@
     	} 
     	return this.actualMetadata.isMultiSourceElement(elementId);
     }
+    
+    @Override
+    public Map<Expression, Integer> getFunctionBasedExpressions(Object metadataID) {
+    	if (metadataID instanceof TempMetadataID) {
+    		return ((TempMetadataID)metadataID).getTableData().getFunctionBasedExpressions();
+    	}
+    	return super.getFunctionBasedExpressions(metadataID);
+    }
 
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -25,6 +25,7 @@
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -33,6 +34,7 @@
 import org.teiid.metadata.AbstractMetadataRecord.Modifiable;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.sql.lang.CacheHint;
+import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.Symbol;
 
 /**
@@ -60,10 +62,11 @@
 		LRUCache<Object, Object> localCache;
 		CacheHint cacheHint;
 		List<List<TempMetadataID>> keys;
-		List<List<TempMetadataID>> indexes;
+		List<TempMetadataID> indexes;
 		long lastDataModification;
 		long lastModified = System.currentTimeMillis();
 		int modCount;
+		private LinkedHashMap<Expression, Integer> functionBasedExpressions;
 		
 		public long getLastDataModification() {
 			return lastDataModification;
@@ -89,7 +92,16 @@
 		public long getLastModified() {
 			return lastModified;
 		}
+
+		public void setFunctionBasedExpressions(
+				LinkedHashMap<Expression, Integer> newExprs) {
+			this.functionBasedExpressions = newExprs;
+		}
 		
+		public LinkedHashMap<Expression, Integer> getFunctionBasedExpressions() {
+			return functionBasedExpressions;
+		}
+		
 	}
 	
 	private static TableData DUMMY_DATA = new TableData();
@@ -98,7 +110,8 @@
 		VIRTUAL,
 		TEMP,
 		SCALAR,
-		XML
+		XML,
+		INDEX
 	}
 	
     private String ID;      // never null, upper cased fully-qualified string
@@ -357,15 +370,18 @@
 		this.getTableData().cacheHint = cacheHint;
 	}
 	
-	public List<List<TempMetadataID>> getIndexes() {
+	public List<TempMetadataID> getIndexes() {
 		return getTableData().indexes;
 	}
 	
-	public void addIndex(List<TempMetadataID> index) {
+	public void addIndex(Object originalMetadataId, List<TempMetadataID> index) {
 		if (this.getTableData().indexes == null) {
-			this.getTableData().indexes = new LinkedList<List<TempMetadataID>>();
+			this.getTableData().indexes = new LinkedList<TempMetadataID>();
 		}
-		this.getTableData().indexes.add(index);
+		TempMetadataID id = new TempMetadataID(ID, Collections.EMPTY_LIST, Type.INDEX);
+		id.getTableData().elements = index;
+		id.setOriginalMetadataID(originalMetadataId);
+		this.getTableData().indexes.add(id);
 	}
 	
 	public List<List<TempMetadataID>> getUniqueKeys() {

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanHints.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanHints.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanHints.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -45,6 +45,8 @@
     public boolean hasOptionalJoin = false;
     
     public boolean hasRelationalProc = false;
+
+	public boolean hasFunctionBasedColumns;
     
     public PlanHints() { }    
     

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	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -407,6 +407,9 @@
             rules.push(RuleConstants.PLAN_JOINS);
         }
         rules.push(RuleConstants.RAISE_ACCESS);
+        if (hints.hasFunctionBasedColumns) {
+        	rules.push(RuleConstants.SUBSTITUE_EXPRESSIONS);
+        }
         if (hints.hasSetQuery) {
             rules.push(RuleConstants.PLAN_UNIONS);
         } 
@@ -828,6 +831,9 @@
             if (metadata.isVirtualGroup(group.getMetadataID())) {
             	hints.hasVirtualGroups = true;
             }
+            if (metadata.getFunctionBasedExpressions(group.getMetadataID()) != null) {
+            	hints.hasFunctionBasedColumns = true;
+            }
             Command nestedCommand = ufc.getExpandedCommand();
             if (nestedCommand == null && !group.isProcedure()) {
             	Object id = getTrackableGroup(group, metadata);
@@ -1251,7 +1257,11 @@
         	}else{
             	this.context.accessedPlanningObject(matMetadataId);
         		qnode = new QueryNode(null);
-        		Query query = createMatViewQuery(matMetadataId, matTableName, Arrays.asList(new MultipleElementSymbol()), isImplicitGlobal);
+        		List<ElementSymbol> symbols = new ArrayList<ElementSymbol>();
+        		for (ElementSymbol el : ResolverUtil.resolveElementsInGroup(virtualGroup, metadata)) {
+        			symbols.add(new ElementSymbol(el.getShortName()));
+        		}
+        		Query query = createMatViewQuery(matMetadataId, matTableName, symbols, isImplicitGlobal);
         		query.setCacheHint(hint);
         		qnode.setCommand(query);
                 cacheString = "matview"; //$NON-NLS-1$

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	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -201,7 +201,7 @@
 			return;
 		}
 		for (LanguageObject languageObject : toCheck) {
-			if (!EvaluatableVisitor.willBecomeConstant(languageObject, true)) {
+			if (!EvaluatableVisitor.willBecomeConstant(languageObject)) {
 	        	markInvalid(obj, "Non-literal comparison not supported by source."); //$NON-NLS-1$
 	        	return;
 			}

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -50,4 +50,5 @@
     public static final OptimizerRule CALCULATE_COST = new RuleCalculateCost();
     public static final OptimizerRule PLAN_SORTS = new RulePlanSorts();
     public static final OptimizerRule DECOMPOSE_JOIN = new RuleDecomposeJoin();
+    public static final OptimizerRule SUBSTITUE_EXPRESSIONS = new RuleSubstituteExpressions();
 }

Added: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleSubstituteExpressions.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleSubstituteExpressions.java	                        (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleSubstituteExpressions.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -0,0 +1,99 @@
+/*
+ * 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.relational.rules;
+
+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.QueryPlannerException;
+import org.teiid.core.TeiidComponentException;
+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.OptimizerRule;
+import org.teiid.query.optimizer.relational.RuleStack;
+import org.teiid.query.optimizer.relational.plantree.NodeConstants;
+import org.teiid.query.optimizer.relational.plantree.NodeEditor;
+import org.teiid.query.optimizer.relational.plantree.PlanNode;
+import org.teiid.query.resolver.util.ResolverUtil;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.util.SymbolMap;
+import org.teiid.query.sql.visitor.ExpressionMappingVisitor;
+import org.teiid.query.util.CommandContext;
+
+/**
+ * Substitutes column references for expressions
+ */
+public class RuleSubstituteExpressions implements OptimizerRule {
+	
+	@Override
+	public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata,
+			CapabilitiesFinder capabilitiesFinder, RuleStack rules,
+			AnalysisRecord analysisRecord, CommandContext context)
+			throws QueryPlannerException, QueryMetadataException,
+			TeiidComponentException {
+		boolean substitued = false;
+		
+        for (PlanNode accessNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.ACCESS)) {
+        	if (accessNode.getParent() == null) {
+        		continue;
+        	}
+            for (GroupSymbol gs : accessNode.getGroups()) {
+            	Map<Expression, Integer> fbis = metadata.getFunctionBasedExpressions(gs.getMetadataID());
+            	if (fbis == null) {
+            		continue;
+            	}
+        		substitued = true;
+        		Map<Expression, ElementSymbol> replacements = new HashMap<Expression, ElementSymbol>();
+        		GroupSymbol gsOrig = new GroupSymbol(gs.getNonCorrelationName());
+        		gsOrig.setMetadataID(gs.getMetadataID());
+        		List<ElementSymbol> curremtElems = ResolverUtil.resolveElementsInGroup(gs, metadata);
+        		List<ElementSymbol> origElems = ResolverUtil.resolveElementsInGroup(gsOrig, metadata);
+        		boolean nameMatches = gs.getNonCorrelationName().equals(gs.getName());
+        		SymbolMap map = SymbolMap.createSymbolMap(origElems, curremtElems);
+        		for (Map.Entry<Expression, Integer> entry : fbis.entrySet()) {
+        			Expression ex = entry.getKey();
+        			if (!nameMatches) {
+        				ex = (Expression)ex.clone();
+        				ExpressionMappingVisitor.mapExpressions(ex, map.asMap());
+        			}
+        			replacements.put(ex, curremtElems.get(entry.getValue()-1));
+				}
+        		FrameUtil.convertFrame(accessNode.getParent(), gs, null, replacements, metadata);
+            }
+        }
+        if (substitued) {
+        	rules.push(RuleConstants.PUSH_SELECT_CRITERIA);
+        }
+        return plan;
+	}
+	
+	@Override
+	public String toString() {
+		return "Substitue Expressions"; //$NON-NLS-1$
+	}
+}


Property changes on: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleSubstituteExpressions.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -33,6 +33,7 @@
 import org.teiid.core.util.Assertion;
 import org.teiid.core.util.PropertiesUtils;
 import org.teiid.core.util.StringUtil;
+import org.teiid.language.SQLConstants;
 import org.teiid.language.SQLConstants.Reserved;
 import org.teiid.metadata.*;
 import org.teiid.metadata.Column.SearchType;
@@ -45,6 +46,7 @@
 import org.teiid.query.sql.lang.ExistsCriteria.SubqueryHint;
 import org.teiid.query.sql.proc.Block;
 import org.teiid.query.sql.proc.Statement;
+import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.translator.TranslatorException;
@@ -653,6 +655,29 @@
 	 	return key;
 	}
 	
+	KeyRecord addFBI(MetadataFactory factory, List<Expression> expressions, Table table, String name) throws ParseException {
+		List<String> columnNames = new ArrayList<String>(expressions.size());
+		List<Boolean> nonColumnExpressions = new ArrayList<Boolean>(expressions.size());
+		boolean fbi = false;
+		for (int i = 0; i < expressions.size(); i++) {
+			Expression ex = expressions.get(i);
+			if (ex instanceof ElementSymbol) {
+	 			columnNames.add(((ElementSymbol)ex).getName());
+	 			nonColumnExpressions.add(Boolean.FALSE);
+			} else {
+				columnNames.add(ex.toString());
+				nonColumnExpressions.add(Boolean.TRUE);
+				fbi = true;
+			}
+		}
+		try{
+			table.addAttchment(MetadataFactory.class, factory);
+	    	return factory.addFunctionBasedIndex(name != null?name:(SQLConstants.NonReserved.INDEX+(fbi?table.getFunctionBasedIndexes().size():table.getIndexes().size())), columnNames, nonColumnExpressions, table);
+	    }catch(TranslatorException e){
+			throw new ParseException(e.getMessage());
+		}
+	}
+	
 	static class  ParsedDataType{
 		String type;
 		Integer length;

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -492,6 +492,10 @@
         return new ArrayList<ElementSymbol>(getGroupInfo(group, metadata).getSymbolList());
     }
     
+    public static void clearGroupInfo(GroupSymbol group, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException {
+    	metadata.addToMetadataCache(group.getMetadataID(), GroupInfo.CACHE_PREFIX + group.getName(), null);
+    }
+    
 	static GroupInfo getGroupInfo(GroupSymbol group,
 			QueryMetadataInterface metadata)
 			throws TeiidComponentException, QueryMetadataException {

Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/GlobalTableStore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/GlobalTableStore.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/GlobalTableStore.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -28,8 +28,6 @@
 import org.teiid.Replicated;
 import org.teiid.Replicated.ReplicationMode;
 import org.teiid.api.exception.query.QueryMetadataException;
-import org.teiid.api.exception.query.QueryResolverException;
-import org.teiid.api.exception.query.QueryValidatorException;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.query.metadata.TempMetadataID;
@@ -38,7 +36,7 @@
 
 public interface GlobalTableStore {
 	
-	TempMetadataID getGlobalTempTableMetadataId(Object groupID) throws QueryMetadataException, TeiidComponentException, QueryResolverException, QueryValidatorException;
+	TempMetadataID getGlobalTempTableMetadataId(Object groupID) throws TeiidComponentException, TeiidProcessingException;
 	
 	TempMetadataID getCodeTableMetadataId(String codeTableName,
 			String returnElementName, String keyElementName,

Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/GlobalTableStoreImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/GlobalTableStoreImpl.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/GlobalTableStoreImpl.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -31,6 +31,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -47,6 +49,9 @@
 import org.teiid.language.SQLConstants.Reserved;
 import org.teiid.logging.LogConstants;
 import org.teiid.logging.LogManager;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.KeyRecord;
+import org.teiid.metadata.Table;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.ReplicatedObject;
 import org.teiid.query.mapping.relational.QueryNode;
@@ -55,17 +60,25 @@
 import org.teiid.query.metadata.TempMetadataID;
 import org.teiid.query.metadata.TempMetadataStore;
 import org.teiid.query.optimizer.relational.RelationalPlanner;
+import org.teiid.query.parser.QueryParser;
 import org.teiid.query.resolver.QueryResolver;
 import org.teiid.query.resolver.util.ResolverUtil;
+import org.teiid.query.resolver.util.ResolverVisitor;
+import org.teiid.query.rewriter.QueryRewriter;
 import org.teiid.query.sql.lang.CacheHint;
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.Create;
 import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.util.SymbolMap;
+import org.teiid.query.sql.visitor.ExpressionMappingVisitor;
 import org.teiid.query.tempdata.TempTableStore.TransactionMode;
 
 public class GlobalTableStoreImpl implements GlobalTableStore, ReplicatedObject<String> {
 	
+	private static final String TEIID_FBI = "teiid:fbi"; //$NON-NLS-1$
+
 	public enum MatState {
 		NEEDS_LOADING,
 		LOADING,
@@ -202,7 +215,7 @@
 			
 	@Override
 	public TempMetadataID getGlobalTempTableMetadataId(Object viewId)
-	throws QueryMetadataException, TeiidComponentException, QueryResolverException, QueryValidatorException {
+	throws TeiidProcessingException, TeiidComponentException {
 		String matViewName = metadata.getFullName(viewId);
 		String matTableName = RelationalPlanner.MAT_PREFIX+matViewName.toUpperCase();
 		GroupSymbol group = new GroupSymbol(matViewName);
@@ -212,9 +225,58 @@
 		if (id == null) {
 			synchronized (viewId) {
 				id = tableStore.getMetadataStore().getTempGroupID(matTableName);
+				LinkedHashMap<Expression, Integer> newExprs = null;
 				if (id == null) {
-					id = tableStore.getMetadataStore().addTempGroup(matTableName, ResolverUtil.resolveElementsInGroup(group, metadata), false, true);
-					id.setQueryNode(metadata.getVirtualPlan(viewId));
+					List<ElementSymbol> allCols = ResolverUtil.resolveElementsInGroup(group, metadata);
+					QueryNode qnode = metadata.getVirtualPlan(viewId);
+					if (viewId instanceof Table) {
+						Table t = (Table)viewId;
+						List<KeyRecord> fbis = t.getFunctionBasedIndexes();
+						if (!fbis.isEmpty()) {
+		    				List<GroupSymbol> groups = Arrays.asList(group);
+		    				int i = 0;
+		    				newExprs = new LinkedHashMap<Expression, Integer>();
+		    				for (KeyRecord keyRecord : fbis) {
+		    					for (int j = 0; j < keyRecord.getColumns().size(); j++) {
+		    						Column c = keyRecord.getColumns().get(j);
+		    						if (c.getParent() != keyRecord) {
+		    							continue;
+		    						}
+		    						String exprString = c.getNameInSource();
+		    						Expression ex = QueryParser.getQueryParser().parseExpression(exprString);
+		    						Integer index = newExprs.get(ex);
+		    						if (index == null) {
+		    							ResolverVisitor.resolveLanguageObject(ex, groups, metadata);
+		    							ex = QueryRewriter.rewriteExpression(ex, null, metadata);
+		    							String colName = TEIID_FBI + i;
+		    							while (t.getColumnByName(colName) != null) {
+		    								colName = TEIID_FBI + (++i);
+		    							}
+		    							ElementSymbol es = new ElementSymbol(colName);
+		    							es.setType(ex.getType());
+		    							allCols.add(es);
+		    							c.setPosition(allCols.size());
+		    							newExprs.put(ex, allCols.size());
+		    							ex = (Expression)ex.clone();
+		    						} else {
+		    							c.setPosition(index);
+		    						}
+		    					}
+		    				}
+		    				ResolverUtil.clearGroupInfo(group, metadata);
+		    				StringBuilder query = new StringBuilder("SELECT x.*, "); //$NON-NLS-1$
+		    				for (Iterator<Expression> iter = newExprs.keySet().iterator(); iter.hasNext();) {
+		    					query.append(iter.next());
+		    					if (iter.hasNext()) {
+		    						query.append(", "); //$NON-NLS-1$
+		    					}
+		    				}
+		    				query.append(" FROM ").append(group).append(" as x option nocache " + group); //$NON-NLS-1$ //$NON-NLS-2$
+		    				qnode = new QueryNode(query.toString());
+						}
+					}
+					id = tableStore.getMetadataStore().addTempGroup(matTableName, allCols, false, true);
+					id.setQueryNode(qnode);
 					id.setCardinality(metadata.getCardinality(viewId));
 					id.setOriginalMetadataID(viewId);
 					
@@ -229,8 +291,25 @@
 					}
 					Collection indexes = metadata.getIndexesInGroup(viewId);
 					for (Object index : indexes) {
-						id.addIndex(resolveIndex(metadata, id, index));
+						id.addIndex(index, resolveIndex(metadata, id, index));
 					}
+					if (newExprs != null) {
+						Table table = (Table)viewId;
+						List<KeyRecord> fbis = table.getFunctionBasedIndexes();
+						for (KeyRecord keyRecord : fbis) {
+							id.addIndex(keyRecord, resolveIndex(metadata, id, keyRecord));
+						}
+						GroupSymbol gs = new GroupSymbol(matTableName);
+						gs.setMetadataID(id);
+						SymbolMap map = SymbolMap.createSymbolMap(group, ResolverUtil.resolveElementsInGroup(gs, metadata).subList(0, allCols.size() - newExprs.size()), metadata);
+						LinkedHashMap<Expression, Integer> mappedExprs = new LinkedHashMap<Expression, Integer>();
+						for (Map.Entry<Expression, Integer> entry : newExprs.entrySet()) {
+							Expression ex = (Expression) entry.getKey().clone();
+							ExpressionMappingVisitor.mapExpressions(ex, map.asMap());
+							mappedExprs.put(ex, entry.getValue());
+						}
+						id.getTableData().setFunctionBasedExpressions(mappedExprs);
+					}
 				}
 			}
 		}

Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-09-10 17:02:33 UTC (rev 4418)
@@ -811,6 +811,7 @@
 	String table = null;
 	String pkId = null;
 	Column col = null;
+	List<String> columnNames = null;
 }
 {
 	<CREATE> <LOCAL> <TEMPORARY> <TABLE> 
@@ -829,17 +830,13 @@
         create.getColumns().add(col);
       }
     )*	
-	[<COMMA> <PRIMARY> <KEY> <LPAREN>
-	  pkId = id()
+	[<COMMA> <PRIMARY> <KEY> 
+	  columnNames = getColumnNames()
 	  {
-	    create.getPrimaryKey().add(new ElementSymbol(validateElementName(pkId)));
-	  }
-	  (<COMMA> pkId = id()
-	   {
-	     create.getPrimaryKey().add(new ElementSymbol(validateElementName(pkId)));
-	   }
-	  )*
-	 <RPAREN>	
+	  	for (String id : columnNames) {
+	  		create.getPrimaryKey().add(new ElementSymbol(validateElementName(id)));
+	  	}
+	  }	  
 	]
 	<RPAREN>
 	{
@@ -4690,6 +4687,7 @@
 	Command query = null;
 	Token comment = null;
 	String name = null;
+	AbstractMetadataRecord constraint = null;
 }
 {
 	<CREATE> (<FOREIGN> <TABLE> | [<VIRTUAL>] <VIEW> {view = true;}) 
@@ -4707,14 +4705,20 @@
     (LOOKAHEAD(3) <COMMA>
       createColumn(factory, table)
     )*	
-    (<COMMA>{name=null;} [<CONSTRAINT> name = id()] (primaryKeys(factory, table, name) | constraints(factory, table, name) | foreignKeys(factory, table, name)))*
+    (<COMMA>{name=null;} [<CONSTRAINT> name = id()] (constraint = primaryKey(factory, table, name) | constraint = constraint(factory, table, name, ParseInfo.DEFAULT_INSTANCE) | constraint = foreignKey(factory, table, name))
+       [optionsClause(constraint, factory)
+	   {
+	      setCommonProperties(constraint, constraint.getProperties());
+	   }
+	]
+    )*
     <RPAREN>]    
     [optionsClause(table, factory)
 	   {
 	      setTableOptions(table);
 	   }
 	]
-	[<AS> { comment = getToken(1).specialToken; } query = queryExpression(new ParseInfo())]
+	[<AS> { comment = getToken(1).specialToken; } query = queryExpression(ParseInfo.DEFAULT_INSTANCE)]
 	{
 		if (query != null){
 		   if (!view) {
@@ -4737,7 +4741,7 @@
 description=Defines the foreign key referential constraint.
 example={code:sql}FOREIGN KEY (a, b) REFERENCES tbl (x, y){code}
 */
-void foreignKeys(MetadataFactory factory, Table table, String name) :
+AbstractMetadataRecord foreignKey(MetadataFactory factory, Table table, String name) :
 {
 	List<String> columnNames = null;
 	String viewName = null;
@@ -4760,16 +4764,11 @@
     [pkColumnNames = getColumnNames()]
     {
 	    try{
-		    key = factory.addForiegnKey(name != null?name:("FK"+table.getForeignKeys().size()), columnNames, pkColumnNames, viewName, table);   
+		    return factory.addForiegnKey(name != null?name:("FK"+table.getForeignKeys().size()), columnNames, pkColumnNames, viewName, table);   
 	    } catch (TranslatorException e){
 	    	throw new ParseException(e.getMessage());
 	    }
     }
-    [optionsClause(key, factory)
-	   {
-	      setCommonProperties(key, key.getProperties());
-	   }
-	]
 }
 
 /*
@@ -4777,7 +4776,7 @@
 description=Defines the primary key.
 example={code:sql}PRIMARY KEY (a, b){code}
 */
-void primaryKeys(MetadataFactory factory, Table table, String name) :
+AbstractMetadataRecord primaryKey(MetadataFactory factory, Table table, String name) :
 {
 	List<String> columnNames = null;
 	Column column = null;
@@ -4785,8 +4784,8 @@
 }
 {
 	<PRIMARY> <KEY>
+	columnNames = getColumnNames()
     {
-    	columnNames = getColumnNames();
 	    for (String col: columnNames) {
 	    	column = getColumn(col, table);
 	    }
@@ -4794,16 +4793,11 @@
 	    	throw new ParseException(QueryPlugin.Util.getString("SQLParser.pk_exists", table.getName()));
 	 	}
 	 	try{
-	 		key = factory.addPrimaryKey(name!=null?name:"PK", columnNames, table);
+	 		return factory.addPrimaryKey(name!=null?name:"PK", columnNames, table);
 	 	} catch(TranslatorException e){
 	 		throw new ParseException(e.getMessage());
 	 	}
     }
-    [optionsClause(key, factory)
-	   {
-	      setCommonProperties(key, key.getProperties());
-	   }
-	]    
 }
 
 /*
@@ -4811,38 +4805,40 @@
 description=Defines ACCESSPATTERN and UNIQUE constraints and INDEXes. 
 example={code:sql}UNIQUE (a){code}
 */
-void constraints(MetadataFactory factory, Table table, String name) :
+AbstractMetadataRecord constraint(MetadataFactory factory, Table table, String name, ParseInfo info) :
 {
 	KeyRecord keyrecord = null;
 	Column column = null;
 	List<String> columnNames = null;
 	Token type = null;
 	KeyRecord key = null;
+	List<Expression> expressions = null;
 }
 {
-	( type = <UNIQUE> | type = <INDEX> | type = <ACCESSPATTERN>)
+	(( type = <UNIQUE> | type = <ACCESSPATTERN>)
+	columnNames = getColumnNames()	    
 	{
-	    columnNames = getColumnNames();	    
 	    for (String col: columnNames) {
 	    	column = getColumn(col, table);
 	    }
 	    try{
-	    	if (type.image.equalsIgnoreCase("INDEX")) { 
-	    		key = factory.addIndex(name != null?name:("INDEX"+table.getIndexes().size()), true, columnNames, table);
-	    	} else if (type.image.equalsIgnoreCase("UNIQUE")) { 
-	    		key = factory.addIndex(name != null?name:("UNIQUE"+table.getUniqueKeys().size()), false, columnNames, table);
+			if (type.image.equalsIgnoreCase("UNIQUE")) { 
+	    		return factory.addIndex(name != null?name:("UNIQUE"+table.getUniqueKeys().size()), false, columnNames, table);
 	    	} else if (type.image.equalsIgnoreCase("ACCESSPATTERN")) { 
-	    		key = factory.addAccessPattern(name != null?name:("AP"+table.getAccessPatterns().size()), columnNames, table);
+	    		return factory.addAccessPattern(name != null?name:("AP"+table.getAccessPatterns().size()), columnNames, table);
 	    	}
     	}catch(TranslatorException e){
     		throw new ParseException(e.getMessage());
     	}	    
-    }
-    [optionsClause(key, factory)
-	   {
-	      setCommonProperties(key, key.getProperties());
-	   }
-	]    
+    }) | (
+    type = <INDEX>
+    <LPAREN>
+ 	expressions = expressionList(info)
+ 	<RPAREN>
+ 	 {
+ 		return addFBI(factory, expressions, table, name);
+ 	 }
+ 	)
 }
 
 /*

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-09-10 17:02:33 UTC (rev 4418)
@@ -1028,6 +1028,9 @@
 TEIID31111=No such accessible property/method {0} on {1}.
 TEIID31112=Only the last parameter of {0} may be VARIADIC.
 TEIID31113={0} extra positional parameter(s) passed to {2}.
+TEIID31114=Function based index {1} expression {0} cannot contain subqueries.
+TEIID31115=Function based index {1} expression {0} is not deterministic.
+TEIID31116=Function based index {1} expression {0} could not be resolved: {2}
 
 SQLParser.proc_type_conflict=Result type {1} conflicts with return type {2} for procedure {0}
 SQLParser.param_out=Procedure {0} RESULT param {1} must be of type OUT.

Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -180,7 +180,7 @@
 		
 	}	
 	
-	@Test
+	@Test 
 	public void testView() throws Exception {
 		String ddl = "CREATE View G1( e1 integer, e2 varchar) OPTIONS (CARDINALITY 12) AS select e1, e2 from foo.bar";
 		String expected = "CREATE VIEW G1 (\n" + 
@@ -257,4 +257,10 @@
 		String expected = "CREATE FOREIGN PROCEDURE myProc(OUT p1 boolean, VARIADIC p3 bigdecimal) RETURNS TABLE (r1 string, r2 bigdecimal)";
 		helpTest(ddl, expected);		
 	}	
+	
+	@Test public void testViewFBI() throws Exception {
+		String ddl = "CREATE View G1( \"a e1\" integer, \"a e2\" varchar, INDEX (\"a e1\", upper(\"a e2\"))) AS select e1, e2 from foo.bar";
+		String expected = "CREATE VIEW G1 (\n	\"a e1\" integer,\n	\"a e2\" string,\n	INDEX(\"a e1\", upper(\"a e2\"))\n)\nAS\nSELECT e1, e2 FROM foo.bar;";
+		helpTest(ddl, expected);
+	}
 }

Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -326,4 +326,28 @@
 		report = new MetadataValidator().validate(this.vdb, this.store);
 		assertTrue(printError(report), report.hasItems());
 	}
+	
+	@Test public void testFBIResolveError() throws Exception {
+		String ddl = "CREATE view G1(e1 integer, e2 varchar, CONSTRAINT fbi INDEX (UPPER(e3))) options (materialized true) as select 1, 'a'";
+
+		buildModel("pm1", true, this.vdb, this.store, ddl);
+		
+		buildTransformationMetadata();
+		
+		ValidatorReport report = new ValidatorReport();
+		report = new MetadataValidator().validate(this.vdb, this.store);
+		assertTrue(printError(report), report.hasItems());
+	}
+	
+	@Test public void testFBISubquery() throws Exception {
+		String ddl = "CREATE view G1(e1 integer, e2 varchar, CONSTRAINT fbi INDEX ((select 1))) options (materialized true) as select 1, 'a'";
+
+		buildModel("pm1", true, this.vdb, this.store, ddl);
+		
+		buildTransformationMetadata();
+		
+		ValidatorReport report = new ValidatorReport();
+		report = new MetadataValidator().validate(this.vdb, this.store);
+		assertTrue(printError(report), report.hasItems());
+	}
 }

Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestDDLParser.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -141,6 +141,17 @@
 		assertEquals(14, table.getColumns().get(1).getScale());		
 	}	
 	
+	@Test public void testFBI() throws Exception {
+		String ddl = "CREATE FOREIGN TABLE G1(e1 integer, e2 varchar, CONSTRAINT fbi INDEX (UPPER(e2)))";
+
+		Schema s = helpParse(ddl, "model").getSchema();
+		Map<String, Table> tableMap = s.getTables();	
+		
+		Table table = tableMap.get("G1");
+		
+		assertEquals(1, table.getFunctionBasedIndexes().size());
+	}
+	
 	@Test
 	public void testMultiKeyPK() throws Exception {
 		String ddl = "CREATE FOREIGN TABLE G1( e1 integer, e2 varchar, e3 date, PRIMARY KEY (e1, e2))";

Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -29,20 +29,15 @@
 import java.util.Map;
 
 import org.junit.Test;
-import org.teiid.adminapi.impl.VDBMetaData;
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.api.exception.query.QueryParserException;
 import org.teiid.api.exception.query.QueryResolverException;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.types.DataTypeManager;
-import org.teiid.metadata.MetadataStore;
 import org.teiid.metadata.Table;
-import org.teiid.query.metadata.CompositeMetadataStore;
-import org.teiid.query.metadata.MetadataValidator;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.metadata.TempMetadataAdapter;
 import org.teiid.query.metadata.TempMetadataID;
-import org.teiid.query.metadata.TestMetadataValidator;
 import org.teiid.query.metadata.TransformationMetadata;
 import org.teiid.query.parser.QueryParser;
 import org.teiid.query.sql.ProcedureReservedWords;
@@ -64,7 +59,6 @@
 import org.teiid.query.sql.visitor.CommandCollectorVisitor;
 import org.teiid.query.sql.visitor.ElementCollectorVisitor;
 import org.teiid.query.unittest.RealMetadataFactory;
-import org.teiid.query.validator.ValidatorReport;
 
 @SuppressWarnings("nls")
 public class TestProcedureResolving {
@@ -1045,17 +1039,7 @@
     }
 
 	public static TransformationMetadata createMetadata(String ddl) throws Exception {
-		VDBMetaData vdb = new VDBMetaData();
-    	MetadataStore store = new MetadataStore();
-    	TestMetadataValidator.buildModel("x", true, vdb, store, ddl);
-    	TransformationMetadata tm = new TransformationMetadata(vdb, new CompositeMetadataStore(Arrays.asList(store)), null, RealMetadataFactory.SFM.getSystemFunctions(), null);
-    	vdb.addAttchment(TransformationMetadata.class, tm);
-    	vdb.addAttchment(QueryMetadataInterface.class, tm);
-    	ValidatorReport report = new MetadataValidator().validate(vdb, store);
-    	if (report.hasItems()) {
-    		throw new RuntimeException(report.getFailureMessage());
-    	}
-		return tm;
+		return RealMetadataFactory.fromDDL(ddl, "test", "test");
 	}
     
     @Test public void testOptionalParams1() throws Exception {

Modified: trunk/runtime/src/main/java/org/teiid/deployers/VDBRepository.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/deployers/VDBRepository.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/runtime/src/main/java/org/teiid/deployers/VDBRepository.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -290,8 +290,7 @@
 
 			if (report.hasItems()) {
 				LogManager.logInfo(LogConstants.CTX_RUNTIME, RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40073, name, version));
-				if (!v.getVDB().isPreview()) {
-					processMetadataValidatorReport(key, report);
+				if (!v.getVDB().isPreview() && !processMetadataValidatorReport(key, report)) {
 					v.getVDB().setStatus(Status.FAILED);
 					LogManager.logInfo(LogConstants.CTX_RUNTIME, RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40003,name, version, metadataAwareVDB.getStatus()));
 					return;
@@ -306,9 +305,11 @@
 	
 	/**
 	 * @param key 
-	 * @param report  
+	 * @param report
+	 * @return if the deployment should finish  
 	 */
-	protected void processMetadataValidatorReport(VDBKey key, ValidatorReport report) {
+	protected boolean processMetadataValidatorReport(VDBKey key, ValidatorReport report) {
+		return false;
 	}
 
 	void validateDataSources(VDBMetaData vdb) {

Modified: trunk/runtime/src/main/java/org/teiid/runtime/EmbeddedServer.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/runtime/EmbeddedServer.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/runtime/src/main/java/org/teiid/runtime/EmbeddedServer.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -241,12 +241,13 @@
 	 */
 	protected VDBRepository repo = new VDBRepository() {
 		@Override
-		protected void processMetadataValidatorReport(VDBKey key, ValidatorReport report) {
+		protected boolean processMetadataValidatorReport(VDBKey key, ValidatorReport report) {
 			if (throwMetadataErrors) {
 				super.processMetadataValidatorReport(key, report); //remove
 				ValidatorFailure firstFailure = report.getItems().iterator().next();
 				throw new VDBValidationError(RuntimePlugin.Event.TEIID40095, firstFailure.getMessage());
 			}
+			return true;
 		}
 	};
 	protected boolean throwMetadataErrors = true;

Modified: trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestSystemVirtualModel.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestSystemVirtualModel.java	2012-09-10 16:27:19 UTC (rev 4417)
+++ trunk/test-integration/common/src/test/java/org/teiid/systemmodel/TestSystemVirtualModel.java	2012-09-10 17:02:33 UTC (rev 4418)
@@ -142,31 +142,7 @@
 	}
 
 	@Test public void testDefect12064() throws Exception {
-		String[] expected = { 
-				"KeyName[string]	RefKeyUID[string]	",  //$NON-NLS-1$
-				"PK_PARTS	null", //$NON-NLS-1$
-				"PK_SHIP_VIA	null", //$NON-NLS-1$
-				"PK_STATUS	null",  //$NON-NLS-1$
-				"PK_SUPPLIER	null",  //$NON-NLS-1$
-				"PK_SUPPLIER_PARTS	null", //$NON-NLS-1$
-				"PK_SUPPLIER_PARTS	null",  //$NON-NLS-1$
-				"idx_matpg_relatt_ids	null",
-				"idx_matpg_relatt_ids	null",
-				"matpg_datatype_ids	null",
-				"matpg_datatype_ids	null",
-				"matpg_datatype_names	null",
-				"matpg_datatype_names	null",				
-				"pk_matpg_relatt_names	null",
-				"pk_matpg_relatt_names	null",
-				"pk_matpg_relatt_names	null",
-				"pk_pg_attr	null",  //$NON-NLS-1$
-				"pk_pg_class	null",  //$NON-NLS-1$
-				"pk_pg_index	null",  //$NON-NLS-1$
-				"pk_pg_proc	null",  //$NON-NLS-1$
-				
-
-		};
-		executeAndAssertResults("select KeyName, RefKeyUID FROM SYS.KeyColumns WHERE RefKeyUID IS NULL order by KeyName",expected); //$NON-NLS-1$
+		checkResult("testDefect12064", "select KeyName, RefKeyUID FROM SYS.KeyColumns WHERE RefKeyUID IS NULL order by KeyName"); //$NON-NLS-1$
 	}
 
 	@Test public void testReferenceKeyColumns() throws Exception {

Added: trunk/test-integration/common/src/test/resources/TestSystemVirtualModel/testDefect12064.expected
===================================================================
--- trunk/test-integration/common/src/test/resources/TestSystemVirtualModel/testDefect12064.expected	                        (rev 0)
+++ trunk/test-integration/common/src/test/resources/TestSystemVirtualModel/testDefect12064.expected	2012-09-10 17:02:33 UTC (rev 4418)
@@ -0,0 +1,25 @@
+string                                                             string                                            
+KeyName                                                            RefKeyUID                                         
+PK_PARTS                                                           <null>                                            
+PK_SHIP_VIA                                                        <null>                                            
+PK_STATUS                                                          <null>                                            
+PK_SUPPLIER                                                        <null>                                            
+PK_SUPPLIER_PARTS                                                  <null>                                            
+PK_SUPPLIER_PARTS                                                  <null>                                            
+idx_matpg_relatt_ids                                               <null>                                            
+idx_matpg_relatt_ids                                               <null>                                            
+matpg_datatype_ids                                                 <null>                                            
+matpg_datatype_ids                                                 <null>                                            
+matpg_datatype_names                                               <null>                                            
+matpg_datatype_names                                               <null>                                            
+pk_matpg_relatt_names                                              <null>                                            
+pk_matpg_relatt_names                                              <null>                                            
+pk_matpg_relatt_names                                              <null>                                            
+pk_pg_attr                                                         <null>                                            
+pk_pg_class                                                        <null>                                            
+pk_pg_index                                                        <null>                                            
+pk_pg_proc                                                         <null>                                            
+Row Count : 19
+getColumnName  getColumnType  getCatalogName  getColumnClassName  getColumnLabel  getColumnTypeName  getSchemaName  getTableName  getColumnDisplaySize  getPrecision  getScale  isAutoIncrement  isCaseSensitive  isCurrency  isDefinitelyWritable  isNullable  isReadOnly  isSearchable  isSigned  isWritable  
+KeyName        12             PartsSupplier   java.lang.String    KeyName         string             SYS            KeyColumns    255                   255           0         false            true             false       false                 1           true        true          false     false       
+RefKeyUID      12             PartsSupplier   java.lang.String    RefKeyUID       string             SYS            KeyColumns    50                    50            0         false            true             false       false                 1           true        true          false     false       



More information about the teiid-commits mailing list