teiid SVN: r2377 - trunk/documentation/client-developers-guide/src/main/docbook/en-US/content.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-07-27 10:21:35 -0400 (Tue, 27 Jul 2010)
New Revision: 2377
Modified:
trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/odbc.xml
Log:
TEIID-860: Correcting ODBC Unix compilation instructions.
Modified: trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/odbc.xml
===================================================================
--- trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/odbc.xml 2010-07-27 04:36:53 UTC (rev 2376)
+++ trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/odbc.xml 2010-07-27 14:21:35 UTC (rev 2377)
@@ -95,14 +95,14 @@
Build and install the driver by running the commands below.</para>
<note><para>You should use super user account or use "sudo" command for running the "make install" command. </para></note>
<programlisting><![CDATA[
- perl Makefile.PL
- make
- make test
- make install
+ % tar -zxvf psqlodbc-xx.xx.xxxx.tar.gz
+ % cd psqlodbc-xx.xx.xxxx
+ % ./configure
+ % make
+ % make install
]]></programlisting>
- <para>Make sure that there are no errors during the "make test" phase. The the next step in the process is to create a
- DSN for accessing the Teiid VDB.</para>
+ <para>The the next step in the process is to create a DSN for accessing the Teiid VDB.</para>
</sect2>
</sect1>
14 years, 5 months
teiid SVN: r2376 - in trunk/engine/src: main/java/org/teiid/query/processor/relational and 3 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-07-27 00:36:53 -0400 (Tue, 27 Jul 2010)
New Revision: 2376
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
trunk/engine/src/test/java/org/teiid/query/processor/xml/TestXMLPlanningEnhancements.java
Log:
TEIID-1167 adding projection support to temp tables, this also cuts down on the number of columns that need buffered
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2010-07-27 02:54:36 UTC (rev 2375)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2010-07-27 04:36:53 UTC (rev 2376)
@@ -36,7 +36,6 @@
import org.teiid.core.id.IntegerID;
import org.teiid.core.id.IntegerIDFactory;
import org.teiid.core.util.Assertion;
-import org.teiid.language.TableReference;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.execution.QueryExecPlugin;
import org.teiid.query.metadata.QueryMetadataInterface;
@@ -468,7 +467,7 @@
return aNode;
}
GroupSymbol group = node.getGroups().iterator().next();
- if (!group.isTempTable() && !CoreConstants.SYSTEM_MODEL.equals(metadata.getFullName(metadata.getModelID(group.getMetadataID())))) {
+ if (!CoreConstants.SYSTEM_MODEL.equals(metadata.getFullName(metadata.getModelID(group.getMetadataID())))) {
return aNode;
}
List projectSymbols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java 2010-07-27 02:54:36 UTC (rev 2375)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java 2010-07-27 04:36:53 UTC (rev 2376)
@@ -357,7 +357,7 @@
return result;
}
- protected List<?> projectTuple(int[] indexes, List<?> tupleValues) {
+ public static List<?> projectTuple(int[] indexes, List<?> tupleValues) {
List<Object> projectedTuple = new ArrayList<Object>(indexes.length);
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java 2010-07-27 02:54:36 UTC (rev 2375)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java 2010-07-27 04:36:53 UTC (rev 2376)
@@ -164,17 +164,34 @@
this.sessionID = sessionID;
}
- public TupleSource createTupleSource(List<Criteria> conditions, OrderBy orderBy) throws TeiidComponentException {
+ public TupleSource createTupleSource(List<SingleElementSymbol> projectedCols, List<Criteria> conditions, OrderBy orderBy) throws TeiidComponentException {
TupleBrowser browser = createTupleBrower(conditions, orderBy);
- TupleBuffer tb = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
+ TupleBuffer tb = bm.createTupleBuffer(getColumns(), sessionID, TupleSourceType.PROCESSOR);
+ Map map = RelationalNode.createLookupMap(getColumns());
+ int[] indexes = RelationalNode.getProjectionIndexes(map, projectedCols);
+ boolean project = false;
+ if (indexes.length == getColumns().size()) {
+ for (int i = 0; i < indexes.length; i++) {
+ if (indexes[i] != i) {
+ project = true;
+ break;
+ }
+ }
+ } else {
+ project = true;
+ }
List next = null;
while ((next = browser.next()) != null) {
if (rowId != null) {
next = next.subList(1, next.size());
}
+ if (project) {
+ next = RelationalNode.projectTuple(indexes, next);
+ }
tb.addTuple(next);
}
tb.close();
+ tb.setForwardOnly(true);
return tb.createIndexedTupleSource(true);
}
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java 2010-07-27 02:54:36 UTC (rev 2375)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java 2010-07-27 04:36:53 UTC (rev 2376)
@@ -51,10 +51,12 @@
import org.teiid.query.sql.lang.ProcedureContainer;
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.Update;
+import org.teiid.query.sql.navigator.PostOrderNavigator;
import org.teiid.query.sql.symbol.Constant;
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.visitor.ExpressionMappingVisitor;
/**
* @since 5.5
@@ -83,18 +85,16 @@
}
List<ElementSymbol> columns = create.getColumns();
- boolean hasKey = !create.getPrimaryKey().isEmpty();
+ //add metadata
+ TempMetadataID id = tempMetadataStore.addTempGroup(tempTableName, columns, false, true);
+ TempTableResolver.addPrimaryKey(create, id);
columns = new ArrayList<ElementSymbol>(create.getColumns());
-
- if (hasKey) {
+ if (!create.getPrimaryKey().isEmpty()) {
//reorder the columns to put the key in front
List<ElementSymbol> primaryKey = create.getPrimaryKey();
columns.removeAll(primaryKey);
columns.addAll(0, primaryKey);
- }
- //add metadata
- TempMetadataID id = tempMetadataStore.addTempGroup(tempTableName, columns, false, true);
- TempTableResolver.addPrimaryKey(create, id);
+ }
TempTable tempTable = new TempTable(buffer, columns, create.getPrimaryKey().size(), sessionID);
groupToTupleSourceID.put(tempTableName, tempTable);
}
@@ -119,7 +119,18 @@
return null;
}
TempTable table = getTempTable(group.getNonCorrelationName().toUpperCase(), command);
- return table.createTupleSource(Criteria.separateCriteriaByAnd(query.getCriteria()), query.getOrderBy());
+ //convert to the actual table symbols (this is typically handled by the languagebridgefactory
+ ExpressionMappingVisitor emv = new ExpressionMappingVisitor(null) {
+ @Override
+ public Expression replaceExpression(Expression element) {
+ if (element instanceof ElementSymbol) {
+ ((ElementSymbol) element).setName(((ElementSymbol) element).getOutputName());
+ }
+ return element;
+ }
+ };
+ PostOrderNavigator.doVisit(query.getSelect(), emv);
+ return table.createTupleSource(command.getProjectedSymbols(), Criteria.separateCriteriaByAnd(query.getCriteria()), query.getOrderBy());
}
if (command instanceof ProcedureContainer) {
GroupSymbol group = ((ProcedureContainer)command).getGroup();
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-27 02:54:36 UTC (rev 2375)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-27 04:36:53 UTC (rev 2376)
@@ -43,10 +43,10 @@
private TempTableDataManager dataManager;
private void execute(String sql, List[] expectedResults) throws Exception {
- execute(expectedResults, TestProcessor.helpGetPlan(sql, metadata));
+ execute(TestProcessor.helpGetPlan(sql, metadata), expectedResults);
}
- private void execute(List[] expectedResults, ProcessorPlan processorPlan) throws Exception {
+ private void execute(ProcessorPlan processorPlan, List[] expectedResults) throws Exception {
TestProcessor.doProcess(processorPlan, dataManager, expectedResults, TestProcessor.createCommandContext());
}
@@ -136,4 +136,11 @@
assertEquals(1, (metadata.getElementIDsInKey(c.iterator().next()).size()));
}
+ @Test public void testProjection() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key (e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ execute("select * from x where e2 = 1", new List[] {Arrays.asList("one", 1)}); //$NON-NLS-1$
+ execute("select e2, e1 from x where e2 = 1", new List[] {Arrays.asList(1, "one")}); //$NON-NLS-1$
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/xml/TestXMLPlanningEnhancements.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/xml/TestXMLPlanningEnhancements.java 2010-07-27 02:54:36 UTC (rev 2375)
+++ trunk/engine/src/test/java/org/teiid/query/processor/xml/TestXMLPlanningEnhancements.java 2010-07-27 04:36:53 UTC (rev 2376)
@@ -22,10 +22,13 @@
package org.teiid.query.processor.xml;
+import static org.junit.Assert.*;
+
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.junit.Test;
import org.teiid.client.metadata.ParameterInfo;
import org.teiid.common.buffer.BufferManager;
import org.teiid.core.types.DataTypeManager;
@@ -38,23 +41,14 @@
import org.teiid.query.optimizer.relational.rules.RuleChooseDependent;
import org.teiid.query.processor.FakeDataManager;
import org.teiid.query.processor.ProcessorPlan;
-import org.teiid.query.processor.xml.ExecSqlInstruction;
-import org.teiid.query.processor.xml.ExecStagingTableInstruction;
-import org.teiid.query.processor.xml.XMLPlan;
import org.teiid.query.unittest.FakeMetadataFacade;
import org.teiid.query.unittest.FakeMetadataFactory;
import org.teiid.query.unittest.FakeMetadataObject;
import org.teiid.query.unittest.FakeMetadataStore;
-import junit.framework.TestCase;
+public class TestXMLPlanningEnhancements {
-public class TestXMLPlanningEnhancements extends TestCase {
-
- public TestXMLPlanningEnhancements(String name) {
- super(name);
- }
-
private FakeMetadataFacade getMetadata(String query) {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadata();
@@ -172,7 +166,7 @@
return doc;
}
- public void testBaseballPlayersDocDefect19541() throws Exception {
+ @Test public void testBaseballPlayersDocDefect19541() throws Exception {
FakeMetadataFacade metadata = FakeMetadataFactory.exampleCase3225();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerCase3225(metadata);
@@ -221,7 +215,7 @@
}
- public void testNested2WithContextCriteria5c() throws Exception {
+ @Test public void testNested2WithContextCriteria5c() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadataCached();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
String resultFile = "TestXMLProcessor-testNested2WithContextCriteria5c.xml"; //$NON-NLS-1$
@@ -230,7 +224,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xmltest.doc9 WHERE NOT(SupplierID='52') AND (OrderID='5' OR OrderID='2')", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testNested2WithContextCriteria5d() throws Exception {
+ @Test public void testNested2WithContextCriteria5d() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadataCached();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
String resultFile = "TestXMLProcessor-testNested2WithContextCriteria5d.xml"; //$NON-NLS-1$
@@ -239,7 +233,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xmltest.doc9 WHERE OrderID='5' OR context(SupplierID, OrderID)='2'", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testNested2WithContextCriteria5d1() throws Exception {
+ @Test public void testNested2WithContextCriteria5d1() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadataCached();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
String resultFile = "TestXMLProcessor-testNested2WithContextCriteria5d.xml"; //$NON-NLS-1$
@@ -248,7 +242,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xmltest.doc9 WHERE context(SupplierID, OrderID)='5' OR OrderID='2'", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testNested2WithContextCriteria5e() throws Exception {
+ @Test public void testNested2WithContextCriteria5e() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadataCached();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
String resultFile = "TestXMLProcessor-testNested2WithContextCriteria5e.xml"; //$NON-NLS-1$
@@ -257,7 +251,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xmltest.doc9 WHERE OrderID='5' OR SupplierID='52'", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testXQTChoice_6796() throws Exception {
+ @Test public void testXQTChoice_6796() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadata2();
FakeDataManager dataMgr = TestXMLProcessor.exampleXQTDataManager(metadata);
String resultFile = "TestXMLProcessor-testXQTChoice_6796.xml"; //$NON-NLS-1$
@@ -266,7 +260,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xqttest.doc4 WHERE root.key.keys.nestedkey = 4", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testOrderByWithChoiceCriteriaElement() throws Exception {
+ @Test public void testOrderByWithChoiceCriteriaElement() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadata2();
FakeDataManager dataMgr = TestXMLProcessor.exampleXQTDataManager(metadata);
String expectedDoc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n <wrapper/>\n <wrapper/>\n <wrapper/>\n <wrapper/>\n <wrapper/>\n <wrapper/>\n <wrapper/>\n <wrapper/>\n <wrapper/>\n</root>"; //$NON-NLS-1$
@@ -274,7 +268,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xqttest.doc5 order by root.wrapper.key", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testXQTChoice_withContextCriteria() throws Exception {
+ @Test public void testXQTChoice_withContextCriteria() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadata2();
FakeDataManager dataMgr = TestXMLProcessor.exampleXQTDataManager(metadata);
String resultFile = "TestXMLProcessor-testXQTChoice_withContextCriteria.xml"; //$NON-NLS-1$
@@ -283,7 +277,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xqttest.doc4 WHERE context(root.key.keys.nestedkey, root.key.keys.nestedkey) = 4", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testXQTChoice_withContextCriteria1() throws Exception {
+ @Test public void testXQTChoice_withContextCriteria1() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadata2();
FakeDataManager dataMgr = TestXMLProcessor.exampleXQTDataManager(metadata);
String resultFile = "TestXMLProcessor-testXQTChoice_withContextCriteria1.xml"; //$NON-NLS-1$
@@ -292,7 +286,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xqttest.doc4 WHERE context(root.key.keys.nestedkey, root.key.keys.nestedkey) = 4 and context(root.wrapper.key.keys.nestedkey, root.wrapper.key.keys.nestedkey) = 3", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testMappingClassWithInlineViewAndCriteria() throws Exception {
+ @Test public void testMappingClassWithInlineViewAndCriteria() throws Exception {
FakeMetadataFacade metadata = getMetadata("SELECT upper(x.supplierNum) as supplierNum, x.supplierName, x.supplierZipCode from (select stock.suppliers.supplierNum, supplierName, supplierZipCode, itemNum FROM stock.suppliers, stock.item_supplier WHERE stock.suppliers.supplierNum = stock.item_supplier.supplierNum) x where x.itemNum = ?"); //$NON-NLS-1$
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
@@ -301,7 +295,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xmltest.doc18a where supplierID<56", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testMappingClassWithUnionAndCriteria() throws Exception {
+ @Test public void testMappingClassWithUnionAndCriteria() throws Exception {
FakeMetadataFacade metadata = getMetadata("SELECT concat(stock.suppliers.supplierNum, '') as supplierNum, supplierName, supplierZipCode FROM stock.suppliers, stock.item_supplier WHERE stock.suppliers.supplierNum = stock.item_supplier.supplierNum AND stock.item_supplier.itemNum = ? union all SELECT concat(stock.suppliers.supplierNum, '1'), supplierName, convert(12345, string) FROM stock.suppliers WHERE stock.suppliers.supplierNum = ?"); //$NON-NLS-1$
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
@@ -310,7 +304,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xmltest.doc18a where supplierID<56", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testMappingClassWithInputSetElementNameConflict() throws Exception {
+ @Test public void testMappingClassWithInputSetElementNameConflict() throws Exception {
FakeMetadataFacade metadata = getMetadata("SELECT concat(stock.suppliers.supplierNum, '') as supplierNum, supplierName, supplierZipCode FROM stock.suppliers, stock.item_supplier WHERE stock.suppliers.supplierNum = stock.item_supplier.supplierNum AND stock.item_supplier.supplierNum = ?"); //$NON-NLS-1$
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
@@ -318,7 +312,7 @@
TestXMLProcessor.helpTestProcess("SELECT * FROM xmltest.doc18a where supplierID<56", expectedDoc, metadata, dataMgr); //$NON-NLS-1$
}
- public void testAutoStagingFailsForMappingClassWithProcRelational() throws Exception {
+ @Test public void testAutoStagingFailsForMappingClassWithProcRelational() throws Exception {
FakeMetadataFacade metadata = getMetadata("SELECT supplierNum, supplierName, supplierZipCode FROM v1.supplierProc where itemnum = ?"); //$NON-NLS-1$
FakeMetadataObject v1 = FakeMetadataFactory.createVirtualModel("v1"); //$NON-NLS-1$
@@ -341,7 +335,7 @@
assertNull(stats.get(ExecStagingTableInstruction.class));
}
- public void testMappingClassWitSelectDistinctAndCriteria() throws Exception {
+ @Test public void testMappingClassWitSelectDistinctAndCriteria() throws Exception {
FakeMetadataFacade metadata = getMetadata("SELECT distinct '1' as supplierNum, '2' as supplierName, '3' as supplierZipCode FROM stock.suppliers, stock.item_supplier WHERE stock.suppliers.supplierNum = stock.item_supplier.supplierNum AND stock.item_supplier.itemNum like substring(?,1,1) || '%'"); //$NON-NLS-1$
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
@@ -357,7 +351,7 @@
* Ensures that correlated references to outer scoped groups can
* be used as inputs
*/
- public void testMappingClassWithStoredProcedureAndCriteria() throws Exception {
+ @Test public void testMappingClassWithStoredProcedureAndCriteria() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadataCached();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
String expectedDoc = TestXMLProcessor.readFile("TestXMLPlanningEnhancements-testMappingClassWithStoredProcedureAndCriteria.xml"); //$NON-NLS-1$
@@ -376,7 +370,7 @@
/**
* @see #testNested2WithCriteria2
*/
- public void testAutoStagingByCosting() throws Exception {
+ @Test public void testAutoStagingByCosting() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadata();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
FakeMetadataObject suppliers = metadata.getStore().findObject("stock.suppliers", FakeMetadataObject.GROUP); //$NON-NLS-1$
@@ -397,7 +391,7 @@
/**
* @see #testNested2WithCriteria2
*/
- public void testAutoStagingFailsByCosting() throws Exception {
+ @Test public void testAutoStagingFailsByCosting() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadata();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
FakeMetadataObject suppliers = metadata.getStore().findObject("stock.suppliers", FakeMetadataObject.GROUP); //$NON-NLS-1$
@@ -415,7 +409,7 @@
assertNull(stats.get(ExecStagingTableInstruction.class));
}
- public void testAutoStagingFailsByNoCache() throws Exception {
+ @Test public void testAutoStagingFailsByNoCache() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadataCached();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
@@ -428,7 +422,7 @@
assertNull(stats.get(ExecStagingTableInstruction.class));
}
- public void testAutoStagingFailsByNoCacheByGroup() throws Exception {
+ @Test public void testAutoStagingFailsByNoCacheByGroup() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadataCached();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
@@ -448,7 +442,7 @@
}
// see the next test with costing information too.
- public void testUseOfStagingCardinalityOnDependentJoinsNoCost() throws Exception {
+ @Test public void testUseOfStagingCardinalityOnDependentJoinsNoCost() throws Exception {
FakeMetadataFacade metadata = getTempTableMetadata(false);
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
@@ -473,7 +467,7 @@
1, // MergeJoin (**We are merge join with out any costing info**)
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
1, // Select
0, // Sort
0 // UnionAll
@@ -482,7 +476,7 @@
TestOptimizer.checkDependentJoinCount(plan, 0);
}
- public void testUseOfStagingCardinalityOnDependentJoinsWithCost() throws Exception {
+ @Test public void testUseOfStagingCardinalityOnDependentJoinsWithCost() throws Exception {
FakeMetadataFacade metadata = getTempTableMetadata(false);
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
FakeMetadataObject orders = metadata.getStore().findObject("stock.orders", FakeMetadataObject.GROUP); //$NON-NLS-1$
@@ -512,7 +506,7 @@
1, // MergeJoin (**We are merge join with out any costing info**)
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
1, // Select
0, // Sort
0 // UnionAll
@@ -521,7 +515,7 @@
TestOptimizer.checkDependentJoinCount(plan, 1);
}
- public void testNoRedundentStagingTables() throws Exception {
+ @Test public void testNoRedundentStagingTables() throws Exception {
FakeMetadataFacade metadata = getTempTableMetadata(true);
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
FakeMetadataObject suppliers = metadata.getStore().findObject("stock.suppliers", FakeMetadataObject.GROUP); //$NON-NLS-1$
@@ -538,7 +532,7 @@
assertEquals(4, ((List)stats.get(ExecStagingTableInstruction.class)).size());
}
- public void testEmptyMappingClass() throws Exception {
+ @Test public void testEmptyMappingClass() throws Exception {
FakeMetadataFacade metadata = TestXMLProcessor.exampleMetadata();
FakeDataManager dataMgr = TestXMLProcessor.exampleDataManagerNested(metadata);
FakeMetadataObject suppliers = metadata.getStore().findObject("xmltest.suppliers", FakeMetadataObject.GROUP); //$NON-NLS-1$
14 years, 5 months
teiid SVN: r2375 - in trunk/engine/src: test/java/org/teiid/common/buffer and 1 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-07-26 22:54:36 -0400 (Mon, 26 Jul 2010)
New Revision: 2375
Added:
trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java
Removed:
trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
Modified:
trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
Log:
TEIID-1167 fixing tree, switching to holding tuplebatches (since that's what our weak references are to), and adding prev for backwards iteration.
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java 2010-07-26 16:57:39 UTC (rev 2374)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java 2010-07-27 02:54:36 UTC (rev 2375)
@@ -24,6 +24,8 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -32,6 +34,9 @@
/**
* A linked list Page entry in the tree
+ *
+ * TODO: return the tuplebatch from getvalues, since that is what we're tracking
+ *
*/
@SuppressWarnings("unchecked")
class SPage {
@@ -41,8 +46,8 @@
static class SearchResult {
int index;
SPage page;
- List values;
- public SearchResult(int index, SPage page, List values) {
+ TupleBatch values;
+ public SearchResult(int index, SPage page, TupleBatch values) {
this.index = index;
this.page = page;
this.values = values;
@@ -53,73 +58,78 @@
STree stree;
- protected SPage next;
+ protected SPage next;
+ protected SPage prev;
protected ManagedBatch managedBatch;
- protected List values;
+ protected TupleBatch values;
protected ArrayList<SPage> children;
SPage(STree stree, boolean leaf) {
this.stree = stree;
- this.values = new ArrayList<SPage>(stree.pageSize);
+ this.values = new TupleBatch(counter.getAndIncrement(), new ArrayList(stree.pageSize/4));
if (!leaf) {
children = new ArrayList<SPage>(stree.pageSize/4);
}
}
- static SearchResult search(SPage page, List k, SearchResult parent, List parentKey) throws TeiidComponentException {
- SPage previous = null;
- List previousValues = null;
+ static int unnecessaryReads;
+
+ static SearchResult search(SPage page, List k, LinkedList<SearchResult> parent) throws TeiidComponentException {
+ TupleBatch previousValues = null;
for (;;) {
- List values = page.getValues();
- int index = Collections.binarySearch(values, k, page.stree.comparator);
- int actual = - index - 1;
- if (previous != null) {
- if (actual == 0) {
- if (values.isEmpty()) {
- page.remove();
- previous.next = page.next;
- }
- return new SearchResult(-previousValues.size() - 1, previous, previousValues);
+ TupleBatch values = page.getValues();
+ int index = Collections.binarySearch(values.getTuples(), k, page.stree.comparator);
+ int flippedIndex = - index - 1;
+ if (previousValues != null) {
+ unnecessaryReads++;
+ if (flippedIndex == 0) {
+ //systemic weakness of the algorithm
+ return new SearchResult(-previousValues.getTuples().size() - 1, page.prev, previousValues);
}
- if (parentKey != null) {
- if (page.stree.comparator.compare(parentKey, values.get(0)) >= 0) {
- //TODO: the entries after this point may also need moved forward
- //TODO: this should be done as part of insert
- parent.page.children.set(Math.max(0, -parent.index - 2), page);
- } else {
- //parentKey < page.keys.get(0)
- //TODO: this circumvents the normal probabilistic process, but
- //ensures there is an index entry.
- page.stree.insert(page.stree.extractKey((List) values.get(0)), parent, page);
- parent.index--;
+ if (parent != null && index != 0) {
+ //for non-matches move the previous pointer over to this page
+ SPage childPage = page;
+ List oldKey = null;
+ List newKey = page.stree.extractKey(values.getTuples().get(0));
+ for (Iterator<SearchResult> desc = parent.descendingIterator(); desc.hasNext();) {
+ SearchResult sr = desc.next();
+ int parentIndex = Math.max(0, -sr.index - 2);
+ if (oldKey == null) {
+ oldKey = sr.values.getTuples().set(parentIndex, newKey);
+ } else if (page.stree.comparator.compare(oldKey, sr.values.getTuples().get(parentIndex)) == 0 ) {
+ sr.values.getTuples().set(parentIndex, newKey);
+ } else {
+ break;
+ }
+ sr.page.children.set(parentIndex, childPage);
+ sr.page.setValues(sr.values);
+ childPage = sr.page;
}
}
}
- if (actual != values.size() || page.next == null) {
+ if (flippedIndex != values.getTuples().size() || page.next == null) {
return new SearchResult(index, page, values);
}
- previous = page;
previousValues = values;
page = page.next;
}
}
- protected void setValues(List values) throws TeiidComponentException {
+ protected void setValues(TupleBatch values) throws TeiidComponentException {
if (managedBatch != null) {
managedBatch.remove();
}
- if (values.size() < MIN_PERSISTENT_SIZE) {
+ if (values.getTuples().size() < MIN_PERSISTENT_SIZE) {
this.values = values;
return;
}
this.values = null;
- TupleBatch batch = TupleBatch.directBatch(counter.getAndIncrement(), values);
if (children != null) {
- batch.setDataTypes(stree.keytypes);
+ values.setDataTypes(stree.keytypes);
} else {
- batch.setDataTypes(stree.types);
+ values.setDataTypes(stree.types);
}
- managedBatch = stree.manager.createManagedBatch(batch);
+ managedBatch = stree.manager.createManagedBatch(values);
}
protected void remove() {
@@ -127,17 +137,95 @@
managedBatch.remove();
managedBatch = null;
}
+ values = null;
+ children = null;
}
- protected List getValues() throws TeiidComponentException {
+ protected TupleBatch getValues() throws TeiidComponentException {
if (values != null) {
return values;
}
if (managedBatch == null) {
- return Collections.emptyList();
+ throw new AssertionError("Batch removed"); //$NON-NLS-1$
}
- TupleBatch batch = managedBatch.getBatch(true, stree.types);
- return batch.getTuples();
+ return managedBatch.getBatch(true, stree.types);
}
+
+ static void merge(LinkedList<SearchResult> places, TupleBatch nextValues, SPage current, TupleBatch currentValues)
+ throws TeiidComponentException {
+ SearchResult parent = places.peekLast();
+ if (parent != null) {
+ correctParents(parent.page, nextValues.getTuples().get(0), current.next, current);
+ }
+ currentValues.getTuples().addAll(nextValues.getTuples());
+ if (current.children != null) {
+ current.children.addAll(current.next.children);
+ }
+ current.next.remove();
+ current.next = current.next.next;
+ if (current.next != null) {
+ current.next.prev = current;
+ }
+ current.setValues(currentValues);
+ }
+ /**
+ * Remove the usage of page in favor of nextPage
+ * @param parent
+ * @param page
+ * @param nextPage
+ * @throws TeiidComponentException
+ */
+ static void correctParents(SPage parent, List key, SPage page, SPage nextPage) throws TeiidComponentException {
+ SearchResult location = SPage.search(parent, key, null);
+ while (location.index == -1 && location.page.prev != null ) {
+ parent = location.page.prev;
+ location = SPage.search(parent, key, null);
+ }
+ parent = location.page;
+ int index = location.index;
+ if (index < 0) {
+ index = -index - 1;
+ }
+ while (parent != null) {
+ while (index < parent.children.size()) {
+ if (parent.children.get(index) != page) {
+ return;
+ }
+ parent.children.set(index++, nextPage);
+ }
+ index = 0;
+ parent = parent.next;
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ try {
+ TupleBatch tb = getValues();
+ result.append(tb.getBeginRow());
+ if (children == null) {
+ if (tb.getTuples().size() <= 1) {
+ result.append(values);
+ } else {
+ result.append("[").append(tb.getTuples().get(0)).append(" . ").append(tb.getTuples().size()). //$NON-NLS-1$ //$NON-NLS-2$
+ append(" . ").append(tb.getTuples().get(tb.getTuples().size() - 1)).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ } else {
+ result.append("["); //$NON-NLS-1$
+ for (int i = 0; i < children.size(); i++) {
+ result.append(tb.getTuples().get(i)).append("->").append(children.get(i).getValues().getBeginRow()); //$NON-NLS-1$
+ if (i < children.size() - 1) {
+ result.append(", "); //$NON-NLS-1$
+ }
+ }
+ result.append("]");//$NON-NLS-1$
+ }
+ } catch (Throwable e) {
+ result.append("Removed"); //$NON-NLS-1$
+ }
+ return result.toString();
+ }
+
}
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/STree.java 2010-07-26 16:57:39 UTC (rev 2374)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/STree.java 2010-07-27 02:54:36 UTC (rev 2375)
@@ -23,7 +23,6 @@
package org.teiid.common.buffer;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
@@ -34,8 +33,6 @@
import org.teiid.common.buffer.SPage.SearchResult;
import org.teiid.core.TeiidComponentException;
-@SuppressWarnings("unchecked")
-
/**
* Self balancing search tree using skip list like logic
* This has similar performance similar to a B+/-Tree
@@ -43,11 +40,15 @@
* TODO: reserve additional memory for delete/update operations
* TODO: double link to support desc key access
*/
+@SuppressWarnings("unchecked")
public class STree {
private static final Random seedGenerator = new Random();
- private int randomSeed;
+ protected int randomSeed;
+ private int mask = 1;
+ private int shift = 1;
+
private SPage[] header = new SPage[] {new SPage(this, true)};
protected BatchManager manager;
protected Comparator comparator;
@@ -64,9 +65,17 @@
int keyLength,
String[] types) {
randomSeed = seedGenerator.nextInt() | 0x00000100; // ensure nonzero
+ //randomSeed=-1031212234;
this.manager = recman;
this.comparator = comparator;
this.pageSize = Math.max(pageSize, SPage.MIN_PERSISTENT_SIZE);
+ pageSize >>>= 4;
+ while (pageSize > 0) {
+ pageSize >>>= 1;
+ shift++;
+ mask <<= 1;
+ mask++;
+ }
this.keyLength = keyLength;
this.types = types;
this.keytypes = Arrays.copyOf(types, keyLength);
@@ -89,8 +98,7 @@
x ^= x >>> 17;
randomSeed = x ^= x << 5;
int level = 0;
- int shift = 8;
- while ((x & 0xff) == 0xff) {
+ while ((x & mask) == mask) {
++level;
x >>>= shift;
}
@@ -105,19 +113,19 @@
* @throws IOException
* @throws TeiidComponentException
*/
- private List find(List n, List<SearchResult> places) throws TeiidComponentException {
+ private List find(List n, LinkedList<SearchResult> places) throws TeiidComponentException {
SPage x = null;
- List parentKey = null;
SearchResult parent = null;
for (int i = header.length - 1; i >= 0; i--) {
if (x == null) {
x = header[i];
}
- SearchResult s = SPage.search(x, n, parent, parentKey);
+ SearchResult s = SPage.search(x, n, places);
+ parent = s;
if (places != null) {
places.add(s);
}
- if ((s.index == -1 && s.page == header[i]) || s.values.isEmpty()) {
+ if ((s.index == -1 && s.page == header[i]) || s.values.getTuples().isEmpty()) {
x = null;
continue; //start at the beginning of the next level
}
@@ -132,17 +140,15 @@
if (!matched) {
return null;
}
- return (List) s.values.get(index);
+ return s.values.getTuples().get(index);
}
- parentKey = (List) s.values.get(index);
- parent = s;
x = x.children.get(index);
}
return null;
}
public List find(List k) throws TeiidComponentException {
- return find(k, null);
+ return find(k, new LinkedList<SearchResult>());
}
public List insert(List tuple, boolean replace) throws TeiidComponentException {
@@ -154,7 +160,7 @@
}
SearchResult last = places.getLast();
SPage page = last.page;
- last.values.set(last.index, tuple);
+ last.values.getTuples().set(last.index, tuple);
page.setValues(last.values);
return match;
}
@@ -169,16 +175,16 @@
for (int i = 0; i <= level; i++) {
if (places.isEmpty()) {
SPage newHead = new SPage(this, false);
- ArrayList newValues = new ArrayList();
- newValues.add(key);
- newHead.setValues(newValues);
+ TupleBatch batch = newHead.getValues();
+ batch.getTuples().add(key);
+ newHead.setValues(batch);
newHead.children.add(page);
header[i] = newHead;
page = newHead;
} else {
SearchResult result = places.removeLast();
Object value = (i == 0 ? tuple : page);
- page = insert(key, result, value);
+ page = insert(key, result, places.peekLast(), value);
}
}
return null;
@@ -188,19 +194,21 @@
return tuple.subList(0, keyLength);
}
- SPage insert(List k, SearchResult result, Object value) throws TeiidComponentException {
+ SPage insert(List k, SearchResult result, SearchResult parent, Object value) throws TeiidComponentException {
SPage page = result.page;
int index = -result.index - 1;
- if (result.values.size() == pageSize) {
+ if (result.values.getTuples().size() == pageSize) {
boolean leaf = !(value instanceof SPage);
SPage nextPage = new SPage(this, leaf);
- ArrayList nextValues = new ArrayList(result.values.subList(pageSize/2, pageSize));
- result.values.subList(pageSize/2, pageSize).clear();
+ TupleBatch nextValues = nextPage.getValues();
+ nextValues.getTuples().addAll(result.values.getTuples().subList(pageSize/2, pageSize));
+ result.values.getTuples().subList(pageSize/2, pageSize).clear();
if (!leaf) {
nextPage.children.addAll(page.children.subList(pageSize/2, pageSize));
page.children.subList(pageSize/2, pageSize).clear();
}
nextPage.next = page.next;
+ nextPage.prev = page;
page.next = nextPage;
boolean inNext = false;
if (index <= pageSize/2) {
@@ -211,6 +219,10 @@
}
nextPage.setValues(nextValues);
page.setValues(result.values);
+ if (parent != null) {
+ List min = nextPage.getValues().getTuples().get(0);
+ SPage.correctParents(parent.page, min, page, nextPage);
+ }
if (inNext) {
page = nextPage;
}
@@ -221,12 +233,12 @@
return page;
}
- static void setValue(int index, List key, Object value, List values, SPage page) {
+ static void setValue(int index, List key, Object value, TupleBatch values, SPage page) {
if (value instanceof SPage) {
- values.add(index, key);
+ values.getTuples().add(index, key);
page.children.add(index, (SPage) value);
} else {
- values.add(index, value);
+ values.getTuples().add(index, (List)value);
}
}
@@ -237,43 +249,57 @@
return null;
}
rowCount.addAndGet(-1);
- for (int i = header.length -1; i >=0; i--) {
- SearchResult searchResult = places.remove();
+ for (int i = 0; i < header.length; i++) {
+ SearchResult searchResult = places.removeLast();
if (searchResult.index < 0) {
continue;
}
- boolean cleanup = false;
- searchResult.values.remove(searchResult.index);
- int size = searchResult.values.size();
+ searchResult.values.getTuples().remove(searchResult.index);
+ if (searchResult.page.children != null) {
+ searchResult.page.children.remove(searchResult.index);
+ }
+ int size = searchResult.values.getTuples().size();
if (size == 0) {
- if (header[i] == searchResult.page && (i != 0 || header[i].next != null)) {
- header[i].remove();
+ if (header[i] != searchResult.page) {
+ searchResult.page.remove();
+ if (searchResult.page.next != null) {
+ searchResult.page.next.prev = searchResult.page.prev;
+ }
+ searchResult.page.prev.next = searchResult.page.next;
+ searchResult.page.next = header[i];
+ searchResult.page.prev = null;
+ continue;
+ }
+ header[i].remove();
+ if (header[i].next != null) {
header[i] = header[i].next;
- if (header[i] == null) {
- //remove the layer
- header = Arrays.copyOf(header, header.length - 1);
+ header[i].prev = null;
+ } else {
+ if (i != 0) {
+ header = Arrays.copyOf(header, i);
+ break;
}
- } else if (i == 0 && header.length > 1) {
- cleanup = true;
+ header[0] = new SPage(this, true);
}
- } else if (searchResult.page.next != null && size < pageSize/4) {
- List nextValues = searchResult.page.next.getValues();
- SPage next = searchResult.page.next;
- if (nextValues.size() + size < pageSize/2) {
- searchResult.page.next = next.next;
- searchResult.values.addAll(nextValues);
- nextValues.clear();
- next.remove();
- //any references to toMerge are now invalid
- //setting back to the header will self heal
- //TODO: this can take advantage of a previous link
- next.next = header[i];
+ continue;
+ } else if (size < pageSize/2) {
+ //check for merge
+ if (searchResult.page.next != null) {
+ TupleBatch nextValues = searchResult.page.next.getValues();
+ if (nextValues.getTuples().size() < pageSize/4) {
+ SPage.merge(places, nextValues, searchResult.page, searchResult.values);
+ continue;
+ }
}
+ if (searchResult.page.prev != null) {
+ TupleBatch prevValues = searchResult.page.prev.getValues();
+ if (prevValues.getTuples().size() < pageSize/4) {
+ SPage.merge(places, searchResult.values, searchResult.page.prev, prevValues);
+ continue;
+ }
+ }
}
searchResult.page.setValues(searchResult.values);
- if (cleanup) {
- find(key, null); //trigger cleanup
- }
}
return tuple;
}
@@ -309,7 +335,8 @@
SPage page = header[0];
int index;
- List values;
+ TupleBatch values;
+ boolean updated;
public boolean matchedLower() {
return false;
@@ -324,11 +351,16 @@
if (values == null) {
values = page.getValues();
}
- if (index < values.size()) {
- return (List) values.get(index++);
+ if (index < values.getTuples().size()) {
+ return values.getTuples().get(index++);
}
+ if (updated) {
+ page.setValues(values);
+ }
+ values = null;
index = 0;
page = page.next;
+ updated = false;
if (page == null) {
return null;
}
@@ -342,8 +374,8 @@
* @throws TeiidComponentException
*/
public void update(List tuple) throws TeiidComponentException {
- values.set(index - 1, tuple);
- page.setValues(values);
+ values.getTuples().set(index - 1, tuple);
+ updated = true;
}
/**
@@ -354,6 +386,22 @@
}
}
+ @Override
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+ for (int i = header.length -1; i >= 0; i--) {
+ SPage page = header[i];
+ result.append("Level ").append(i).append(" "); //$NON-NLS-1$ //$NON-NLS-2$
+ while (page != null) {
+ result.append(page);
+ result.append(", "); //$NON-NLS-1$
+ page = page.next;
+ }
+ result.append("\n"); //$NON-NLS-1$
+ }
+ return result.toString();
+ }
+
public int getKeyLength() {
return keyLength;
}
Copied: trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java (from rev 2371, trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java)
===================================================================
--- trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java 2010-07-27 02:54:36 UTC (rev 2375)
@@ -0,0 +1,60 @@
+/*
+ * 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.common.buffer;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.teiid.common.buffer.BufferManager.TupleSourceType;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.query.sql.symbol.ElementSymbol;
+
+@SuppressWarnings("nls")
+public class TestSTree {
+
+ @Test public void testRemoveAll() throws TeiidComponentException {
+ BufferManager bm = BufferManagerFactory.getStandaloneBufferManager();
+ ElementSymbol e1 = new ElementSymbol("x");
+ e1.setType(Integer.class);
+ ElementSymbol e2 = new ElementSymbol("y");
+ e2.setType(String.class);
+ List elements = Arrays.asList(e1, e2);
+ STree map = bm.createSTree(elements, "1", TupleSourceType.PROCESSOR, 1);
+
+ for (int i = 20000; i > 0; i--) {
+ assertNull(map.insert(Arrays.asList(i, String.valueOf(i)), true));
+ assertEquals(20000 - i + 1, map.getRowCount());
+ }
+
+ for (int i = 20000; i > 0; i--) {
+ assertNotNull(String.valueOf(i), map.remove(Arrays.asList(i)));
+ }
+
+ assertEquals(0, map.getRowCount());
+ assertNull(map.insert(Arrays.asList(1, String.valueOf(1)), true));
+ }
+
+}
Property changes on: trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java 2010-07-26 16:57:39 UTC (rev 2374)
+++ trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java 2010-07-27 02:54:36 UTC (rev 2375)
@@ -1,62 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.common.buffer.impl;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-
-import org.junit.Test;
-import org.teiid.common.buffer.BufferManager;
-import org.teiid.common.buffer.BufferManagerFactory;
-import org.teiid.common.buffer.STree;
-import org.teiid.common.buffer.BufferManager.TupleSourceType;
-import org.teiid.core.TeiidComponentException;
-import org.teiid.query.sql.symbol.ElementSymbol;
-
-public class TestSTree {
-
- @Test public void testRemoveAll() throws TeiidComponentException, IOException {
- BufferManager bm = BufferManagerFactory.getStandaloneBufferManager();
- ElementSymbol e1 = new ElementSymbol("x");
- e1.setType(Integer.class);
- ElementSymbol e2 = new ElementSymbol("y");
- e2.setType(String.class);
- List elements = Arrays.asList(e1, e2);
- STree map = bm.createSTree(elements, "1", TupleSourceType.PROCESSOR, 1);
-
- for (int i = 20000; i > 0; i--) {
- map.insert(Arrays.asList(i, String.valueOf(i)), true);
- }
-
- for (int i = 20000; i > 0; i--) {
- map.remove(Arrays.asList(i));
- }
-
- assertEquals(0, map.getRowCount());
- assertNull(map.insert(Arrays.asList(1, String.valueOf(1)), true));
- }
-
-}
14 years, 5 months
teiid SVN: r2374 - in trunk: client/src/main/java/org/teiid/net and 7 other directories.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-07-26 12:57:39 -0400 (Mon, 26 Jul 2010)
New Revision: 2374
Modified:
trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java
trunk/client/src/main/java/org/teiid/jdbc/TeiidDataSource.java
trunk/client/src/main/java/org/teiid/net/TeiidURL.java
trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java
trunk/engine/src/main/java/org/teiid/security/SecurityHelper.java
trunk/jboss-integration/src/main/java/org/teiid/jboss/JBossSecurityHelper.java
trunk/runtime/src/main/java/org/teiid/services/SessionServiceImpl.java
trunk/runtime/src/main/java/org/teiid/services/TeiidLoginContext.java
trunk/runtime/src/main/java/org/teiid/transport/LocalServerConnection.java
trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties
trunk/runtime/src/test/java/org/teiid/services/TestMembershipServiceImpl.java
trunk/runtime/src/test/java/org/teiid/services/TestSessionServiceImpl.java
Log:
TEIID-1048: adding ability to control the pass though with explicit flag. Also ability to switch identities on the same connection if the passed in subject does not match with the original subject.
Modified: trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -71,7 +71,8 @@
BaseDataSource.USER_NAME,
BaseDataSource.PASSWORD,
TeiidURL.CONNECTION.AUTO_FAILOVER,
- TeiidURL.CONNECTION.DISCOVERY_STRATEGY));
+ TeiidURL.CONNECTION.DISCOVERY_STRATEGY,
+ TeiidURL.CONNECTION.PASSTHROUGH_AUTHENTICATION));
props.addAll(EXECUTION_PROPERTIES);
return Collections.unmodifiableSet(props);
}
Modified: trunk/client/src/main/java/org/teiid/jdbc/TeiidDataSource.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/TeiidDataSource.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/client/src/main/java/org/teiid/jdbc/TeiidDataSource.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -92,10 +92,13 @@
private String discoveryStrategy;
- /**
- * Constructor for MMDataSource.
- */
- public TeiidDataSource() {
+ /**
+ * when "true", in the "embedded" scenario, authentication is information is read in pass though manner.
+ */
+ private boolean passthroughAuthentication = false;
+
+
+ public TeiidDataSource() {
}
// --------------------------------------------------------------------------------------------
@@ -227,6 +230,7 @@
private Properties buildEmbeddedProperties(final String userName, final String password) {
Properties props = buildProperties(userName, password);
+ props.setProperty(TeiidURL.CONNECTION.PASSTHROUGH_AUTHENTICATION, Boolean.toString(this.passthroughAuthentication));
return props;
}
@@ -264,7 +268,14 @@
*/
public boolean isSecure() {
return this.secure;
- }
+ }
+ /**
+ * Same as "isSecure". Required by the reflection login in connection pools to identify the type
+ * @return
+ */
+ public boolean getSecure() {
+ return this.secure;
+ }
/**
* Returns a string containing a comma delimited list of alternate
@@ -475,6 +486,31 @@
public void setDiscoveryStrategy(String discoveryStrategy) {
this.discoveryStrategy = discoveryStrategy;
- }
+ }
+
+ /**
+ * When true, this connection uses the passed in security domain to do the authentication.
+ * @return
+ */
+ public boolean isPassthroughAuthentication() {
+ return passthroughAuthentication;
+ }
+
+ /**
+ * Same as "isPassthroughAuthentication". Required by the reflection login in connection pools to identify the type
+ * @return
+ */
+ public boolean getPassthroughAuthentication() {
+ return passthroughAuthentication;
+ }
+
+ /**
+ * When set to true, the connection uses the passed in security domain to do the authentication.
+ * @since 7.1
+ * @return
+ */
+ public void setPassthroughAuthentication(final boolean passthroughAuthentication) {
+ this.passthroughAuthentication = passthroughAuthentication;
+ }
}
Modified: trunk/client/src/main/java/org/teiid/net/TeiidURL.java
===================================================================
--- trunk/client/src/main/java/org/teiid/net/TeiidURL.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/client/src/main/java/org/teiid/net/TeiidURL.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -77,6 +77,8 @@
public static final String PASSWORD = "password"; //$NON-NLS-1$
public static final String ADMIN = "admin"; //$NON-NLS-1$
+
+ public static final String PASSTHROUGH_AUTHENTICATION = "PassthroughAuthentication"; //$NON-NLS-1$
}
public static final String DOT_DELIMITER = "."; //$NON-NLS-1$
Modified: trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -132,7 +132,7 @@
@Test public void testGetPropertyInfo1() throws Exception {
DriverPropertyInfo info[] = drv.getPropertyInfo("jdbc:metamatrix:vdb@mm://localhost:12345;applicationName=x", null); //$NON-NLS-1$
- assertEquals(18, info.length);
+ assertEquals(19, info.length);
assertEquals(false, info[0].required);
assertEquals("ApplicationName", info[0].name); //$NON-NLS-1$
assertEquals("x", info[0].value); //$NON-NLS-1$
Modified: trunk/engine/src/main/java/org/teiid/security/SecurityHelper.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/security/SecurityHelper.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/engine/src/main/java/org/teiid/security/SecurityHelper.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -37,4 +37,6 @@
Object createSecurityContext(String securityDomain, Principal p, Object credentials, Subject subject);
Subject getSubjectInContext(String securityDomain);
+
+ boolean sameSubject(String securityDomain, Object context, Subject subject);
}
Modified: trunk/jboss-integration/src/main/java/org/teiid/jboss/JBossSecurityHelper.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/JBossSecurityHelper.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/JBossSecurityHelper.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -29,6 +29,7 @@
import org.jboss.security.SecurityContext;
import org.jboss.security.SubjectInfo;
+import org.teiid.core.util.Assertion;
import org.teiid.security.SecurityHelper;
public class JBossSecurityHelper implements SecurityHelper, Serializable {
@@ -77,5 +78,21 @@
}
return null;
}
+
+ @Override
+ public boolean sameSubject(String securityDomain, Object context, Subject subject) {
+ Assertion.isNotNull(context);
+ SecurityContext previousContext = (SecurityContext)context;
+ Subject previousUser = previousContext.getSubjectInfo().getAuthenticatedSubject();
+
+ SecurityContext currentContext = SecurityActions.getSecurityContext();
+ if (currentContext != null && currentContext.getSecurityDomain().equals(securityDomain)) {
+ Subject currentUser = currentContext.getSubjectInfo().getAuthenticatedSubject();
+ if (previousUser.equals(currentUser)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
Modified: trunk/runtime/src/main/java/org/teiid/services/SessionServiceImpl.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/services/SessionServiceImpl.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/runtime/src/main/java/org/teiid/services/SessionServiceImpl.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -150,7 +150,8 @@
if (!domains.isEmpty()) {
// Authenticate user...
// if not authenticated, this method throws exception
- TeiidLoginContext membership = authenticate(userName, credentials, applicationName, domains, this.securityHelper);
+ boolean onlyAllowPassthrough = Boolean.valueOf(properties.getProperty(TeiidURL.CONNECTION.PASSTHROUGH_AUTHENTICATION, "false")); //$NON-NLS-1$
+ TeiidLoginContext membership = authenticate(userName, credentials, applicationName, domains, this.securityHelper, onlyAllowPassthrough);
loginContext = membership.getLoginContext();
userName = membership.getUserName();
securityDomain = membership.getSecurityDomain();
@@ -204,10 +205,10 @@
return newSession;
}
- protected TeiidLoginContext authenticate(String userName, Credentials credentials, String applicationName, List<String> domains, SecurityHelper helper)
+ protected TeiidLoginContext authenticate(String userName, Credentials credentials, String applicationName, List<String> domains, SecurityHelper helper, boolean onlyallowPassthrough)
throws LoginException {
TeiidLoginContext membership = new TeiidLoginContext(helper);
- membership.authenticateUser(userName, credentials, applicationName, domains);
+ membership.authenticateUser(userName, credentials, applicationName, domains, onlyallowPassthrough);
return membership;
}
Modified: trunk/runtime/src/main/java/org/teiid/services/TeiidLoginContext.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/services/TeiidLoginContext.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/runtime/src/main/java/org/teiid/services/TeiidLoginContext.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -64,24 +64,32 @@
this.securityHelper = helper;
}
- public void authenticateUser(String username, final Credentials credential, String applicationName, List<String> domains) throws LoginException {
+ public void authenticateUser(String username, final Credentials credential,
+ String applicationName, List<String> domains, boolean onlyallowPassthrough)
+ throws LoginException {
LogManager.logDetail(LogConstants.CTX_SECURITY, new Object[] {"authenticateUser", username, applicationName}); //$NON-NLS-1$
final String baseUsername = getBaseUsername(username);
-
+
+ if (onlyallowPassthrough) {
+ for (String domain:getDomainsForUser(domains, username)) {
+ Subject existing = this.securityHelper.getSubjectInContext(domain);
+ if (existing != null) {
+ this.userName = getUserName(existing)+AT+domain;
+ this.securitydomain = domain;
+ this.loginContext = createLoginContext(domain, existing);
+ return;
+ }
+ }
+ throw new LoginException(RuntimePlugin.Util.getString("no_passthrough_identity_found")); //$NON-NLS-1$
+ }
+
+
// If username specifies a domain (user@domain) only that domain is authenticated against.
// If username specifies no domain, then all domains are tried in order.
for (String domain:getDomainsForUser(domains, username)) {
-
- Subject existing = this.securityHelper.getSubjectInContext(domain);
- if (existing != null) {
- this.userName = getUserName(existing)+AT+domain;
- this.securitydomain = domain;
- this.loginContext = createLoginContext(domain, existing);
- return;
- }
-
+
try {
CallbackHandler handler = new CallbackHandler() {
@Override
Modified: trunk/runtime/src/main/java/org/teiid/transport/LocalServerConnection.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/LocalServerConnection.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/runtime/src/main/java/org/teiid/transport/LocalServerConnection.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -46,20 +46,25 @@
import org.teiid.net.ConnectionException;
import org.teiid.net.NetPlugin;
import org.teiid.net.ServerConnection;
+import org.teiid.net.TeiidURL;
public class LocalServerConnection implements ServerConnection {
private static final String TEIID_RUNTIME = "teiid/engine-deployer"; //$NON-NLS-1$
- private final LogonResult result;
+ private LogonResult result;
private boolean shutdown;
private ClientServiceRegistry csr;
private DQPWorkContext workContext = new DQPWorkContext();
+ private Properties connectionProperties;
+ private boolean passthrough;
public LocalServerConnection(Properties connectionProperties) throws CommunicationException, ConnectionException{
+ this.connectionProperties = connectionProperties;
this.csr = getClientServiceRegistry();
workContext.setSecurityHelper(csr.getSecurityHelper());
- this.result = authenticate(connectionProperties);
+ authenticate(connectionProperties);
+ passthrough = Boolean.valueOf(connectionProperties.getProperty(TeiidURL.CONNECTION.PASSTHROUGH_AUTHENTICATION, "false")); //$NON-NLS-1$
}
protected ClientServiceRegistry getClientServiceRegistry() {
@@ -71,10 +76,9 @@
}
}
- public synchronized LogonResult authenticate(Properties connProps) throws ConnectionException, CommunicationException {
+ public synchronized void authenticate(Properties connProps) throws ConnectionException, CommunicationException {
try {
- LogonResult logonResult = this.getService(ILogon.class).logon(connProps);
- return logonResult;
+ this.result = this.getService(ILogon.class).logon(connProps);
} catch (LogonException e) {
// Propagate the original message as it contains the message we want
// to give to the user
@@ -95,6 +99,14 @@
throw ExceptionUtil.convertException(arg1, new TeiidComponentException(NetPlugin.Util.getString("LocalTransportHandler.Transport_shutdown"))); //$NON-NLS-1$
}
try {
+ if (passthrough && !arg1.getDeclaringClass().equals(ILogon.class)) {
+ // check to make sure the current security context same as logged one
+ if (!csr.getSecurityHelper().sameSubject(workContext.getSession().getSecurityDomain(), workContext.getSession().getSecurityContext(), workContext.getSubject())) {
+ logoff();
+ authenticate(connectionProperties);
+ }
+ }
+
final T service = csr.getClientService(iface);
return workContext.runInContext(new Callable<Object>() {
public Object call() throws Exception {
@@ -128,19 +140,23 @@
}
if (logoff) {
- try {
- //make a best effort to send the logoff
- Future<?> writeFuture = this.getService(ILogon.class).logoff();
- if (writeFuture != null) {
- writeFuture.get(5000, TimeUnit.MILLISECONDS);
- }
- } catch (Exception e) {
- //ignore
- }
+ logoff();
}
this.shutdown = true;
}
+ private void logoff() {
+ try {
+ //make a best effort to send the logoff
+ Future<?> writeFuture = this.getService(ILogon.class).logoff();
+ if (writeFuture != null) {
+ writeFuture.get(5000, TimeUnit.MILLISECONDS);
+ }
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+
public LogonResult getLogonResult() {
return result;
}
Modified: trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties
===================================================================
--- trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties 2010-07-26 16:57:39 UTC (rev 2374)
@@ -264,6 +264,7 @@
SessionServiceImpl.The_username_0_and/or_password_are_incorrect=The username "{0}" and/or password and/or payload token could not be authenticated by any membership domain.
SessionServiceImpl.terminateSession = Admin [{0}] is terminating this session: {1}.
+no_passthrough_identity_found = Passthrough authentication failed. No authentication information found.
LogonImpl.Invalid_use_of_credentials_and_token=Conflicting use of both client session token and credentials.
Modified: trunk/runtime/src/test/java/org/teiid/services/TestMembershipServiceImpl.java
===================================================================
--- trunk/runtime/src/test/java/org/teiid/services/TestMembershipServiceImpl.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/runtime/src/test/java/org/teiid/services/TestMembershipServiceImpl.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -81,7 +81,7 @@
TeiidLoginContext ms = createMembershipService();
List<String> domains = new ArrayList<String>();
domains.add("testFile"); //$NON-NLS-1$
- ms.authenticateUser("user1", new Credentials("pass1".toCharArray()), null, domains); //$NON-NLS-1$ //$NON-NLS-2$
+ ms.authenticateUser("user1", new Credentials("pass1".toCharArray()), null, domains, false); //$NON-NLS-1$ //$NON-NLS-2$
Mockito.verify(ms.getLoginContext()).login();
@@ -93,7 +93,7 @@
TeiidLoginContext ms = createMembershipService();
List<String> domains = new ArrayList<String>();
domains.add("passthrough"); //$NON-NLS-1$
- ms.authenticateUser("user1", new Credentials("pass1".toCharArray()), null, domains); //$NON-NLS-1$ //$NON-NLS-2$
+ ms.authenticateUser("user1", new Credentials("pass1".toCharArray()), null, domains, true); //$NON-NLS-1$ //$NON-NLS-2$
assertEquals("alreadylogged@passthrough", ms.getUserName()); //$NON-NLS-1$
}
Modified: trunk/runtime/src/test/java/org/teiid/services/TestSessionServiceImpl.java
===================================================================
--- trunk/runtime/src/test/java/org/teiid/services/TestSessionServiceImpl.java 2010-07-26 14:17:53 UTC (rev 2373)
+++ trunk/runtime/src/test/java/org/teiid/services/TestSessionServiceImpl.java 2010-07-26 16:57:39 UTC (rev 2374)
@@ -31,9 +31,9 @@
SessionServiceImpl ssi = new SessionServiceImpl() {
@Override
- protected TeiidLoginContext authenticate(String userName, Credentials credentials, String applicationName, List<String> domains, SecurityHelper helper)
+ protected TeiidLoginContext authenticate(String userName, Credentials credentials, String applicationName, List<String> domains, SecurityHelper helper, boolean passthough)
throws LoginException {
- impl.authenticateUser(userName, credentials, applicationName, domains);
+ impl.authenticateUser(userName, credentials, applicationName, domains, passthough);
return impl;
}
};
@@ -49,7 +49,7 @@
SessionMetadata info = ssi.createSession("steve", null, "foo", new Properties(), false); //$NON-NLS-1$ //$NON-NLS-2$
if (securityEnabled) {
- Mockito.verify(impl).authenticateUser("steve", null, "foo", domains);
+ Mockito.verify(impl).authenticateUser("steve", null, "foo", domains, false);
}
String id1 = info.getSessionId();
14 years, 5 months
teiid SVN: r2373 - in trunk: connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver and 21 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-07-26 10:17:53 -0400 (Mon, 26 Jul 2010)
New Revision: 2373
Added:
trunk/engine/src/main/java/org/teiid/query/metadata/CompositeMetadataStore.java
trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
trunk/engine/src/test/java/org/teiid/query/metadata/
trunk/metadata/src/main/java/org/teiid/metadata/VdbConstants.java
Removed:
trunk/engine/src/main/java/org/teiid/metadata/
trunk/engine/src/test/java/org/teiid/metadata/
Modified:
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/RuntimeMetadataImpl.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.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/PlanToProcessConverter.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java
trunk/engine/src/test/java/org/teiid/query/metadata/TestTransformationMetadata.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestDependentJoins.java
trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTextTable.java
trunk/engine/src/test/java/org/teiid/query/unittest/FakeMetadataFactory.java
trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
trunk/metadata/src/main/java/org/teiid/metadata/index/IndexMetadataFactory.java
trunk/metadata/src/test/java/org/teiid/metadata/index/TestMultipleModelIndexes.java
trunk/metadata/src/test/java/org/teiid/metadata/index/VDBMetadataFactory.java
trunk/runtime/src/main/java/org/teiid/deployers/CompositeVDB.java
trunk/runtime/src/main/java/org/teiid/deployers/VDBDeployer.java
trunk/runtime/src/main/java/org/teiid/deployers/VDBRepository.java
trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/BaseQueryTest.java
trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestXMLTypeTranslations.java
Log:
TEIID-1167 adding primary key metadata TEIID-1166 fixing assertion error
Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -36,12 +36,12 @@
import org.teiid.dqp.internal.datamgr.FakeExecutionContextImpl;
import org.teiid.language.Command;
import org.teiid.metadata.Column;
-import org.teiid.metadata.CompositeMetadataStore;
import org.teiid.metadata.MetadataStore;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
+import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.FakeMetadataFactory;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.TranslatorException;
Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -30,12 +30,12 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.language.Command;
import org.teiid.metadata.Column;
-import org.teiid.metadata.CompositeMetadataStore;
import org.teiid.metadata.MetadataStore;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
+import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.jdbc.TranslationHelper;
Modified: trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
===================================================================
--- trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -39,14 +39,14 @@
import org.teiid.language.Command;
import org.teiid.language.Select;
import org.teiid.metadata.Column;
-import org.teiid.metadata.CompositeMetadataStore;
import org.teiid.metadata.MetadataStore;
import org.teiid.metadata.RuntimeMetadata;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.metadata.Column.SearchType;
+import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.ldap.IQueryToLdapSearchParser;
Modified: trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java
===================================================================
--- trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -31,13 +31,13 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.language.Select;
import org.teiid.metadata.Column;
-import org.teiid.metadata.CompositeMetadataStore;
import org.teiid.metadata.MetadataStore;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.metadata.Column.SearchType;
+import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.salesforce.execution.visitors.JoinQueryVisitor;
import org.teiid.translator.salesforce.execution.visitors.SelectVisitor;
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/RuntimeMetadataImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/RuntimeMetadataImpl.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/RuntimeMetadataImpl.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -27,9 +27,12 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.util.ArgCheck;
-import org.teiid.metadata.*;
-import org.teiid.query.metadata.QueryMetadataInterface;
-import org.teiid.query.metadata.StoredProcedureInfo;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.Procedure;
+import org.teiid.metadata.ProcedureParameter;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.metadata.Table;
+import org.teiid.query.metadata.*;
import org.teiid.query.sql.lang.SPParameter;
import org.teiid.translator.TranslatorException;
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -60,7 +60,6 @@
import org.teiid.language.SQLConstants.Reserved;
import org.teiid.metadata.AbstractMetadataRecord;
import org.teiid.metadata.Column;
-import org.teiid.metadata.CompositeMetadataStore;
import org.teiid.metadata.Datatype;
import org.teiid.metadata.ForeignKey;
import org.teiid.metadata.KeyRecord;
@@ -68,7 +67,8 @@
import org.teiid.metadata.ProcedureParameter;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
+import org.teiid.query.metadata.CompositeMetadataStore;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.processor.CollectionTupleSource;
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.processor.QueryProcessor;
Copied: trunk/engine/src/main/java/org/teiid/query/metadata/CompositeMetadataStore.java (from rev 2371, trunk/engine/src/main/java/org/teiid/metadata/CompositeMetadataStore.java)
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/CompositeMetadataStore.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/CompositeMetadataStore.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -0,0 +1,145 @@
+/*
+ * 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.metadata;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.teiid.api.exception.query.QueryMetadataException;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.metadata.MetadataStore;
+import org.teiid.metadata.Procedure;
+import org.teiid.metadata.Schema;
+import org.teiid.metadata.Table;
+import org.teiid.metadata.Table.Type;
+
+
+/**
+ * Aggregates the metadata from multiple stores.
+ * IMPORTANT: All strings queries should be in lower case.
+ */
+public class CompositeMetadataStore extends MetadataStore {
+
+
+ public CompositeMetadataStore(MetadataStore metadataStore) {
+ addMetadataStore(metadataStore);
+ }
+
+ public CompositeMetadataStore(List<MetadataStore> metadataStores) {
+ for (MetadataStore metadataStore : metadataStores) {
+ addMetadataStore(metadataStore);
+ }
+ }
+
+ public void addMetadataStore(MetadataStore metadataStore) {
+ this.schemas.putAll(metadataStore.getSchemas());
+ this.datatypes.addAll(metadataStore.getDatatypes());
+ }
+
+ public Schema getSchema(String fullName)
+ throws QueryMetadataException {
+ Schema result = getSchemas().get(fullName);
+ if (result == null) {
+ throw new QueryMetadataException(fullName+TransformationMetadata.NOT_EXISTS_MESSAGE);
+ }
+ return result;
+ }
+
+ public Table findGroup(String fullName)
+ throws QueryMetadataException {
+ int index = fullName.indexOf(TransformationMetadata.DELIMITER_STRING);
+ if (index == -1) {
+ throw new QueryMetadataException(fullName+TransformationMetadata.NOT_EXISTS_MESSAGE);
+ }
+ String schema = fullName.substring(0, index);
+ Table result = getSchema(schema).getTables().get(fullName.substring(index + 1));
+ if (result == null) {
+ throw new QueryMetadataException(fullName+TransformationMetadata.NOT_EXISTS_MESSAGE);
+ }
+ return result;
+ }
+
+ /**
+ * TODO: this resolving mode allows partial matches of a full group name containing .
+ * @param partialGroupName
+ * @return
+ */
+ public Collection<Table> getGroupsForPartialName(String partialGroupName) {
+ List<Table> result = new LinkedList<Table>();
+ for (Schema schema : getSchemas().values()) {
+ for (Table t : schema.getTables().values()) {
+ String fullName = t.getFullName();
+ if (fullName.regionMatches(true, fullName.length() - partialGroupName.length(), partialGroupName, 0, partialGroupName.length())) {
+ result.add(t);
+ }
+ }
+ }
+ return result;
+ }
+
+ public Collection<Procedure> getStoredProcedure(String name)
+ throws TeiidComponentException, QueryMetadataException {
+ List<Procedure> result = new LinkedList<Procedure>();
+ int index = name.indexOf(TransformationMetadata.DELIMITER_STRING);
+ if (index > -1) {
+ String schema = name.substring(0, index);
+ Procedure proc = getSchema(schema).getProcedures().get(name.substring(index + 1));
+ if (proc != null) {
+ result.add(proc);
+ return result;
+ }
+ }
+ //assume it's a partial name
+ name = TransformationMetadata.DELIMITER_STRING + name;
+ for (Schema schema : getSchemas().values()) {
+ for (Procedure p : schema.getProcedures().values()) {
+ String fullName = p.getFullName();
+ if (fullName.regionMatches(true, fullName.length() - name.length(), name, 0, name.length())) {
+ result.add(p);
+ }
+ }
+ }
+ if (result.isEmpty()) {
+ throw new QueryMetadataException(name.substring(1)+TransformationMetadata.NOT_EXISTS_MESSAGE);
+ }
+ return result;
+ }
+
+ /*
+ * The next method is a hold over from XML/UUID resolving and will perform poorly
+ */
+
+ public Collection<Table> getXMLTempGroups(Table tableRecord) {
+ ArrayList<Table> results = new ArrayList<Table>();
+ String namePrefix = tableRecord.getFullName() + TransformationMetadata.DELIMITER_STRING;
+ for (Table table : tableRecord.getParent().getTables().values()) {
+ if (table.getTableType() == Type.XmlStagingTable && table.getName().startsWith(namePrefix)) {
+ results.add(table);
+ }
+ }
+ return results;
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/metadata/CompositeMetadataStore.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -23,6 +23,7 @@
package org.teiid.query.metadata;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -371,7 +372,11 @@
throws TeiidComponentException, QueryMetadataException {
if(groupID instanceof TempMetadataID) {
- return Collections.EMPTY_LIST;
+ TempMetadataID id = (TempMetadataID)groupID;
+ if (id.getPrimaryKey() == null) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(groupID);
}
return this.actualMetadata.getUniqueKeysInGroup(groupID);
}
@@ -396,6 +401,10 @@
public List getElementIDsInKey(Object keyID)
throws TeiidComponentException, QueryMetadataException {
+ if (keyID instanceof TempMetadataID) {
+ return ((TempMetadataID)keyID).getPrimaryKey();
+ }
+
return this.actualMetadata.getElementIDsInKey(keyID);
}
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -51,6 +51,7 @@
private int cardinality = QueryMetadataInterface.UNKNOWN_CARDINALITY;
private LRUCache localCache;
private boolean scalarGroup;
+ private List<TempMetadataID> primaryKey;
/**
* Constructor for group form of metadata ID.
@@ -58,8 +59,7 @@
* @param elements List of TempMetadataID representing elements
*/
public TempMetadataID(String ID, List<TempMetadataID> elements) {
- this.ID = ID;
- this.elements = elements;
+ this(ID, elements, true, false);
}
/**
@@ -246,5 +246,13 @@
public void setScalarGroup(boolean scalarGroup) {
this.scalarGroup = scalarGroup;
}
+
+ public List<TempMetadataID> getPrimaryKey() {
+ return primaryKey;
+ }
+
+ public void setPrimaryKey(List<TempMetadataID> primaryKey) {
+ this.primaryKey = primaryKey;
+ }
}
Copied: trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java (from rev 2371, trunk/engine/src/main/java/org/teiid/metadata/TransformationMetadata.java)
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -0,0 +1,1070 @@
+/*
+ * 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.metadata;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.jboss.virtual.VirtualFile;
+import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.api.exception.query.QueryMetadataException;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.types.BlobImpl;
+import org.teiid.core.types.ClobImpl;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.types.InputStreamFactory;
+import org.teiid.core.types.SQLXMLImpl;
+import org.teiid.core.util.ArgCheck;
+import org.teiid.core.util.LRUCache;
+import org.teiid.core.util.ObjectConverterUtil;
+import org.teiid.core.util.StringUtil;
+import org.teiid.dqp.DQPPlugin;
+import org.teiid.metadata.AbstractMetadataRecord;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.ColumnSet;
+import org.teiid.metadata.Datatype;
+import org.teiid.metadata.ForeignKey;
+import org.teiid.metadata.KeyRecord;
+import org.teiid.metadata.Procedure;
+import org.teiid.metadata.ProcedureParameter;
+import org.teiid.metadata.Schema;
+import org.teiid.metadata.Table;
+import org.teiid.metadata.BaseColumn.NullType;
+import org.teiid.metadata.Column.SearchType;
+import org.teiid.metadata.ProcedureParameter.Type;
+import org.teiid.query.QueryPlugin;
+import org.teiid.query.function.FunctionLibrary;
+import org.teiid.query.function.FunctionTree;
+import org.teiid.query.function.SystemFunctionManager;
+import org.teiid.query.function.UDFSource;
+import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.query.mapping.relational.QueryNode;
+import org.teiid.query.mapping.xml.MappingDocument;
+import org.teiid.query.mapping.xml.MappingLoader;
+import org.teiid.query.mapping.xml.MappingNode;
+import org.teiid.query.sql.lang.SPParameter;
+
+
+/**
+ * Teiid's implementation of the QueryMetadataInterface that reads columns, groups, models etc.
+ * from the metadata object model.
+ */
+public class TransformationMetadata extends BasicQueryMetadata implements Serializable {
+
+ private final class VirtualFileInputStreamFactory extends
+ InputStreamFactory {
+ private final VirtualFile f;
+
+ private VirtualFileInputStreamFactory(VirtualFile f) {
+ this.f = f;
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return f.openStream();
+ }
+
+ @Override
+ public long getLength() {
+ try {
+ return f.getSize();
+ } catch (IOException e) {
+ }
+ return super.getLength();
+ }
+
+ @Override
+ public void free() throws IOException {
+ f.close();
+ }
+ }
+
+ public static class Resource {
+ public Resource(VirtualFile file, boolean visible) {
+ this.file = file;
+ this.visible = visible;
+ }
+ VirtualFile file;
+ boolean visible;
+ }
+
+ private static final long serialVersionUID = 1058627332954475287L;
+
+ /** Delimiter character used when specifying fully qualified entity names */
+ public static final char DELIMITER_CHAR = StringUtil.Constants.DOT_CHAR;
+ public static final String DELIMITER_STRING = String.valueOf(DELIMITER_CHAR);
+
+ // error message cached to avoid i18n lookup each time
+ public static String NOT_EXISTS_MESSAGE = StringUtil.Constants.SPACE+DQPPlugin.Util.getString("TransformationMetadata.does_not_exist._1"); //$NON-NLS-1$
+
+ private static Properties EMPTY_PROPS = new Properties();
+
+ private final CompositeMetadataStore store;
+ private Map<String, Resource> vdbEntries;
+ private FunctionLibrary functionLibrary;
+ private VDBMetaData vdbMetaData;
+
+ /*
+ * TODO: move caching to jboss cache structure
+ */
+ private final Map<String, Object> metadataCache = Collections.synchronizedMap(new LRUCache<String, Object>(250));
+ private final Map<String, Object> groupInfoCache = Collections.synchronizedMap(new LRUCache<String, Object>(250));
+ private final Map<String, Collection<Table>> partialNameToFullNameCache = Collections.synchronizedMap(new LRUCache<String, Collection<Table>>(1000));
+ private final Map<String, Collection<StoredProcedureInfo>> procedureCache = Collections.synchronizedMap(new LRUCache<String, Collection<StoredProcedureInfo>>(200));
+ /**
+ * TransformationMetadata constructor
+ * @param context Object containing the info needed to lookup metadta.
+ */
+ public TransformationMetadata(VDBMetaData vdbMetadata, final CompositeMetadataStore store, Map<String, Resource> vdbEntries, Collection <FunctionMethod> udfMethods) {
+ ArgCheck.isNotNull(store);
+ this.vdbMetaData = vdbMetadata;
+ this.store = store;
+ if (vdbEntries == null) {
+ this.vdbEntries = Collections.emptyMap();
+ } else {
+ this.vdbEntries = vdbEntries;
+ }
+ if (udfMethods == null) {
+ udfMethods = Collections.emptyList();
+ }
+ this.functionLibrary = new FunctionLibrary(SystemFunctionManager.getSystemFunctions(), new FunctionTree(new UDFSource(udfMethods)));
+ }
+
+ //==================================================================================
+ // I N T E R F A C E M E T H O D S
+ //==================================================================================
+
+ public Object getElementID(final String elementName) throws TeiidComponentException, QueryMetadataException {
+ int columnIndex = elementName.lastIndexOf(TransformationMetadata.DELIMITER_STRING);
+ if (columnIndex == -1) {
+ throw new QueryMetadataException(elementName+TransformationMetadata.NOT_EXISTS_MESSAGE);
+ }
+ Table table = this.store.findGroup(elementName.substring(0, columnIndex));
+ String shortElementName = elementName.substring(columnIndex + 1);
+ for (Column column : (List<Column>)getElementIDsInGroupID(table)) {
+ if (column.getName().equalsIgnoreCase(shortElementName)) {
+ return column;
+ }
+ }
+ throw new QueryMetadataException(elementName+TransformationMetadata.NOT_EXISTS_MESSAGE);
+ }
+
+ public Object getGroupID(final String groupName) throws TeiidComponentException, QueryMetadataException {
+ return getMetadataStore().findGroup(groupName.toLowerCase());
+ }
+
+ public Collection getGroupsForPartialName(final String partialGroupName)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isNotEmpty(partialGroupName);
+
+ Collection<Table> matches = this.partialNameToFullNameCache.get(partialGroupName);
+
+ if (matches == null) {
+ String partialName = DELIMITER_CHAR + partialGroupName.toLowerCase();
+
+ matches = getMetadataStore().getGroupsForPartialName(partialName);
+
+ this.partialNameToFullNameCache.put(partialGroupName, matches);
+ }
+
+ if (matches.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ Collection<String> filteredResult = new ArrayList<String>(matches.size());
+ for (Table table : matches) {
+ if (vdbMetaData == null || vdbMetaData.getModel(table.getParent().getName()).isVisible()) {
+ filteredResult.add(table.getFullName());
+ }
+ }
+ return filteredResult;
+ }
+
+ public Object getModelID(final Object groupOrElementID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(AbstractMetadataRecord.class, groupOrElementID);
+ AbstractMetadataRecord metadataRecord = (AbstractMetadataRecord) groupOrElementID;
+ AbstractMetadataRecord parent = metadataRecord.getParent();
+ if (parent instanceof Schema) {
+ return parent;
+ }
+ if (parent == null) {
+ throw createInvalidRecordTypeException(groupOrElementID);
+ }
+ parent = metadataRecord.getParent();
+ if (parent instanceof Schema) {
+ return parent;
+ }
+ throw createInvalidRecordTypeException(groupOrElementID);
+ }
+
+ public String getFullName(final Object metadataID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
+ AbstractMetadataRecord metadataRecord = (AbstractMetadataRecord) metadataID;
+ return metadataRecord.getFullName();
+ }
+
+ public String getFullElementName(final String fullGroupName, final String shortElementName)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isNotEmpty(fullGroupName);
+ ArgCheck.isNotEmpty(shortElementName);
+
+ return fullGroupName + DELIMITER_CHAR + shortElementName;
+ }
+
+ public String getShortElementName(final String fullElementName) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isNotEmpty(fullElementName);
+ int index = fullElementName.lastIndexOf(DELIMITER_CHAR);
+ if(index >= 0) {
+ return fullElementName.substring(index+1);
+ }
+ return fullElementName;
+ }
+
+ /**
+ * Return the text portion of the fullElementName representing a group.
+ * That means that this should only return text that is part of the
+ * fullElementName and not look up new IDs or do much of anything fancy.
+ * This method is used by the resolver to decide which portion of a fully-
+ * qualified element name is the group name. It will compare whatever comes
+ * back with the actual group names and aliases in the query, which is
+ * why it is important not to introduce new metadata here. Also, returning
+ * null indicates that no portion of the fullElementName is a
+ * group name - that is ok as it will be resolved as an ambiguous element.
+ * @see org.teiid.query.metadata.QueryMetadataInterface#getGroupName(java.lang.String)
+ */
+ public String getGroupName(final String fullElementName) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isNotEmpty(fullElementName);
+
+ int index = fullElementName.lastIndexOf(DELIMITER_CHAR);
+ if(index >= 0) {
+ return fullElementName.substring(0, index);
+ }
+ return null;
+ }
+
+ public List getElementIDsInGroupID(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ return ((Table)groupID).getColumns();
+ }
+
+ public Object getGroupIDForElementID(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ Column columnRecord = (Column) elementID;
+ return this.getGroupID(getGroupName(columnRecord.getFullName()));
+ } else if(elementID instanceof ProcedureParameter){
+ ProcedureParameter columnRecord = (ProcedureParameter) elementID;
+ return this.getGroupID(getGroupName(columnRecord.getFullName()));
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public StoredProcedureInfo getStoredProcedureInfoForProcedure(final String fullyQualifiedProcedureName)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isNotEmpty(fullyQualifiedProcedureName);
+ String lowerGroupName = fullyQualifiedProcedureName.toLowerCase();
+ Collection<StoredProcedureInfo> results = this.procedureCache.get(lowerGroupName);
+
+ if (results == null) {
+ Collection<Procedure> procRecords = getMetadataStore().getStoredProcedure(lowerGroupName);
+ results = new ArrayList<StoredProcedureInfo>(procRecords.size());
+ for (Procedure procRecord : procRecords) {
+ String procedureFullName = procRecord.getFullName();
+
+ // create the storedProcedure info object that would hold procedure's metadata
+ StoredProcedureInfo procInfo = new StoredProcedureInfo();
+ procInfo.setProcedureCallableName(procedureFullName);
+ procInfo.setProcedureID(procRecord);
+
+ // modelID for the procedure
+ procInfo.setModelID(procRecord.getParent());
+
+ // get the parameter metadata info
+ for (ProcedureParameter paramRecord : procRecord.getParameters()) {
+ String runtimeType = paramRecord.getRuntimeType();
+ int direction = this.convertParamRecordTypeToStoredProcedureType(paramRecord.getType());
+ // create a parameter and add it to the procedure object
+ SPParameter spParam = new SPParameter(paramRecord.getPosition(), direction, paramRecord.getFullName());
+ spParam.setMetadataID(paramRecord);
+ spParam.setClassType(DataTypeManager.getDataTypeClass(runtimeType));
+ procInfo.addParameter(spParam);
+ }
+
+ // if the procedure returns a resultSet, obtain resultSet metadata
+ if(procRecord.getResultSet() != null) {
+ ColumnSet<Procedure> resultRecord = procRecord.getResultSet();
+ // resultSet is the last parameter in the procedure
+ int lastParamIndex = procInfo.getParameters().size() + 1;
+ SPParameter param = new SPParameter(lastParamIndex, SPParameter.RESULT_SET, resultRecord.getFullName());
+ param.setClassType(java.sql.ResultSet.class);
+ param.setMetadataID(resultRecord);
+
+ for (Column columnRecord : resultRecord.getColumns()) {
+ String colType = columnRecord.getRuntimeType();
+ param.addResultSetColumn(columnRecord.getFullName(), DataTypeManager.getDataTypeClass(colType), columnRecord);
+ }
+
+ procInfo.addParameter(param);
+ }
+
+ // if this is a virtual procedure get the procedure plan
+ if(procRecord.isVirtual()) {
+ QueryNode queryNode = new QueryNode(procedureFullName, procRecord.getQueryPlan());
+ procInfo.setQueryPlan(queryNode);
+ }
+
+ //subtract 1, to match up with the server
+ procInfo.setUpdateCount(procRecord.getUpdateCount() -1);
+ results.add(procInfo);
+ }
+ this.procedureCache.put(lowerGroupName, results);
+ }
+
+ StoredProcedureInfo result = null;
+
+ for (StoredProcedureInfo storedProcedureInfo : results) {
+ Schema schema = (Schema)storedProcedureInfo.getModelID();
+ if(vdbMetaData == null || vdbMetaData.getModel(schema.getName()).isVisible()){
+ if (result != null) {
+ throw new QueryMetadataException(QueryPlugin.Util.getString("ambiguous_procedure", fullyQualifiedProcedureName)); //$NON-NLS-1$
+ }
+ result = storedProcedureInfo;
+ }
+ }
+
+ if (result == null) {
+ throw new QueryMetadataException(fullyQualifiedProcedureName+NOT_EXISTS_MESSAGE);
+ }
+
+ return result;
+ }
+
+ /**
+ * Method to convert the parameter type returned from a ProcedureParameterRecord
+ * to the parameter type expected by StoredProcedureInfo
+ * @param parameterType
+ * @return
+ */
+ private int convertParamRecordTypeToStoredProcedureType(final ProcedureParameter.Type parameterType) {
+ switch (parameterType) {
+ case In : return SPParameter.IN;
+ case Out : return SPParameter.OUT;
+ case InOut : return SPParameter.INOUT;
+ case ReturnValue : return SPParameter.RETURN_VALUE;
+ default :
+ return -1;
+ }
+ }
+
+ public String getElementType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getRuntimeType();
+ } else if(elementID instanceof ProcedureParameter){
+ return ((ProcedureParameter) elementID).getRuntimeType();
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public Object getDefaultValue(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getDefaultValue();
+ } else if(elementID instanceof ProcedureParameter){
+ return ((ProcedureParameter) elementID).getDefaultValue();
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public Object getMinimumValue(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getMinimumValue();
+ } else if(elementID instanceof ProcedureParameter){
+ return null;
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public Object getMaximumValue(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getMaximumValue();
+ } else if(elementID instanceof ProcedureParameter){
+ return null;
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public boolean isVirtualGroup(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ return ((Table) groupID).isVirtual();
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#isProcedureInputElement(java.lang.Object)
+ * @since 4.2
+ */
+ public boolean isProcedure(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ if(groupID instanceof Procedure) {
+ return true;
+ }
+ if(groupID instanceof Table){
+ return false;
+ }
+ throw createInvalidRecordTypeException(groupID);
+ }
+
+ public boolean isVirtualModel(final Object modelID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Schema.class, modelID);
+ Schema modelRecord = (Schema) modelID;
+ return !modelRecord.isPhysical();
+ }
+
+ public QueryNode getVirtualPlan(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+
+ Table tableRecord = (Table) groupID;
+ if (!tableRecord.isVirtual()) {
+ throw new QueryMetadataException(DQPPlugin.Util.getString("TransformationMetadata.QueryPlan_could_not_be_found_for_physical_group__6")+tableRecord.getFullName()); //$NON-NLS-1$
+ }
+ String transQuery = tableRecord.getSelectTransformation();
+ QueryNode queryNode = new QueryNode(tableRecord.getFullName(), transQuery);
+
+ // get any bindings and add them onto the query node
+ List bindings = tableRecord.getBindings();
+ if(bindings != null) {
+ for(Iterator bindIter = bindings.iterator();bindIter.hasNext();) {
+ queryNode.addBinding((String)bindIter.next());
+ }
+ }
+
+ return queryNode;
+ }
+
+ public String getInsertPlan(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecordImpl = (Table)groupID;
+ if (!tableRecordImpl.isVirtual()) {
+ throw new QueryMetadataException(DQPPlugin.Util.getString("TransformationMetadata.InsertPlan_could_not_be_found_for_physical_group__8")+tableRecordImpl.getFullName()); //$NON-NLS-1$
+ }
+ return ((Table)groupID).getInsertPlan();
+ }
+
+ public String getUpdatePlan(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecordImpl = (Table)groupID;
+ if (!tableRecordImpl.isVirtual()) {
+ throw new QueryMetadataException(DQPPlugin.Util.getString("TransformationMetadata.InsertPlan_could_not_be_found_for_physical_group__10")+tableRecordImpl.getFullName()); //$NON-NLS-1$
+ }
+ return ((Table)groupID).getUpdatePlan();
+ }
+
+ public String getDeletePlan(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecordImpl = (Table)groupID;
+ if (!tableRecordImpl.isVirtual()) {
+ throw new QueryMetadataException(DQPPlugin.Util.getString("TransformationMetadata.DeletePlan_could_not_be_found_for_physical_group__12")+tableRecordImpl.getFullName()); //$NON-NLS-1$
+ }
+ return ((Table)groupID).getDeletePlan();
+ }
+
+ public boolean modelSupports(final Object modelID, final int modelConstant)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Schema.class, modelID);
+
+ switch(modelConstant) {
+ default:
+ throw new UnsupportedOperationException(DQPPlugin.Util.getString("TransformationMetadata.Unknown_support_constant___12") + modelConstant); //$NON-NLS-1$
+ }
+ }
+
+ public boolean groupSupports(final Object groupID, final int groupConstant)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecord = (Table) groupID;
+
+ switch(groupConstant) {
+ case SupportConstants.Group.UPDATE:
+ return tableRecord.supportsUpdate();
+ default:
+ throw new UnsupportedOperationException(DQPPlugin.Util.getString("TransformationMetadata.Unknown_support_constant___12") + groupConstant); //$NON-NLS-1$
+ }
+ }
+
+ public boolean elementSupports(final Object elementID, final int elementConstant)
+ throws TeiidComponentException, QueryMetadataException {
+
+ if(elementID instanceof Column) {
+ Column columnRecord = (Column) elementID;
+ switch(elementConstant) {
+ case SupportConstants.Element.NULL:
+ return columnRecord.getNullType() == NullType.Nullable;
+ case SupportConstants.Element.NULL_UNKNOWN:
+ return columnRecord.getNullType() == NullType.Unknown;
+ case SupportConstants.Element.SEARCHABLE_COMPARE:
+ return (columnRecord.getSearchType() == SearchType.Searchable || columnRecord.getSearchType() == SearchType.All_Except_Like);
+ case SupportConstants.Element.SEARCHABLE_LIKE:
+ return (columnRecord.getSearchType() == SearchType.Searchable || columnRecord.getSearchType() == SearchType.Like_Only);
+ case SupportConstants.Element.SELECT:
+ return columnRecord.isSelectable();
+ case SupportConstants.Element.UPDATE:
+ return columnRecord.isUpdatable();
+ case SupportConstants.Element.DEFAULT_VALUE:
+ Object defaultValue = columnRecord.getDefaultValue();
+ if(defaultValue == null) {
+ return false;
+ }
+ return true;
+ case SupportConstants.Element.AUTO_INCREMENT:
+ return columnRecord.isAutoIncremented();
+ case SupportConstants.Element.CASE_SENSITIVE:
+ return columnRecord.isCaseSensitive();
+ case SupportConstants.Element.SIGNED:
+ return columnRecord.isSigned();
+ default:
+ throw new UnsupportedOperationException(DQPPlugin.Util.getString("TransformationMetadata.Unknown_support_constant___12") + elementConstant); //$NON-NLS-1$
+ }
+ } else if(elementID instanceof ProcedureParameter) {
+ ProcedureParameter columnRecord = (ProcedureParameter) elementID;
+ switch(elementConstant) {
+ case SupportConstants.Element.NULL:
+ return columnRecord.getNullType() == NullType.Nullable;
+ case SupportConstants.Element.NULL_UNKNOWN:
+ return columnRecord.getNullType() == NullType.Unknown;
+ case SupportConstants.Element.SEARCHABLE_COMPARE:
+ case SupportConstants.Element.SEARCHABLE_LIKE:
+ return false;
+ case SupportConstants.Element.SELECT:
+ return columnRecord.getType() != Type.In;
+ case SupportConstants.Element.UPDATE:
+ return false;
+ case SupportConstants.Element.DEFAULT_VALUE:
+ Object defaultValue = columnRecord.getDefaultValue();
+ if(defaultValue == null) {
+ return false;
+ }
+ return true;
+ case SupportConstants.Element.AUTO_INCREMENT:
+ return false;
+ case SupportConstants.Element.CASE_SENSITIVE:
+ return false;
+ case SupportConstants.Element.SIGNED:
+ return true;
+ default:
+ throw new UnsupportedOperationException(DQPPlugin.Util.getString("TransformationMetadata.Unknown_support_constant___12") + elementConstant); //$NON-NLS-1$
+ }
+
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ private IllegalArgumentException createInvalidRecordTypeException(Object elementID) {
+ return new IllegalArgumentException(DQPPlugin.Util.getString("TransformationMetadata.Invalid_type", elementID.getClass().getName())); //$NON-NLS-1$
+ }
+
+ public int getMaxSetSize(final Object modelID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Schema.class, modelID);
+ return 0;
+ }
+
+ public Collection getIndexesInGroup(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ return ((Table)groupID).getIndexes();
+ }
+
+ public Collection getUniqueKeysInGroup(final Object groupID)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecordImpl = (Table)groupID;
+ ArrayList<ColumnSet> result = new ArrayList<ColumnSet>(tableRecordImpl.getUniqueKeys());
+ if (tableRecordImpl.getPrimaryKey() != null) {
+ result.add(tableRecordImpl.getPrimaryKey());
+ }
+ for (KeyRecord key : tableRecordImpl.getIndexes()) {
+ if (key.getType() == KeyRecord.Type.Index) {
+ result.add(key);
+ }
+ }
+ return result;
+ }
+
+ public Collection getForeignKeysInGroup(final Object groupID)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ return ((Table)groupID).getForeignKeys();
+ }
+
+ public Object getPrimaryKeyIDForForeignKeyID(final Object foreignKeyID)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(ForeignKey.class, foreignKeyID);
+ ForeignKey fkRecord = (ForeignKey) foreignKeyID;
+ return fkRecord.getPrimaryKey();
+ }
+
+ public Collection getAccessPatternsInGroup(final Object groupID)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ return ((Table)groupID).getAccessPatterns();
+ }
+
+ public List getElementIDsInIndex(final Object index) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(ColumnSet.class, index);
+ return ((ColumnSet)index).getColumns();
+ }
+
+ public List getElementIDsInKey(final Object key) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(ColumnSet.class, key);
+ return ((ColumnSet)key).getColumns();
+ }
+
+ public List getElementIDsInAccessPattern(final Object accessPattern)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(ColumnSet.class, accessPattern);
+ return ((ColumnSet)accessPattern).getColumns();
+ }
+
+ public boolean isXMLGroup(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+
+ Table tableRecord = (Table) groupID;
+ return tableRecord.getTableType() == Table.Type.Document;
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#hasMaterialization(java.lang.Object)
+ * @since 4.2
+ */
+ public boolean hasMaterialization(final Object groupID) throws TeiidComponentException,
+ QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecord = (Table) groupID;
+ return tableRecord.isMaterialized();
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#getMaterialization(java.lang.Object)
+ * @since 4.2
+ */
+ public Object getMaterialization(final Object groupID) throws TeiidComponentException,
+ QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecord = (Table) groupID;
+ if(tableRecord.isMaterialized()) {
+ return tableRecord.getMaterializedTable();
+ }
+ return null;
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#getMaterializationStage(java.lang.Object)
+ * @since 4.2
+ */
+ public Object getMaterializationStage(final Object groupID) throws TeiidComponentException,
+ QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecord = (Table) groupID;
+ if(tableRecord.isMaterialized()) {
+ return tableRecord.getMaterializedStageTable();
+ }
+ return null;
+ }
+
+ public MappingNode getMappingNode(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+
+ Table tableRecord = (Table) groupID;
+ final String groupName = tableRecord.getFullName();
+ if(tableRecord.isVirtual()) {
+ // get mappin transform
+ String document = tableRecord.getSelectTransformation();
+ InputStream inputStream = new ByteArrayInputStream(document.getBytes());
+ MappingLoader reader = new MappingLoader();
+ MappingDocument mappingDoc = null;
+ try{
+ mappingDoc = reader.loadDocument(inputStream);
+ mappingDoc.setName(groupName);
+ } catch (Exception e){
+ throw new TeiidComponentException(e, DQPPlugin.Util.getString("TransformationMetadata.Error_trying_to_read_virtual_document_{0},_with_body__n{1}_1", groupName, mappingDoc)); //$NON-NLS-1$
+ } finally {
+ try {
+ inputStream.close();
+ } catch(Exception e) {}
+ }
+ return (MappingDocument)mappingDoc.clone();
+ }
+
+ return null;
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#getVirtualDatabaseName()
+ */
+ public String getVirtualDatabaseName() throws TeiidComponentException, QueryMetadataException {
+ if (vdbMetaData == null) {
+ return null;
+ }
+ return vdbMetaData.getName();
+ }
+
+ public int getVirtualDatabaseVersion() {
+ if (vdbMetaData == null) {
+ return 0;
+ }
+ return vdbMetaData.getVersion();
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#getXMLTempGroups(java.lang.Object)
+ */
+ public Collection getXMLTempGroups(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecord = (Table) groupID;
+
+ if(tableRecord.getTableType() == Table.Type.Document) {
+ return this.store.getXMLTempGroups(tableRecord);
+ }
+ return Collections.EMPTY_SET;
+ }
+
+ public int getCardinality(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ return ((Table) groupID).getCardinality();
+ }
+
+ public List<SQLXMLImpl> getXMLSchemas(final Object groupID) throws TeiidComponentException, QueryMetadataException {
+
+ ArgCheck.isInstanceOf(Table.class, groupID);
+ Table tableRecord = (Table) groupID;
+
+ // lookup transformation record for the group
+ String groupName = tableRecord.getFullName();
+
+ // get the schema Paths
+ List<String> schemaPaths = tableRecord.getSchemaPaths();
+
+ List<SQLXMLImpl> schemas = new LinkedList<SQLXMLImpl>();
+ if (schemaPaths == null) {
+ return schemas;
+ }
+ File f = new File(tableRecord.getResourcePath());
+ String path = f.getParent();
+ if (File.separatorChar != '/') {
+ path = path.replace(File.separatorChar, '/');
+ }
+ for (String string : schemaPaths) {
+ SQLXMLImpl schema = getVDBResourceAsSQLXML(string);
+
+ if (schema == null) {
+ schema = getVDBResourceAsSQLXML(path + '/' + string);
+ }
+
+ if (schema == null) {
+ throw new TeiidComponentException(DQPPlugin.Util.getString("TransformationMetadata.Error_trying_to_read_schemas_for_the_document/table____1")+groupName); //$NON-NLS-1$
+ }
+ schemas.add(schema);
+ }
+
+ return schemas;
+ }
+
+ public String getNameInSource(final Object metadataID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
+ return ((AbstractMetadataRecord) metadataID).getNameInSource();
+ }
+
+ public int getElementLength(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getLength();
+ } else if(elementID instanceof ProcedureParameter){
+ return ((ProcedureParameter) elementID).getLength();
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public int getPosition(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getPosition();
+ } else if(elementID instanceof ProcedureParameter) {
+ return ((ProcedureParameter) elementID).getPosition();
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public int getPrecision(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getPrecision();
+ } else if(elementID instanceof ProcedureParameter) {
+ return ((ProcedureParameter) elementID).getPrecision();
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public int getRadix(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getRadix();
+ } else if(elementID instanceof ProcedureParameter) {
+ return ((ProcedureParameter) elementID).getRadix();
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public String getFormat(Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getFormat();
+ }
+ throw createInvalidRecordTypeException(elementID);
+ }
+
+ public int getScale(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getScale();
+ } else if(elementID instanceof ProcedureParameter) {
+ return ((ProcedureParameter) elementID).getScale();
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public int getDistinctValues(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getDistinctValues();
+ } else if(elementID instanceof ProcedureParameter) {
+ return -1;
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public int getNullValues(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getNullValues();
+ } else if(elementID instanceof ProcedureParameter) {
+ return -1;
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public String getNativeType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ if(elementID instanceof Column) {
+ return ((Column) elementID).getNativeType();
+ } else if(elementID instanceof ProcedureParameter) {
+ return null;
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ public Properties getExtensionProperties(final Object metadataID) throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
+ AbstractMetadataRecord metadataRecord = (AbstractMetadataRecord) metadataID;
+ Map<String, String> result = metadataRecord.getProperties();
+ if (result == null) {
+ return EMPTY_PROPS;
+ }
+ Properties p = new Properties();
+ p.putAll(result);
+ return p;
+ }
+
+ /**
+ * @see org.teiid.query.metadata.BasicQueryMetadata#getBinaryVDBResource(java.lang.String)
+ * @since 4.3
+ */
+ public byte[] getBinaryVDBResource(String resourcePath) throws TeiidComponentException, QueryMetadataException {
+ final VirtualFile f = getFile(resourcePath);
+ if (f == null) {
+ return null;
+ }
+ try {
+ return ObjectConverterUtil.convertToByteArray(f.openStream());
+ } catch (IOException e) {
+ throw new TeiidComponentException(e);
+ }
+ }
+
+ public ClobImpl getVDBResourceAsClob(String resourcePath) {
+ final VirtualFile f = getFile(resourcePath);
+ if (f == null) {
+ return null;
+ }
+ return new ClobImpl(new VirtualFileInputStreamFactory(f), -1);
+ }
+
+ public SQLXMLImpl getVDBResourceAsSQLXML(String resourcePath) {
+ final VirtualFile f = getFile(resourcePath);
+ if (f == null) {
+ return null;
+ }
+ return new SQLXMLImpl(new VirtualFileInputStreamFactory(f));
+ }
+
+ public BlobImpl getVDBResourceAsBlob(String resourcePath) {
+ final VirtualFile f = getFile(resourcePath);
+ if (f == null) {
+ return null;
+ }
+ return new BlobImpl(new VirtualFileInputStreamFactory(f));
+ }
+
+ private VirtualFile getFile(String resourcePath) {
+ if (resourcePath == null) {
+ return null;
+ }
+ Resource r = this.vdbEntries.get(resourcePath);
+ if (r != null && r.visible) {
+ return r.file;
+ }
+ return null;
+ }
+
+ /**
+ * @see org.teiid.query.metadata.BasicQueryMetadata#getCharacterVDBResource(java.lang.String)
+ * @since 4.3
+ */
+ public String getCharacterVDBResource(String resourcePath) throws TeiidComponentException, QueryMetadataException {
+ try {
+ byte[] bytes = getBinaryVDBResource(resourcePath);
+ if (bytes == null) {
+ return null;
+ }
+ return ObjectConverterUtil.convertToString(new ByteArrayInputStream(bytes));
+ } catch (IOException e) {
+ throw new TeiidComponentException(e);
+ }
+ }
+
+ public CompositeMetadataStore getMetadataStore() {
+ return this.store;
+ }
+
+ /**
+ * @see org.teiid.query.metadata.BasicQueryMetadata#getVDBResourcePaths()
+ * @since 4.3
+ */
+ public String[] getVDBResourcePaths() throws TeiidComponentException, QueryMetadataException {
+ LinkedList<String> paths = new LinkedList<String>();
+ for (Map.Entry<String, Resource> entry : this.vdbEntries.entrySet()) {
+ if (entry.getValue().visible) {
+ paths.add(entry.getKey());
+ }
+ }
+ return paths.toArray(new String[paths.size()]);
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#getModeledType(java.lang.Object)
+ * @since 5.0
+ */
+ public String getModeledType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ Datatype record = getDatatypeRecord(elementID);
+ if (record != null) {
+ return record.getDatatypeID();
+ }
+ return null;
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#getModeledBaseType(java.lang.Object)
+ * @since 5.0
+ */
+ public String getModeledBaseType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ Datatype record = getDatatypeRecord(elementID);
+ if (record != null) {
+ return record.getBasetypeID();
+ }
+ return null;
+ }
+
+ /**
+ * @see org.teiid.query.metadata.QueryMetadataInterface#getModeledPrimitiveType(java.lang.Object)
+ * @since 5.0
+ */
+ public String getModeledPrimitiveType(final Object elementID) throws TeiidComponentException, QueryMetadataException {
+ Datatype record = getDatatypeRecord(elementID);
+ if (record != null) {
+ return record.getPrimitiveTypeID();
+ }
+ return null;
+ }
+
+ private Datatype getDatatypeRecord(final Object elementID) {
+ if (elementID instanceof Column) {
+ return ((Column)elementID).getDatatype();
+ } else if (elementID instanceof ProcedureParameter) {
+ return ((ProcedureParameter)elementID).getDatatype();
+ } else {
+ throw createInvalidRecordTypeException(elementID);
+ }
+ }
+
+ @Override
+ public Object addToMetadataCache(Object metadataID, String key, Object value)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
+ boolean groupInfo = key.startsWith(GroupInfo.CACHE_PREFIX);
+ key = getCacheKey(key, (AbstractMetadataRecord)metadataID);
+ if (groupInfo) {
+ return this.groupInfoCache.put(key, value);
+ }
+ return this.metadataCache.put(key, value);
+ }
+
+ @Override
+ public Object getFromMetadataCache(Object metadataID, String key)
+ throws TeiidComponentException, QueryMetadataException {
+ ArgCheck.isInstanceOf(AbstractMetadataRecord.class, metadataID);
+ boolean groupInfo = key.startsWith(GroupInfo.CACHE_PREFIX);
+ key = getCacheKey(key, (AbstractMetadataRecord)metadataID);
+ if (groupInfo) {
+ return this.groupInfoCache.get(key);
+ }
+ return this.metadataCache.get(key);
+ }
+
+ private String getCacheKey(String key, AbstractMetadataRecord record) {
+ return record.getUUID() + "/" + key; //$NON-NLS-1$
+ }
+
+ @Override
+ public FunctionLibrary getFunctionLibrary() {
+ return this.functionLibrary;
+ }
+}
\ No newline at end of file
Property changes on: trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -36,6 +36,7 @@
import org.teiid.core.id.IntegerID;
import org.teiid.core.id.IntegerIDFactory;
import org.teiid.core.util.Assertion;
+import org.teiid.language.TableReference;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.execution.QueryExecPlugin;
import org.teiid.query.metadata.QueryMetadataInterface;
@@ -83,6 +84,7 @@
import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.StoredProcedure;
+import org.teiid.query.sql.lang.TableFunctionReference;
import org.teiid.query.sql.lang.TextTable;
import org.teiid.query.sql.lang.XMLTable;
import org.teiid.query.sql.lang.SetQuery.Operation;
@@ -90,6 +92,7 @@
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.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.sql.visitor.EvaluatableVisitor;
import org.teiid.query.sql.visitor.GroupCollectorVisitor;
@@ -377,6 +380,7 @@
XMLTableNode xtn = new XMLTableNode(getID());
//we handle the projection filtering once here rather than repeating the
//path analysis on a per plan basis
+ updateGroupName(node, xt);
Map elementMap = RelationalNode.createLookupMap(xt.getProjectedSymbols());
List cols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols);
@@ -392,7 +396,9 @@
}
if (source instanceof TextTable) {
TextTableNode ttn = new TextTableNode(getID());
- ttn.setTable((TextTable)source);
+ TextTable tt = (TextTable)source;
+ updateGroupName(node, tt);
+ ttn.setTable(tt);
processNode = ttn;
break;
}
@@ -447,6 +453,14 @@
return processNode;
}
+ private void updateGroupName(PlanNode node, TableFunctionReference tt) {
+ String groupName = node.getGroups().iterator().next().getName();
+ tt.getGroupSymbol().setName(groupName);
+ for (ElementSymbol symbol : tt.getProjectedSymbols()) {
+ symbol.setName(groupName + SingleElementSymbol.SEPARATOR + symbol.getShortName());
+ }
+ }
+
private RelationalNode correctProjectionInternalTables(PlanNode node,
AccessNode aNode, Query query) throws QueryMetadataException,
TeiidComponentException {
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -22,6 +22,7 @@
package org.teiid.query.resolver.command;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -77,15 +78,25 @@
//if we get here then either the group does not exist or has already been defined as a temp table
//if it has been defined as a temp table, that's ok we'll use this as the new definition and throw an
//exception at runtime if the user has not dropped the previous table yet
- ResolverUtil.addTempTable(metadata, group, create.getColumns());
-
- ResolverUtil.resolveGroup(((Create)command).getTable(), metadata);
+ TempMetadataID tempTable = ResolverUtil.addTempTable(metadata, group, create.getColumns());
+ ResolverUtil.resolveGroup(create.getTable(), metadata);
Set<GroupSymbol> groups = new HashSet<GroupSymbol>();
- groups.add(((Create)command).getTable());
+ groups.add(create.getTable());
ResolverVisitor.resolveLanguageObject(command, groups, metadata);
+ addPrimaryKey(create, tempTable);
} else if(command.getType() == Command.TYPE_DROP) {
ResolverUtil.resolveGroup(((Drop)command).getTable(), metadata);
}
}
+ public static void addPrimaryKey(Create create, TempMetadataID tempTable) {
+ if (!create.getPrimaryKey().isEmpty()) {
+ ArrayList<TempMetadataID> primaryKey = new ArrayList<TempMetadataID>(create.getPrimaryKey().size());
+ for (ElementSymbol symbol : create.getPrimaryKey()) {
+ primaryKey.add((TempMetadataID) symbol.getMetadataID());
+ }
+ tempTable.setPrimaryKey(primaryKey);
+ }
+ }
+
}
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 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -631,10 +631,10 @@
return store.addTempGroup(symbol.getName(), symbols, !tempTable, tempTable);
}
- public static void addTempTable(TempMetadataAdapter metadata,
+ public static TempMetadataID addTempTable(TempMetadataAdapter metadata,
GroupSymbol symbol,
List symbols) throws QueryResolverException {
- addTempGroup(metadata, symbol, symbols, true);
+ return addTempGroup(metadata, symbol, symbols, true);
}
/**
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -38,8 +38,10 @@
import org.teiid.core.TeiidProcessingException;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.execution.QueryExecPlugin;
+import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.processor.CollectionTupleSource;
+import org.teiid.query.resolver.command.TempTableResolver;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.Create;
import org.teiid.query.sql.lang.Criteria;
@@ -91,7 +93,8 @@
columns.addAll(0, primaryKey);
}
//add metadata
- tempMetadataStore.addTempGroup(tempTableName, columns, false, true);
+ TempMetadataID id = tempMetadataStore.addTempGroup(tempTableName, columns, false, true);
+ TempTableResolver.addPrimaryKey(create, id);
TempTable tempTable = new TempTable(buffer, columns, create.getPrimaryKey().size(), sessionID);
groupToTupleSourceID.put(tempTableName, tempTable);
}
Copied: trunk/engine/src/test/java/org/teiid/query/metadata (from rev 2371, trunk/engine/src/test/java/org/teiid/metadata)
Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestTransformationMetadata.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/metadata/TestTransformationMetadata.java 2010-07-23 21:44:19 UTC (rev 2371)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestTransformationMetadata.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -20,7 +20,7 @@
* 02110-1301 USA.
*/
-package org.teiid.metadata;
+package org.teiid.query.metadata;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@@ -39,6 +39,8 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.metadata.Datatype;
import org.teiid.metadata.MetadataFactory;
+import org.teiid.query.metadata.CompositeMetadataStore;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.FakeMetadataFactory;
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestDependentJoins.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestDependentJoins.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestDependentJoins.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -29,8 +29,8 @@
import junit.framework.TestCase;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -358,7 +358,17 @@
process(sql, expected);
}
+
+ @Test public void testXmlTableSubquery() throws Exception {
+ String sql = "select * from xmltable('/a/b' passing convert('<a><b>first</b><b x=\"attr\">c</b></a>', xml) columns x string path '@x', val string path '/.') as x where val = (select max(e1) from pm1.g1 as x)";
+
+ List[] expected = new List[] {
+ Arrays.asList("attr", "c"),
+ };
+ process(sql, expected);
+ }
+
private static FakeDataManager dataManager = new FakeDataManager();
@BeforeClass public static void oneTimeSetUp() {
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -22,7 +22,10 @@
package org.teiid.query.processor;
+import static org.junit.Assert.*;
+
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import org.junit.Before;
@@ -33,15 +36,19 @@
import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.unittest.FakeMetadataFactory;
-
+@SuppressWarnings("nls")
public class TestTempTables {
private TempMetadataAdapter metadata;
private TempTableDataManager dataManager;
private void execute(String sql, List[] expectedResults) throws Exception {
- TestProcessor.doProcess(TestProcessor.helpGetPlan(sql, metadata), dataManager, expectedResults, TestProcessor.createCommandContext());
+ execute(expectedResults, TestProcessor.helpGetPlan(sql, metadata));
}
+
+ private void execute(List[] expectedResults, ProcessorPlan processorPlan) throws Exception {
+ TestProcessor.doProcess(processorPlan, dataManager, expectedResults, TestProcessor.createCommandContext());
+ }
@Before public void setUp() {
TempTableStore tempStore = new TempTableStore(BufferManagerFactory.getStandaloneBufferManager(), "1", null); //$NON-NLS-1$
@@ -122,4 +129,11 @@
execute("select count(*) from x", new List[] {Arrays.asList(2)}); //$NON-NLS-1$
}
+ @Test public void testPrimaryKeyMetadata() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key (e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ Collection c = metadata.getUniqueKeysInGroup(metadata.getGroupID("x"));
+ assertEquals(1, c.size());
+ assertEquals(1, (metadata.getElementIDsInKey(c.iterator().next()).size()));
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTextTable.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTextTable.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTextTable.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -185,7 +185,19 @@
process(sql, expected);
}
+
+ @Test public void testTextTableSubquery() throws Exception {
+ String sql = "select x.* from pm1.g1, texttable(e1 || ',' || e2 COLUMNS x string, y integer) x where y < (select avg(e2) from pm1.g1 as x)";
+
+ List[] expected = new List[] {
+ Arrays.asList("a", 0),
+ Arrays.asList("c", 1),
+ Arrays.asList("a", 0),
+ };
+ process(sql, expected);
+ }
+
public static void process(String sql, List[] expectedResults) throws Exception {
FakeDataManager dataManager = new FakeDataManager();
sampleData1(dataManager);
Modified: trunk/engine/src/test/java/org/teiid/query/unittest/FakeMetadataFactory.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/unittest/FakeMetadataFactory.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/test/java/org/teiid/query/unittest/FakeMetadataFactory.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -39,16 +39,16 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.dqp.internal.process.DQPWorkContext;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.query.mapping.relational.QueryNode;
import org.teiid.query.mapping.xml.MappingAttribute;
import org.teiid.query.mapping.xml.MappingDocument;
import org.teiid.query.mapping.xml.MappingElement;
import org.teiid.query.mapping.xml.MappingSequenceNode;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.sql.symbol.ElementSymbol;
-
+@SuppressWarnings("nls")
public class FakeMetadataFactory {
private static FakeMetadataFacade CACHED_EXAMPLE1 = example1();
Modified: trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -32,17 +32,17 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.metadata.Column;
import org.teiid.metadata.ColumnSet;
-import org.teiid.metadata.CompositeMetadataStore;
import org.teiid.metadata.MetadataStore;
import org.teiid.metadata.Procedure;
import org.teiid.metadata.ProcedureParameter;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.metadata.BaseColumn.NullType;
import org.teiid.metadata.Column.SearchType;
import org.teiid.metadata.ProcedureParameter.Type;
import org.teiid.query.mapping.relational.QueryNode;
+import org.teiid.query.metadata.CompositeMetadataStore;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.sql.lang.SPParameter;
Copied: trunk/metadata/src/main/java/org/teiid/metadata/VdbConstants.java (from rev 2371, trunk/engine/src/main/java/org/teiid/metadata/VdbConstants.java)
===================================================================
--- trunk/metadata/src/main/java/org/teiid/metadata/VdbConstants.java (rev 0)
+++ trunk/metadata/src/main/java/org/teiid/metadata/VdbConstants.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.metadata;
+
+
+
+/**
+ * Constants used for VDB processing.
+ */
+public interface VdbConstants {
+
+ public static final String DEPLOYMENT_FILE = "vdb.xml"; // !!! DO NOT CHANGE VALUE as this would cause problems with existing VDBs having DEF files !!! //$NON-NLS-1$
+ public static final String VDB_ARCHIVE_EXTENSION = ".vdb"; //$NON-NLS-1$
+ public final static String INDEX_EXT = ".INDEX"; //$NON-NLS-1$
+ public final static String SEARCH_INDEX_EXT = ".SEARCH_INDEX"; //$NON-NLS-1$
+ public final static String MODEL_EXT = ".xmi"; //$NON-NLS-1$
+}
Modified: trunk/metadata/src/main/java/org/teiid/metadata/index/IndexMetadataFactory.java
===================================================================
--- trunk/metadata/src/main/java/org/teiid/metadata/index/IndexMetadataFactory.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/metadata/src/main/java/org/teiid/metadata/index/IndexMetadataFactory.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -62,9 +62,9 @@
import org.teiid.metadata.ProcedureParameter;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.metadata.VdbConstants;
-import org.teiid.metadata.TransformationMetadata.Resource;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.metadata.TransformationMetadata.Resource;
/**
Modified: trunk/metadata/src/test/java/org/teiid/metadata/index/TestMultipleModelIndexes.java
===================================================================
--- trunk/metadata/src/test/java/org/teiid/metadata/index/TestMultipleModelIndexes.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/metadata/src/test/java/org/teiid/metadata/index/TestMultipleModelIndexes.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -29,7 +29,7 @@
import org.junit.Test;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.metadata.Table;
-import org.teiid.metadata.TransformationMetadata;
+import org.teiid.query.metadata.TransformationMetadata;
@SuppressWarnings("nls")
public class TestMultipleModelIndexes {
Modified: trunk/metadata/src/test/java/org/teiid/metadata/index/VDBMetadataFactory.java
===================================================================
--- trunk/metadata/src/test/java/org/teiid/metadata/index/VDBMetadataFactory.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/metadata/src/test/java/org/teiid/metadata/index/VDBMetadataFactory.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -38,11 +38,11 @@
import org.teiid.core.util.FileUtils;
import org.teiid.core.util.LRUCache;
import org.teiid.core.util.UnitTestUtil;
-import org.teiid.metadata.CompositeMetadataStore;
import org.teiid.metadata.MetadataStore;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.query.function.metadata.FunctionMetadataReader;
import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.query.metadata.CompositeMetadataStore;
+import org.teiid.query.metadata.TransformationMetadata;
@SuppressWarnings("nls")
Modified: trunk/runtime/src/main/java/org/teiid/deployers/CompositeVDB.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/deployers/CompositeVDB.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/runtime/src/main/java/org/teiid/deployers/CompositeVDB.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -29,12 +29,12 @@
import org.teiid.adminapi.impl.DataPolicyMetadata;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.VDBMetaData;
-import org.teiid.metadata.CompositeMetadataStore;
import org.teiid.metadata.MetadataStore;
-import org.teiid.metadata.TransformationMetadata;
-import org.teiid.metadata.TransformationMetadata.Resource;
import org.teiid.query.function.metadata.FunctionMethod;
+import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.metadata.TransformationMetadata.Resource;
import org.teiid.vdb.runtime.VDBKey;
Modified: trunk/runtime/src/main/java/org/teiid/deployers/VDBDeployer.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/deployers/VDBDeployer.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/runtime/src/main/java/org/teiid/deployers/VDBDeployer.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -47,8 +47,8 @@
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.metadata.MetadataStore;
-import org.teiid.metadata.TransformationMetadata.Resource;
import org.teiid.metadata.index.IndexMetadataFactory;
+import org.teiid.query.metadata.TransformationMetadata.Resource;
import org.teiid.runtime.RuntimePlugin;
import org.teiid.translator.ExecutionFactory;
import org.teiid.translator.TranslatorException;
Modified: trunk/runtime/src/main/java/org/teiid/deployers/VDBRepository.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/deployers/VDBRepository.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/runtime/src/main/java/org/teiid/deployers/VDBRepository.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -45,7 +45,7 @@
import org.teiid.metadata.Datatype;
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.MetadataStore;
-import org.teiid.metadata.TransformationMetadata.Resource;
+import org.teiid.query.metadata.TransformationMetadata.Resource;
import org.teiid.runtime.RuntimePlugin;
import org.teiid.translator.TranslatorException;
import org.teiid.vdb.runtime.VDBKey;
Modified: trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/BaseQueryTest.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/BaseQueryTest.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/BaseQueryTest.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -26,10 +26,10 @@
import junit.framework.TestCase;
import org.teiid.dqp.message.RequestID;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.metadata.index.VDBMetadataFactory;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.optimizer.QueryOptimizer;
import org.teiid.query.optimizer.TestOptimizer;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
Modified: trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestXMLTypeTranslations.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestXMLTypeTranslations.java 2010-07-24 03:25:41 UTC (rev 2372)
+++ trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestXMLTypeTranslations.java 2010-07-26 14:17:53 UTC (rev 2373)
@@ -35,8 +35,8 @@
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.dqp.message.RequestID;
-import org.teiid.metadata.TransformationMetadata;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
14 years, 5 months
teiid SVN: r2372 - in trunk: engine/src/main/java/org/teiid/dqp/internal and 7 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-07-23 23:25:41 -0400 (Fri, 23 Jul 2010)
New Revision: 2372
Added:
trunk/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/TransactionServerImpl.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestAuthorizationValidationVisitor.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestTransactionServer.java
Removed:
trunk/engine/src/main/java/org/teiid/dqp/internal/process/validator/
trunk/engine/src/main/java/org/teiid/dqp/internal/transaction/
trunk/engine/src/test/java/org/teiid/dqp/internal/process/validator/
trunk/engine/src/test/java/org/teiid/dqp/internal/transaction/
Modified:
trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
trunk/engine/src/test/java/org/teiid/common/queue/TestThreadReuseExecutor.java
trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/FakeTransactionService.java
trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java
Log:
TEIID-1167 removing unnecessary buffering and minor repackaging
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/STree.java 2010-07-23 21:44:19 UTC (rev 2371)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/STree.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -334,6 +334,24 @@
}
}
}
+
+ /**
+ * Perform an in-place update of the tuple just returned by the next method
+ * WARNING - this must not change the key value
+ * @param tuple
+ * @throws TeiidComponentException
+ */
+ public void update(List tuple) throws TeiidComponentException {
+ values.set(index - 1, tuple);
+ page.setValues(values);
+ }
+
+ /**
+ * Notify the browser that the last value was deleted.
+ */
+ public void removed() {
+ index--;
+ }
}
public int getKeyLength() {
Copied: trunk/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java (from rev 2371, trunk/engine/src/main/java/org/teiid/dqp/internal/process/validator/AuthorizationValidationVisitor.java)
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/AuthorizationValidationVisitor.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -0,0 +1,357 @@
+/*
+ * 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.dqp.internal.process;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.teiid.adminapi.DataPolicy;
+import org.teiid.adminapi.impl.DataPolicyMetadata;
+import org.teiid.adminapi.impl.ModelMetaData;
+import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.api.exception.query.QueryMetadataException;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.dqp.DQPPlugin;
+import org.teiid.dqp.internal.process.multisource.MultiSourceElement;
+import org.teiid.logging.AuditMessage;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.logging.MessageLevel;
+import org.teiid.query.function.FunctionLibrary;
+import org.teiid.query.metadata.TempMetadataID;
+import org.teiid.query.resolver.util.ResolverUtil;
+import org.teiid.query.sql.lang.Delete;
+import org.teiid.query.sql.lang.Insert;
+import org.teiid.query.sql.lang.Into;
+import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.StoredProcedure;
+import org.teiid.query.sql.lang.Update;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Function;
+import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.Symbol;
+import org.teiid.query.sql.visitor.ElementCollectorVisitor;
+import org.teiid.query.sql.visitor.GroupCollectorVisitor;
+import org.teiid.query.validator.AbstractValidationVisitor;
+
+
+public class AuthorizationValidationVisitor extends AbstractValidationVisitor {
+
+ public enum Context {
+ QUERY,
+ INSERT,
+ UPDATE,
+ DELETE,
+ STORED_PROCEDURE;
+ }
+
+ private VDBMetaData vdb;
+ private HashMap<String, DataPolicy> allowedPolicies;
+ private String userName;
+ private boolean useEntitlements;
+
+ public AuthorizationValidationVisitor(VDBMetaData vdb, boolean useEntitlements, HashMap<String, DataPolicy> policies, String user) {
+ this.vdb = vdb;
+ this.allowedPolicies = policies;
+ this.userName = user;
+ this.useEntitlements = useEntitlements;
+ }
+
+ // ############### Visitor methods for language objects ##################
+
+ @Override
+ public void visit(GroupSymbol obj) {
+ try {
+ Object modelID = getMetadata().getModelID(obj.getMetadataID());
+ this.validateModelVisibility(modelID, obj);
+ } catch(QueryMetadataException e) {
+ handleException(e, obj);
+ } catch(TeiidComponentException e) {
+ handleException(e, obj);
+ }
+ }
+
+ public void visit(Delete obj) {
+ validateEntitlements(obj);
+ }
+
+ public void visit(Insert obj) {
+ validateEntitlements(obj);
+ }
+
+ public void visit(Query obj) {
+ validateEntitlements(obj);
+ }
+
+ public void visit(Update obj) {
+ validateEntitlements(obj);
+ }
+
+ public void visit(StoredProcedure obj) {
+ this.validateModelVisibility(obj.getModelID(), obj.getGroup());
+ validateEntitlements(obj);
+ }
+
+ public void visit(Function obj) {
+ if (FunctionLibrary.LOOKUP.equalsIgnoreCase(obj.getName())) {
+ try {
+ ResolverUtil.ResolvedLookup lookup = ResolverUtil.resolveLookup(obj, this.getMetadata());
+ validateModelVisibility(getMetadata().getModelID(lookup.getGroup().getMetadataID()), lookup.getGroup());
+ List<Symbol> symbols = new LinkedList<Symbol>();
+ symbols.add(lookup.getGroup());
+ symbols.add(lookup.getKeyElement());
+ symbols.add(lookup.getReturnElement());
+ validateEntitlements(symbols, DataPolicy.PermissionType.READ, Context.QUERY);
+ } catch (TeiidComponentException e) {
+ handleException(e, obj);
+ } catch (TeiidProcessingException e) {
+ handleException(e, obj);
+ }
+ }
+ }
+
+ // ######################### Validation methods #########################
+
+ /**
+ * Validate insert entitlements
+ */
+ protected void validateEntitlements(Insert obj) {
+ validateEntitlements(
+ obj.getVariables(),
+ DataPolicy.PermissionType.CREATE,
+ Context.INSERT);
+ }
+
+ /**
+ * Validate update entitlements
+ */
+ protected void validateEntitlements(Update obj) {
+ // Check that all elements used in criteria have read permission
+ if (obj.getCriteria() != null) {
+ validateEntitlements(
+ ElementCollectorVisitor.getElements(obj.getCriteria(), true),
+ DataPolicy.PermissionType.READ,
+ Context.UPDATE);
+ }
+
+ // The variables from the changes must be checked for UPDATE entitlement
+ // validateEntitlements on all the variables used in the update.
+ validateEntitlements(obj.getChangeList().getClauseMap().keySet(), DataPolicy.PermissionType.UPDATE, Context.UPDATE);
+ }
+
+ /**
+ * Validate delete entitlements
+ */
+ protected void validateEntitlements(Delete obj) {
+ // Check that all elements used in criteria have read permission
+ if (obj.getCriteria() != null) {
+ validateEntitlements(
+ ElementCollectorVisitor.getElements(obj.getCriteria(), true),
+ DataPolicy.PermissionType.READ,
+ Context.DELETE);
+ }
+
+ // Check that all elements of group being deleted have delete permission
+ HashSet deleteVars = new HashSet();
+ deleteVars.add(obj.getGroup());
+ validateEntitlements(deleteVars, DataPolicy.PermissionType.DELETE, Context.DELETE);
+ }
+
+ /**
+ * Validate query entitlements
+ */
+ protected void validateEntitlements(Query obj) {
+ // If query contains SELECT INTO, validate INTO portion
+ Into intoObj = obj.getInto();
+ if ( intoObj != null ) {
+ GroupSymbol intoGroup = intoObj.getGroup();
+ List intoElements = null;
+ try {
+ intoElements = ResolverUtil.resolveElementsInGroup(intoGroup, getMetadata());
+ } catch (QueryMetadataException err) {
+ handleException(err, intoGroup);
+ } catch (TeiidComponentException err) {
+ handleException(err, intoGroup);
+ }
+ validateEntitlements(intoElements,
+ DataPolicy.PermissionType.CREATE,
+ Context.INSERT);
+ }
+
+ // Validate this query's entitlements
+ Collection entitledObjects = GroupCollectorVisitor.getGroups(obj, true);
+ if (!isXMLCommand(obj)) {
+ entitledObjects.addAll(ElementCollectorVisitor.getElements(obj, true));
+ }
+
+ if(entitledObjects.size() == 0) {
+ return;
+ }
+
+ validateEntitlements(entitledObjects, DataPolicy.PermissionType.READ, Context.QUERY);
+ }
+
+ /**
+ * Validate query entitlements
+ */
+ protected void validateEntitlements(StoredProcedure obj) {
+ List symbols = new ArrayList(1);
+ symbols.add(obj.getGroup());
+ validateEntitlements(symbols, DataPolicy.PermissionType.READ, Context.STORED_PROCEDURE);
+ }
+
+ private String getActionLabel(DataPolicy.PermissionType actionCode) {
+ switch(actionCode) {
+ case READ: return "Read"; //$NON-NLS-1$
+ case CREATE: return "Create"; //$NON-NLS-1$
+ case UPDATE: return "Update"; //$NON-NLS-1$
+ case DELETE: return "Delete"; //$NON-NLS-1$
+ default: return "UNKNOWN"; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Check that the user is entitled to access all data elements in the command.
+ *
+ * @param symbols The collection of <code>Symbol</code>s affected by these actions.
+ * @param actionCode The actions to validate for
+ * @param auditContext The {@link AuthorizationService} to use when resource auditing is done.
+ */
+ protected void validateEntitlements(Collection symbols, DataPolicy.PermissionType actionCode, Context auditContext) {
+ Map nameToSymbolMap = new HashMap();
+ Iterator symbolIter = symbols.iterator();
+ while(symbolIter.hasNext()) {
+ Object symbol = symbolIter.next();
+ try {
+ String fullName = null;
+ Object metadataID = null;
+ if(symbol instanceof ElementSymbol) {
+ metadataID = ((ElementSymbol)symbol).getMetadataID();
+ if (metadataID instanceof MultiSourceElement || metadataID instanceof TempMetadataID) {
+ continue;
+ }
+ } else if(symbol instanceof GroupSymbol) {
+ GroupSymbol group = (GroupSymbol)symbol;
+ metadataID = group.getMetadataID();
+ if (metadataID instanceof TempMetadataID && !group.isProcedure()) {
+ continue;
+ }
+ }
+ fullName = getMetadata().getFullName(metadataID);
+ nameToSymbolMap.put(fullName, symbol);
+ } catch(QueryMetadataException e) {
+ handleException(e);
+ } catch(TeiidComponentException e) {
+ handleException(e);
+ }
+ }
+
+ if (!nameToSymbolMap.isEmpty()) {
+ Collection inaccessibleResources = getInaccessibleResources(actionCode, nameToSymbolMap.keySet(), auditContext);
+ if(inaccessibleResources.size() > 0) {
+ List inaccessibleSymbols = new ArrayList(inaccessibleResources.size());
+ Iterator nameIter = inaccessibleResources.iterator();
+ while(nameIter.hasNext()) {
+ String name = (String) nameIter.next();
+ inaccessibleSymbols.add(nameToSymbolMap.get(name));
+ }
+
+ // CASE 2362 - do not include the names of the elements for which the user
+ // is not authorized in the exception message
+
+ handleValidationError(
+ DQPPlugin.Util.getString("ERR.018.005.0095", new Object[]{DQPWorkContext.getWorkContext().getSessionId(), getActionLabel(actionCode)}), //$NON-NLS-1$
+ inaccessibleSymbols);
+ }
+ }
+
+ }
+
+ protected void validateModelVisibility(Object modelID, GroupSymbol group) {
+ if(modelID instanceof TempMetadataID){
+ return;
+ }
+ try {
+ String modelName = getMetadata().getFullName(modelID);
+ ModelMetaData model = vdb.getModel(modelName);
+ if(!model.isVisible()) {
+ handleValidationError(DQPPlugin.Util.getString("ERR.018.005.0088", getMetadata().getFullName(group.getMetadataID()))); //$NON-NLS-1$
+ }
+ } catch (TeiidComponentException e) {
+ handleException(e, group);
+ }
+ }
+
+
+ /**
+ * Out of resources specified, return the subset for which the specified not have authorization to access.
+ */
+ public Set<String> getInaccessibleResources(DataPolicy.PermissionType action, Set<String> resources, Context context) {
+ if (!this.useEntitlements) {
+ return Collections.emptySet();
+ }
+
+ if (LogManager.isMessageToBeRecorded(LogConstants.CTX_AUDITLOGGING, MessageLevel.DETAIL)) {
+ // Audit - request
+ AuditMessage msg = new AuditMessage(context.name(), "getInaccessibleResources-request", this.userName, resources.toArray(new String[resources.size()])); //$NON-NLS-1$
+ LogManager.logDetail(LogConstants.CTX_AUDITLOGGING, msg);
+ }
+
+ HashSet<String> results = new HashSet<String>(resources);
+
+ for(DataPolicy p:this.allowedPolicies.values()) {
+ DataPolicyMetadata policy = (DataPolicyMetadata)p;
+
+ if (results.isEmpty()) {
+ break;
+ }
+
+ Iterator<String> i = results.iterator();
+ while (i.hasNext()) {
+ if (policy.allows(i.next(), action)) {
+ i.remove();
+ }
+ }
+ }
+
+ if (LogManager.isMessageToBeRecorded(LogConstants.CTX_AUDITLOGGING, MessageLevel.DETAIL)) {
+ if (results.isEmpty()) {
+ AuditMessage msg = new AuditMessage(context.name(), "getInaccessibleResources-granted all", this.userName, resources.toArray(new String[resources.size()])); //$NON-NLS-1$
+ LogManager.logDetail(LogConstants.CTX_AUDITLOGGING, msg);
+ } else {
+ AuditMessage msg = new AuditMessage(context.name(), "getInaccessibleResources-denied", this.userName, resources.toArray(new String[resources.size()])); //$NON-NLS-1$
+ LogManager.logDetail(LogConstants.CTX_AUDITLOGGING, msg);
+ }
+ }
+ return results;
+ }
+}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2010-07-23 21:44:19 UTC (rev 2371)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -49,7 +49,6 @@
import org.teiid.dqp.internal.process.multisource.MultiSourceCapabilitiesFinder;
import org.teiid.dqp.internal.process.multisource.MultiSourceMetadataWrapper;
import org.teiid.dqp.internal.process.multisource.MultiSourcePlanToProcessConverter;
-import org.teiid.dqp.internal.process.validator.AuthorizationValidationVisitor;
import org.teiid.dqp.message.RequestID;
import org.teiid.dqp.service.TransactionContext;
import org.teiid.dqp.service.TransactionService;
Copied: trunk/engine/src/main/java/org/teiid/dqp/internal/process/TransactionServerImpl.java (from rev 2371, trunk/engine/src/main/java/org/teiid/dqp/internal/transaction/TransactionServerImpl.java)
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/TransactionServerImpl.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/TransactionServerImpl.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -0,0 +1,541 @@
+/*
+ * 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.dqp.internal.process;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+
+import javax.resource.NotSupportedException;
+import javax.resource.spi.XATerminator;
+import javax.resource.spi.work.WorkException;
+import javax.resource.spi.work.WorkManager;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.teiid.adminapi.AdminException;
+import org.teiid.adminapi.AdminProcessingException;
+import org.teiid.adminapi.impl.TransactionMetadata;
+import org.teiid.client.xa.XATransactionException;
+import org.teiid.client.xa.XidImpl;
+import org.teiid.core.util.Assertion;
+import org.teiid.dqp.DQPPlugin;
+import org.teiid.dqp.internal.process.DQPCore.FutureWork;
+import org.teiid.dqp.service.TransactionContext;
+import org.teiid.dqp.service.TransactionService;
+import org.teiid.dqp.service.TransactionContext.Scope;
+
+
+public class TransactionServerImpl implements TransactionService {
+
+ private static class TransactionMapping {
+
+ // (connection -> transaction for global and local)
+ private Map<String, TransactionContext> threadToTransactionContext = new HashMap<String, TransactionContext>();
+ // (MMXid -> global transactions keyed)
+ private Map<Xid, TransactionContext> xidToTransactionContext = new HashMap<Xid, TransactionContext>();
+
+ public synchronized TransactionContext getOrCreateTransactionContext(String threadId) {
+ TransactionContext tc = threadToTransactionContext.get(threadId);
+
+ if (tc == null) {
+ tc = new TransactionContext();
+ tc.setThreadId(threadId);
+ threadToTransactionContext.put(threadId, tc);
+ }
+
+ return tc;
+ }
+
+ public synchronized TransactionContext getTransactionContext(String threadId) {
+ return threadToTransactionContext.get(threadId);
+ }
+
+ public synchronized TransactionContext getTransactionContext(XidImpl xid) {
+ return xidToTransactionContext.get(xid);
+ }
+
+ public synchronized TransactionContext removeTransactionContext(String threadId) {
+ return threadToTransactionContext.remove(threadId);
+ }
+
+ public synchronized void removeTransactionContext(TransactionContext tc) {
+ if (tc.getXid() != null) {
+ this.xidToTransactionContext.remove(tc.getXid());
+ }
+ if (tc.getThreadId() != null) {
+ this.threadToTransactionContext.remove(tc.getThreadId());
+ }
+ }
+
+ public synchronized void addTransactionContext(TransactionContext tc) {
+ if (tc.getXid() != null) {
+ this.xidToTransactionContext.put(tc.getXid(), tc);
+ }
+ if (tc.getThreadId() != null) {
+ this.threadToTransactionContext.put(tc.getThreadId(), tc);
+ }
+ }
+ }
+
+ private TransactionMapping transactions = new TransactionMapping();
+
+ private XATerminator xaTerminator;
+ private TransactionManager transactionManager;
+ private WorkManager workManager;
+
+ public void setXaTerminator(XATerminator xaTerminator) {
+ this.xaTerminator = xaTerminator;
+ }
+
+ public void setTransactionManager(TransactionManager transactionManager) {
+ this.transactionManager = transactionManager;
+ }
+
+ public void setWorkManager(WorkManager workManager) {
+ this.workManager = workManager;
+ }
+
+ /**
+ * Global Transaction
+ */
+ public int prepare(final String threadId, XidImpl xid, boolean singleTM) throws XATransactionException {
+ TransactionContext tc = checkXAState(threadId, xid, true, false);
+ if (!tc.getSuspendedBy().isEmpty()) {
+ throw new XATransactionException(XAException.XAER_PROTO, DQPPlugin.Util.getString("TransactionServer.suspended_exist", xid)); //$NON-NLS-1$
+ }
+
+ // In the container this pass though
+ if (singleTM) {
+ return XAResource.XA_RDONLY;
+ }
+
+ try {
+ return this.xaTerminator.prepare(tc.getXid());
+ } catch (XAException e) {
+ throw new XATransactionException(e);
+ }
+ }
+
+ /**
+ * Global Transaction
+ */
+ public void commit(final String threadId, XidImpl xid, boolean onePhase, boolean singleTM) throws XATransactionException {
+ TransactionContext tc = checkXAState(threadId, xid, true, false);
+ try {
+ if (singleTM || (onePhase && XAResource.XA_RDONLY == prepare(threadId, xid, singleTM))) {
+ return; //nothing to do
+ }
+ //TODO: we have no way of knowing for sure if we can safely use the onephase optimization
+ this.xaTerminator.commit(tc.getXid(), false);
+ } catch (XAException e) {
+ throw new XATransactionException(e);
+ } finally {
+ this.transactions.removeTransactionContext(tc);
+ }
+ }
+
+ /**
+ * Global Transaction
+ */
+ public void rollback(final String threadId, XidImpl xid, boolean singleTM) throws XATransactionException {
+ TransactionContext tc = checkXAState(threadId, xid, true, false);
+ try {
+ // In the case of single TM, the container directly roll backs the sources.
+ if (!singleTM) {
+ this.xaTerminator.rollback(tc.getXid());
+ }
+ } catch (XAException e) {
+ throw new XATransactionException(e);
+ } finally {
+ this.transactions.removeTransactionContext(tc);
+ }
+ }
+
+ /**
+ * Global Transaction
+ */
+ public Xid[] recover(int flag, boolean singleTM) throws XATransactionException {
+ // In case of single TM, container knows this list.
+ if (singleTM) {
+ return new Xid[0];
+ }
+
+ try {
+ return this.xaTerminator.recover(flag);
+ } catch (XAException e) {
+ throw new XATransactionException(e);
+ }
+ }
+
+ /**
+ * Global Transaction
+ */
+ public void forget(final String threadId, XidImpl xid, boolean singleTM) throws XATransactionException {
+ TransactionContext tc = checkXAState(threadId, xid, true, false);
+ try {
+ if (singleTM) {
+ return;
+ }
+ this.xaTerminator.forget(xid);
+ } catch (XAException err) {
+ throw new XATransactionException(err);
+ } finally {
+ this.transactions.removeTransactionContext(tc);
+ }
+ }
+
+ /**
+ * Global Transaction
+ */
+ public void start(final String threadId, final XidImpl xid, int flags, int timeout, boolean singleTM) throws XATransactionException {
+
+ TransactionContext tc = null;
+
+ switch (flags) {
+ case XAResource.TMNOFLAGS: {
+ try {
+ checkXAState(threadId, xid, false, false);
+ tc = transactions.getOrCreateTransactionContext(threadId);
+ if (tc.getTransactionType() != TransactionContext.Scope.NONE) {
+ throw new XATransactionException(XAException.XAER_PROTO, DQPPlugin.Util.getString("TransactionServer.existing_transaction")); //$NON-NLS-1$
+ }
+ tc.setTransactionTimeout(timeout);
+ tc.setXid(xid);
+ tc.setTransactionType(TransactionContext.Scope.GLOBAL);
+ if (singleTM) {
+ tc.setTransaction(transactionManager.getTransaction());
+ assert tc.getTransaction() != null;
+ } else {
+ FutureWork<Transaction> work = new FutureWork<Transaction>(new Callable<Transaction>() {
+ @Override
+ public Transaction call() throws Exception {
+ return transactionManager.getTransaction();
+ }
+ }, 0);
+ workManager.doWork(work, WorkManager.INDEFINITE, tc, null);
+ tc.setTransaction(work.getResult().get());
+ }
+ } catch (NotSupportedException e) {
+ throw new XATransactionException(e, XAException.XAER_INVAL);
+ } catch (WorkException e) {
+ throw new XATransactionException(e, XAException.XAER_INVAL);
+ } catch (InterruptedException e) {
+ throw new XATransactionException(e, XAException.XAER_INVAL);
+ } catch (ExecutionException e) {
+ throw new XATransactionException(e, XAException.XAER_INVAL);
+ } catch (SystemException e) {
+ throw new XATransactionException(e, XAException.XAER_INVAL);
+ }
+ break;
+ }
+ case XAResource.TMJOIN:
+ case XAResource.TMRESUME: {
+ tc = checkXAState(threadId, xid, true, false);
+ TransactionContext threadContext = transactions.getOrCreateTransactionContext(threadId);
+ if (threadContext.getTransactionType() != TransactionContext.Scope.NONE) {
+ throw new XATransactionException(XAException.XAER_PROTO, DQPPlugin.Util.getString("TransactionServer.existing_transaction")); //$NON-NLS-1$
+ }
+
+ if (flags == XAResource.TMRESUME && !tc.getSuspendedBy().remove(threadId)) {
+ throw new XATransactionException(XAException.XAER_PROTO, DQPPlugin.Util.getString("TransactionServer.resume_failed", new Object[] {xid, threadId})); //$NON-NLS-1$
+ }
+ break;
+ }
+ default:
+ throw new XATransactionException(XAException.XAER_INVAL, DQPPlugin.Util.getString("TransactionServer.unknown_flags")); //$NON-NLS-1$
+ }
+
+ tc.setThreadId(threadId);
+ transactions.addTransactionContext(tc);
+ }
+
+ /**
+ * Global Transaction
+ */
+ public void end(final String threadId, XidImpl xid, int flags, boolean singleTM) throws XATransactionException {
+ TransactionContext tc = checkXAState(threadId, xid, true, true);
+ try {
+ switch (flags) {
+ case XAResource.TMSUSPEND: {
+ tc.getSuspendedBy().add(threadId);
+ break;
+ }
+ case XAResource.TMSUCCESS: {
+ //TODO: should close all statements
+ break;
+ }
+ case XAResource.TMFAIL: {
+ cancelTransactions(threadId, false);
+ break;
+ }
+ default:
+ throw new XATransactionException(XAException.XAER_INVAL, DQPPlugin.Util.getString("TransactionServer.unknown_flags")); //$NON-NLS-1$
+ }
+ } finally {
+ tc.setThreadId(null);
+ transactions.removeTransactionContext(threadId);
+ }
+ }
+
+ private TransactionContext checkXAState(final String threadId, final XidImpl xid, boolean transactionExpected, boolean threadBound) throws XATransactionException {
+ TransactionContext tc = transactions.getTransactionContext(xid);
+
+ if (transactionExpected && tc == null) {
+ throw new XATransactionException(XAException.XAER_NOTA, DQPPlugin.Util.getString("TransactionServer.no_global_transaction", xid)); //$NON-NLS-1$
+ } else if (!transactionExpected) {
+ if (tc != null) {
+ throw new XATransactionException(XAException.XAER_DUPID, DQPPlugin.Util.getString("TransactionServer.existing_global_transaction", new Object[] {xid})); //$NON-NLS-1$
+ }
+ if (!threadBound) {
+ tc = transactions.getOrCreateTransactionContext(threadId);
+ if (tc.getTransactionType() != TransactionContext.Scope.NONE) {
+ throw new XATransactionException(XAException.XAER_PROTO, DQPPlugin.Util.getString("TransactionServer.existing_transaction", new Object[] {xid, threadId})); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+
+ if (threadBound) {
+ if (!threadId.equals(tc.getThreadId())) {
+ throw new XATransactionException(XAException.XAER_PROTO, DQPPlugin.Util.getString("TransactionServer.wrong_transaction", xid)); //$NON-NLS-1$
+ }
+ } else if (tc.getThreadId() != null) {
+ throw new XATransactionException(XAException.XAER_PROTO, DQPPlugin.Util.getString("TransactionServer.concurrent_transaction", xid)); //$NON-NLS-1$
+ }
+
+ return tc;
+ }
+
+ private TransactionContext checkLocalTransactionState(String threadId, boolean transactionExpected)
+ throws XATransactionException {
+
+ final TransactionContext tc = transactions.getOrCreateTransactionContext(threadId);
+
+ try {
+ if (tc.getTransactionType() != TransactionContext.Scope.NONE) {
+ if (tc.getTransactionType() != TransactionContext.Scope.LOCAL) {
+ throw new InvalidTransactionException(DQPPlugin.Util.getString("TransactionServer.existing_transaction")); //$NON-NLS-1$
+ }
+ if (!transactionExpected) {
+ throw new InvalidTransactionException(DQPPlugin.Util.getString("TransactionServer.existing_transaction")); //$NON-NLS-1$
+ }
+ transactionManager.resume(tc.getTransaction());
+ } else if (transactionExpected) {
+ throw new InvalidTransactionException(DQPPlugin.Util.getString("TransactionServer.no_transaction", threadId)); //$NON-NLS-1$
+ }
+ } catch (InvalidTransactionException e) {
+ throw new XATransactionException(e);
+ } catch (SystemException e) {
+ throw new XATransactionException(e);
+ }
+ return tc;
+ }
+
+ private void beginDirect(TransactionContext tc) throws XATransactionException {
+ try {
+ transactionManager.begin();
+ Transaction tx = transactionManager.suspend();
+ tc.setTransaction(tx);
+ tc.setCreationTime(System.currentTimeMillis());
+ } catch (javax.transaction.NotSupportedException err) {
+ throw new XATransactionException(err);
+ } catch (SystemException err) {
+ throw new XATransactionException(err);
+ }
+ }
+
+ private void commitDirect(TransactionContext context)
+ throws XATransactionException {
+ try {
+ transactionManager.commit();
+ } catch (SecurityException e) {
+ throw new XATransactionException(e);
+ } catch (RollbackException e) {
+ throw new XATransactionException(e);
+ } catch (HeuristicMixedException e) {
+ throw new XATransactionException(e);
+ } catch (HeuristicRollbackException e) {
+ throw new XATransactionException(e);
+ } catch (SystemException e) {
+ throw new XATransactionException(e);
+ } finally {
+ transactions.removeTransactionContext(context);
+ }
+ }
+
+ private void rollbackDirect(TransactionContext tc)
+ throws XATransactionException {
+ try {
+ this.transactionManager.rollback();
+ } catch (SecurityException e) {
+ throw new XATransactionException(e);
+ } catch (SystemException e) {
+ throw new XATransactionException(e);
+ } finally {
+ transactions.removeTransactionContext(tc);
+ }
+ }
+
+ public void suspend(TransactionContext context) throws XATransactionException {
+ try {
+ this.transactionManager.suspend();
+ } catch (SystemException e) {
+ throw new XATransactionException(e);
+ }
+ }
+
+ public void resume(TransactionContext context) throws XATransactionException {
+ try {
+ this.transactionManager.resume(context.getTransaction());
+ } catch (InvalidTransactionException e) {
+ throw new XATransactionException(e);
+ } catch (SystemException e) {
+ throw new XATransactionException(e);
+ }
+ }
+
+ /**
+ * Local Transaction
+ */
+ public TransactionContext begin(String threadId) throws XATransactionException {
+ TransactionContext tc = checkLocalTransactionState(threadId, false);
+ beginDirect(tc);
+ tc.setTransactionType(TransactionContext.Scope.LOCAL);
+ return tc;
+ }
+
+ /**
+ * Local Transaction
+ */
+ public void commit(String threadId) throws XATransactionException {
+ TransactionContext tc = checkLocalTransactionState(threadId, true);
+ commitDirect(tc);
+ }
+
+ /**
+ * Local Transaction
+ */
+ public void rollback(String threadId) throws XATransactionException {
+ TransactionContext tc = checkLocalTransactionState(threadId, true);
+ rollbackDirect(tc);
+ }
+
+ public TransactionContext getOrCreateTransactionContext(String threadId) {
+ return transactions.getOrCreateTransactionContext(threadId);
+ }
+
+ /**
+ * Request level transaction
+ */
+ public TransactionContext begin(TransactionContext context) throws XATransactionException{
+ if (context.getTransactionType() != TransactionContext.Scope.NONE) {
+ throw new XATransactionException(DQPPlugin.Util.getString("TransactionServer.existing_transaction")); //$NON-NLS-1$
+ }
+ beginDirect(context);
+ context.setTransactionType(TransactionContext.Scope.REQUEST);
+ return context;
+ }
+
+ /**
+ * Request level transaction
+ */
+ public TransactionContext commit(TransactionContext context) throws XATransactionException {
+ Assertion.assertTrue(context.getTransactionType() == TransactionContext.Scope.REQUEST);
+ commitDirect(context);
+ return context;
+ }
+
+ /**
+ * Request level transaction
+ */
+ public TransactionContext rollback(TransactionContext context) throws XATransactionException {
+ Assertion.assertTrue(context.getTransactionType() == TransactionContext.Scope.REQUEST);
+ rollbackDirect(context);
+ return context;
+ }
+
+ public void cancelTransactions(String threadId, boolean requestOnly) throws XATransactionException {
+ TransactionContext tc = transactions.getTransactionContext(threadId);
+
+ if (tc == null || tc.getTransactionType() == TransactionContext.Scope.NONE
+ || (requestOnly && tc.getTransactionType() != TransactionContext.Scope.REQUEST)) {
+ return;
+ }
+
+ try {
+ tc.getTransaction().setRollbackOnly();
+ } catch (SystemException e) {
+ throw new XATransactionException(e);
+ }
+ }
+
+ @Override
+ public Collection<org.teiid.adminapi.Transaction> getTransactions() {
+ Set<TransactionContext> txnSet = Collections.newSetFromMap(new IdentityHashMap<TransactionContext, Boolean>());
+ synchronized (this.transactions) {
+ txnSet.addAll(this.transactions.threadToTransactionContext.values());
+ txnSet.addAll(this.transactions.xidToTransactionContext.values());
+ }
+ Collection<org.teiid.adminapi.Transaction> result = new ArrayList<org.teiid.adminapi.Transaction>(txnSet.size());
+ for (TransactionContext transactionContext : txnSet) {
+ if (transactionContext.getTransactionType() == Scope.NONE) {
+ continue;
+ }
+ TransactionMetadata txnImpl = new TransactionMetadata();
+ txnImpl.setAssociatedSession(Long.parseLong(transactionContext.getThreadId()));
+ txnImpl.setCreatedTime(transactionContext.getCreationTime());
+ txnImpl.setScope(transactionContext.getTransactionType().toString());
+ txnImpl.setId(transactionContext.getTransactionId());
+ result.add(txnImpl);
+ }
+ return result;
+ }
+
+ @Override
+ public void terminateTransaction(String threadId) throws AdminException {
+ if (threadId == null) {
+ return;
+ }
+ try {
+ cancelTransactions(threadId, false);
+ } catch (XATransactionException e) {
+ throw new AdminProcessingException(e);
+ }
+ }
+
+}
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java 2010-07-23 21:44:19 UTC (rev 2371)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -58,7 +58,6 @@
* A Teiid Temp Table
* TODO: an update will not happen unless the tuplesource is accessed
* TODO: better handling for blocked exceptions (should be rare)
- * TODO: non-pk updates/deletes through the browser
*/
class TempTable {
@@ -166,15 +165,11 @@
}
public TupleSource createTupleSource(List<Criteria> conditions, OrderBy orderBy) throws TeiidComponentException {
- return createTupleSource(conditions, orderBy, true);
- }
-
- private TupleSource createTupleSource(List<Criteria> conditions, OrderBy orderBy, boolean filterRowId) throws TeiidComponentException {
+ TupleBrowser browser = createTupleBrower(conditions, orderBy);
TupleBuffer tb = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
- TupleBrowser browser = tree.browse(null, null, OrderBy.ASC);
List next = null;
while ((next = browser.next()) != null) {
- if (rowId != null && filterRowId) {
+ if (rowId != null) {
next = next.subList(1, next.size());
}
tb.addTuple(next);
@@ -183,6 +178,10 @@
return tb.createIndexedTupleSource(true);
}
+ private TupleBrowser createTupleBrower(List<Criteria> conditions, OrderBy orderBy) throws TeiidComponentException {
+ return tree.browse(null, null, OrderBy.ASC);
+ }
+
public int getRowCount() {
return tree.getRowCount();
}
@@ -221,11 +220,37 @@
};
return uts;
}
+
+ private TupleSource asTupleSource(final TupleBrowser browser) {
+ return new TupleSource() {
+
+ @Override
+ public List<?> nextTuple() throws TeiidComponentException,
+ TeiidProcessingException {
+ return browser.next();
+ }
+
+ @Override
+ public List<? extends Expression> getSchema() {
+ return columns;
+ }
+
+ @Override
+ public void closeSource() {
+
+ }
+
+ @Override
+ public int available() {
+ return 0;
+ }
+ };
+ }
public TupleSource update(Criteria crit, final SetClauseList update) throws TeiidComponentException {
final boolean primaryKeyChangePossible = canChangePrimaryKey(update);
-
- UpdateTupleSource uts = new UpdateTupleSource(crit, createTupleSource(null, null, false)) {
+ final TupleBrowser browser = createTupleBrower(null, null);
+ UpdateTupleSource uts = new UpdateTupleSource(crit, asTupleSource(browser)) {
protected TupleBuffer changeSet;
protected TupleSource changeSetProcessor;
@@ -239,13 +264,14 @@
newTuple.set((Integer)lookup.get(entry.getKey()), eval.evaluate(entry.getValue(), tuple));
}
if (primaryKeyChangePossible) {
+ browser.removed();
deleteTuple(tuple);
if (changeSet == null) {
changeSet = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
}
changeSet.addTuple(newTuple);
} else {
- updateTuple(newTuple);
+ browser.update(newTuple);
}
}
@@ -312,11 +338,13 @@
}
public TupleSource delete(Criteria crit) throws TeiidComponentException {
- UpdateTupleSource uts = new UpdateTupleSource(crit, createTupleSource(null, null, false)) {
+ final TupleBrowser browser = createTupleBrower(null, null);
+ UpdateTupleSource uts = new UpdateTupleSource(crit, asTupleSource(browser)) {
@Override
protected void tuplePassed(List tuple)
throws ExpressionEvaluationException,
BlockedException, TeiidComponentException {
+ browser.removed();
deleteTuple(tuple);
}
Modified: trunk/engine/src/test/java/org/teiid/common/queue/TestThreadReuseExecutor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/common/queue/TestThreadReuseExecutor.java 2010-07-23 21:44:19 UTC (rev 2371)
+++ trunk/engine/src/test/java/org/teiid/common/queue/TestThreadReuseExecutor.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -154,7 +154,7 @@
}, 0, 30, TimeUnit.MILLISECONDS);
Thread.sleep(120);
future.cancel(true);
- assertEquals(2, result.size());
+ assertTrue(result.size() < 3);
}
@Test public void testFailingWork() throws Exception {
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/FakeTransactionService.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/FakeTransactionService.java 2010-07-23 21:44:19 UTC (rev 2371)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/FakeTransactionService.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -27,7 +27,7 @@
import org.teiid.common.queue.FakeWorkManager;
import org.teiid.core.util.SimpleMock;
-import org.teiid.dqp.internal.transaction.TransactionServerImpl;
+import org.teiid.dqp.internal.process.TransactionServerImpl;
public class FakeTransactionService extends TransactionServerImpl {
Copied: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestAuthorizationValidationVisitor.java (from rev 2371, trunk/engine/src/test/java/org/teiid/dqp/internal/process/validator/TestAuthorizationValidationVisitor.java)
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestAuthorizationValidationVisitor.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestAuthorizationValidationVisitor.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -0,0 +1,305 @@
+/*
+ * 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.dqp.internal.process;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.teiid.adminapi.DataPolicy;
+import org.teiid.adminapi.DataPolicy.PermissionType;
+import org.teiid.adminapi.impl.DataPolicyMetadata;
+import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.adminapi.impl.DataPolicyMetadata.PermissionMetaData;
+import org.teiid.api.exception.query.QueryParserException;
+import org.teiid.api.exception.query.QueryResolverException;
+import org.teiid.api.exception.query.QueryValidatorException;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.dqp.internal.process.AuthorizationValidationVisitor;
+import org.teiid.dqp.internal.process.Request;
+import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.parser.QueryParser;
+import org.teiid.query.resolver.QueryResolver;
+import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.symbol.Symbol;
+import org.teiid.query.unittest.FakeMetadataFactory;
+import org.teiid.query.validator.Validator;
+import org.teiid.query.validator.ValidatorFailure;
+import org.teiid.query.validator.ValidatorReport;
+
+
+public class TestAuthorizationValidationVisitor extends TestCase {
+
+ public static final String CONN_ID = "connID"; //$NON-NLS-1$
+
+ /**
+ * Constructor for TestAuthorizationValidationVisitor.
+ * @param name
+ */
+ public TestAuthorizationValidationVisitor(String name) {
+ super(name);
+ }
+
+ PermissionMetaData addResource(PermissionType type, boolean flag, String resource) {
+ PermissionMetaData p = new PermissionMetaData();
+ p.setResourceName(resource);
+ switch(type) {
+ case CREATE:
+ p.setAllowCreate(flag);
+ break;
+ case DELETE:
+ p.setAllowDelete(flag);
+ break;
+ case READ:
+ p.setAllowRead(flag);
+ break;
+ case UPDATE:
+ p.setAllowUpdate(flag);
+ break;
+ }
+ return p;
+ }
+ PermissionMetaData addResource(PermissionType type, String resource) {
+ return addResource(type, true, resource);
+ }
+
+ private DataPolicyMetadata exampleAuthSvc1() {
+ DataPolicyMetadata svc = new DataPolicyMetadata();
+ svc.setName("test"); //$NON-NLS-1$
+
+ // pm1.g1
+ svc.addPermission(addResource(PermissionType.DELETE, "pm1.g1")); //$NON-NLS-1$
+
+ svc.addPermission(addResource(DataPolicy.PermissionType.READ, "pm1.g1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.READ, "pm1.g1.e1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.READ, false, "pm1.g1.e2")); //$NON-NLS-1$
+
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g1.e1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g1.e2")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g1.e3")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g1.e4")); //$NON-NLS-1$
+
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, "pm1.g1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, false, "pm1.g1.e1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, "pm1.g1.e2")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, "pm1.g1.e3")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, "pm1.g1.e4")); //$NON-NLS-1$
+
+
+ // pm1.g2
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g2")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, false, "pm1.g2.e1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g2.e2")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g2.e3")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g2.e4")); //$NON-NLS-1$
+
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, "pm1.g2")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, false, "pm1.g2.e1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, "pm1.g2.e2")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, "pm1.g2.e3")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.UPDATE, "pm1.g2.e4")); //$NON-NLS-1$
+
+ // pm1.g4
+ svc.addPermission(addResource(DataPolicy.PermissionType.DELETE, "pm1.g4")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.DELETE, "pm1.g4.e1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.DELETE, "pm1.g4.e2")); //$NON-NLS-1$
+
+ // pm1.sq2
+ svc.addPermission(addResource(DataPolicy.PermissionType.READ, "pm1.sq1")); //$NON-NLS-1$
+
+ return svc;
+ }
+
+ //allow by default
+ private DataPolicyMetadata exampleAuthSvc2() {
+ DataPolicyMetadata svc = new DataPolicyMetadata();
+ svc.setName("test"); //$NON-NLS-1$
+
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm1.g2")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.READ, "pm1.g2")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.READ, "pm2.g1")); //$NON-NLS-1$
+
+ // pm2.g2
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm2.g2.e1")); //$NON-NLS-1$
+
+ // pm3.g2
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm3.g2.e1")); //$NON-NLS-1$
+ svc.addPermission(addResource(DataPolicy.PermissionType.CREATE, "pm3.g2.e2")); //$NON-NLS-1$
+
+ return svc;
+ }
+
+ private void helpTest(DataPolicyMetadata policy, String sql, QueryMetadataInterface metadata, String[] expectedInaccesible, VDBMetaData vdb) throws QueryParserException, QueryResolverException, TeiidComponentException {
+ QueryParser parser = QueryParser.getQueryParser();
+ Command command = parser.parseCommand(sql);
+ QueryResolver.resolveCommand(command, metadata);
+
+ vdb.addAttchment(QueryMetadataInterface.class, metadata);
+
+ HashMap<String, DataPolicy> policies = new HashMap<String, DataPolicy>();
+ policies.put(policy.getName(), policy);
+
+ AuthorizationValidationVisitor visitor = new AuthorizationValidationVisitor(vdb, true, policies, "test"); //$NON-NLS-1$
+ ValidatorReport report = Validator.validate(command, metadata, visitor);
+ if(report.hasItems()) {
+ ValidatorFailure firstFailure = (ValidatorFailure) report.getItems().iterator().next();
+
+ // strings
+ Set expected = new HashSet(Arrays.asList(expectedInaccesible));
+ // elements
+ Set actual = new HashSet();
+ Iterator iter = firstFailure.getInvalidObjects().iterator();
+ while(iter.hasNext()) {
+ Symbol symbol = (Symbol) iter.next();
+ actual.add(symbol.getName());
+ }
+ assertEquals(expected, actual);
+ } else if(expectedInaccesible.length > 0) {
+ fail("Expected inaccessible objects, but got none."); //$NON-NLS-1$
+ }
+ }
+
+ public void testEverythingAccessible() throws Exception {
+ helpTest(exampleAuthSvc1(), "SELECT e1 FROM pm1.g1", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testEverythingAccessible1() throws Exception {
+ helpTest(exampleAuthSvc1(), "SELECT e1 FROM (select e1 from pm1.g1) x", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testEverythingAccessible2() throws Exception {
+ helpTest(exampleAuthSvc1(), "SELECT lookup('pm1.g1', 'e1', 'e1', '1'), e1 FROM (select e1 from pm1.g1) x", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testInaccesibleElement() throws Exception {
+ helpTest(exampleAuthSvc1(), "SELECT e2 FROM pm1.g1", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g1.e2"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testInaccesibleElement2() throws Exception {
+ helpTest(exampleAuthSvc1(), "SELECT lookup('pm1.g1', 'e1', 'e2', '1')", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g1.e2"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testInaccesibleGroup() throws Exception {
+ helpTest(exampleAuthSvc1(), "SELECT e1 FROM pm1.g2", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g2", "pm1.g2.e1"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ public void testInsert() throws Exception {
+ helpTest(exampleAuthSvc1(), "INSERT INTO pm1.g1 (e1, e2, e3, e4) VALUES ('x', 5, {b'true'}, 1.0)", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testInsertInaccessible() throws Exception {
+ helpTest(exampleAuthSvc1(), "INSERT INTO pm1.g2 (e1, e2, e3, e4) VALUES ('x', 5, {b'true'}, 1.0)", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g2.e1"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testUpdate() throws Exception {
+ helpTest(exampleAuthSvc1(), "UPDATE pm1.g1 SET e2 = 5", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testUpdateCriteriaInaccessibleForRead() throws Exception {
+ helpTest(exampleAuthSvc1(), "UPDATE pm1.g2 SET e2 = 5 WHERE e1 = 'x'", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g2.e1"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testUpdateElementInaccessibleForUpdate() throws Exception {
+ helpTest(exampleAuthSvc1(), "UPDATE pm1.g1 SET e1 = 5 WHERE e1 = 'x'", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g1.e1"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testDelete() throws Exception {
+ helpTest(exampleAuthSvc1(), "DELETE FROM pm1.g1", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testDeleteCriteriaInaccesibleForRead() throws Exception {
+ helpTest(exampleAuthSvc1(), "DELETE FROM pm1.g2 WHERE e1 = 'x'", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g2.e1"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testDeleteInaccesibleGroup() throws Exception {
+ helpTest(exampleAuthSvc1(), "DELETE FROM pm1.g3", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g3"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testProc() throws Exception {
+ helpTest(exampleAuthSvc1(), "EXEC pm1.sq1()", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testProcInaccesible() throws Exception {
+ helpTest(exampleAuthSvc1(), "EXEC pm1.sq2('xyz')", FakeMetadataFactory.example1Cached(), new String[] {"pm1.sq2"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testSelectIntoEverythingAccessible() throws Exception {
+ helpTest(exampleAuthSvc2(), "SELECT e1, e2, e3, e4 INTO pm1.g2 FROM pm2.g1", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testSelectIntoTarget_e1_NotAccessible() throws Exception {
+ helpTest(exampleAuthSvc2(), "SELECT e1, e2, e3, e4 INTO pm2.g2 FROM pm2.g1", FakeMetadataFactory.example1Cached(), new String[] {"pm2.g2.e2","pm2.g2.e4","pm2.g2.e3"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+
+ public void testSelectIntoTarget_e1e2_NotAccessible() throws Exception {
+ helpTest(exampleAuthSvc2(), "SELECT e1, e2, e3, e4 INTO pm3.g2 FROM pm2.g1", FakeMetadataFactory.example1Cached(), new String[] {"pm3.g2.e4", "pm3.g2.e3"},FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ public void testTempTableSelectInto() throws Exception {
+ helpTest(exampleAuthSvc1(), "SELECT e1 INTO #temp FROM pm1.g1", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testTempTableSelectInto1() throws Exception {
+ helpTest(exampleAuthSvc1(), "SELECT e1, e2 INTO #temp FROM pm1.g1", FakeMetadataFactory.example1Cached(), new String[] {"pm1.g1.e2"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testTempTableInsert() throws Exception {
+ helpTest(exampleAuthSvc2(), "insert into #temp (e1, e2, e3, e4) values ('1', '2', '3', '4')", FakeMetadataFactory.example1Cached(), new String[] {}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$
+ }
+
+ public void testXMLAccessible() throws Exception {
+ helpTest(exampleAuthSvc2(), "select * from xmltest.doc1", FakeMetadataFactory.example1Cached(), new String[] {"xmltest.doc1"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void testXMLInAccessible() throws Exception {
+ helpTest(exampleAuthSvc1(), "select * from xmltest.doc1", FakeMetadataFactory.example1Cached(), new String[] {"xmltest.doc1"}, FakeMetadataFactory.example1VDB()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private void helpTestLookupVisibility(boolean visible) throws QueryParserException, QueryValidatorException, TeiidComponentException {
+ VDBMetaData vdb = FakeMetadataFactory.example1VDB();
+ vdb.getModel("pm1").setVisible(visible); //$NON-NLS-1$
+ AuthorizationValidationVisitor mvvv = new AuthorizationValidationVisitor(vdb, false, new HashMap<String, DataPolicy>(), "test"); //$NON-NLS-1$
+ String sql = "select lookup('pm1.g1', 'e1', 'e2', 1)"; //$NON-NLS-1$
+ Command command = QueryParser.getQueryParser().parseCommand(sql);
+ Request.validateWithVisitor(mvvv, FakeMetadataFactory.example1Cached(), command);
+ }
+
+ public void testLookupVisibility() throws Exception {
+ helpTestLookupVisibility(true);
+ }
+
+ public void testLookupVisibilityFails() throws Exception {
+ try {
+ helpTestLookupVisibility(false);
+ fail("expected exception"); //$NON-NLS-1$
+ } catch (QueryValidatorException e) {
+ assertEquals("Group does not exist: pm1.g1", e.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+}
Copied: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestTransactionServer.java (from rev 2371, trunk/engine/src/test/java/org/teiid/dqp/internal/transaction/TestTransactionServer.java)
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestTransactionServer.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestTransactionServer.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -0,0 +1,399 @@
+/*
+ * 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.dqp.internal.process;
+
+import static org.junit.Assert.*;
+
+import javax.resource.spi.XATerminator;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAResource;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.teiid.adminapi.Transaction;
+import org.teiid.client.xa.XATransactionException;
+import org.teiid.client.xa.XidImpl;
+import org.teiid.common.queue.FakeWorkManager;
+import org.teiid.dqp.internal.process.TransactionServerImpl;
+import org.teiid.dqp.service.TransactionContext;
+
+public class TestTransactionServer {
+
+ private TransactionServerImpl server;
+ private XATerminator xaTerminator;
+ private TransactionManager tm;
+ private javax.transaction.Transaction txn;
+
+ private static final String THREAD1 = "1"; //$NON-NLS-1$
+ private static final String THREAD2 = "2"; //$NON-NLS-1$
+
+ private static final XidImpl XID1 = new XidImpl(0, new byte[] {
+ 1
+ }, new byte[0]);
+ private static final XidImpl XID2 = new XidImpl(0, new byte[] {
+ 2
+ }, new byte[0]);
+
+ @Before public void setUp() throws Exception {
+ server = new TransactionServerImpl();
+ xaTerminator = Mockito.mock(XATerminator.class);
+ tm = Mockito.mock(TransactionManager.class);
+ txn = Mockito.mock(javax.transaction.Transaction.class);
+ Mockito.stub(tm.getTransaction()).toReturn(txn);
+ Mockito.stub(tm.suspend()).toReturn(txn);
+ server.setXaTerminator(xaTerminator);
+ server.setTransactionManager(tm);
+ server.setWorkManager(new FakeWorkManager());
+ }
+
+ /**
+ * once in a local, cannot start a global
+ */
+ @Test public void testTransactionExclusion() throws Exception {
+ server.begin(THREAD1);
+
+ try {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100, false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Client thread already involved in a transaction. Transaction nesting is not supported. The current transaction must be completed first.", //$NON-NLS-1$
+ ex.getMessage());
+ }
+ }
+
+ /**
+ * once in a global, cannot start a local
+ */
+ @Test public void testTransactionExclusion1() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100, false);
+
+ try {
+ server.begin(THREAD1);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Client thread already involved in a transaction. Transaction nesting is not supported. The current transaction must be completed first.", //$NON-NLS-1$
+ ex.getMessage());
+ }
+ }
+
+ /**
+ * global can only be started once
+ */
+ @Test public void testTransactionExclusion2() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+
+ try {
+ server.start(THREAD2, XID1, XAResource.TMNOFLAGS, 100,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Global transaction Teiid-Xid global:1 branch:null format:0 already exists.", ex.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * global cannot be nested
+ */
+ @Test public void testTransactionExclusion3() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+
+ try {
+ server.start(THREAD1, XID2, XAResource.TMNOFLAGS, 100,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Client thread already involved in a transaction. Transaction nesting is not supported. The current transaction must be completed first.", //$NON-NLS-1$
+ ex.getMessage());
+ }
+ }
+
+ /**
+ * local cannot be nested
+ */
+ @Test public void testTransactionExclusion4() throws Exception {
+ server.begin(THREAD1);
+
+ try {
+ server.begin(THREAD1);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Client thread already involved in a transaction. Transaction nesting is not supported. The current transaction must be completed first.", //$NON-NLS-1$
+ ex.getMessage());
+ }
+ }
+
+ /**
+ * global cannot be nested
+ */
+ @Test public void testTransactionExclusion5() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ server.start(THREAD2, XID2, XAResource.TMNOFLAGS, 100,false);
+ server.end(THREAD2, XID2, XAResource.TMSUCCESS,false);
+
+ try {
+ server.start(THREAD1, XID2, XAResource.TMJOIN, 100,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Client thread already involved in a transaction. Transaction nesting is not supported. The current transaction must be completed first.", //$NON-NLS-1$
+ ex.getMessage());
+ }
+ }
+
+ @Test public void testLocalCommit() throws Exception {
+ server.begin(THREAD1);
+ server.commit(THREAD1);
+
+ Mockito.verify(tm).commit();
+
+ try {
+ server.commit(THREAD1);
+ } catch (XATransactionException e) {
+ assertEquals("No transaction found for client 1.", e.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ @Test public void testTwoPhaseCommit() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ server.end(THREAD1, XID1, XAResource.TMSUCCESS, false);
+ server.commit(THREAD1, XID1, false, false);
+
+ Mockito.verify(xaTerminator).commit(XID1, false);
+ }
+
+ @Test public void testLocalRollback() throws Exception {
+ server.begin(THREAD1);
+ server.rollback(THREAD1);
+ Mockito.verify(tm).rollback();
+
+ try {
+ server.rollback(THREAD1);
+ } catch (XATransactionException e) {
+ assertEquals("No transaction found for client 1.", e.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ @Test public void testConcurrentEnlistment() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+
+ try {
+ server.start(THREAD1, XID1, XAResource.TMJOIN, 100,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Concurrent enlistment in global transaction Teiid-Xid global:1 branch:null format:0 is not supported.", //$NON-NLS-1$
+ ex.getMessage());
+ }
+ }
+
+ @Test public void testSuspend() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ server.end(THREAD1, XID1, XAResource.TMSUSPEND,false);
+
+ try {
+ server.end(THREAD1, XID1, XAResource.TMSUSPEND,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Client is not currently enlisted in transaction Teiid-Xid global:1 branch:null format:0.", ex.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ @Test public void testSuspendResume() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ server.end(THREAD1, XID1, XAResource.TMSUSPEND,false);
+ server.start(THREAD1, XID1, XAResource.TMRESUME, 100,false);
+ server.end(THREAD1, XID1, XAResource.TMSUSPEND,false);
+
+ try {
+ server.start(THREAD2, XID1, XAResource.TMRESUME, 100,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Cannot resume, transaction Teiid-Xid global:1 branch:null format:0 was not suspended by client 2.", ex.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ @Test public void testUnknownFlags() throws Exception {
+ try {
+ server.start(THREAD1, XID1, Integer.MAX_VALUE, 100,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Unknown flags", ex.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ @Test public void testUnknownGlobalTransaction() throws Exception {
+ try {
+ server.end(THREAD1, XID1, XAResource.TMSUCCESS,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("No global transaction found for Teiid-Xid global:1 branch:null format:0.", ex.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ @Test public void testPrepareWithSuspended() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ server.end(THREAD1, XID1, XAResource.TMSUSPEND,false);
+
+ try {
+ server.prepare(THREAD1, XID1,false);
+ fail("exception expected"); //$NON-NLS-1$
+ } catch (XATransactionException ex) {
+ assertEquals("Suspended work still exists on transaction Teiid-Xid global:1 branch:null format:0.", ex.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ @Test public void testGetTransactionContext() throws Exception {
+ assertSame(server.getOrCreateTransactionContext(THREAD1), server.getOrCreateTransactionContext(THREAD1));
+ }
+
+ @Test public void testGetTransactions() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ server.begin(THREAD2);
+
+ assertEquals(2, server.getTransactions().size());
+
+ server.commit(THREAD2);
+ assertEquals(1, server.getTransactions().size());
+
+ Transaction t = server.getTransactions().iterator().next();
+ assertEquals(Long.parseLong(THREAD1), t.getAssociatedSession());
+ assertNotNull(t.getId());
+ }
+
+ @Test public void testGlobalPrepare() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+ server.end(THREAD1, XID1, XAResource.TMSUCCESS, false);
+
+ server.prepare(THREAD1, XID1, false);
+
+ Mockito.verify(xaTerminator).prepare(tc.getXid());
+
+ server.commit(THREAD1, XID1, true, false);
+ }
+
+ @Test public void testGlobalPrepareFail() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ server.end(THREAD1, XID1, XAResource.TMFAIL, false);
+ Mockito.verify(txn).setRollbackOnly();
+ }
+
+ @Test public void testGlobalOnePhaseCommit() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+
+ server.end(THREAD1, XID1, XAResource.TMSUCCESS, false);
+
+ server.prepare(THREAD1, XID1, false);
+
+
+ server.commit(THREAD1, XID1, true, false);
+ Mockito.verify(xaTerminator).commit(tc.getXid(), false);
+ }
+
+ @Test public void testGlobalOnePhaseCommit_force_prepare_through() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+
+ server.end(THREAD1, XID1, XAResource.TMSUCCESS, false);
+
+
+ server.commit(THREAD1, XID1, true, false);
+
+ Mockito.verify(xaTerminator).prepare(tc.getXid());
+ Mockito.verify(xaTerminator).commit(tc.getXid(), false);
+ }
+
+ @Test public void testGlobalOnePhaseCommit_force_prepare() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+
+ server.end(THREAD1, XID1, XAResource.TMSUCCESS, false);
+
+
+ server.commit(THREAD1, XID1, true, false);
+
+ // since there are two sources the commit is not single phase
+ Mockito.verify(xaTerminator).prepare(tc.getXid());
+ Mockito.verify(xaTerminator).commit(tc.getXid(), false);
+ }
+
+
+ @Test public void testGlobalOnePhase_teiid_multiple() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+
+ server.end(THREAD1, XID1, XAResource.TMSUCCESS, false);
+
+ server.prepare(THREAD1, XID1, false);
+
+
+ server.commit(THREAD1, XID1, true, false);
+
+ // since there are two sources the commit is not single phase
+ Mockito.verify(xaTerminator).commit(tc.getXid(), false);
+ }
+
+ @Test public void testGlobalOnePhaseRoolback() throws Exception {
+ server.start(THREAD1, XID1, XAResource.TMNOFLAGS, 100,false);
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+
+ server.end(THREAD1, XID1, XAResource.TMSUCCESS, false);
+
+ server.prepare(THREAD1, XID1, false);
+
+
+ server.rollback(THREAD1, XID1, false);
+
+ // since there are two sources the commit is not single phase
+ Mockito.verify(xaTerminator).rollback(tc.getXid());
+ }
+
+ @Test public void testRequestCommit() throws Exception{
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+ server.begin(tc);
+ server.commit(tc);
+ Mockito.verify(tm).commit();
+ }
+
+ @Test public void testRequestRollback() throws Exception{
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+ server.begin(tc);
+
+ server.rollback(tc);
+ Mockito.verify(tm).rollback();
+ }
+
+ @Test public void testLocalCancel() throws Exception {
+ server.begin(THREAD1);
+
+ server.cancelTransactions(THREAD1, false);
+
+ Mockito.verify(txn).setRollbackOnly();
+ }
+
+ @Test public void testRequestCancel() throws Exception{
+ TransactionContext tc = server.getOrCreateTransactionContext(THREAD1);
+ server.begin(tc);
+
+ server.cancelTransactions(THREAD1, true);
+ Mockito.verify(txn).setRollbackOnly();
+ }
+}
Modified: trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java 2010-07-23 21:44:19 UTC (rev 2371)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java 2010-07-24 03:25:41 UTC (rev 2372)
@@ -65,7 +65,7 @@
import org.teiid.dqp.internal.process.DQPConfiguration;
import org.teiid.dqp.internal.process.DQPCore;
import org.teiid.dqp.internal.process.DQPWorkContext;
-import org.teiid.dqp.internal.transaction.TransactionServerImpl;
+import org.teiid.dqp.internal.process.TransactionServerImpl;
import org.teiid.dqp.service.BufferService;
import org.teiid.dqp.service.SessionService;
import org.teiid.dqp.service.SessionServiceException;
14 years, 5 months
teiid SVN: r2371 - in trunk: build/kits/jboss-container and 29 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-07-23 17:44:19 -0400 (Fri, 23 Jul 2010)
New Revision: 2371
Added:
trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
Removed:
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStoreImpl.java
trunk/engine/src/test/java/org/teiid/internal/
trunk/runtime/src/test/java/com/metamatrix/dqp/
Modified:
trunk/api/src/main/java/org/teiid/language/SQLConstants.java
trunk/build/kits/jboss-container/teiid-releasenotes.html
trunk/engine/src/main/java/org/teiid/common/buffer/BufferManager.java
trunk/engine/src/main/java/org/teiid/common/buffer/TupleBatch.java
trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java
trunk/engine/src/main/java/org/teiid/common/buffer/impl/BufferManagerImpl.java
trunk/engine/src/main/java/org/teiid/common/buffer/impl/MemoryStorageManager.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/CodeTableCache.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanJoins.java
trunk/engine/src/main/java/org/teiid/query/processor/CollectionTupleSource.java
trunk/engine/src/main/java/org/teiid/query/processor/batch/BatchedUpdatePlan.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/PlanExecutionNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectIntoNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/UnionAllNode.java
trunk/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Create.java
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.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/dqp/internal/process/TestCodeTableCache.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestProjectIntoNode.java
trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
trunk/engine/src/test/java/org/teiid/query/sql/util/TestElementSymbolOptimizer.java
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
Log:
TEIID-1167 initial support for temp tables with primary keys. We're using a simplified tree structure as the index with everything hooked (or forced) into the existing buffer support. search optimizations and other concerns have not been hooked up yet.
Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -96,6 +96,8 @@
public static final String NULLS = "NULLS"; //$NON-NLS-1$
public static final String FIRST = "FIRST"; //$NON-NLS-1$
public static final String LAST = "LAST"; //$NON-NLS-1$
+
+ public static final String KEY = "KEY"; //$NON-NLS-1$
}
public interface Reserved {
Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-07-23 21:44:19 UTC (rev 2371)
@@ -120,6 +120,7 @@
The following components have been updated:
<h4>From 7.0</h4>
<ul>
+ <li>Direct integration of JBossCache jars were removed.
<li>Netty was upgraded to 3.2.0
<li>JDOM was removed.
</ul>
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/BufferManager.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/BufferManager.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/BufferManager.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -114,4 +114,6 @@
*/
int getSchemaSize(List elements);
+ STree createSTree(final List elements, String groupName, TupleSourceType tupleSourceType, int keyLength);
+
}
Added: trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -0,0 +1,143 @@
+/*
+ * 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.common.buffer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.common.buffer.BatchManager.ManagedBatch;
+import org.teiid.core.TeiidComponentException;
+
+/**
+ * A linked list Page entry in the tree
+ */
+@SuppressWarnings("unchecked")
+class SPage {
+
+ static final int MIN_PERSISTENT_SIZE = 16;
+
+ static class SearchResult {
+ int index;
+ SPage page;
+ List values;
+ public SearchResult(int index, SPage page, List values) {
+ this.index = index;
+ this.page = page;
+ this.values = values;
+ }
+ }
+
+ private static AtomicInteger counter = new AtomicInteger();
+
+ STree stree;
+
+ protected SPage next;
+ protected ManagedBatch managedBatch;
+ protected List values;
+ protected ArrayList<SPage> children;
+
+ SPage(STree stree, boolean leaf) {
+ this.stree = stree;
+ this.values = new ArrayList<SPage>(stree.pageSize);
+ if (!leaf) {
+ children = new ArrayList<SPage>(stree.pageSize/4);
+ }
+ }
+
+ static SearchResult search(SPage page, List k, SearchResult parent, List parentKey) throws TeiidComponentException {
+ SPage previous = null;
+ List previousValues = null;
+ for (;;) {
+ List values = page.getValues();
+ int index = Collections.binarySearch(values, k, page.stree.comparator);
+ int actual = - index - 1;
+ if (previous != null) {
+ if (actual == 0) {
+ if (values.isEmpty()) {
+ page.remove();
+ previous.next = page.next;
+ }
+ return new SearchResult(-previousValues.size() - 1, previous, previousValues);
+ }
+ if (parentKey != null) {
+ if (page.stree.comparator.compare(parentKey, values.get(0)) >= 0) {
+ //TODO: the entries after this point may also need moved forward
+ //TODO: this should be done as part of insert
+ parent.page.children.set(Math.max(0, -parent.index - 2), page);
+ } else {
+ //parentKey < page.keys.get(0)
+ //TODO: this circumvents the normal probabilistic process, but
+ //ensures there is an index entry.
+ page.stree.insert(page.stree.extractKey((List) values.get(0)), parent, page);
+ parent.index--;
+ }
+ }
+ }
+ if (actual != values.size() || page.next == null) {
+ return new SearchResult(index, page, values);
+ }
+ previous = page;
+ previousValues = values;
+ page = page.next;
+ }
+ }
+
+ protected void setValues(List values) throws TeiidComponentException {
+ if (managedBatch != null) {
+ managedBatch.remove();
+ }
+ if (values.size() < MIN_PERSISTENT_SIZE) {
+ this.values = values;
+ return;
+ }
+ this.values = null;
+ TupleBatch batch = TupleBatch.directBatch(counter.getAndIncrement(), values);
+ if (children != null) {
+ batch.setDataTypes(stree.keytypes);
+ } else {
+ batch.setDataTypes(stree.types);
+ }
+ managedBatch = stree.manager.createManagedBatch(batch);
+ }
+
+ protected void remove() {
+ if (managedBatch != null) {
+ managedBatch.remove();
+ managedBatch = null;
+ }
+ }
+
+ protected List getValues() throws TeiidComponentException {
+ if (values != null) {
+ return values;
+ }
+ if (managedBatch == null) {
+ return Collections.emptyList();
+ }
+ TupleBatch batch = managedBatch.getBatch(true, stree.types);
+ return batch.getTuples();
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/common/buffer/SPage.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/STree.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/STree.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -0,0 +1,343 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.common.buffer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.common.buffer.SPage.SearchResult;
+import org.teiid.core.TeiidComponentException;
+
+@SuppressWarnings("unchecked")
+
+/**
+ * Self balancing search tree using skip list like logic
+ * This has similar performance similar to a B+/-Tree
+ *
+ * TODO: reserve additional memory for delete/update operations
+ * TODO: double link to support desc key access
+ */
+public class STree {
+
+ private static final Random seedGenerator = new Random();
+
+ private int randomSeed;
+ private SPage[] header = new SPage[] {new SPage(this, true)};
+ protected BatchManager manager;
+ protected Comparator comparator;
+ protected int pageSize;
+ protected int keyLength;
+ protected String[] types;
+ protected String[] keytypes;
+
+ private AtomicInteger rowCount = new AtomicInteger();
+
+ public STree(BatchManager recman,
+ final Comparator comparator,
+ int pageSize,
+ int keyLength,
+ String[] types) {
+ randomSeed = seedGenerator.nextInt() | 0x00000100; // ensure nonzero
+ this.manager = recman;
+ this.comparator = comparator;
+ this.pageSize = Math.max(pageSize, SPage.MIN_PERSISTENT_SIZE);
+ this.keyLength = keyLength;
+ this.types = types;
+ this.keytypes = Arrays.copyOf(types, keyLength);
+ }
+
+ /**
+ * Determine a new random level using an XOR rng.
+ *
+ * This uses the simplest of the generators described in George
+ * Marsaglia's "Xorshift RNGs" paper. This is not a high-quality
+ * generator but is acceptable here.
+ *
+ * See also the JSR-166 working group ConcurrentSkipListMap implementation.
+ *
+ * @return
+ */
+ private int randomLevel() {
+ int x = randomSeed;
+ x ^= x << 13;
+ x ^= x >>> 17;
+ randomSeed = x ^= x << 5;
+ int level = 0;
+ int shift = 8;
+ while ((x & 0xff) == 0xff) {
+ ++level;
+ x >>>= shift;
+ }
+ return level;
+ }
+
+ /**
+ * Search each level to find the pointer to the next level
+ * @param n
+ * @param places
+ * @return
+ * @throws IOException
+ * @throws TeiidComponentException
+ */
+ private List find(List n, List<SearchResult> places) throws TeiidComponentException {
+ SPage x = null;
+ List parentKey = null;
+ SearchResult parent = null;
+ for (int i = header.length - 1; i >= 0; i--) {
+ if (x == null) {
+ x = header[i];
+ }
+ SearchResult s = SPage.search(x, n, parent, parentKey);
+ if (places != null) {
+ places.add(s);
+ }
+ if ((s.index == -1 && s.page == header[i]) || s.values.isEmpty()) {
+ x = null;
+ continue; //start at the beginning of the next level
+ }
+ x = s.page;
+ int index = s.index;
+ boolean matched = true;
+ if (index < 0) {
+ matched = false;
+ index = Math.max(0, -index - 2);
+ }
+ if (i == 0) {
+ if (!matched) {
+ return null;
+ }
+ return (List) s.values.get(index);
+ }
+ parentKey = (List) s.values.get(index);
+ parent = s;
+ x = x.children.get(index);
+ }
+ return null;
+ }
+
+ public List find(List k) throws TeiidComponentException {
+ return find(k, null);
+ }
+
+ public List insert(List tuple, boolean replace) throws TeiidComponentException {
+ LinkedList<SearchResult> places = new LinkedList<SearchResult>();
+ List match = find(tuple, places);
+ if (match != null) {
+ if (!replace) {
+ return match;
+ }
+ SearchResult last = places.getLast();
+ SPage page = last.page;
+ last.values.set(last.index, tuple);
+ page.setValues(last.values);
+ return match;
+ }
+ List key = extractKey(tuple);
+ int level = randomLevel();
+ assert header.length == places.size();
+ if (level >= header.length) {
+ header = Arrays.copyOf(header, level + 1);
+ }
+ rowCount.addAndGet(1);
+ SPage page = null;
+ for (int i = 0; i <= level; i++) {
+ if (places.isEmpty()) {
+ SPage newHead = new SPage(this, false);
+ ArrayList newValues = new ArrayList();
+ newValues.add(key);
+ newHead.setValues(newValues);
+ newHead.children.add(page);
+ header[i] = newHead;
+ page = newHead;
+ } else {
+ SearchResult result = places.removeLast();
+ Object value = (i == 0 ? tuple : page);
+ page = insert(key, result, value);
+ }
+ }
+ return null;
+ }
+
+ List extractKey(List tuple) {
+ return tuple.subList(0, keyLength);
+ }
+
+ SPage insert(List k, SearchResult result, Object value) throws TeiidComponentException {
+ SPage page = result.page;
+ int index = -result.index - 1;
+ if (result.values.size() == pageSize) {
+ boolean leaf = !(value instanceof SPage);
+ SPage nextPage = new SPage(this, leaf);
+ ArrayList nextValues = new ArrayList(result.values.subList(pageSize/2, pageSize));
+ result.values.subList(pageSize/2, pageSize).clear();
+ if (!leaf) {
+ nextPage.children.addAll(page.children.subList(pageSize/2, pageSize));
+ page.children.subList(pageSize/2, pageSize).clear();
+ }
+ nextPage.next = page.next;
+ page.next = nextPage;
+ boolean inNext = false;
+ if (index <= pageSize/2) {
+ setValue(index, k, value, result.values, page);
+ } else {
+ inNext = true;
+ setValue(index - pageSize/2, k, value, nextValues, nextPage);
+ }
+ nextPage.setValues(nextValues);
+ page.setValues(result.values);
+ if (inNext) {
+ page = nextPage;
+ }
+ } else {
+ setValue(index, k, value, result.values, page);
+ page.setValues(result.values);
+ }
+ return page;
+ }
+
+ static void setValue(int index, List key, Object value, List values, SPage page) {
+ if (value instanceof SPage) {
+ values.add(index, key);
+ page.children.add(index, (SPage) value);
+ } else {
+ values.add(index, value);
+ }
+ }
+
+ public List remove(List key) throws TeiidComponentException {
+ LinkedList<SearchResult> places = new LinkedList<SearchResult>();
+ List tuple = find(key, places);
+ if (tuple == null) {
+ return null;
+ }
+ rowCount.addAndGet(-1);
+ for (int i = header.length -1; i >=0; i--) {
+ SearchResult searchResult = places.remove();
+ if (searchResult.index < 0) {
+ continue;
+ }
+ boolean cleanup = false;
+ searchResult.values.remove(searchResult.index);
+ int size = searchResult.values.size();
+ if (size == 0) {
+ if (header[i] == searchResult.page && (i != 0 || header[i].next != null)) {
+ header[i].remove();
+ header[i] = header[i].next;
+ if (header[i] == null) {
+ //remove the layer
+ header = Arrays.copyOf(header, header.length - 1);
+ }
+ } else if (i == 0 && header.length > 1) {
+ cleanup = true;
+ }
+ } else if (searchResult.page.next != null && size < pageSize/4) {
+ List nextValues = searchResult.page.next.getValues();
+ SPage next = searchResult.page.next;
+ if (nextValues.size() + size < pageSize/2) {
+ searchResult.page.next = next.next;
+ searchResult.values.addAll(nextValues);
+ nextValues.clear();
+ next.remove();
+ //any references to toMerge are now invalid
+ //setting back to the header will self heal
+ //TODO: this can take advantage of a previous link
+ next.next = header[i];
+ }
+ }
+ searchResult.page.setValues(searchResult.values);
+ if (cleanup) {
+ find(key, null); //trigger cleanup
+ }
+ }
+ return tuple;
+ }
+
+ public void remove() {
+ truncate();
+ this.manager.remove();
+ }
+
+ public int getRowCount() {
+ return this.rowCount.get();
+ }
+
+ public TupleBrowser browse(List lowerBound, List upperBound, boolean direction) {
+ return new TupleBrowser();
+ }
+
+ public int truncate() {
+ int oldSize = rowCount.getAndSet(0);
+ for (int i = 0; i < header.length; i++) {
+ SPage page = header[i];
+ while (page != null) {
+ page.remove();
+ page = page.next;
+ }
+ }
+ header = new SPage[] {new SPage(this, true)};
+ return oldSize;
+ }
+
+ //TODO: support update/delete from the browser
+ public class TupleBrowser {
+
+ SPage page = header[0];
+ int index;
+ List values;
+
+ public boolean matchedLower() {
+ return false;
+ }
+
+ public boolean matchedUpper() {
+ return false;
+ }
+
+ public List next() throws TeiidComponentException {
+ for (;;) {
+ if (values == null) {
+ values = page.getValues();
+ }
+ if (index < values.size()) {
+ return (List) values.get(index++);
+ }
+ index = 0;
+ page = page.next;
+ if (page == null) {
+ return null;
+ }
+ }
+ }
+ }
+
+ public int getKeyLength() {
+ return keyLength;
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/engine/src/main/java/org/teiid/common/buffer/STree.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/TupleBatch.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/TupleBatch.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/TupleBatch.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -26,6 +26,8 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.teiid.client.BatchSerializer;
@@ -45,7 +47,7 @@
private static final long serialVersionUID = 6304443387337336957L;
private int rowOffset;
- private List[] tuples;
+ private List<List> tuples;
// Optional state
private boolean terminationFlag = false;
@@ -61,6 +63,13 @@
public TupleBatch() {
}
+ public static TupleBatch directBatch(int rowOffset, List<List> tuples) {
+ TupleBatch result = new TupleBatch();
+ result.rowOffset = rowOffset;
+ result.tuples = tuples;
+ return result;
+ }
+
/**
* Constructor
* @param beginRow indicates the row of the tuple source which is the
@@ -70,7 +79,7 @@
*/
public TupleBatch(int beginRow, List[] tuples) {
this.rowOffset = beginRow;
- this.tuples = tuples;
+ this.tuples = Arrays.asList(tuples);
}
/**
@@ -82,7 +91,7 @@
*/
public TupleBatch(int beginRow, List listOfTupleLists) {
this.rowOffset = beginRow;
- this.tuples = (List[]) listOfTupleLists.toArray(new List[listOfTupleLists.size()]);
+ this.tuples = new ArrayList(listOfTupleLists);
}
/**
@@ -100,7 +109,7 @@
* @return the last row contained in this tuple batch
*/
public int getEndRow() {
- return rowOffset + tuples.length - 1;
+ return rowOffset + tuples.size() - 1;
}
/**
@@ -108,7 +117,7 @@
* @return the number of rows contained in this tuple batch
*/
public int getRowCount() {
- return tuples.length;
+ return tuples.size();
}
/**
@@ -116,15 +125,19 @@
* @return the tuple at the given index
*/
public List getTuple(int rowIndex) {
- return tuples[rowIndex-rowOffset];
+ return tuples.get(rowIndex-rowOffset);
}
+ public List<List> getTuples() {
+ return tuples;
+ }
+
/**
* Get all tuples
* @return All tuples
*/
public List[] getAllTuples() {
- return tuples;
+ return tuples.toArray(new List[tuples.size()]);
}
/**
@@ -164,21 +177,22 @@
s.append("TupleBatch; beginning row="); //$NON-NLS-1$
s.append(rowOffset);
s.append(", number of rows="); //$NON-NLS-1$
- s.append(tuples.length);
+ s.append(tuples.size());
s.append(", lastBatch="); //$NON-NLS-1$
s.append(this.terminationFlag);
return s.toString();
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- //rowOffset = in.readInt();
terminationFlag = in.readBoolean();
- tuples = BatchSerializer.readBatch(in, types);
+ tuples = new ArrayList<List>();
+ for (List tuple : BatchSerializer.readBatch(in, types)) {
+ tuples.add(tuple);
+ }
}
public void writeExternal(ObjectOutput out) throws IOException {
- //out.writeInt(rowOffset);
out.writeBoolean(terminationFlag);
- BatchSerializer.writeBatch(out, types, tuples);
+ BatchSerializer.writeBatch(out, types, getAllTuples());
}
public void setRowOffset(int rowOffset) {
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/TupleBuffer.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -106,7 +106,7 @@
public void addTuple(List<?> tuple) throws TeiidComponentException {
if (lobs) {
- correctLobReferences(new List[] {tuple});
+ correctLobReferences(schema.size(), tuple);
}
this.rowCount++;
if (batchBuffer == null) {
@@ -126,12 +126,12 @@
public void addTupleBatch(TupleBatch batch, boolean save) throws TeiidComponentException {
setRowCount(batch.getBeginRow() - 1);
if (save) {
- for (List<?> tuple : batch.getAllTuples()) {
+ for (List<?> tuple : batch.getTuples()) {
addTuple(tuple);
}
} else {
//add the lob references only, since they may still be referenced later
- correctLobReferences(batch.getAllTuples());
+ correctLobReferences(batch.getTuples());
}
}
@@ -210,7 +210,7 @@
BatchManager.ManagedBatch batch = entry.getValue();
result = batch.getBatch(!forwardOnly, types);
if (lobs && result.getDataTypes() == null) {
- correctLobReferences(result.getAllTuples());
+ correctLobReferences(result.getTuples());
}
result.setDataTypes(types);
if (forwardOnly) {
@@ -277,42 +277,51 @@
* @throws TeiidComponentException
*/
@SuppressWarnings("unchecked")
- private void correctLobReferences(List[] rows) throws TeiidComponentException {
+ private void correctLobReferences(List<List> rows) throws TeiidComponentException {
int columns = schema.size();
// walk through the results and find all the lobs
- for (int row = 0; row < rows.length; row++) {
- for (int col = 0; col < columns; col++) {
- Object anObj = rows[row].get(col);
-
- if (!(anObj instanceof Streamable<?>)) {
- continue;
- }
- Streamable lob = (Streamable)anObj;
- String id = lob.getReferenceStreamId();
- if (id == null) {
- id = String.valueOf(LOB_ID.getAndIncrement());
- lob.setReferenceStreamId(id);
- }
- if (this.lobReferences == null) {
- this.lobReferences = new ConcurrentHashMap<String, Streamable<?>>();
- }
- this.lobReferences.put(id, lob);
- if (lob.getReference() == null) {
- lob.setReference(getLobReference(lob.getReferenceStreamId()).getReference());
- }
- }
+ for (List list : rows) {
+ correctLobReferences(columns, list);
}
}
+
+ private void correctLobReferences(int columns, List list)
+ throws TeiidComponentException {
+ for (int col = 0; col < columns; col++) {
+ Object anObj = list.get(col);
+
+ if (!(anObj instanceof Streamable<?>)) {
+ continue;
+ }
+ Streamable lob = (Streamable)anObj;
+ String id = lob.getReferenceStreamId();
+ if (id == null) {
+ id = String.valueOf(LOB_ID.getAndIncrement());
+ lob.setReferenceStreamId(id);
+ }
+ if (this.lobReferences == null) {
+ this.lobReferences = new ConcurrentHashMap<String, Streamable<?>>();
+ }
+ this.lobReferences.put(id, lob);
+ if (lob.getReference() == null) {
+ lob.setReference(getLobReference(lob.getReferenceStreamId()).getReference());
+ }
+ }
+ }
public void setForwardOnly(boolean forwardOnly) {
this.forwardOnly = forwardOnly;
}
+ public IndexedTupleSource createIndexedTupleSource() {
+ return createIndexedTupleSource(false);
+ }
+
/**
* Create a new iterator for this buffer
* @return
*/
- public IndexedTupleSource createIndexedTupleSource() {
+ public IndexedTupleSource createIndexedTupleSource(final boolean singleUse) {
return new AbstractTupleSource() {
@Override
@@ -337,6 +346,14 @@
protected TupleBatch getBatch(int row) throws TeiidComponentException {
return TupleBuffer.this.getBatch(row);
}
+
+ @Override
+ public void closeSource() {
+ super.closeSource();
+ if (singleUse) {
+ remove();
+ }
+ }
};
}
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/impl/BufferManagerImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/impl/BufferManagerImpl.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/impl/BufferManagerImpl.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -30,21 +30,29 @@
import java.io.OutputStream;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.xml.transform.Source;
import org.teiid.common.buffer.BatchManager;
import org.teiid.common.buffer.BufferManager;
import org.teiid.common.buffer.FileStore;
+import org.teiid.common.buffer.STree;
import org.teiid.common.buffer.StorageManager;
import org.teiid.common.buffer.TupleBatch;
import org.teiid.common.buffer.TupleBuffer;
@@ -62,6 +70,7 @@
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.query.execution.QueryExecPlugin;
+import org.teiid.query.processor.relational.ListNestedSortComparator;
import org.teiid.query.processor.xml.XMLUtil;
@@ -84,7 +93,87 @@
public class BufferManagerImpl implements BufferManager, StorageManager {
private static final int IO_BUFFER_SIZE = 1 << 14;
+ private static final int COMPACTION_THRESHOLD = 1 << 25; //start checking at 32 megs
+ private final class BatchManagerImpl implements BatchManager {
+ private final String id;
+ private final int columnCount;
+ private volatile FileStore store;
+ private Map<Long, long[]> physicalMapping = new ConcurrentHashMap<Long, long[]>();
+ private Map<Long, String[]> types = new ConcurrentSkipListMap<Long, String[]>();
+ private ReadWriteLock compactionLock = new ReentrantReadWriteLock();
+ private AtomicLong unusedSpace = new AtomicLong();
+
+ private BatchManagerImpl(String newID, int columnCount) {
+ this.id = newID;
+ this.columnCount = columnCount;
+ this.store = createFileStore(id);
+ this.store.setCleanupReference(this);
+ }
+
+ @Override
+ public ManagedBatch createManagedBatch(TupleBatch batch)
+ throws TeiidComponentException {
+ ManagedBatchImpl mbi = new ManagedBatchImpl(batch, this);
+ mbi.addToCache(false);
+ persistBatchReferences();
+ return mbi;
+ }
+
+ private boolean shouldCompact(long offset) {
+ return offset > COMPACTION_THRESHOLD && unusedSpace.get() * 4 > offset * 3;
+ }
+
+ private long getOffset() throws TeiidComponentException {
+ long offset = store.getLength();
+ if (!shouldCompact(offset)) {
+ return offset;
+ }
+ try {
+ this.compactionLock.writeLock().lock();
+ offset = store.getLength();
+ //retest the condition to ensure that compaction is still needed
+ if (!shouldCompact(offset)) {
+ return offset;
+ }
+ FileStore newStore = createFileStore(id);
+ newStore.setCleanupReference(this);
+ byte[] buffer = new byte[IO_BUFFER_SIZE];
+ List<long[]> values = new ArrayList<long[]>(physicalMapping.values());
+ Collections.sort(values, new Comparator<long[]>() {
+ @Override
+ public int compare(long[] o1, long[] o2) {
+ return Long.signum(o1[0] - o2[0]);
+ }
+ });
+ for (long[] info : values) {
+ long oldOffset = info[0];
+ info[0] = newStore.getLength();
+ int size = (int)info[1];
+ while (size > 0) {
+ int toWrite = Math.min(IO_BUFFER_SIZE, size);
+ store.readFully(oldOffset, buffer, 0, toWrite);
+ newStore.write(buffer, 0, toWrite);
+ size -= toWrite;
+ }
+ }
+ store.remove();
+ store = newStore;
+ long oldOffset = offset;
+ offset = store.getLength();
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, "Compacted store", id, "pre-size", oldOffset, "post-size", offset); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return offset;
+ } finally {
+ this.compactionLock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void remove() {
+ this.store.remove();
+ }
+ }
+
/**
* Holder for active batches
*/
@@ -95,33 +184,26 @@
ManagedBatchImpl removeBatch(int row) {
ManagedBatchImpl result = batches.remove(row);
if (result != null) {
- activeBatchColumnCount -= result.columnCount;
+ activeBatchColumnCount -= result.batchManager.columnCount;
}
return result;
}
}
private final class ManagedBatchImpl implements ManagedBatch {
- final private String id;
- final private FileStore store;
-
- private long offset = -1;
private boolean persistent;
private volatile TupleBatch activeBatch;
private volatile Reference<TupleBatch> batchReference;
private int beginRow;
- private int columnCount;
+ private BatchManagerImpl batchManager;
+ private long id;
- public ManagedBatchImpl(String id, FileStore store, TupleBatch batch) {
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, "Add batch to BufferManager", batchAdded.incrementAndGet()); //$NON-NLS-1$
- this.id = id;
- this.store = store;
+ public ManagedBatchImpl(TupleBatch batch, BatchManagerImpl manager) {
+ id = batchAdded.incrementAndGet();
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, "Add batch to BufferManager", id); //$NON-NLS-1$
this.activeBatch = batch;
this.beginRow = batch.getBeginRow();
- List[] allTuples = batch.getAllTuples();
- if (allTuples.length > 0) {
- columnCount = allTuples[0].size();
- }
+ this.batchManager = manager;
}
private void addToCache(boolean update) {
@@ -130,19 +212,19 @@
if (batch == null) {
return; //already removed
}
- activeBatchColumnCount += columnCount;
+ activeBatchColumnCount += batchManager.columnCount;
TupleBufferInfo tbi = null;
if (update) {
- tbi = activeBatches.remove(this.id);
+ tbi = activeBatches.remove(batchManager.id);
} else {
- tbi = activeBatches.get(this.id);
+ tbi = activeBatches.get(batchManager.id);
}
if (tbi == null) {
tbi = new TupleBufferInfo();
update = true;
}
if (update) {
- activeBatches.put(this.id, tbi);
+ activeBatches.put(batchManager.id, tbi);
}
Assertion.isNull(tbi.batches.put(this.beginRow, this));
}
@@ -151,9 +233,9 @@
@Override
public TupleBatch getBatch(boolean cache, String[] types) throws TeiidComponentException {
long reads = readAttempts.incrementAndGet();
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, id, "getting batch", reads, "reference hits", referenceHit.get()); //$NON-NLS-1$ //$NON-NLS-2$
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, batchManager.id, "getting batch", reads, "reference hits", referenceHit.get()); //$NON-NLS-1$ //$NON-NLS-2$
synchronized (activeBatches) {
- TupleBufferInfo tbi = activeBatches.remove(this.id);
+ TupleBufferInfo tbi = activeBatches.remove(batchManager.id);
if (tbi != null) {
boolean put = true;
if (!cache) {
@@ -164,7 +246,7 @@
}
if (put) {
tbi.lastUsed = this.beginRow;
- activeBatches.put(this.id, tbi);
+ activeBatches.put(batchManager.id, tbi);
}
}
}
@@ -188,9 +270,11 @@
}
}
long count = readCount.incrementAndGet();
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, id, beginRow, "reading batch from disk, total reads:", count); //$NON-NLS-1$
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, batchManager.id, id, "reading batch from disk, total reads:", count); //$NON-NLS-1$
try {
- ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(store.createInputStream(this.offset), IO_BUFFER_SIZE));
+ this.batchManager.compactionLock.readLock().lock();
+ long[] info = batchManager.physicalMapping.get(this.id);
+ ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(batchManager.store.createInputStream(info[0]), IO_BUFFER_SIZE));
batch = new TupleBatch();
batch.setDataTypes(types);
batch.readExternal(ois);
@@ -202,28 +286,36 @@
}
return batch;
} catch(IOException e) {
- throw new TeiidComponentException(e, QueryExecPlugin.Util.getString("FileStoreageManager.error_reading", id)); //$NON-NLS-1$
+ throw new TeiidComponentException(e, QueryExecPlugin.Util.getString("FileStoreageManager.error_reading", batchManager.id)); //$NON-NLS-1$
} catch (ClassNotFoundException e) {
- throw new TeiidComponentException(e, QueryExecPlugin.Util.getString("FileStoreageManager.error_reading", id)); //$NON-NLS-1$
+ throw new TeiidComponentException(e, QueryExecPlugin.Util.getString("FileStoreageManager.error_reading", batchManager.id)); //$NON-NLS-1$
+ } finally {
+ this.batchManager.compactionLock.readLock().unlock();
}
}
}
public synchronized void persist() throws TeiidComponentException {
+ boolean lockheld = false;
try {
TupleBatch batch = activeBatch;
if (batch != null) {
if (!persistent) {
long count = writeCount.incrementAndGet();
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, id, beginRow, "writing batch to disk, total writes: ", count); //$NON-NLS-1$
- synchronized (store) {
- offset = store.getLength();
- OutputStream fsos = new BufferedOutputStream(store.createOutputStream(), IO_BUFFER_SIZE);
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, batchManager.id, id, "writing batch to disk, total writes: ", count); //$NON-NLS-1$
+ long offset = 0;
+ synchronized (batchManager.store) {
+ offset = batchManager.getOffset();
+ OutputStream fsos = new BufferedOutputStream(batchManager.store.createOutputStream(), IO_BUFFER_SIZE);
ObjectOutputStream oos = new ObjectOutputStream(fsos);
batch.writeExternal(oos);
oos.close();
+ long size = batchManager.store.getLength() - offset;
+ long[] info = new long[] {offset, size};
+ batchManager.physicalMapping.put(this.id, info);
+ batchManager.types.put(this.id, batch.getDataTypes());
}
- LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, id, beginRow, "batch written starting at:", offset); //$NON-NLS-1$
+ LogManager.logTrace(LogConstants.CTX_BUFFER_MGR, batchManager.id, id, "batch written starting at:", offset); //$NON-NLS-1$
}
this.batchReference = new WeakReference<TupleBatch>(batch);
}
@@ -232,23 +324,32 @@
} finally {
persistent = true;
activeBatch = null;
+ if (lockheld) {
+ this.batchManager.compactionLock.writeLock().unlock();
+ }
}
}
public void remove() {
synchronized (activeBatches) {
- TupleBufferInfo tbi = activeBatches.get(this.id);
- if (tbi != null && tbi.removeBatch(this.beginRow) != null && tbi.batches.isEmpty()) {
- activeBatches.remove(this.id);
+ TupleBufferInfo tbi = activeBatches.get(batchManager.id);
+ if (tbi != null && tbi.removeBatch(this.beginRow) != null) {
+ if (tbi.batches.isEmpty()) {
+ activeBatches.remove(batchManager.id);
+ }
}
}
+ long[] info = batchManager.physicalMapping.remove(id);
+ if (info != null) {
+ batchManager.unusedSpace.addAndGet(info[1]);
+ }
activeBatch = null;
batchReference = null;
}
@Override
public String toString() {
- return "ManagedBatch " + id + " " + activeBatch; //$NON-NLS-1$ //$NON-NLS-2$
+ return "ManagedBatch " + batchManager.id + " " + activeBatch; //$NON-NLS-1$ //$NON-NLS-2$
}
}
@@ -267,7 +368,7 @@
private StorageManager diskMgr;
- private AtomicLong currentTuple = new AtomicLong();
+ private AtomicLong tsId = new AtomicLong();
private AtomicLong batchAdded = new AtomicLong();
private AtomicLong readCount = new AtomicLong();
private AtomicLong writeCount = new AtomicLong();
@@ -342,37 +443,26 @@
@Override
public TupleBuffer createTupleBuffer(final List elements, String groupName,
TupleSourceType tupleSourceType) {
- final String newID = String.valueOf(this.currentTuple.getAndIncrement());
+ final String newID = String.valueOf(this.tsId.getAndIncrement());
- BatchManager batchManager = new BatchManager() {
- private FileStore store;
-
- @Override
- public ManagedBatch createManagedBatch(TupleBatch batch)
- throws TeiidComponentException {
- if (this.store == null) {
- this.store = createFileStore(newID);
- this.store.setCleanupReference(this);
- }
- ManagedBatchImpl mbi = new ManagedBatchImpl(newID, store, batch);
- mbi.addToCache(false);
- persistBatchReferences();
- return mbi;
- }
-
- @Override
- public void remove() {
- if (this.store != null) {
- this.store.remove();
- this.store = null;
- }
- }
- };
+ BatchManager batchManager = new BatchManagerImpl(newID, elements.size());
TupleBuffer tupleBuffer = new TupleBuffer(batchManager, newID, elements, getProcessorBatchSize());
LogManager.logDetail(LogConstants.CTX_BUFFER_MGR, "Creating TupleBuffer:", newID, "of type ", tupleSourceType); //$NON-NLS-1$ //$NON-NLS-2$
return tupleBuffer;
}
+ public STree createSTree(final List elements, String groupName, TupleSourceType tupleSourceType, int keyLength) {
+ final String newID = String.valueOf(this.tsId.getAndIncrement());
+
+ BatchManager bm = new BatchManagerImpl(newID, elements.size());
+ int[] compareIndexes = new int[keyLength];
+ for (int i = 1; i < compareIndexes.length; i++) {
+ compareIndexes[i] = i;
+ }
+ LogManager.logDetail(LogConstants.CTX_BUFFER_MGR, "Creating STree:", newID, "of type ", tupleSourceType); //$NON-NLS-1$ //$NON-NLS-2$
+ return new STree(bm, new ListNestedSortComparator(compareIndexes), getProcessorBatchSize(), keyLength, TupleBuffer.getTypeNames(elements));
+ }
+
@Override
public FileStore createFileStore(String name) {
LogManager.logDetail(LogConstants.CTX_BUFFER_MGR, "Creating FileStore:", name); //$NON-NLS-1$
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/impl/MemoryStorageManager.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/impl/MemoryStorageManager.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/impl/MemoryStorageManager.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -43,6 +43,7 @@
public void writeDirect(byte[] bytes, int offset, int length) throws TeiidComponentException {
if (getLength() + length > buffer.capacity()) {
ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2 + length);
+ buffer.position(0);
newBuffer.put(buffer);
buffer = newBuffer;
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/CodeTableCache.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/CodeTableCache.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/CodeTableCache.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -138,7 +138,7 @@
* @param results QueryResults of <List<List<keyValue, returnValue>>
* @throws TeiidProcessingException
*/
- public synchronized void loadTable(CacheKey cacheKey, List[] records) throws TeiidProcessingException {
+ public synchronized void loadTable(CacheKey cacheKey, List<List> records) throws TeiidProcessingException {
// Lookup the existing data
// Map of data: keyValue --> returnValue;
CodeTable table = codeTableCache.get(cacheKey);
@@ -148,7 +148,7 @@
// Determine whether the results should be added to code table cache
// Depends on size of results and available memory and system parameters
- int potentialSize = table.codeMap.size() + records.length;
+ int potentialSize = table.codeMap.size() + records.size();
if (potentialSize > maxCodeTableRecords) {
throw new TeiidProcessingException("ERR.018.005.0100", DQPPlugin.Util.getString("ERR.018.005.0100", "maxCodeTables")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@@ -158,9 +158,8 @@
}
// Add data: <List<List<keyValue, returnValue>> from results to the code table cache
- for ( int i = 0; i < records.length; i++ ) {
+ for (List<Object> record : records) {
// each record or row
- List<Object> record = records[i];
Object keyValue = record.get(0);
Object returnValue = record.get(1);
Object existing = table.codeMap.put(keyValue, returnValue);
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -72,7 +72,7 @@
import org.teiid.logging.MessageLevel;
import org.teiid.logging.CommandLogMessage.Event;
import org.teiid.query.processor.ProcessorDataManager;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
/**
@@ -144,9 +144,9 @@
static class ClientState {
List<RequestID> requests;
- TempTableStoreImpl tempTableStoreImpl;
+ TempTableStore tempTableStoreImpl;
- public ClientState(TempTableStoreImpl tableStoreImpl) {
+ public ClientState(TempTableStore tableStoreImpl) {
this.tempTableStoreImpl = tableStoreImpl;
}
@@ -236,7 +236,7 @@
synchronized (clientState) {
ClientState state = clientState.get(key);
if (state == null && create) {
- state = new ClientState(new TempTableStoreImpl(bufferManager, key, null));
+ state = new ClientState(new TempTableStore(bufferManager, key, null));
clientState.put(key, state);
}
return state;
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -406,7 +406,7 @@
processor.setNonBlocking(true); //process lookup as fully blocking
while (true) {
TupleBatch batch = processor.nextBatch();
- codeTableCache.loadTable(codeRequestId, batch.getAllTuples());
+ codeTableCache.loadTable(codeRequestId, batch.getTuples());
if (batch.getTerminationFlag()) {
break;
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -431,11 +431,8 @@
} else if (fromBuffer && isForwardOnly()) {
savedBatch = batch;
}
- int firstOffset = beginRow - batch.getBeginRow();
- List[] memoryRows = batch.getAllTuples();
- List[] rows = new List[count];
- System.arraycopy(memoryRows, firstOffset, rows, 0, endRow - beginRow + 1);
- batch = new TupleBatch(beginRow, rows);
+ List<List> memoryRows = batch.getTuples();
+ batch = new TupleBatch(beginRow, memoryRows.subList(beginRow - batch.getBeginRow(), endRow - batch.getBeginRow() + 1));
batch.setTerminationFlag(last);
} else if (!fromBuffer){
result = !isForwardOnly();
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -141,7 +141,11 @@
break;
case NodeConstants.Types.GROUP:
- estimateNodeCost(node, (List)node.getProperty(NodeConstants.Info.GROUP_COLS), metadata);
+ if (!node.hasCollectionProperty(NodeConstants.Info.GROUP_COLS)) {
+ setCardinalityEstimate(node, 1f);
+ } else {
+ estimateNodeCost(node, (List)node.getProperty(NodeConstants.Info.GROUP_COLS), metadata);
+ }
break;
case NodeConstants.Types.ACCESS:
case NodeConstants.Types.SORT:
@@ -153,7 +157,7 @@
break;
}
case NodeConstants.Types.NULL:
- setCardinalityEstimate(node, new Float(0));
+ setCardinalityEstimate(node, 0f);
break;
case NodeConstants.Types.PROJECT:
@@ -164,7 +168,7 @@
PlanNode child = node.getFirstChild();
childCost = (Float)child.getProperty(NodeConstants.Info.EST_CARDINALITY);
} else {
- childCost = new Float(1);
+ childCost = 1f;
}
setCardinalityEstimate(node, childCost);
break;
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanJoins.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanJoins.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanJoins.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -268,7 +268,7 @@
* If we failed to find direct criteria, but still have non-pushable or criteria to
* other groups we'll use additional checks
*/
- if ((!hasJoinCriteria || (hasJoinCriteria && joinCriteriaNodes.isEmpty())) && !canPushCrossJoin(metadata, context, accessNode1, accessNode2)) {
+ if ((!hasJoinCriteria || joinCriteriaNodes.isEmpty()) && !canPushCrossJoin(metadata, context, accessNode1, accessNode2)) {
continue;
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/CollectionTupleSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/CollectionTupleSource.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/processor/CollectionTupleSource.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -35,7 +35,7 @@
public class CollectionTupleSource implements TupleSource {
private Iterator<? extends List<?>> tuples;
- private List<SingleElementSymbol> schema;
+ private List<? extends SingleElementSymbol> schema;
public static CollectionTupleSource createUpdateCountTupleSource(int count) {
return new CollectionTupleSource(Arrays.asList(Arrays.asList(count)).iterator(), Command.getUpdateCommandSymbol());
@@ -46,7 +46,7 @@
}
public CollectionTupleSource(Iterator<? extends List<?>> tuples,
- List<SingleElementSymbol> schema) {
+ List<? extends SingleElementSymbol> schema) {
this.tuples = tuples;
this.schema = schema;
}
@@ -60,7 +60,7 @@
}
@Override
- public List<SingleElementSymbol> getSchema() {
+ public List<? extends SingleElementSymbol> getSchema() {
return schema;
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/batch/BatchedUpdatePlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/batch/BatchedUpdatePlan.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/processor/batch/BatchedUpdatePlan.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -145,9 +145,9 @@
openPlan();
}
// Execute nextBatch() on each plan in sequence
- List[] currentBatch = updatePlans[planIndex].nextBatch().getAllTuples(); // Can throw BlockedException
- for (int i = 0; i < currentBatch.length; i++, commandIndex++) {
- updateCounts[commandIndex] = currentBatch[i];
+ List<List> currentBatch = updatePlans[planIndex].nextBatch().getTuples(); // Can throw BlockedException
+ for (int i = 0; i < currentBatch.size(); i++, commandIndex++) {
+ updateCounts[commandIndex] = currentBatch.get(i);
}
// since we are done with the plan explicitly close it.
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -65,7 +65,7 @@
import org.teiid.query.sql.symbol.Reference;
import org.teiid.query.sql.util.VariableContext;
import org.teiid.query.tempdata.TempTableStore;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.util.CommandContext;
import org.teiid.query.util.ErrorMessageKeys;
@@ -205,7 +205,7 @@
context.setValue(entry.getKey(), value);
}
}
- tempTableStore = new TempTableStoreImpl(bufferMgr, getContext().getConnectionID(), null);
+ tempTableStore = new TempTableStore(bufferMgr, getContext().getConnectionID(), null);
this.dataMgr = new TempTableDataManager(dataMgr, tempTableStore);
}
this.evaluatedParams = true;
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/PlanExecutionNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/PlanExecutionNode.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/PlanExecutionNode.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -113,7 +113,7 @@
TupleBatch batch = plan.nextBatch();
- for (List tuple : batch.getAllTuples()) {
+ for (List tuple : batch.getTuples()) {
addBatchRow(tuple);
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectIntoNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectIntoNode.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/ProjectIntoNode.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -116,7 +116,9 @@
currentBatch = getChildren()[0].nextBatch(); // can throw BlockedException
this.batchRow = currentBatch.getBeginRow();
- if(currentBatch.getRowCount() == 0 && !this.intoGroup.isImplicitTempGroupSymbol()) {
+ //normally we would want to skip a 0 sized batch, but it typically represents the terminal batch
+ //and for implicit temp tables we need to issue an empty insert
+ if(currentBatch.getRowCount() == 0 && (!this.intoGroup.isImplicitTempGroupSymbol() || !currentBatch.getTerminationFlag())) {
continue;
}
} else if (currentBatch.getTerminationFlag() && this.batchRow > currentBatch.getEndRow()) {
@@ -131,10 +133,10 @@
List<Constant> parameters = new ArrayList<Constant>(intoElements.size());
for (int i = 0; i < intoElements.size(); i++) {
Constant value = new Constant(null, ((ElementSymbol)intoElements.get(i)).getType());
- value.setMultiValued(new ArrayList<Object>(currentBatch.getAllTuples().length));
+ value.setMultiValued(new ArrayList<Object>(currentBatch.getTuples().size()));
parameters.add(value);
}
- for (List row : currentBatch.getAllTuples()) {
+ for (List row : currentBatch.getTuples()) {
for (int i = 0; i < row.size(); i++) {
((List<Object>)parameters.get(i).getValue()).add(row.get(i));
}
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/UnionAllNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/UnionAllNode.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/UnionAllNode.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -117,7 +117,7 @@
TupleBatch outputBatch = null;
if(batch != null) {
// Rebuild the batch to reset the output row
- outputBatch = new TupleBatch(outputRow, batch.getAllTuples());
+ outputBatch = new TupleBatch(outputRow, batch.getTuples());
// This is the last unioned batch if:
// 1) This batch is a termination batch from the child
Modified: trunk/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/processor/xml/XMLPlan.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -61,7 +61,7 @@
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.tempdata.TempTableStore;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.util.CommandContext;
import org.teiid.query.util.ErrorMessageKeys;
import org.xml.sax.Attributes;
@@ -108,7 +108,7 @@
*/
public void initialize(CommandContext context, ProcessorDataManager dataMgr, BufferManager bufferMgr) {
setContext(context);
- TempTableStore tempTableStore = new TempTableStoreImpl(bufferMgr, context.getConnectionID(), (TempTableStore)context.getTempTableStore());
+ TempTableStore tempTableStore = new TempTableStore(bufferMgr, context.getConnectionID(), (TempTableStore)context.getTempTableStore());
//this.dataMgr = new StagingTableDataManager(new TempTableDataManager(dataMgr, tempTableStore), env);
this.dataMgr = new TempTableDataManager(dataMgr, tempTableStore);
this.bufferMgr = bufferMgr;
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/TempTableResolver.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -80,7 +80,7 @@
ResolverUtil.addTempTable(metadata, group, create.getColumns());
ResolverUtil.resolveGroup(((Create)command).getTable(), metadata);
- Set groups = new HashSet();
+ Set<GroupSymbol> groups = new HashSet<GroupSymbol>();
groups.add(((Create)command).getTable());
ResolverVisitor.resolveLanguageObject(command, groups, metadata);
} else if(command.getType() == Command.TYPE_DROP) {
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -299,10 +299,14 @@
try {
resolveFunction(obj, this.metadata.getFunctionLibrary());
} catch(QueryResolverException e) {
- if (unresolvedFunctions == null) {
- unresolvedFunctions = new LinkedHashMap<Function, QueryResolverException>();
+ if (ErrorMessageKeys.RESOLVER_0036.equals(e.getCode()) || ErrorMessageKeys.RESOLVER_0035.equals(e.getCode())) {
+ if (unresolvedFunctions == null) {
+ unresolvedFunctions = new LinkedHashMap<Function, QueryResolverException>();
+ }
+ unresolvedFunctions.put(obj, e);
+ } else {
+ handleException(e);
}
- unresolvedFunctions.put(obj, e);
} catch(TeiidComponentException e) {
handleException(e);
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Create.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Create.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Create.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -27,6 +27,7 @@
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
+import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
@@ -42,6 +43,8 @@
private List<ElementSymbol> columns = new ArrayList<ElementSymbol>();
+ private List<ElementSymbol> primaryKey = new ArrayList<ElementSymbol>();
+
public GroupSymbol getTable() {
return table;
}
@@ -54,6 +57,10 @@
return columns;
}
+ public List<ElementSymbol> getPrimaryKey() {
+ return primaryKey;
+ }
+
/**
* @see org.teiid.query.sql.lang.Command#getType()
* @since 5.5
@@ -70,7 +77,8 @@
Create copy = new Create();
GroupSymbol copyTable = (GroupSymbol) table.clone();
copy.setTable(copyTable);
- copy.setColumns(columns);
+ copy.setColumns(LanguageObject.Util.deepClone(columns, ElementSymbol.class));
+ copy.primaryKey = LanguageObject.Util.deepClone(primaryKey, ElementSymbol.class);
copyMetadataState(copy);
return copy;
}
@@ -128,6 +136,7 @@
Create other = (Create) obj;
return EquivalenceUtil.areEqual(getTable(), other.getTable()) &&
- EquivalenceUtil.areEqual(getColumns(), other.getColumns());
+ EquivalenceUtil.areEqual(getColumns(), other.getColumns()) &&
+ EquivalenceUtil.areEqual(getPrimaryKey(), other.getPrimaryKey());
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -306,6 +306,7 @@
preVisitVisitor(obj);
visitNode(obj.getTable());
visitNodes(obj.getColumns());
+ visitNodes(obj.getPrimaryKey());
postVisitVisitor(obj);
}
public void visit(Drop obj) {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -442,14 +442,28 @@
Iterator<ElementSymbol> iter = columns.iterator();
while(iter.hasNext()) {
ElementSymbol element = iter.next();
- element.setDisplayMode(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME);
- parts.add(registerNode(element));
+ outputShortName(element);
parts.add(SPACE);
parts.add(DataTypeManager.getDataTypeName(element.getType()));
if(iter.hasNext()) {
parts.add(", "); //$NON-NLS-1$
}
}
+ if (!obj.getPrimaryKey().isEmpty()) {
+ parts.add(", "); //$NON-NLS-1$
+ parts.add(PRIMARY);
+ parts.add(" "); //$NON-NLS-1$
+ parts.add(NonReserved.KEY);
+ parts.add(Tokens.LPAREN);
+ iter = obj.getPrimaryKey().iterator();
+ while(iter.hasNext()) {
+ outputShortName(iter.next());
+ if (iter.hasNext()) {
+ parts.add(", "); //$NON-NLS-1$
+ }
+ }
+ parts.add(Tokens.RPAREN);
+ }
parts.add(")"); //$NON-NLS-1$
}
@@ -746,8 +760,7 @@
parts.add(SPACE);
for (int i = 0; i < obj.getAsColumns().size(); i++) {
ElementSymbol symbol = (ElementSymbol)obj.getAsColumns().get(i);
- symbol.setDisplayMode(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME);
- parts.add(registerNode(symbol));
+ outputShortName(symbol);
parts.add(SPACE);
parts.add(DataTypeManager.getDataTypeName(symbol.getType()));
if (i < obj.getAsColumns().size() - 1) {
@@ -794,8 +807,7 @@
public void visit(SetClause obj) {
ElementSymbol symbol = obj.getSymbol();
- symbol.setDisplayMode(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME);
- parts.add(registerNode(symbol));
+ outputShortName(symbol);
parts.add(" = "); //$NON-NLS-1$
parts.add(registerNode(obj.getValue()));
}
@@ -1187,19 +1199,20 @@
}
public void visit(ElementSymbol obj) {
+ if (obj.getDisplayMode().equals(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME)) {
+ outputShortName(obj);
+ return;
+ }
String name = obj.getOutputName();
if (obj.getDisplayMode().equals(ElementSymbol.DisplayMode.FULLY_QUALIFIED)) {
name = obj.getName();
- } else if (obj.getDisplayMode().equals(ElementSymbol.DisplayMode.SHORT_OUTPUT_NAME)) {
- String shortName = SingleElementSymbol.getShortName(name);
- //TODO: this is a hack - since we default to not supporting double quoted identifiers, we need to fully qualify reserved
- if (!isReservedWord(shortName)) {
- name = shortName;
- }
}
-
outputDisplayName(name);
}
+
+ private void outputShortName(ElementSymbol obj) {
+ outputDisplayName(SingleElementSymbol.getShortName(obj.getOutputName()));
+ }
private void outputDisplayName(String name) {
String[] pathParts = name.split("\\."); //$NON-NLS-1$
Added: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -0,0 +1,349 @@
+/*
+ * 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.tempdata;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.common.buffer.BlockedException;
+import org.teiid.common.buffer.BufferManager;
+import org.teiid.common.buffer.STree;
+import org.teiid.common.buffer.TupleBuffer;
+import org.teiid.common.buffer.TupleSource;
+import org.teiid.common.buffer.BufferManager.TupleSourceType;
+import org.teiid.common.buffer.STree.TupleBrowser;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.query.QueryPlugin;
+import org.teiid.query.eval.Evaluator;
+import org.teiid.query.processor.CollectionTupleSource;
+import org.teiid.query.processor.relational.RelationalNode;
+import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.lang.OrderBy;
+import org.teiid.query.sql.lang.SetClauseList;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
+
+/**
+ * A Teiid Temp Table
+ * TODO: an update will not happen unless the tuplesource is accessed
+ * TODO: better handling for blocked exceptions (should be rare)
+ * TODO: non-pk updates/deletes through the browser
+ */
+class TempTable {
+
+ private abstract class UpdateTupleSource implements TupleSource {
+ private TupleSource ts;
+ protected final Map lookup;
+ protected final Evaluator eval;
+ private final Criteria crit;
+ protected int updateCount = 0;
+ protected boolean done;
+ private List currentTuple;
+
+ protected TupleBuffer undoLog;
+
+ UpdateTupleSource(Criteria crit, TupleSource ts) throws TeiidComponentException {
+ this.ts = ts;
+ this.lookup = RelationalNode.createLookupMap(columns);
+ this.eval = new Evaluator(lookup, null, null);
+ this.crit = crit;
+ this.undoLog = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
+ }
+
+ void process() throws TeiidComponentException, TeiidProcessingException {
+ //still have to worry about blocked exceptions...
+ while (currentTuple != null || (currentTuple = ts.nextTuple()) != null) {
+ if (crit == null || eval.evaluate(crit, currentTuple)) {
+ tuplePassed(currentTuple);
+ updateCount++;
+ undoLog.addTuple(currentTuple);
+ }
+ currentTuple = null;
+ }
+ }
+
+ @Override
+ public List<?> nextTuple() throws TeiidComponentException,
+ TeiidProcessingException {
+ if (done) {
+ return null;
+ }
+ try {
+ process();
+ done = true;
+ } catch (BlockedException e) {
+ //this is horrible...
+ throw e;
+ } finally {
+ if (!done) {
+ TupleSource undoTs = undoLog.createIndexedTupleSource();
+ List<?> tuple = null;
+ try {
+ while ((tuple = undoTs.nextTuple()) != null) {
+ undo(tuple);
+ }
+ } catch (TeiidException e) {
+
+ }
+ }
+ }
+ return Arrays.asList(updateCount);
+ }
+
+ protected abstract void tuplePassed(List tuple) throws BlockedException, TeiidComponentException, TeiidProcessingException;
+
+ protected abstract void undo(List tuple) throws TeiidComponentException, TeiidProcessingException;
+
+ @Override
+ public List<SingleElementSymbol> getSchema() {
+ return Command.getUpdateCommandSymbol();
+ }
+
+ @Override
+ public int available() {
+ return 0;
+ }
+
+ @Override
+ public void closeSource() {
+ ts.closeSource();
+ undoLog.remove();
+ }
+
+ }
+
+ private STree tree;
+ private AtomicInteger rowId;
+ private List<ElementSymbol> columns;
+ private BufferManager bm;
+ private String sessionID;
+
+ TempTable(BufferManager bm, List<ElementSymbol> columns, int primaryKeyLength, String sessionID) {
+ this.bm = bm;
+ if (primaryKeyLength == 0) {
+ ElementSymbol id = new ElementSymbol("rowId"); //$NON-NLS-1$
+ id.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ columns.add(0, id);
+ //we start at max, since the default sort order is ascending
+ rowId = new AtomicInteger(Integer.MAX_VALUE);
+ tree = bm.createSTree(columns, sessionID, TupleSourceType.PROCESSOR, 1);
+ } else {
+ tree = bm.createSTree(columns, sessionID, TupleSourceType.PROCESSOR, primaryKeyLength);
+ }
+ this.columns = columns;
+ this.sessionID = sessionID;
+ }
+
+ public TupleSource createTupleSource(List<Criteria> conditions, OrderBy orderBy) throws TeiidComponentException {
+ return createTupleSource(conditions, orderBy, true);
+ }
+
+ private TupleSource createTupleSource(List<Criteria> conditions, OrderBy orderBy, boolean filterRowId) throws TeiidComponentException {
+ TupleBuffer tb = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
+ TupleBrowser browser = tree.browse(null, null, OrderBy.ASC);
+ List next = null;
+ while ((next = browser.next()) != null) {
+ if (rowId != null && filterRowId) {
+ next = next.subList(1, next.size());
+ }
+ tb.addTuple(next);
+ }
+ tb.close();
+ return tb.createIndexedTupleSource(true);
+ }
+
+ public int getRowCount() {
+ return tree.getRowCount();
+ }
+
+ public int truncate() {
+ return tree.truncate();
+ }
+
+ public void remove() {
+ tree.remove();
+ }
+
+ public List<ElementSymbol> getColumns() {
+ if (rowId != null) {
+ return columns.subList(1, columns.size());
+ }
+ return columns;
+ }
+
+ public TupleSource insert(List<List<Object>> tuples) throws TeiidComponentException {
+ UpdateTupleSource uts = new UpdateTupleSource(null, new CollectionTupleSource(tuples.iterator(), getColumns())) {
+
+ protected void tuplePassed(List tuple)
+ throws BlockedException, TeiidComponentException, TeiidProcessingException {
+ if (rowId != null) {
+ tuple.add(0, rowId.getAndAdd(-1));
+ }
+ insertTuple(tuple);
+ }
+
+ @Override
+ protected void undo(List tuple) throws TeiidComponentException {
+ deleteTuple(tuple);
+ }
+
+ };
+ return uts;
+ }
+
+ public TupleSource update(Criteria crit, final SetClauseList update) throws TeiidComponentException {
+ final boolean primaryKeyChangePossible = canChangePrimaryKey(update);
+
+ UpdateTupleSource uts = new UpdateTupleSource(crit, createTupleSource(null, null, false)) {
+
+ protected TupleBuffer changeSet;
+ protected TupleSource changeSetProcessor;
+
+ @Override
+ protected void tuplePassed(List tuple)
+ throws ExpressionEvaluationException,
+ BlockedException, TeiidComponentException {
+ List<Object> newTuple = new ArrayList<Object>(tuple);
+ for (Map.Entry<ElementSymbol, Expression> entry : update.getClauseMap().entrySet()) {
+ newTuple.set((Integer)lookup.get(entry.getKey()), eval.evaluate(entry.getValue(), tuple));
+ }
+ if (primaryKeyChangePossible) {
+ deleteTuple(tuple);
+ if (changeSet == null) {
+ changeSet = bm.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
+ }
+ changeSet.addTuple(newTuple);
+ } else {
+ updateTuple(newTuple);
+ }
+ }
+
+ @Override
+ void process() throws TeiidComponentException,
+ TeiidProcessingException {
+ super.process();
+ //existing tuples have been removed
+ //changeSet contains possible updates
+ if (primaryKeyChangePossible) {
+ if (changeSetProcessor == null) {
+ changeSetProcessor = new UpdateTupleSource(null, changeSet.createIndexedTupleSource(true)) {
+ @Override
+ protected void tuplePassed(List tuple) throws BlockedException,
+ TeiidComponentException, TeiidProcessingException {
+ insertTuple(tuple);
+ }
+
+ @Override
+ protected void undo(List tuple) throws TeiidComponentException,
+ TeiidProcessingException {
+ deleteTuple(tuple);
+ }
+
+ };
+ }
+ changeSetProcessor.nextTuple(); //when this returns, we're up to date
+ }
+ }
+
+ @Override
+ protected void undo(List tuple) throws TeiidComponentException, TeiidProcessingException {
+ if (primaryKeyChangePossible) {
+ insertTuple(tuple);
+ } else {
+ updateTuple(tuple);
+ }
+ }
+
+ @Override
+ public void closeSource() {
+ super.closeSource();
+ if (changeSetProcessor != null) {
+ changeSetProcessor.closeSource(); // causes a revert of the change set
+ }
+ if (changeSet != null) {
+ changeSet.remove();
+ }
+ }
+
+ };
+ return uts;
+ }
+
+ private boolean canChangePrimaryKey(final SetClauseList update) {
+ if (rowId == null) {
+ Set<ElementSymbol> affectedColumns = new HashSet<ElementSymbol>(update.getClauseMap().keySet());
+ affectedColumns.retainAll(columns.subList(0, tree.getKeyLength()));
+ if (!affectedColumns.isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public TupleSource delete(Criteria crit) throws TeiidComponentException {
+ UpdateTupleSource uts = new UpdateTupleSource(crit, createTupleSource(null, null, false)) {
+ @Override
+ protected void tuplePassed(List tuple)
+ throws ExpressionEvaluationException,
+ BlockedException, TeiidComponentException {
+ deleteTuple(tuple);
+ }
+
+ @Override
+ protected void undo(List tuple) throws TeiidComponentException, TeiidProcessingException {
+ insertTuple(tuple);
+ }
+ };
+ return uts;
+ }
+
+ private void insertTuple(List<Object> list) throws TeiidComponentException, TeiidProcessingException {
+ if (tree.insert(list, false) != null) {
+ throw new TeiidProcessingException(QueryPlugin.Util.getString("TempTable.duplicate_key")); //$NON-NLS-1$
+ }
+ }
+
+ private void deleteTuple(List<?> tuple) throws TeiidComponentException {
+ if (tree.remove(tuple) == null) {
+ throw new AssertionError("Delete failed"); //$NON-NLS-1$
+ }
+ }
+
+ private void updateTuple(List<?> tuple) throws TeiidComponentException {
+ if (tree.insert(tuple, true) == null) {
+ throw new AssertionError("Update failed"); //$NON-NLS-1$
+ }
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTable.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -22,32 +22,238 @@
package org.teiid.query.tempdata;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
-import org.teiid.common.buffer.TupleBuffer;
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.api.exception.query.QueryProcessingException;
+import org.teiid.common.buffer.BlockedException;
+import org.teiid.common.buffer.BufferManager;
import org.teiid.common.buffer.TupleSource;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.eval.Evaluator;
+import org.teiid.query.execution.QueryExecPlugin;
import org.teiid.query.metadata.TempMetadataStore;
+import org.teiid.query.processor.CollectionTupleSource;
import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.Create;
+import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.lang.Delete;
+import org.teiid.query.sql.lang.Drop;
+import org.teiid.query.sql.lang.Insert;
+import org.teiid.query.sql.lang.ProcedureContainer;
+import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.Update;
+import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.GroupSymbol;
-
/**
* @since 5.5
*/
-public interface TempTableStore {
+public class TempTableStore {
+
+ private BufferManager buffer;
+ private TempMetadataStore tempMetadataStore = new TempMetadataStore();
+ private Map<String, TempTable> groupToTupleSourceID = new HashMap<String, TempTable>();
+ private String sessionID;
+ private TempTableStore parentTempTableStore;
- void removeTempTables() throws TeiidComponentException;
-
- TempMetadataStore getMetadataStore();
+ public TempTableStore(BufferManager buffer, String sessionID, TempTableStore parentTempTableStore) {
+ this.buffer = buffer;
+ this.sessionID = sessionID;
+ this.parentTempTableStore = parentTempTableStore;
+ }
- public TupleSource registerRequest(Command command) throws TeiidComponentException, TeiidProcessingException;
+ void addTempTable(Create create, boolean removeExistingTable) throws QueryProcessingException{
+ String tempTableName = create.getTable().getName().toUpperCase();
+ if(tempMetadataStore.getTempGroupID(tempTableName) != null) {
+ if(!removeExistingTable) {
+ throw new QueryProcessingException(QueryExecPlugin.Util.getString("TempTableStore.table_exist_error", tempTableName));//$NON-NLS-1$
+ }
+ removeTempTableByName(tempTableName);
+ }
+ List<ElementSymbol> columns = create.getColumns();
+
+ boolean hasKey = !create.getPrimaryKey().isEmpty();
+ columns = new ArrayList<ElementSymbol>(create.getColumns());
+
+ if (hasKey) {
+ //reorder the columns to put the key in front
+ List<ElementSymbol> primaryKey = create.getPrimaryKey();
+ columns.removeAll(primaryKey);
+ columns.addAll(0, primaryKey);
+ }
+ //add metadata
+ tempMetadataStore.addTempGroup(tempTableName, columns, false, true);
+ TempTable tempTable = new TempTable(buffer, columns, create.getPrimaryKey().size(), sessionID);
+ groupToTupleSourceID.put(tempTableName, tempTable);
+ }
+
+ public void removeTempTableByName(String tempTableName) {
+ tempMetadataStore.removeTempGroup(tempTableName);
+ TempTable table = this.groupToTupleSourceID.remove(tempTableName);
+ if(table != null) {
+ table.remove();
+ }
+ }
- public boolean hasTempTable(Command command);
+ public TempMetadataStore getMetadataStore() {
+ return tempMetadataStore;
+ }
+
+ public TupleSource registerRequest(Command command) throws TeiidComponentException, TeiidProcessingException{
+ if (command instanceof Query) {
+ Query query = (Query)command;
+ GroupSymbol group = (GroupSymbol)query.getFrom().getGroups().get(0);
+ if (!group.isTempGroupSymbol()) {
+ return null;
+ }
+ TempTable table = getTempTable(group.getNonCorrelationName().toUpperCase(), command);
+ return table.createTupleSource(Criteria.separateCriteriaByAnd(query.getCriteria()), query.getOrderBy());
+ }
+ if (command instanceof ProcedureContainer) {
+ GroupSymbol group = ((ProcedureContainer)command).getGroup();
+ if (!group.isTempGroupSymbol()) {
+ return null;
+ }
+ final String groupKey = group.getNonCorrelationName().toUpperCase();
+ final TempTable table = getTempTable(groupKey, command);
+ if (command instanceof Insert) {
+ List<List<Object>> tuples = getBulkRows((Insert)command, table.getColumns());
+ if (tuples.isEmpty()) {
+ return CollectionTupleSource.createUpdateCountTupleSource(0);
+ }
+ return table.insert(tuples);
+ }
+ if (command instanceof Update) {
+ final Update update = (Update)command;
+ final Criteria crit = update.getCriteria();
+ return table.update(crit, update.getChangeList());
+ }
+ if (command instanceof Delete) {
+ final Delete delete = (Delete)command;
+ final Criteria crit = delete.getCriteria();
+ if (crit == null) {
+ //because we are non-transactional, just use a truncate
+ int rows = table.truncate();
+ return CollectionTupleSource.createUpdateCountTupleSource(rows);
+ }
+ return table.delete(crit);
+ }
+ }
+ if (command instanceof Create) {
+ Create create = (Create)command;
+ addTempTable(create, false);
+ return CollectionTupleSource.createUpdateCountTupleSource(0);
+ }
+ if (command instanceof Drop) {
+ String tempTableName = ((Drop)command).getTable().getName().toUpperCase();
+ removeTempTableByName(tempTableName);
+ return CollectionTupleSource.createUpdateCountTupleSource(0);
+ }
+ return null;
+ }
- public Set getAllTempTables();
+ public void removeTempTables() {
+ for (String name : new ArrayList<String>( groupToTupleSourceID.keySet() )) {
+ removeTempTableByName(name);
+ }
+ }
- public void removeTempTableByName(String tempTableName) throws TeiidComponentException;
+ private TempTable getTempTable(String tempTableID, Command command) throws QueryProcessingException{
+ TempTable tsID = groupToTupleSourceID.get(tempTableID);
+ if(tsID != null) {
+ return tsID;
+ }
+ if(this.parentTempTableStore != null){
+ tsID = this.parentTempTableStore.groupToTupleSourceID.get(tempTableID);
+ if(tsID != null) {
+ return tsID;
+ }
+ }
+ //allow implicit temp group definition
+ List<ElementSymbol> columns = null;
+ if (command instanceof Insert) {
+ Insert insert = (Insert)command;
+ GroupSymbol group = insert.getGroup();
+ if(group.isImplicitTempGroupSymbol()) {
+ columns = insert.getVariables();
+ }
+ }
+ if (columns == null) {
+ throw new QueryProcessingException(QueryExecPlugin.Util.getString("TempTableStore.table_doesnt_exist_error", tempTableID)); //$NON-NLS-1$
+ }
+ Create create = new Create();
+ create.setTable(new GroupSymbol(tempTableID));
+ create.setColumns(columns);
+ addTempTable(create, true);
+ return groupToTupleSourceID.get(tempTableID);
+ }
+
+ public static List<List<Object>> getBulkRows(Insert insert, List<ElementSymbol> elements) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
+ int bulkRowCount = 1;
+ if (insert.isBulk()) {
+ Constant c = (Constant)insert.getValues().get(0);
+ bulkRowCount = ((List<?>)c.getValue()).size();
+ }
+
+ List<List<Object>> tuples = new ArrayList<List<Object>>(bulkRowCount);
+
+ for (int row = 0; row < bulkRowCount; row++) {
+ List<Object> currentRow = new ArrayList<Object>(insert.getValues().size());
+ for (ElementSymbol symbol : elements) {
+ int index = insert.getVariables().indexOf(symbol);
+ Object value = null;
+ if (index != -1) {
+ if (insert.isBulk()) {
+ Constant multiValue = (Constant)insert.getValues().get(index);
+ value = ((List<?>)multiValue.getValue()).get(row);
+ } else {
+ Expression expr = (Expression)insert.getValues().get(index);
+ value = Evaluator.evaluate(expr);
+ }
+ }
+ currentRow.add(value);
+ }
+ tuples.add(currentRow);
+ }
+ return tuples;
+ }
- public TupleBuffer getTupleSourceID(String tempTableName);
+ public boolean hasTempTable(Command command){
+ switch (command.getType()) {
+ case Command.TYPE_INSERT:
+ {
+ Insert insert = (Insert)command;
+ GroupSymbol group = insert.getGroup();
+ return group.isTempGroupSymbol();
+ }
+ case Command.TYPE_QUERY:
+ {
+ if(command instanceof Query) {
+ Query query = (Query)command;
+ GroupSymbol group = (GroupSymbol)query.getFrom().getGroups().get(0);
+ return group.isTempGroupSymbol();
+ }
+ break;
+ }
+ case Command.TYPE_CREATE:
+ return true;
+ case Command.TYPE_DROP:
+ return true;
+ }
+ return false;
+ }
+
+ public Set<String> getAllTempTables() {
+ return new HashSet<String>(this.groupToTupleSourceID.keySet());
+ }
+
}
Deleted: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStoreImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStoreImpl.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStoreImpl.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -1,373 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.query.tempdata;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.teiid.api.exception.query.ExpressionEvaluationException;
-import org.teiid.api.exception.query.QueryMetadataException;
-import org.teiid.api.exception.query.QueryProcessingException;
-import org.teiid.common.buffer.BlockedException;
-import org.teiid.common.buffer.BufferManager;
-import org.teiid.common.buffer.TupleBuffer;
-import org.teiid.common.buffer.TupleSource;
-import org.teiid.common.buffer.BufferManager.TupleSourceType;
-import org.teiid.core.TeiidComponentException;
-import org.teiid.core.TeiidProcessingException;
-import org.teiid.query.eval.Evaluator;
-import org.teiid.query.execution.QueryExecPlugin;
-import org.teiid.query.metadata.TempMetadataAdapter;
-import org.teiid.query.metadata.TempMetadataStore;
-import org.teiid.query.processor.CollectionTupleSource;
-import org.teiid.query.processor.relational.RelationalNode;
-import org.teiid.query.resolver.util.ResolverUtil;
-import org.teiid.query.sql.lang.Command;
-import org.teiid.query.sql.lang.Create;
-import org.teiid.query.sql.lang.Criteria;
-import org.teiid.query.sql.lang.Delete;
-import org.teiid.query.sql.lang.Drop;
-import org.teiid.query.sql.lang.Insert;
-import org.teiid.query.sql.lang.ProcedureContainer;
-import org.teiid.query.sql.lang.Query;
-import org.teiid.query.sql.lang.Update;
-import org.teiid.query.sql.symbol.Constant;
-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.symbol.SingleElementSymbol;
-
-
-/**
- * @since 5.5
- */
-public class TempTableStoreImpl implements TempTableStore {
-
- private abstract class UpdateTupleSource implements TupleSource {
- private final String groupKey;
- private final TupleBuffer oldBuffer;
- private final TupleSource ts;
- protected final Map lookup;
- private final TupleBuffer newBuffer;
- protected final Evaluator eval;
- private final Criteria crit;
- protected int updateCount = 0;
- private boolean done;
- private List<?> currentTuple;
-
- private UpdateTupleSource(String groupKey, TupleBuffer tsId, Criteria crit) throws TeiidComponentException {
- this.groupKey = groupKey;
- this.oldBuffer = tsId;
- this.ts = tsId.createIndexedTupleSource();
- List columns = tsId.getSchema();
- this.lookup = RelationalNode.createLookupMap(columns);
- this.newBuffer = buffer.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
- this.eval = new Evaluator(lookup, null, null);
- this.crit = crit;
- }
-
- @Override
- public List<?> nextTuple() throws TeiidComponentException,
- TeiidProcessingException {
- if (done) {
- return null;
- }
-
- //still have to worry about blocked exceptions...
- while (currentTuple != null || (currentTuple = ts.nextTuple()) != null) {
- if (eval.evaluate(crit, currentTuple)) {
- tuplePassed(currentTuple);
- } else {
- tupleFailed(currentTuple);
- }
- currentTuple = null;
- }
- newBuffer.close();
- groupToTupleSourceID.put(groupKey, newBuffer);
- oldBuffer.remove();
- done = true;
- return Arrays.asList(updateCount);
- }
-
- protected void addTuple(List<?> tuple) throws TeiidComponentException {
- newBuffer.addTuple(tuple);
- }
-
- protected abstract void tuplePassed(List<?> tuple) throws ExpressionEvaluationException, BlockedException, TeiidComponentException;
-
- protected abstract void tupleFailed(List<?> tuple) throws TeiidComponentException;
-
- @Override
- public List<SingleElementSymbol> getSchema() {
- return Command.getUpdateCommandSymbol();
- }
-
- @Override
- public void closeSource() {
-
- }
-
- @Override
- public int available() {
- return 0;
- }
- }
-
- private BufferManager buffer;
- private TempMetadataStore tempMetadataStore = new TempMetadataStore();
- private Map<String, TupleBuffer> groupToTupleSourceID = new HashMap<String, TupleBuffer>();
- private String sessionID;
- private TempTableStore parentTempTableStore;
-
- public TempTableStoreImpl(BufferManager buffer, String sessionID, TempTableStore parentTempTableStore) {
- this.buffer = buffer;
- this.sessionID = sessionID;
- this.parentTempTableStore = parentTempTableStore;
- }
-
- public void addTempTable(String tempTableName, List columns, boolean removeExistingTable) throws TeiidComponentException, QueryProcessingException{
- if(tempMetadataStore.getTempGroupID(tempTableName) != null) {
- if(!removeExistingTable) {
- throw new QueryProcessingException(QueryExecPlugin.Util.getString("TempTableStore.table_exist_error", tempTableName));//$NON-NLS-1$
- }
- removeTempTableByName(tempTableName);
- }
-
- //add metadata
- tempMetadataStore.addTempGroup(tempTableName, columns, false, true);
- //create tuple source
- TupleBuffer tupleBuffer = buffer.createTupleBuffer(columns, sessionID, TupleSourceType.PROCESSOR);
- tupleBuffer.setFinal(true); //final, but not closed so that we can append on insert
- groupToTupleSourceID.put(tempTableName, tupleBuffer);
- }
-
- public void removeTempTableByName(String tempTableName) throws TeiidComponentException {
- tempMetadataStore.removeTempGroup(tempTableName);
- TupleBuffer tsId = this.groupToTupleSourceID.remove(tempTableName);
- if(tsId != null) {
- tsId.remove();
- }
- }
-
- public TempMetadataStore getMetadataStore() {
- return tempMetadataStore;
- }
-
- public TupleSource registerRequest(Command command) throws TeiidComponentException, ExpressionEvaluationException, QueryProcessingException{
- if (command instanceof Query) {
- Query query = (Query)command;
- GroupSymbol group = (GroupSymbol)query.getFrom().getGroups().get(0);
- if (!group.isTempGroupSymbol()) {
- return null;
- }
- TupleBuffer tsId = getTupleSourceID(group.getNonCorrelationName().toUpperCase(), command);
- return tsId.createIndexedTupleSource();
- }
- if (command instanceof ProcedureContainer) {
- GroupSymbol group = ((ProcedureContainer)command).getGroup();
- if (!group.isTempGroupSymbol()) {
- return null;
- }
- final String groupKey = group.getNonCorrelationName().toUpperCase();
- final TupleBuffer tsId = getTupleSourceID(groupKey, command);
- if (command instanceof Insert) {
- return addTuple((Insert)command, tsId);
- }
- if (command instanceof Update) {
- final Update update = (Update)command;
- final Criteria crit = update.getCriteria();
- return new UpdateTupleSource(groupKey, tsId, crit) {
- @Override
- protected void tuplePassed(List<?> tuple)
- throws ExpressionEvaluationException,
- BlockedException, TeiidComponentException {
- List<Object> newTuple = new ArrayList<Object>(tuple);
- for (Map.Entry<ElementSymbol, Expression> entry : update.getChangeList().getClauseMap().entrySet()) {
- newTuple.set((Integer)lookup.get(entry.getKey()), eval.evaluate(entry.getValue(), tuple));
- }
- updateCount++;
- addTuple(newTuple);
- }
-
- protected void tupleFailed(java.util.List<?> tuple) throws TeiidComponentException {
- addTuple(tuple);
- }
- };
- }
- if (command instanceof Delete) {
- final Delete delete = (Delete)command;
- final Criteria crit = delete.getCriteria();
- if (crit == null) {
- int rows = tsId.getRowCount();
- addTempTable(groupKey, tsId.getSchema(), true);
- return CollectionTupleSource.createUpdateCountTupleSource(rows);
- }
- return new UpdateTupleSource(groupKey, tsId, crit) {
- @Override
- protected void tuplePassed(List<?> tuple)
- throws ExpressionEvaluationException,
- BlockedException, TeiidComponentException {
- updateCount++;
- }
-
- protected void tupleFailed(java.util.List<?> tuple) throws TeiidComponentException {
- addTuple(tuple);
- }
- };
- }
- }
- if (command instanceof Create) {
- addTempTable(((Create)command).getTable().getName().toUpperCase(), ((Create)command).getColumns(), false);
- return CollectionTupleSource.createUpdateCountTupleSource(0);
- }
- if (command instanceof Drop) {
- String tempTableName = ((Drop)command).getTable().getName().toUpperCase();
- removeTempTableByName(tempTableName);
- return CollectionTupleSource.createUpdateCountTupleSource(0);
- }
- return null;
- }
-
- public void removeTempTables() throws TeiidComponentException{
- for (String name : new ArrayList<String>( groupToTupleSourceID.keySet() )) {
- removeTempTableByName(name);
- }
- }
-
- private TupleBuffer getTupleSourceID(String tempTableID, Command command) throws TeiidComponentException, QueryProcessingException{
- TupleBuffer tsID = groupToTupleSourceID.get(tempTableID);
- if(tsID != null) {
- return tsID;
- }
- if(this.parentTempTableStore != null){
- tsID = this.parentTempTableStore.getTupleSourceID(tempTableID);
- if(tsID != null) {
- return tsID;
- }
- }
- //allow implicit temp group definition
- List columns = null;
- if (command instanceof Insert) {
- Insert insert = (Insert)command;
- GroupSymbol group = insert.getGroup();
- if(group.isImplicitTempGroupSymbol()) {
- columns = insert.getVariables();
- }
- }
- if (columns == null) {
- throw new QueryProcessingException(QueryExecPlugin.Util.getString("TempTableStore.table_doesnt_exist_error", tempTableID)); //$NON-NLS-1$
- }
- addTempTable(tempTableID, columns, true);
- return groupToTupleSourceID.get(tempTableID);
- }
-
- private TupleSource addTuple(Insert insert, TupleBuffer tsId) throws TeiidComponentException, ExpressionEvaluationException {
- GroupSymbol group = insert.getGroup();
- int tuplesAdded = 0;
- try {
- List<ElementSymbol> elements = ResolverUtil.resolveElementsInGroup(group, new TempMetadataAdapter(null, tempMetadataStore));
-
- List<List<Object>> tuples = getBulkRows(insert, elements);
-
- for (List<Object> list : tuples) {
- tsId.addTuple(list);
- }
- //TODO: this leads to fragmented batches, which may require recreating the table
- tsId.saveBatch();
-
- tuplesAdded = tuples.size();
- } catch (QueryMetadataException err) {
- throw new TeiidComponentException(err);
- }
-
- return CollectionTupleSource.createUpdateCountTupleSource(tuplesAdded);
- }
-
- public static List<List<Object>> getBulkRows(Insert insert, List<ElementSymbol> elements) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
- int bulkRowCount = 1;
- if (insert.isBulk()) {
- Constant c = (Constant)insert.getValues().get(0);
- bulkRowCount = ((List<?>)c.getValue()).size();
- }
-
- List<List<Object>> tuples = new ArrayList<List<Object>>(bulkRowCount);
-
- for (int row = 0; row < bulkRowCount; row++) {
- List<Object> currentRow = new ArrayList<Object>(insert.getValues().size());
- for (ElementSymbol symbol : elements) {
- int index = insert.getVariables().indexOf(symbol);
- Object value = null;
- if (index != -1) {
- if (insert.isBulk()) {
- Constant multiValue = (Constant)insert.getValues().get(index);
- value = ((List<?>)multiValue.getValue()).get(row);
- } else {
- Expression expr = (Expression)insert.getValues().get(index);
- value = Evaluator.evaluate(expr);
- }
- }
- currentRow.add(value);
- }
- tuples.add(currentRow);
- }
- return tuples;
- }
-
- public boolean hasTempTable(Command command){
- switch (command.getType()) {
- case Command.TYPE_INSERT:
- {
- Insert insert = (Insert)command;
- GroupSymbol group = insert.getGroup();
- return group.isTempGroupSymbol();
- }
- case Command.TYPE_QUERY:
- {
- if(command instanceof Query) {
- Query query = (Query)command;
- GroupSymbol group = (GroupSymbol)query.getFrom().getGroups().get(0);
- return group.isTempGroupSymbol();
- }
- break;
- }
- case Command.TYPE_CREATE:
- return true;
- case Command.TYPE_DROP:
- return true;
- }
- return false;
- }
-
- public Set<String> getAllTempTables() {
- return new HashSet<String>(this.groupToTupleSourceID.keySet());
- }
-
- public TupleBuffer getTupleSourceID(String tempTableName) {
- return groupToTupleSourceID.get(tempTableName.toUpperCase());
- }
-}
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-07-23 21:44:19 UTC (rev 2371)
@@ -500,6 +500,7 @@
Create create = new Create();
String table = null;
List columns = null;
+ String pkId = null;
}
{
<CREATE> <LOCAL> <TEMPORARY> <TABLE>
@@ -512,6 +513,18 @@
{
create.setColumns(columns);
}
+ [<COMMA> <PRIMARY> nonReserved("KEY") <LPAREN>
+ pkId = id()
+ {
+ create.getPrimaryKey().add(new ElementSymbol(validateElementName(pkId)));
+ }
+ (<COMMA> pkId = id()
+ {
+ create.getPrimaryKey().add(new ElementSymbol(validateElementName(pkId)));
+ }
+ )*
+ <RPAREN>
+ ]
<RPAREN>
{
return create;
@@ -1087,7 +1100,7 @@
symbol.setType(DataTypeManager.getDataTypeClass(type.getValue().toString()));
elements.add(symbol);
}
- (<COMMA>
+ (LOOKAHEAD(2) <COMMA>
element = id()
type = dataType()
{
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-07-23 21:44:19 UTC (rev 2371)
@@ -945,4 +945,6 @@
WorkerPool.New_thread=Created worker thread "{0}".
WorkerPool.uncaughtException=Uncaught exception processing work
-XMLSystemFunctions.invalid_namespaces=Invalid namespaces supplied for XPath expression - ''{0}''
\ No newline at end of file
+XMLSystemFunctions.invalid_namespaces=Invalid namespaces supplied for XPath expression - ''{0}''
+
+TempTable.duplicate_key=Duplicate key
\ No newline at end of file
Added: trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -0,0 +1,62 @@
+/*
+ * 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.common.buffer.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.teiid.common.buffer.BufferManager;
+import org.teiid.common.buffer.BufferManagerFactory;
+import org.teiid.common.buffer.STree;
+import org.teiid.common.buffer.BufferManager.TupleSourceType;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.query.sql.symbol.ElementSymbol;
+
+public class TestSTree {
+
+ @Test public void testRemoveAll() throws TeiidComponentException, IOException {
+ BufferManager bm = BufferManagerFactory.getStandaloneBufferManager();
+ ElementSymbol e1 = new ElementSymbol("x");
+ e1.setType(Integer.class);
+ ElementSymbol e2 = new ElementSymbol("y");
+ e2.setType(String.class);
+ List elements = Arrays.asList(e1, e2);
+ STree map = bm.createSTree(elements, "1", TupleSourceType.PROCESSOR, 1);
+
+ for (int i = 20000; i > 0; i--) {
+ map.insert(Arrays.asList(i, String.valueOf(i)), true);
+ }
+
+ for (int i = 20000; i > 0; i--) {
+ map.remove(Arrays.asList(i));
+ }
+
+ assertEquals(0, map.getRowCount());
+ assertNull(map.insert(Arrays.asList(1, String.valueOf(1)), true));
+ }
+
+}
Property changes on: trunk/engine/src/test/java/org/teiid/common/buffer/impl/TestSTree.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestCodeTableCache.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestCodeTableCache.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestCodeTableCache.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -69,7 +69,7 @@
// r2--> 'Germany', 'GM'
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
} catch (TeiidProcessingException e) {
throw new RuntimeException(e);
}
@@ -90,7 +90,7 @@
// r2--> 'Germany', 'GM'
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
} catch (TeiidProcessingException e) {
throw new RuntimeException(e);
}
@@ -203,7 +203,7 @@
};
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
fail("expected exception"); //$NON-NLS-1$
} catch (TeiidProcessingException e) {
assertEquals("Duplicate code table 'table' key 'value' value '1'", e.getMessage()); //$NON-NLS-1$
@@ -221,7 +221,7 @@
};
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
fail("expected exception"); //$NON-NLS-1$
} catch (TeiidProcessingException e) {
assertEquals("Error Code:ERR.018.005.0100 Message:Unable to load code table for because result sizes exceeds the allowed parameter - maxCodeTableRecords.", e.getMessage()); //$NON-NLS-1$
@@ -239,7 +239,7 @@
};
try {
- ctc.loadTable(nodeId, results);
+ ctc.loadTable(nodeId, Arrays.asList(results));
fail("expected exception"); //$NON-NLS-1$
} catch (TeiidProcessingException e) {
assertEquals("Error Code:ERR.018.005.0100 Message:Unable to load code table for because result sizes exceeds the allowed parameter - maxCodeTables.", e.getMessage()); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -304,7 +304,7 @@
0, // Null
0, // PlanExecution
3, // Project
- 0, // Select
+ 1, // Select
0, // Sort
0 // UnionAll
});
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -6569,6 +6569,21 @@
helpException("Create local TEMPORARY table tempTable (c1.x boolean, c2 byte)" ,"Parsing error: Invalid simple identifier format: [c1.x]"); //$NON-NLS-1$ //$NON-NLS-2$
}
+ @Test public void testCreateTempTableWithPrimaryKey() {
+ Create create = new Create();
+ create.setTable(new GroupSymbol("tempTable")); //$NON-NLS-1$
+ List columns = new ArrayList();
+ ElementSymbol column = new ElementSymbol("c1");//$NON-NLS-1$
+ column.setType(DataTypeManager.DefaultDataClasses.BOOLEAN);
+ columns.add(column);
+ column = new ElementSymbol("c2");//$NON-NLS-1$
+ column.setType(DataTypeManager.DefaultDataClasses.BYTE);
+ columns.add(column);
+ create.setColumns(columns);
+ create.getPrimaryKey().add(column);
+ helpTest("Create local TEMPORARY table tempTable(c1 boolean, c2 byte, primary key (c2))", "CREATE LOCAL TEMPORARY TABLE tempTable (c1 boolean, c2 byte, PRIMARY KEY(c2))", create); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
@Test public void testDropTable() {
Drop drop = new Drop();
drop.setTable(new GroupSymbol("tempTable")); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -297,8 +297,8 @@
props.setProperty("soap_host", "my.host.com"); //$NON-NLS-1$ //$NON-NLS-2$
props.setProperty("soap_port", "12345"); //$NON-NLS-1$ //$NON-NLS-2$
CommandContext context = new CommandContext("0", "test", "user", null, "myvdb", 1, props, DEBUG, false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- context.setProcessorBatchSize(2000);
- context.setConnectorBatchSize(2000);
+ context.setProcessorBatchSize(BufferManager.DEFAULT_PROCESSOR_BATCH_SIZE);
+ context.setConnectorBatchSize(BufferManager.DEFAULT_CONNECTOR_BATCH_SIZE);
context.setBufferManager(BufferManagerFactory.getStandaloneBufferManager());
context.setProcessDebug(DEBUG);
return context;
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestTempTables.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -28,10 +28,9 @@
import org.junit.Before;
import org.junit.Test;
import org.teiid.common.buffer.BufferManagerFactory;
-import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
import org.teiid.query.metadata.TempMetadataAdapter;
-import org.teiid.query.processor.TempTableDataManager;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.unittest.FakeMetadataFactory;
@@ -44,8 +43,8 @@
TestProcessor.doProcess(TestProcessor.helpGetPlan(sql, metadata), dataManager, expectedResults, TestProcessor.createCommandContext());
}
- @Before public void setUp() throws TeiidComponentException {
- TempTableStoreImpl tempStore = new TempTableStoreImpl(BufferManagerFactory.getStandaloneBufferManager(), "1", null); //$NON-NLS-1$
+ @Before public void setUp() {
+ TempTableStore tempStore = new TempTableStore(BufferManagerFactory.getStandaloneBufferManager(), "1", null); //$NON-NLS-1$
metadata = new TempMetadataAdapter(FakeMetadataFactory.example1Cached(), tempStore.getMetadataStore());
FakeDataManager fdm = new FakeDataManager();
TestProcessor.sampleData1(fdm);
@@ -90,5 +89,37 @@
execute("delete from x", new List[] {Arrays.asList(6)}); //$NON-NLS-1$
execute("select e1 from x order by e1", new List[] {}); //$NON-NLS-1$
}
-
+
+ @Test(expected=TeiidProcessingException.class) public void testDuplicatePrimaryKey() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key (e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ }
+
+ @Test public void testAtomicUpdate() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key (e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (2, 'one')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ try {
+ execute("update x set e2 = 3", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ } catch (TeiidProcessingException e) {
+ //should be a duplicate key
+ }
+ //should revert back to original
+ execute("select count(*) from x", new List[] {Arrays.asList(2)}); //$NON-NLS-1$
+ }
+
+ @Test public void testAtomicDelete() throws Exception {
+ execute("create local temporary table x (e1 string, e2 integer, primary key (e2))", new List[] {Arrays.asList(0)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (1, 'one')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ execute("insert into x (e2, e1) values (2, 'one')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ try {
+ execute("delete from x where 1/(e2 - 2) <> 4", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ } catch (TeiidProcessingException e) {
+ //should be a duplicate key
+ }
+ //should revert back to original
+ execute("select count(*) from x", new List[] {Arrays.asList(2)}); //$NON-NLS-1$
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -64,7 +64,7 @@
import org.teiid.query.validator.ValidatorFailure;
import org.teiid.query.validator.ValidatorReport;
-
+@SuppressWarnings("unchecked")
public class TestProcedureProcessor {
public static ProcessorPlan getProcedurePlan(String userQuery, FakeMetadataFacade metadata) throws Exception {
@@ -111,25 +111,25 @@
}
}
- private void helpTestProcessFailure(boolean optimistic, ProcessorPlan procPlan,
- FakeDataManager dataMgr, String failMessage) throws Exception {
+ private void helpTestProcessFailure(ProcessorPlan procPlan, FakeDataManager dataMgr,
+ String failMessage) throws Exception {
try {
- helpTestProcess(optimistic, procPlan, new List[] {}, dataMgr, true);
+ helpTestProcess(procPlan, new List[] {}, dataMgr, true);
} catch(TeiidException ex) {
assertEquals(failMessage, ex.getMessage());
}
}
public static void helpTestProcess(ProcessorPlan procPlan, List[] expectedResults, ProcessorDataManager dataMgr) throws Exception {
- helpTestProcess(false, procPlan, expectedResults, dataMgr, false);
+ helpTestProcess(procPlan, expectedResults, dataMgr, false);
}
private void helpTestProcess(ProcessorPlan procPlan, int expectedRows, FakeDataManager dataMgr) throws Exception {
helpTestProcess(procPlan, expectedRows, null, false, dataMgr, null);
}
- static void helpTestProcess(boolean optimistic, ProcessorPlan procPlan, List[] expectedResults,
- ProcessorDataManager dataMgr, boolean shouldFail) throws Exception {
+ static void helpTestProcess(ProcessorPlan procPlan, List[] expectedResults, ProcessorDataManager dataMgr,
+ boolean shouldFail) throws Exception {
helpTestProcess(procPlan, 0, expectedResults, shouldFail, dataMgr, null);
}
@@ -451,7 +451,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, "Error Code:ERR.015.006.0058 Message:Unable to evaluate (SELECT pm1.g1.e2 FROM pm1.g1): Error Code:ERR.015.006.0058 Message:The command of this scalar subquery returned more than one value: SELECT pm1.g1.e2 FROM pm1.g1"); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, "Error Code:ERR.015.006.0058 Message:Unable to evaluate (SELECT pm1.g1.e2 FROM pm1.g1): Error Code:ERR.015.006.0058 Message:The command of this scalar subquery returned more than one value: SELECT pm1.g1.e2 FROM pm1.g1"); //$NON-NLS-1$
}
// error statement
@@ -488,7 +488,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, ErrorInstruction.ERROR_PREFIX + "5MY ERROR"); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, ErrorInstruction.ERROR_PREFIX + "5MY ERROR"); //$NON-NLS-1$
}
private void helpTestErrorStatment(String errorValue, String expected) throws Exception {
@@ -508,7 +508,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, ErrorInstruction.ERROR_PREFIX + expected);
+ helpTestProcessFailure(plan, dataMgr, ErrorInstruction.ERROR_PREFIX + expected);
}
/** test if statement's if block with lookup in if condition */
@@ -1502,8 +1502,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false,
- plan,
+ helpTestProcessFailure(plan,
dataMgr,
"Couldn't execute the dynamic SQL command \"EXECUTE STRING 'EXEC pm1.sq2(''First'')' AS e1 string, e2 integer\" with the SQL statement \"'EXEC pm1.sq2(''First'')'\" due to: There is a recursive invocation of group 'PM1.SQ2'. Please correct the SQL."); //$NON-NLS-1$
}
@@ -1535,7 +1534,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, "Couldn't execute the dynamic SQL command \"EXECUTE STRING 'EXEC pm1.sq1(''First'')' AS e1 string, e2 integer\" with the SQL statement \"'EXEC pm1.sq1(''First'')'\" due to: The dynamic sql string contains an incorrect number of elements."); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, "Couldn't execute the dynamic SQL command \"EXECUTE STRING 'EXEC pm1.sq1(''First'')' AS e1 string, e2 integer\" with the SQL statement \"'EXEC pm1.sq1(''First'')'\" due to: The dynamic sql string contains an incorrect number of elements."); //$NON-NLS-1$
}
@Test public void testDynamicCommandPositional() throws Exception {
@@ -1587,7 +1586,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, "Couldn't execute the dynamic SQL command \"EXECUTE STRING 'select e1 from pm1.g1'\" with the SQL statement \"'select e1 from pm1.g1'\" due to: The datatype 'string' for element 'E1' in the dynamic SQL cannot be implicitly converted to 'integer'."); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, "Couldn't execute the dynamic SQL command \"EXECUTE STRING 'select e1 from pm1.g1'\" with the SQL statement \"'select e1 from pm1.g1'\" due to: The datatype 'string' for element 'E1' in the dynamic SQL cannot be implicitly converted to 'integer'."); //$NON-NLS-1$
}
@Test public void testDynamicCommandWithTwoDynamicStatements() throws Exception {
@@ -1877,7 +1876,7 @@
ProcessorPlan plan = getProcedurePlan(userUpdateStr, metadata);
- helpTestProcessFailure(false, plan, dataMgr, "Temporary table \"T1\" already exists."); //$NON-NLS-1$
+ helpTestProcessFailure(plan, dataMgr, "Temporary table \"T1\" already exists."); //$NON-NLS-1$
}
/**
Modified: trunk/engine/src/test/java/org/teiid/query/processor/relational/TestProjectIntoNode.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/relational/TestProjectIntoNode.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/processor/relational/TestProjectIntoNode.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -42,7 +42,7 @@
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
-import org.teiid.query.tempdata.TempTableStoreImpl;
+import org.teiid.query.tempdata.TempTableStore;
import org.teiid.query.util.CommandContext;
import junit.framework.TestCase;
@@ -140,7 +140,7 @@
if (command instanceof Insert) {
Insert insert = (Insert)command;
if (insert.isBulk()) {
- List batch = TempTableStoreImpl.getBulkRows(insert, insert.getVariables());
+ List batch = TempTableStore.getBulkRows(insert, insert.getVariables());
batchSize = batch.size();
assertEquals("Unexpected batch on call " + callCount, expectedBatchSize, batchSize); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -38,6 +38,7 @@
import java.util.Map;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryResolverException;
@@ -94,8 +95,9 @@
import org.teiid.query.unittest.FakeMetadataObject;
import org.teiid.query.unittest.FakeMetadataStore;
import org.teiid.query.unittest.TimestampUtil;
+import org.teiid.query.util.ErrorMessageKeys;
-
+@SuppressWarnings("nls")
public class TestResolver {
private FakeMetadataFacade metadata;
@@ -2400,6 +2402,16 @@
helpResolveException(sql, "Cannot create temporary table \"pm1.g1\". Local temporary tables must be created with unqualified names."); //$NON-NLS-1$
}
+ @Test public void testCreatePk() {
+ String sql = "CREATE LOCAL TEMPORARY TABLE foo (column1 string, column2 integer, primary key (column1, column2))"; //$NON-NLS-1$
+ helpResolve(sql);
+ }
+
+ @Test public void testCreateUnknownPk() {
+ String sql = "CREATE LOCAL TEMPORARY TABLE foo (column1 string, primary key (column2))"; //$NON-NLS-1$
+ helpResolveException(sql, "Element \"column2\" is not defined by any relevant group."); //$NON-NLS-1$
+ }
+
@Test public void testCreateAlreadyExists() {
String sql = "CREATE LOCAL TEMPORARY TABLE g1 (column1 string)"; //$NON-NLS-1$
helpResolveException(sql, "Cannot create temporary table \"g1\". A table with the same name already exists."); //$NON-NLS-1$
@@ -2863,6 +2875,21 @@
@Test public void testSecondPassFunctionResolving() {
helpResolve("SELECT pm1.g1.e1 FROM pm1.g1 where lower(?) = e1 "); //$NON-NLS-1$
}
+
+ @Test public void testSecondPassFunctionResolving1() {
+ try {
+ helpResolve("SELECT pm1.g1.e1 FROM pm1.g1 where 1/(e1 - 2) <> 4 "); //$NON-NLS-1$
+ fail("expected exception");
+ } catch (RuntimeException e) {
+ QueryResolverException qre = (QueryResolverException)e.getCause();
+ assertEquals(ErrorMessageKeys.RESOLVER_0040, qre.getCode());
+ }
+ }
+
+ @Ignore("currently not supported - we get type hints from the criteria not from the possible signatures")
+ @Test public void testSecondPassFunctionResolving2() {
+ helpResolve("SELECT pm1.g1.e1 FROM pm1.g1 where (lower(?) || 1) = e1 "); //$NON-NLS-1$
+ }
/**
* Test <code>QueryResolver</code>'s ability to resolve a query that
Modified: trunk/engine/src/test/java/org/teiid/query/sql/util/TestElementSymbolOptimizer.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/util/TestElementSymbolOptimizer.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/sql/util/TestElementSymbolOptimizer.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -183,7 +183,7 @@
helpTestOptimize("EXEC pm1.sq2(pm1.sq3.in)", //$NON-NLS-1$
FakeMetadataFactory.example1Cached(),
- "EXEC pm1.sq2(pm1.sq3.\"in\")", //$NON-NLS-1$
+ "EXEC pm1.sq2(\"in\")", //$NON-NLS-1$
externalMetadata);
}
Modified: trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2010-07-23 20:47:35 UTC (rev 2370)
+++ trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2010-07-23 21:44:19 UTC (rev 2371)
@@ -1127,7 +1127,7 @@
public void testElementSymbol5() {
ElementSymbol es = new ElementSymbol("m.g.select", false); //$NON-NLS-1$
es.setGroupSymbol(new GroupSymbol("m.g")); //$NON-NLS-1$
- helpTest(es, "m.g.\"select\""); //$NON-NLS-1$
+ helpTest(es, "\"select\""); //$NON-NLS-1$
}
public void testExpressionSymbol1() {
14 years, 5 months
teiid SVN: r2370 - trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-07-23 16:47:35 -0400 (Fri, 23 Jul 2010)
New Revision: 2370
Modified:
trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java
Log:
Giving the runtime engine a explicit name so that it can found by name.
Modified: trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java 2010-07-22 21:40:25 UTC (rev 2369)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java 2010-07-23 20:47:35 UTC (rev 2370)
@@ -84,7 +84,7 @@
import org.teiid.transport.SocketListener;
-@ManagementObject(isRuntime=true, componentType=@ManagementComponent(type="teiid",subtype="dqp"), properties=ManagementProperties.EXPLICIT)
+@ManagementObject(name="RuntimeEngineDeployer", isRuntime=true, componentType=@ManagementComponent(type="teiid",subtype="dqp"), properties=ManagementProperties.EXPLICIT)
public class RuntimeEngineDeployer extends DQPConfiguration implements DQPManagement, Serializable , ClientServiceRegistry {
private static final long serialVersionUID = -4676205340262775388L;
14 years, 5 months