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