/* * 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.runtime; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.math.BigDecimal; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.sql.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.resource.spi.XATerminator; import javax.transaction.*; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; import org.postgresql.Driver; import org.teiid.CommandContext; import org.teiid.PreParser; import org.teiid.adminapi.Model.Type; import org.teiid.adminapi.impl.ModelMetaData; import org.teiid.common.buffer.BufferManager; import org.teiid.common.buffer.impl.BufferFrontedFileStoreCache; import org.teiid.common.buffer.impl.FileStorageManager; import org.teiid.common.buffer.impl.SplittableStorageManager; import org.teiid.common.queue.FakeWorkManager; import org.teiid.core.TeiidRuntimeException; import org.teiid.core.types.DataTypeManager; import org.teiid.core.types.InputStreamFactory; import org.teiid.core.types.SQLXMLImpl; import org.teiid.core.util.ObjectConverterUtil; import org.teiid.core.util.SimpleMock; import org.teiid.core.util.UnitTestUtil; import org.teiid.deployers.VirtualDatabaseException; import org.teiid.jdbc.SQLStates; import org.teiid.jdbc.TeiidDriver; import org.teiid.jdbc.TeiidSQLException; import org.teiid.language.Command; import org.teiid.language.Literal; import org.teiid.language.QueryExpression; import org.teiid.language.visitor.CollectorVisitor; import org.teiid.metadata.Column; import org.teiid.metadata.MetadataException; import org.teiid.metadata.MetadataFactory; import org.teiid.metadata.MetadataRepository; import org.teiid.metadata.RuntimeMetadata; import org.teiid.metadata.Table; import org.teiid.query.sql.symbol.Reference; import org.teiid.runtime.EmbeddedServer.ConnectionFactoryProvider; import org.teiid.translator.DataNotAvailableException; import org.teiid.translator.ExecutionContext; import org.teiid.translator.ExecutionFactory; import org.teiid.translator.ResultSetExecution; import org.teiid.translator.Translator; import org.teiid.translator.TranslatorBatchException; import org.teiid.translator.TranslatorException; import org.teiid.translator.TypeFacility; import org.teiid.translator.UpdateExecution; import org.teiid.transport.SSLConfiguration; import org.teiid.transport.SocketConfiguration; import org.teiid.transport.WireProtocol; @SuppressWarnings("nls") public class TestEmbeddedServer { @Translator (name="y") public static class FakeTranslator extends ExecutionFactory<AtomicInteger, Object> { private boolean batch; public FakeTranslator() { this.batch = false; } public FakeTranslator(boolean batch) { this.batch = batch; } @Override public Object getConnection(AtomicInteger factory) throws TranslatorException { return factory.incrementAndGet(); } @Override public void closeConnection(Object connection, AtomicInteger factory) { } @Override public boolean supportsBulkUpdate() { return true; } @Override public void getMetadata(MetadataFactory metadataFactory, Object conn) throws TranslatorException { assertEquals(conn, Integer.valueOf(1)); Table t = metadataFactory.addTable("my-table"); t.setSupportsUpdate(true); Column c = metadataFactory.addColumn("my-column", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); } @Override public ResultSetExecution createResultSetExecution( QueryExpression command, ExecutionContext executionContext, RuntimeMetadata metadata, Object connection) throws TranslatorException { ResultSetExecution rse = new ResultSetExecution() { @Override public void execute() throws TranslatorException { } @Override public void close() { } @Override public void cancel() throws TranslatorException { } @Override public List<?> next() throws TranslatorException, DataNotAvailableException { return null; } }; return rse; } @Override public UpdateExecution createUpdateExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, Object connection) throws TranslatorException { UpdateExecution ue = new UpdateExecution() { @Override public void execute() throws TranslatorException { } @Override public void close() { } @Override public void cancel() throws TranslatorException { } @Override public int[] getUpdateCounts() throws DataNotAvailableException, TranslatorException { if (!batch) { return new int[] {2}; } return new int[] {1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1}; } }; return ue; } @Override public boolean isSourceRequiredForMetadata() { return false; } } public static final class MockTransactionManager implements TransactionManager { ThreadLocal<Transaction> txns = new ThreadLocal<Transaction>(); List<Transaction> txnHistory = new ArrayList<Transaction>(); @Override public Transaction suspend() throws SystemException { Transaction result = txns.get(); txns.remove(); return result; } @Override public void setTransactionTimeout(int seconds) throws SystemException { } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { Transaction result = txns.get(); if (result == null) { throw new IllegalStateException(); } result.setRollbackOnly(); } @Override public void rollback() throws IllegalStateException, SecurityException, SystemException { Transaction t = checkNull(false); txns.remove(); t.rollback(); } @Override public void resume(Transaction tobj) throws InvalidTransactionException, IllegalStateException, SystemException { checkNull(true); txns.set(tobj); } private Transaction checkNull(boolean isNull) { Transaction t = txns.get(); if ((!isNull && t == null) || (isNull && t != null)) { throw new IllegalStateException(); } return t; } @Override public Transaction getTransaction() throws SystemException { return txns.get(); } @Override public int getStatus() throws SystemException { Transaction t = txns.get(); if (t == null) { return Status.STATUS_NO_TRANSACTION; } return t.getStatus(); } @Override public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { Transaction t = checkNull(false); txns.remove(); t.commit(); } @Override public void begin() throws NotSupportedException, SystemException { checkNull(true); Transaction t = Mockito.mock(Transaction.class); txnHistory.add(t); txns.set(t); } public void reset() { txnHistory.clear(); txns = new ThreadLocal<Transaction>(); } } EmbeddedServer es; @Before public void setup() { es = new EmbeddedServer(); } @After public void teardown() { if (es != null) { es.stop(); } } @Test public void testDeploy() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); es.addTranslator("y", new FakeTranslator(false)); final AtomicInteger counter = new AtomicInteger(); ConnectionFactoryProvider<AtomicInteger> cfp = new EmbeddedServer.SimpleConnectionFactoryProvider<AtomicInteger>(counter); es.addConnectionFactoryProvider("z", cfp); ModelMetaData mmd = new ModelMetaData(); mmd.setName("my-schema"); mmd.addSourceMapping("x", "y", "z"); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("virt"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view \"my-view\" OPTIONS (UPDATABLE 'true') as select * from \"my-table\""); es.deployVDB("test", mmd, mmd1); TeiidDriver td = es.getDriver(); Connection c = td.connect("jdbc:teiid:test", null); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("select * from \"my-view\""); assertFalse(rs.next()); assertEquals("my-column", rs.getMetaData().getColumnLabel(1)); s.execute("update \"my-view\" set \"my-column\" = 'a'"); assertEquals(2, s.getUpdateCount()); es.deployVDB("empty"); c = es.getDriver().connect("jdbc:teiid:empty", null); s = c.createStatement(); s.execute("select * from tables"); assertNotNull(es.getSchemaDdl("empty", "SYS")); assertNull(es.getSchemaDdl("empty", "xxx")); } @Test public void testBatchedUpdate() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.bufferService.setProcessorBatchSize(1); es.start(ec); es.addTranslator("y", new FakeTranslator(true)); final AtomicInteger counter = new AtomicInteger(); ConnectionFactoryProvider<AtomicInteger> cfp = new EmbeddedServer.SimpleConnectionFactoryProvider<AtomicInteger>(counter); es.addConnectionFactoryProvider("z", cfp); ModelMetaData mmd = new ModelMetaData(); mmd.setName("my-schema"); mmd.addSourceMapping("x", "y", "z"); es.deployVDB("test", mmd); Connection c = es.getDriver().connect("jdbc:teiid:test", null); PreparedStatement ps = c.prepareStatement("insert into \"my-table\" values (?)"); for (int i = 0; i < 16; i++) { ps.setString(1, "a"); ps.addBatch(); } int[] result = ps.executeBatch(); assertArrayEquals(new int[] {1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1}, result); } @Test(expected=VirtualDatabaseException.class) public void testInvalidName() throws Exception { es.start(new EmbeddedConfiguration()); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("virt.1"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view \"my-view\" as select 1"); es.deployVDB("x", mmd1); } @Test public void testDeployZip() throws Exception { es.start(new EmbeddedConfiguration()); File f = UnitTestUtil.getTestScratchFile("some.vdb"); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f)); out.putNextEntry(new ZipEntry("v1.ddl")); out.write("CREATE VIEW helloworld as SELECT 'HELLO WORLD';".getBytes("UTF-8")); out.putNextEntry(new ZipEntry("META-INF/vdb.xml")); out.write("<vdb name=\"test\" version=\"1\"><model name=\"test\" type=\"VIRTUAL\"><metadata type=\"DDL-FILE\">/v1.ddl</metadata></model></vdb>".getBytes("UTF-8")); out.close(); es.deployVDBZip(f.toURI().toURL()); ResultSet rs = es.getDriver().connect("jdbc:teiid:test", null).createStatement().executeQuery("select * from helloworld"); rs.next(); assertEquals("HELLO WORLD", rs.getString(1)); } @Test public void testDeployZipDDL() throws Exception { es.start(new EmbeddedConfiguration()); File f = UnitTestUtil.getTestScratchFile("some.vdb"); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f)); out.putNextEntry(new ZipEntry("v1.ddl")); out.write("CREATE VIEW helloworld as SELECT 'HELLO WORLD';".getBytes("UTF-8")); out.putNextEntry(new ZipEntry("META-INF/vdb.ddl")); String externalDDL = "CREATE DATABASE test VERSION '1';" + "USE DATABASE test VERSION '1';" + "CREATE VIRTUAL SCHEMA test2;" + "IMPORT FOREIGN SCHEMA public FROM REPOSITORY \"DDL-FILE\" INTO test2 OPTIONS(\"ddl-file\" '/v1.ddl');"; out.write(externalDDL.getBytes("UTF-8")); out.close(); es.deployVDBZip(f.toURI().toURL()); ResultSet rs = es.getDriver().connect("jdbc:teiid:test", null).createStatement().executeQuery("select * from helloworld"); rs.next(); assertEquals("HELLO WORLD", rs.getString(1)); } @Test public void testDDLVDBImport() throws Exception { es.start(new EmbeddedConfiguration()); String ddl1 = "CREATE DATABASE x VERSION '1';" + "USE DATABASE x VERSION '1';" + "CREATE VIRTUAL SCHEMA test2;" + "SET SCHEMA test2;" + "CREATE VIEW x as select 1;"; String ddl2 = "CREATE DATABASE test VERSION '1';" + "USE DATABASE test VERSION '1';" + "IMPORT DATABASE x VERSION '1';"; es.deployVDB(new ByteArrayInputStream(ddl1.getBytes("UTF-8")), true); es.deployVDB(new ByteArrayInputStream(ddl2.getBytes("UTF-8")), true); } @Test(expected=MetadataException.class) public void testAlterImported() throws Exception { es.start(new EmbeddedConfiguration()); String ddl1 = "CREATE DATABASE x VERSION '1';" + "USE DATABASE x VERSION '1';" + "CREATE VIRTUAL SCHEMA test2;" + "SET SCHEMA test2;" + "CREATE VIEW x as select 1;"; String ddl2 = "CREATE DATABASE test VERSION '1';" + "USE DATABASE test VERSION '1';" + "IMPORT DATABASE x VERSION '1';" + "set schema test2;" + "DROP VIEW x;"; es.deployVDB(new ByteArrayInputStream(ddl1.getBytes("UTF-8")), true); es.deployVDB(new ByteArrayInputStream(ddl2.getBytes("UTF-8")), true); } @Test public void testDeployDesignerZip() throws Exception { es.start(new EmbeddedConfiguration()); es.deployVDBZip(UnitTestUtil.getTestDataFile("matviews.vdb").toURI().toURL()); ResultSet rs = es.getDriver().connect("jdbc:teiid:matviews", null).createStatement().executeQuery("select count(*) from tables where schemaname='test'"); rs.next(); assertEquals(4, rs.getInt(1)); } @Test public void testXMLDeploy() throws Exception { es.start(new EmbeddedConfiguration()); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\" type=\"VIRTUAL\"><metadata type=\"DDL\"><![CDATA[CREATE VIEW helloworld as SELECT 'HELLO WORLD';]]> </metadata></model></vdb>".getBytes())); ResultSet rs =es.getDriver().connect("jdbc:teiid:test", null).createStatement().executeQuery("select * from helloworld"); rs.next(); assertEquals("HELLO WORLD", rs.getString(1)); } @Test public void testXMLDeployWithVDBImport() throws Exception { es.start(new EmbeddedConfiguration()); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\" type=\"VIRTUAL\"><metadata type=\"DDL\"><![CDATA[CREATE VIEW helloworld as SELECT 'HELLO WORLD';]]> </metadata></model></vdb>".getBytes())); es.deployVDB(new ByteArrayInputStream("<vdb name=\"importer\" version=\"1\"><import-vdb name=\"test\" version=\"1\"/></vdb>".getBytes())); ResultSet rs =es.getDriver().connect("jdbc:teiid:importer", null).createStatement().executeQuery("select * from helloworld"); rs.next(); assertEquals("HELLO WORLD", rs.getString(1)); es.deployVDB(new ByteArrayInputStream("<vdb name=\"importer1\" version=\"1\"><import-vdb name=\"importer\" version=\"1\"/></vdb>".getBytes())); rs =es.getDriver().connect("jdbc:teiid:importer1", null).createStatement().executeQuery("select * from helloworld"); rs.next(); assertEquals("HELLO WORLD", rs.getString(1)); } @Test public void testRemoteJDBCTrasport() throws Exception { SocketConfiguration s = new SocketConfiguration(); InetSocketAddress addr = new InetSocketAddress(0); s.setBindAddress(addr.getHostName()); s.setPortNumber(addr.getPort()); s.setProtocol(WireProtocol.teiid); EmbeddedConfiguration config = new EmbeddedConfiguration(); config.addTransport(s); es.start(config); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\" type=\"VIRTUAL\"><metadata type=\"DDL\"><![CDATA[CREATE VIEW helloworld as SELECT 'HELLO WORLD';]]> </metadata></model></vdb>".getBytes())); Connection conn = null; try { TeiidDriver driver = new TeiidDriver(); conn = driver.connect("jdbc:teiid:test@mm://"+addr.getHostName()+":"+es.transports.get(0).getPort(), null); conn.createStatement().execute("set showplan on"); //trigger alternative serialization for byte count ResultSet rs = conn.createStatement().executeQuery("select * from helloworld"); rs.next(); assertEquals("HELLO WORLD", rs.getString(1)); } finally { if (conn != null) { conn.close(); } } } @Test(expected=TeiidRuntimeException.class) public void testRemoteTrasportSSLFail() throws Exception { SocketConfiguration s = new SocketConfiguration(); InetSocketAddress addr = new InetSocketAddress(0); s.setBindAddress(addr.getHostName()); s.setPortNumber(addr.getPort()); s.setProtocol(WireProtocol.teiid); SSLConfiguration sslConfiguration = new SSLConfiguration(); sslConfiguration.setSslProtocol("x"); sslConfiguration.setMode("enabled"); s.setSSLConfiguration(sslConfiguration); EmbeddedConfiguration config = new EmbeddedConfiguration(); config.addTransport(s); es.start(config); } @Test public void testRemoteODBCTrasport() throws Exception { SocketConfiguration s = new SocketConfiguration(); InetSocketAddress addr = new InetSocketAddress(0); s.setBindAddress(addr.getHostName()); s.setPortNumber(addr.getPort()); s.setProtocol(WireProtocol.pg); EmbeddedConfiguration config = new EmbeddedConfiguration(); config.addTransport(s); es.start(config); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\" type=\"VIRTUAL\"><metadata type=\"DDL\"><![CDATA[CREATE VIEW helloworld as SELECT 'HELLO WORLD';]]> </metadata></model></vdb>".getBytes())); Connection conn = null; try { Driver d = new Driver(); Properties p = new Properties(); p.setProperty("user", "testuser"); p.setProperty("password", "testpassword"); conn = d.connect("jdbc:postgresql://"+addr.getHostName()+":"+es.transports.get(0).getPort()+"/test", p); ResultSet rs = conn.createStatement().executeQuery("select * from helloworld"); rs.next(); assertEquals("HELLO WORLD", rs.getString(1)); } finally { if (conn != null) { conn.close(); } } } @Test(expected=VirtualDatabaseException.class) public void testXMLDeployFails() throws Exception { es.start(new EmbeddedConfiguration()); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\" type=\"VIRTUAL\"><metadata type=\"DDL\"><![CDATA[CREATE VIEW helloworld as SELECT 'HELLO WORLD';]]> </metadata></model><translator name=\"foo\" type=\"h2\"></translator></vdb>".getBytes())); } /** * Ensures schema validation is performed * @throws Exception */ @Test(expected=VirtualDatabaseException.class) public void testXMLDeployFails1() throws Exception { es.start(new EmbeddedConfiguration()); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\"><source/></model><translator name=\"foo\" type=\"h2\"></translator></vdb>".getBytes())); } @Test(expected=VirtualDatabaseException.class) public void testDeploymentError() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("virt"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view \"my-view\" OPTIONS (UPDATABLE 'true') as select * from \"my-table\""); es.deployVDB("test", mmd1); } @Test public void testValidationOrder() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view v as select 1"); ModelMetaData mmd2 = new ModelMetaData(); mmd2.setName("a"); mmd2.setModelType(Type.VIRTUAL); mmd2.setSchemaSourceType("ddl"); mmd2.setSchemaText("create view v1 as select * from v"); //We need mmd1 to validate before mmd2, reversing the order will result in an exception es.deployVDB("test", mmd1, mmd2); try { es.deployVDB("test2", mmd2, mmd1); fail(); } catch (VirtualDatabaseException e) { } } @Test public void testTransactions() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view v as select 1; " + "create virtual procedure proc () options (updatecount 2) as begin select * from v; end; " + "create virtual procedure proc0 () as begin atomic select * from v; end; " + "create virtual procedure proc1 () as begin atomic insert into #temp values (1); insert into #temp values (1); end; " + "create virtual procedure proc2 (x integer) as begin atomic insert into #temp values (1); insert into #temp values (1); select 1; begin select 1/x; end exception e end; " + "create virtual procedure proc3 (x integer) as begin begin atomic call proc (); select 1; end create local temporary table x (y string); begin atomic call proc (); select 1; end end;"); es.deployVDB("test", mmd1); TeiidDriver td = es.getDriver(); Connection c = td.connect("jdbc:teiid:test", null); //local txn c.setAutoCommit(false); Statement s = c.createStatement(); s.execute("select 1"); c.setAutoCommit(true); assertEquals(1, tm.txnHistory.size()); Transaction txn = tm.txnHistory.remove(0); Mockito.verify(txn).commit(); //should be an auto-commit txn (could also force with autoCommitTxn=true) s.execute("call proc ()"); assertEquals(1, tm.txnHistory.size()); txn = tm.txnHistory.remove(0); Mockito.verify(txn).commit(); //no txn needed s.execute("call proc0()"); assertEquals(0, tm.txnHistory.size()); //block txn s.execute("call proc1()"); assertEquals(1, tm.txnHistory.size()); txn = tm.txnHistory.remove(0); Mockito.verify(txn).commit(); s.execute("set autoCommitTxn on"); s.execute("set noexec on"); s.execute("select 1"); assertFalse(s.getResultSet().next()); s.execute("set autoCommitTxn off"); s.execute("set noexec off"); s.execute("call proc2(0)"); //verify that the block txn was committed because the exception was caught assertEquals(1, tm.txnHistory.size()); txn = tm.txnHistory.remove(0); Mockito.verify(txn).rollback(); //test detection tm.txnHistory.clear(); tm.begin(); try { c.setAutoCommit(false); s.execute("select 1"); //needed since we lazily start the transaction fail("should fail since we aren't allowing a nested transaction"); } catch (TeiidSQLException e) { } txn = tm.txnHistory.remove(0); Mockito.verify(txn, Mockito.times(0)).commit(); tm.commit(); c.setAutoCommit(true); tm.txnHistory.clear(); //ensure that we properly reset the txn context s.execute("call proc3(0)"); assertEquals(2, tm.txnHistory.size()); txn = tm.txnHistory.remove(0); Mockito.verify(txn, Mockito.times(0)).registerSynchronization((Synchronization) Mockito.any()); } @Test public void testMultiSourcePreparedDynamicUpdate() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); es.addTranslator("t", new ExecutionFactory<Void, Void>()); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view v (i integer) OPTIONS (UPDATABLE true) as select 1; " + "create trigger on v instead of update as for each row begin atomic " + "IF (CHANGING.i)\n" + "EXECUTE IMMEDIATE 'select \"new\".i'; " + "end; "); mmd1.setSupportsMultiSourceBindings(true); mmd1.addSourceMapping("x", "t", null); mmd1.addSourceMapping("y", "t", null); es.deployVDB("vdb", mmd1); Connection c = es.getDriver().connect("jdbc:teiid:vdb", null); PreparedStatement ps = c.prepareStatement("update v set i = ? where i = ?"); ps.setInt(1, 2); ps.setInt(2, 1); assertEquals(1, ps.executeUpdate()); ps.setInt(1, 3); ps.setInt(2, 1); assertEquals(1, ps.executeUpdate()); } @Test public void testGeneratedKeysVirtual() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); es.addTranslator("t", new ExecutionFactory<Void, Void>()); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setModelType(Type.VIRTUAL); mmd1.addSourceMetadata("ddl", "create view v (i integer, k integer auto_increment) OPTIONS (UPDATABLE true) as select 1, 2; " + "create trigger on v instead of insert as for each row begin atomic " + "\ncreate local temporary table x (y serial, z integer, primary key (y));" + "\ninsert into x (z) values (1);" + "end; "); es.deployVDB("vdb", mmd1); Connection c = es.getDriver().connect("jdbc:teiid:vdb", null); PreparedStatement ps = c.prepareStatement("insert into v (i) values (1)", Statement.RETURN_GENERATED_KEYS); assertEquals(1, ps.executeUpdate()); ResultSet rs = ps.getGeneratedKeys(); assertFalse(rs.next()); } @Test public void testGeneratedKeysTemp() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setModelType(Type.VIRTUAL); mmd1.addSourceMetadata("ddl", "create view v as select 1"); es.deployVDB("vdb", mmd1); Connection c = es.getDriver().connect("jdbc:teiid:vdb", null); Statement s = c.createStatement(); s.execute("create temporary table t (x serial, y string, primary key (x))"); PreparedStatement ps = c.prepareStatement("insert into t (y) values ('a')", Statement.RETURN_GENERATED_KEYS); assertFalse(ps.execute()); assertEquals(1, ps.getUpdateCount()); ResultSet rs = ps.getGeneratedKeys(); assertTrue(rs.next()); assertEquals(1, rs.getInt(1)); //should just be the default, rather than an exception assertEquals(11, rs.getMetaData().getColumnDisplaySize(1)); } @Test public void testMultiSourceMetadata() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); es.addTranslator("t", new ExecutionFactory<Void, Void>()); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create foreign table t (x string)"); mmd1.setSupportsMultiSourceBindings(true); mmd1.addSourceMapping("x", "t", null); mmd1.addSourceMapping("y", "t", null); es.deployVDB("vdb", mmd1); Connection c = es.getDriver().connect("jdbc:teiid:vdb", null); PreparedStatement ps = c.prepareStatement("select * from t"); ResultSetMetaData metadata = ps.getMetaData(); assertEquals(1, metadata.getColumnCount()); mmd1.addProperty("multisource.addColumn", Boolean.TRUE.toString()); es.undeployVDB("vdb"); es.deployVDB("vdb", mmd1); c = es.getDriver().connect("jdbc:teiid:vdb", null); ps = c.prepareStatement("select * from t"); metadata = ps.getMetaData(); assertEquals(2, metadata.getColumnCount()); mmd1.addProperty("multisource.columnName", "y"); es.undeployVDB("vdb"); es.deployVDB("vdb", mmd1); c = es.getDriver().connect("jdbc:teiid:vdb", null); ps = c.prepareStatement("select * from t"); metadata = ps.getMetaData(); assertEquals(2, metadata.getColumnCount()); assertEquals("y", metadata.getColumnName(2)); } /** * Check that we'll consult each source * @throws Exception */ @Test public void testMultiSourceMetadataMissingSource() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); es.addTranslator("t", new ExecutionFactory<Object, Object>() { @Override public Object getConnection(Object factory) throws TranslatorException { return factory; } @Override public void closeConnection(Object connection, Object factory) { } @Override public void getMetadata(MetadataFactory metadataFactory, Object conn) throws TranslatorException { assertNotNull(conn); Table t = metadataFactory.addTable("x"); metadataFactory.addColumn("a", "string", t); } }); es.addConnectionFactory("b", new Object()); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setSupportsMultiSourceBindings(true); mmd1.addSourceMapping("x", "t", "a"); //a is missing mmd1.addSourceMapping("y", "t", "b"); es.deployVDB("vdb", mmd1); } @Test public void testDynamicUpdate() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); es.addTranslator("t", new ExecutionFactory<Void, Void>() { @Override public boolean supportsCompareCriteriaEquals() { return true; } @Override public boolean isSourceRequired() { return false; } @Override public UpdateExecution createUpdateExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, Void connection) throws TranslatorException { Collection<Literal> values = CollectorVisitor.collectObjects(Literal.class, command); assertEquals(2, values.size()); for (Literal literal : values) { assertFalse(literal.getValue() instanceof Reference); } return new UpdateExecution() { @Override public void execute() throws TranslatorException { } @Override public void close() { } @Override public void cancel() throws TranslatorException { } @Override public int[] getUpdateCounts() throws DataNotAvailableException, TranslatorException { return new int[] {1}; } }; } }); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("accounts"); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText(ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("dynamic_update.sql"))); mmd1.addSourceMapping("y", "t", null); es.deployVDB("vdb", mmd1); Connection c = es.getDriver().connect("jdbc:teiid:vdb", null); PreparedStatement ps = c.prepareStatement("update hello1 set SchemaName=? where Name=?"); ps.setString(1,"test1223"); ps.setString(2,"Columns"); assertEquals(1, ps.executeUpdate()); } public static boolean started; public static class MyEF extends ExecutionFactory<Void, Void> { @Override public void start() throws TranslatorException { started = true; } } @Test public void testStart() throws TranslatorException { es.addTranslator(MyEF.class); assertTrue(started); } @Test public void testGlobalTempTables() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setMaxResultSetCacheStaleness(0); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\" type=\"VIRTUAL\"><metadata type=\"DDL\"><![CDATA[CREATE global temporary table some_temp (col1 string, col2 time) options (updatable true);]]> </metadata></model></vdb>".getBytes())); Connection c = es.getDriver().connect("jdbc:teiid:test", null); PreparedStatement ps = c.prepareStatement("/*+ cache */ select * from some_temp"); ResultSet rs = ps.executeQuery(); assertFalse(rs.next()); Connection c1 = es.getDriver().connect("jdbc:teiid:test", null); c1.createStatement().execute("insert into some_temp (col1) values ('a')"); PreparedStatement ps1 = c1.prepareStatement("/*+ cache */ select * from some_temp"); ResultSet rs1 = ps1.executeQuery(); assertTrue(rs1.next()); //there's a result for the second session rs = ps.executeQuery(); assertFalse(rs.next()); //still no result in the first session c.createStatement().execute("insert into some_temp (col1) values ('b')"); rs = ps.executeQuery(); assertTrue(rs.next()); //still no result in the first session //ensure without caching that we have the right results rs = c.createStatement().executeQuery("select * from some_temp"); assertTrue(rs.next()); assertEquals("b", rs.getString(1)); rs = c1.createStatement().executeQuery("select * from some_temp"); assertTrue(rs.next()); assertEquals("a", rs.getString(1)); } @Test public void testMaxRows() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setMaxResultSetCacheStaleness(0); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\" type=\"VIRTUAL\"><metadata type=\"DDL\"><![CDATA[CREATE virtual procedure proc (out col1 string result) returns TABLE (r1 string) as begin col1 = 'a'; select 'b' union all select 'c'; end;]]> </metadata></model></vdb>".getBytes())); Connection c = es.getDriver().connect("jdbc:teiid:test", null); CallableStatement cs = c.prepareCall("{? = call proc()}"); ResultSet rs = cs.executeQuery(); assertTrue(rs.next()); assertTrue(rs.next()); assertFalse(rs.next()); assertEquals("a", cs.getString(1)); //ensure that we don't drop the parameter row (which is last) cs.setMaxRows(1); rs = cs.executeQuery(); assertTrue(rs.next()); assertFalse(rs.next()); assertEquals("a", cs.getString(1)); //ensure that we can skip batches cs.setMaxRows(1); cs.setFetchSize(1); rs = cs.executeQuery(); assertTrue(rs.next()); assertFalse(rs.next()); assertEquals("a", cs.getString(1)); //cache should behave as expected when populated cs = c.prepareCall("/*+ cache */ {? = call proc()}"); cs.setMaxRows(1); rs = cs.executeQuery(); assertTrue(rs.next()); assertFalse(rs.next()); assertEquals("a", cs.getString(1)); //accessing from cache without the max should still give us the full result cs.setMaxRows(0); rs = cs.executeQuery(); assertTrue(rs.next()); assertTrue(rs.next()); assertFalse(rs.next()); assertEquals("a", cs.getString(1)); //accessing again with max should give the smaller result cs.setMaxRows(1); rs = cs.executeQuery(); assertTrue(rs.next()); assertFalse(rs.next()); assertEquals("a", cs.getString(1)); } @Test public void testSourceLobUnderTxn() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setMaxResultSetCacheStaleness(0); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); final AtomicBoolean closed = new AtomicBoolean(); es.addTranslator("foo", new ExecutionFactory() { @Override public boolean isSourceRequired() { return false; } @Override public ResultSetExecution createResultSetExecution( QueryExpression command, ExecutionContext executionContext, RuntimeMetadata metadata, Object connection) throws TranslatorException { return new ResultSetExecution() { private boolean returned; @Override public void execute() throws TranslatorException { } @Override public void close() { closed.set(true); } @Override public void cancel() throws TranslatorException { } @Override public List<?> next() throws TranslatorException, DataNotAvailableException { if (returned) { return null; } returned = true; ArrayList<Object> result = new ArrayList<Object>(1); result.add(new SQLXMLImpl(new InputStreamFactory() { @Override public InputStream getInputStream() throws IOException { //need to make it of a sufficient size to not be inlined return new ByteArrayInputStream(new byte[DataTypeManager.MAX_LOB_MEMORY_BYTES + 1]); } })); return result; } }; } }); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\"><source name=\"foo\" translator-name=\"foo\"/><metadata type=\"DDL\"><![CDATA[CREATE foreign table x (y xml);]]> </metadata></model></vdb>".getBytes())); Connection c = es.getDriver().connect("jdbc:teiid:test", null); c.setAutoCommit(false); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("select * from x"); rs.next(); assertFalse(closed.get()); s.close(); assertTrue(closed.get()); } @Test public void testUndeploy() throws Exception { es.start(new EmbeddedConfiguration()); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model type=\"VIRTUAL\" name=\"test\"><metadata type=\"DDL\"><![CDATA[CREATE view x as select 1;]]> </metadata></model></vdb>".getBytes())); Connection c = es.getDriver().connect("jdbc:teiid:test", null); assertTrue(c.isValid(10)); es.undeployVDB("test"); assertTrue(!c.isValid(10)); } @Test public void testQueryTimeout() throws Exception { es.start(new EmbeddedConfiguration()); es.addTranslator("foo", new ExecutionFactory() { @Override public boolean isSourceRequired() { return false; } @Override public ResultSetExecution createResultSetExecution( QueryExpression command, ExecutionContext executionContext, RuntimeMetadata metadata, Object connection) throws TranslatorException { try { Thread.sleep(5000); } catch (InterruptedException e) { } return super.createResultSetExecution(command, executionContext, metadata, connection); } }); es.deployVDB(new ByteArrayInputStream("<vdb name=\"test\" version=\"1\"><model name=\"test\"><source name=\"foo\" translator-name=\"foo\"/><metadata type=\"DDL\"><![CDATA[CREATE foreign table x (y xml);]]> </metadata></model></vdb>".getBytes())); Connection c = es.getDriver().connect("jdbc:teiid:test", null); Statement s = c.createStatement(); s.setQueryTimeout(1); try { s.execute("select * from x"); fail(); } catch (SQLException e) { assertEquals(SQLStates.QUERY_CANCELED, e.getSQLState()); } } @Test public void testMultipleEmbeddedServerInOneVM() throws TranslatorException { es.addTranslator(MyEFES1.class); es.start(new EmbeddedConfiguration()); assertTrue(isES1started); EmbeddedServer es2 = new EmbeddedServer(); es2.start(new EmbeddedConfiguration()); es2.addTranslator(MyEFES2.class); assertTrue(isES2started); es2.stop(); } public static boolean isES1started; public static boolean isES2started; public static class MyEFES1 extends ExecutionFactory<Void, Void> { @Override public void start() throws TranslatorException { isES1started = true; } } public static class MyEFES2 extends ExecutionFactory<Void, Void> { @Override public void start() throws TranslatorException { isES2started = true; } } @Test public void testExternalMaterializationManagement() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); ec.setTransactionManager(SimpleMock.createSimpleMock(TransactionManager.class)); es.transactionService.setXaTerminator(SimpleMock.createSimpleMock(XATerminator.class)); es.transactionService.setWorkManager(new FakeWorkManager()); es.start(ec); es.transactionService.setDetectTransactions(false); final AtomicBoolean loaded = new AtomicBoolean(); final AtomicBoolean valid = new AtomicBoolean(); final AtomicInteger matTableCount = new AtomicInteger(); final AtomicInteger tableCount = new AtomicInteger(); final AtomicBoolean hasStatus = new AtomicBoolean(); es.addTranslator("y", new ExecutionFactory<AtomicInteger, Object> () { public boolean supportsCompareCriteriaEquals() { return true; } @Override public Object getConnection(AtomicInteger factory) throws TranslatorException { return factory.incrementAndGet(); } @Override public void closeConnection(Object connection, AtomicInteger factory) { } @Override public void getMetadata(MetadataFactory metadataFactory, Object conn) throws TranslatorException { assertEquals(conn, Integer.valueOf(1)); Table t = metadataFactory.addTable("my_table"); t.setSupportsUpdate(true); Column c = metadataFactory.addColumn("my_column", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); // mat table t = metadataFactory.addTable("mat_table"); t.setSupportsUpdate(true); c = metadataFactory.addColumn("my_column", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); // status table t = metadataFactory.addTable("status"); t.setSupportsUpdate(true); c = metadataFactory.addColumn("VDBName", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); c = metadataFactory.addColumn("VDBVersion", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); c = metadataFactory.addColumn("SchemaName", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); c = metadataFactory.addColumn("Name", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); c = metadataFactory.addColumn("TargetSchemaName", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); c = metadataFactory.addColumn("TargetName", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); c = metadataFactory.addColumn("Valid", TypeFacility.RUNTIME_NAMES.BOOLEAN, t); c.setUpdatable(true); c = metadataFactory.addColumn("LoadState", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); c = metadataFactory.addColumn("Cardinality", TypeFacility.RUNTIME_NAMES.LONG, t); c.setUpdatable(true); c = metadataFactory.addColumn("Updated", TypeFacility.RUNTIME_NAMES.TIMESTAMP, t); c.setUpdatable(true); c = metadataFactory.addColumn("LoadNumber", TypeFacility.RUNTIME_NAMES.LONG, t); c.setUpdatable(true); c = metadataFactory.addColumn("NodeName", TypeFacility.RUNTIME_NAMES.STRING, t); c.setUpdatable(true); c = metadataFactory.addColumn("StaleCount", TypeFacility.RUNTIME_NAMES.LONG, t); c.setUpdatable(true); metadataFactory.addPrimaryKey("PK", Arrays.asList("VDBName", "VDBVersion", "SchemaName", "Name"), t); } @Override public ResultSetExecution createResultSetExecution( final QueryExpression command, final ExecutionContext executionContext, final RuntimeMetadata metadata, final Object connection) throws TranslatorException { return new ResultSetExecution() { Iterator<? extends List<? extends Object>> results; @Override public void execute() throws TranslatorException { } @Override public void close() { } @Override public void cancel() throws TranslatorException { } @Override public List<?> next() throws TranslatorException, DataNotAvailableException { String status = "SELECT status.TargetSchemaName, status.TargetName, status.Valid, " + "status.LoadState, status.Updated, status.Cardinality, status.LoadNumber " + "FROM status WHERE status.VDBName = 'test' AND status.VDBVersion = '1.0.0' " + "AND status.SchemaName = 'virt' AND status.Name = 'my_view'"; if (results == null) { String commandString = command.toString(); if (hasStatus.get() && commandString.equals(status)) { results = Arrays.asList(Arrays.asList(null, "mat_table", valid.get(), loaded.get()?"LOADED":"LOADING", new Timestamp(System.currentTimeMillis()), -1, new Integer(1))).iterator(); } else if (hasStatus.get() && commandString.startsWith("SELECT status.Valid, status.LoadState FROM status")) { results = Arrays.asList(Arrays.asList(valid.get(), loaded.get()?"LOADED":"LOADING")).iterator(); } else if (loaded.get() && commandString.equals("SELECT mat_table.my_column FROM mat_table")) { matTableCount.getAndIncrement(); results = Arrays.asList(Arrays.asList("mat_column0"), Arrays.asList("mat_column1")).iterator(); } else if (commandString.equals("SELECT my_table.my_column FROM my_table")) { tableCount.getAndIncrement(); results = Arrays.asList(Arrays.asList("regular_column")).iterator(); } } if (results != null && results.hasNext()) { return results.next(); } return null; } }; } @Override public UpdateExecution createUpdateExecution(final Command command, final ExecutionContext executionContext, final RuntimeMetadata metadata, final Object connection) throws TranslatorException { UpdateExecution ue = new UpdateExecution() { @Override public void execute() throws TranslatorException { String commandString = command.toString(); if (commandString.startsWith("INSERT INTO status")) { hasStatus.set(true); } if (commandString.startsWith("INSERT INTO status") || commandString.startsWith("UPDATE status SET")) { if (commandString.contains("LoadState")) { synchronized (loaded) { loaded.set(commandString.indexOf("LOADED") != -1); loaded.notifyAll(); } } if (commandString.contains("Valid")) { valid.set(commandString.indexOf("TRUE") != -1); } } } @Override public void close() { } @Override public void cancel() throws TranslatorException { } @Override public int[] getUpdateCounts() throws DataNotAvailableException, TranslatorException { return new int[] {1}; } }; return ue; } }); final AtomicInteger counter = new AtomicInteger(); ConnectionFactoryProvider<AtomicInteger> cfp = new EmbeddedServer.SimpleConnectionFactoryProvider<AtomicInteger>(counter); es.addConnectionFactoryProvider("z", cfp); ModelMetaData mmd = new ModelMetaData(); mmd.setName("my_schema"); mmd.addSourceMapping("x", "y", "z"); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("virt"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText(" create view my_view OPTIONS (" + "UPDATABLE 'true',MATERIALIZED 'TRUE',\n" + "MATERIALIZED_TABLE 'my_schema.mat_table', \n" + "\"teiid_rel:MATERIALIZED_STAGE_TABLE\" 'my_schema.mat_table',\n" + "\"teiid_rel:ALLOW_MATVIEW_MANAGEMENT\" 'true', \n" + "\"teiid_rel:MATVIEW_STATUS_TABLE\" 'my_schema.status', \n" + "\"teiid_rel:MATVIEW_AFTER_LOAD_SCRIPT\" 'select 1; select 1, ''a''', \n" + "\"teiid_rel:MATVIEW_SHARE_SCOPE\" 'NONE',\n" + "\"teiid_rel:MATVIEW_ONERROR_ACTION\" 'THROW_EXCEPTION',\n" + "\"teiid_rel:MATVIEW_TTL\" 100000)" + "as select * from \"my_table\";" + " create view mat_table as select 'I conflict';"); es.deployVDB("test", mmd, mmd1); synchronized (loaded) { while (!loaded.get()) { loaded.wait(); } } Thread.sleep(2000); //need to ensure that the mat view is built final TeiidDriver td = es.getDriver(); Connection c = td.connect("jdbc:teiid:test", null); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("select * from my_view"); assertTrue(rs.next()); assertEquals("mat_column0", rs.getString(1)); s.execute("update my_schema.status set valid=false"); try { rs = s.executeQuery("select * from my_view"); fail("expected throw exception to work"); } catch (SQLException e) { } assertEquals(1, tableCount.get()); //make sure a similar name doesn't cause an issue rs = s.executeQuery("select * from (call sysadmin.updateMatView('virt', 'my_view', 'true')) as x"); rs.next(); assertEquals(2, rs.getInt(1)); assertEquals(2, tableCount.get()); s.execute("call setProperty((SELECT UID FROM Sys.Tables WHERE SchemaName = 'virt' AND Name = 'my_view'), 'teiid_rel:MATVIEW_ONERROR_ACTION', 'WAIT')"); //this thread should hang, until the status changes final AtomicBoolean success = new AtomicBoolean(); Thread t = new Thread() { public void run() { try { Connection c1 = td.connect("jdbc:teiid:test", null); Statement s1 = c1.createStatement(); s1.executeQuery("select * from my_view"); success.set(true); } catch (SQLException e) { } }; }; t.start(); //wait to ensure that the thread is blocked Thread.sleep(5000); //update the status and make sure the thread finished s.execute("update my_schema.status set valid=true"); t.join(10000); assertTrue(success.get()); } @Test public void testPreparedTypeResolving() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); ec.setUseDisk(false); es.start(ec); es.addTranslator("t", new ExecutionFactory<Void, Void>()); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view v (i integer) as select 1"); es.deployVDB("vdb", mmd1); Connection c = es.getDriver().connect("jdbc:teiid:vdb", null); //should expect a clob PreparedStatement ps = c.prepareStatement("select * from texttable(? columns a string) as x"); ps.setCharacterStream(1, new StringReader("a\nb")); assertTrue(ps.execute()); } @Test public void testGeometrySelect() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setModelType(Type.VIRTUAL); mmd1.setSchemaSourceType("ddl"); mmd1.setSchemaText("create view v (i geometry) as select ST_GeomFromText('POLYGON ((100 100, 200 200, 75 75, 100 100))')"); es.deployVDB("vdb", mmd1); Connection c = es.getDriver().connect("jdbc:teiid:vdb", null); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("select * from v"); assertEquals("geometry", rs.getMetaData().getColumnTypeName(1)); assertEquals(Types.BLOB, rs.getMetaData().getColumnType(1)); assertEquals("java.sql.Blob", rs.getMetaData().getColumnClassName(1)); rs.next(); assertEquals(77, rs.getBlob(1).length()); } @Test public void testUpdateCountAnonProc() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); ModelMetaData mmd1 = new ModelMetaData(); mmd1.setName("b"); mmd1.setModelType(Type.VIRTUAL); mmd1.addSourceMetadata("ddl", "create view v as select 1"); es.deployVDB("vdb", mmd1); Connection c = es.getDriver().connect("jdbc:teiid:vdb", null); Statement s = c.createStatement(); s.execute("set autoCommitTxn off"); PreparedStatement ps = c.prepareStatement("begin select 1 without return; end"); assertNull(ps.getMetaData()); ps.execute(); assertEquals(0, ps.getUpdateCount()); assertNull(ps.getMetaData()); } public static class MyPreParser implements PreParser { @Override public String preParse(String command, CommandContext context) { if (command.equals("select 'goodbye'")) { return "select 'vdb'"; } return command; } } @Test public void testPreParser() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setPreParser(new PreParser() { @Override public String preParse(String command, CommandContext context) { if (command.equals("select 'hello world'")) { return "select 'goodbye'"; } return command; } }); es.start(ec); ModelMetaData mmd = new ModelMetaData(); mmd.setName("y"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", "create view dummy as select 1;"); es.deployVDB("x", mmd); Connection c = es.getDriver().connect("jdbc:teiid:x", null); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("select 'hello world'"); rs.next(); assertEquals("goodbye", rs.getString(1)); String perVdb = "<vdb name=\"x1\" version=\"1\"><property name=\"preparser-class\" value=\""+MyPreParser.class.getName()+"\"/><model name=\"x\" type=\"VIRTUAL\"><metadata type=\"ddl\">create view v as select 1</metadata></model></vdb>"; es.deployVDB(new ByteArrayInputStream(perVdb.getBytes("UTF-8"))); c = es.getDriver().connect("jdbc:teiid:x1", null); s = c.createStatement(); rs = s.executeQuery("select 'hello world'"); rs.next(); assertEquals("vdb", rs.getString(1)); } @Test public void testTurnOffLobCleaning() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); ModelMetaData mmd = new ModelMetaData(); mmd.setName("y"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", "create view dummy as select 1;"); es.deployVDB("x", mmd); Connection c = es.getDriver().connect("jdbc:teiid:x", null); Statement s = c.createStatement(); s.execute("select teiid_session_set('clean_lobs_onclose', false)"); ResultSet rs = s.executeQuery("WITH t(n) AS ( VALUES (1) UNION ALL SELECT n+1 FROM t WHERE n < 5000 ) SELECT xmlelement(root, xmlagg(xmlelement(val, n))) FROM t"); assertTrue(rs.next()); SQLXML val = rs.getSQLXML(1); rs.close(); assertEquals(73906, val.getString().length()); } @Test public void testDefaultEscape() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); ModelMetaData mmd = new ModelMetaData(); mmd.setName("y"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", "create view dummy as select 1;"); es.deployVDB("x", mmd); Connection c = es.getDriver().connect("jdbc:teiid:x", null); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("select '_a' like '\\_a'"); rs.next(); assertFalse(rs.getBoolean(1)); s.execute("select teiid_session_set('backslashDefaultMatchEscape', true)"); rs = s.executeQuery("select '_a' like '\\_a'"); rs.next(); assertTrue(rs.getBoolean(1)); } @Test public void testBufferManagerProperties() throws TranslatorException { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(true); ec.setBufferDirectory(System.getProperty("java.io.tmpdir")); ec.setProcessorBatchSize(BufferManager.DEFAULT_PROCESSOR_BATCH_SIZE); ec.setMaxReserveKb(BufferManager.DEFAULT_RESERVE_BUFFER_KB); ec.setMaxProcessingKb(BufferManager.DEFAULT_MAX_PROCESSING_KB); ec.setInlineLobs(true); ec.setMaxOpenFiles(FileStorageManager.DEFAULT_MAX_OPEN_FILES); ec.setMaxBufferSpace(FileStorageManager.DEFAULT_MAX_BUFFERSPACE>>20); ec.setMaxFileSize(SplittableStorageManager.DEFAULT_MAX_FILESIZE); ec.setEncryptFiles(false); ec.setMaxStorageObjectSize(BufferFrontedFileStoreCache.DEFAuLT_MAX_OBJECT_SIZE); ec.setMemoryBufferOffHeap(false); started = false; es.addTranslator(MyEF.class); es.start(ec); assertTrue(started); } @Test(expected=VirtualDatabaseException.class) public void testRequireRoles() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); es.repo.setDataRolesRequired(true); ModelMetaData mmd = new ModelMetaData(); mmd.setName("y"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", "create view dummy as select 1;"); es.deployVDB("x", mmd); } @Test public void testSystemSubquery() throws Exception { //already working String query = "SELECT t.Name FROM (select * from SYS.Tables AS t limit 10) as t, (SELECT DISTINCT c.TableName FROM SYS.Columns AS c where c.Name > 'A') AS X__1 WHERE t.Name = X__1.TableName"; EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); ModelMetaData mmd = new ModelMetaData(); mmd.setName("x"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", "create view v as select 1 as c"); es.deployVDB("x", mmd); Connection c = es.getDriver().connect("jdbc:teiid:x", null); Statement s = c.createStatement(); extractRowCount(query, s, 10); //was throwing exception query = "SELECT t.Name FROM (select * from SYS.Tables AS t limit 10) as t, (SELECT DISTINCT c.TableName FROM SYS.Columns AS c) AS X__1 WHERE t.Name = X__1.TableName"; extractRowCount(query, s, 10); } private void extractRowCount(String query, Statement s, int count) throws SQLException { s.execute(query); ResultSet rs = s.getResultSet(); int i = 0; while (rs.next()) { i++; } assertEquals(count, i); } @Test public void testTempVisibilityToExecuteImmediate() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); ModelMetaData mmd = new ModelMetaData(); mmd.setName("x"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", "create procedure p () as execute immediate 'select 1' as x integer into #temp;"); es.deployVDB("x", mmd); Connection c = es.getDriver().connect("jdbc:teiid:x", null); Statement s = c.createStatement(); s.execute("create local temporary table #temp (x integer)"); s.execute("exec p()"); extractRowCount("select * from #temp", s, 0); } @Test public void testSubqueryCache() throws Exception { UnitTestUtil.enableLogging(Level.WARNING, "org.teiid"); EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); ModelMetaData mmd = new ModelMetaData(); mmd.setName("x"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("proc.sql"))); es.deployVDB("x", mmd); Connection c = es.getDriver().connect("jdbc:teiid:x", null); Statement s = c.createStatement(); String[] statements = ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("data.sql")).split(";"); for (String statement:statements) { s.execute(statement); } s.execute("set autoCommitTxn off"); s.execute("SELECT \"citmp.KoordX\" ,\"citmp.KoordY\" ,( SELECT \"store.insideFence\" FROM ( EXEC point_inside_store ( CAST ( \"citmp.KoordX\" AS float ) ,CAST ( \"citmp.KoordY\" AS float ) ) ) as \"store\" ) as \"insideStore\" ,( SELECT \"firstsection.insideFence\" FROM ( EXEC point_inside_store ( CAST ( \"citmp.KoordX\" AS float ) ,CAST ( \"citmp.KoordY\" AS float ) ) ) as \"firstsection\" ) as \"insideFirstsection\" FROM sample_coords as \"citmp\" ORDER BY insideStore ASC ,insideFirstsection DESC"); ResultSet rs = s.getResultSet(); while (rs.next()) { //the last two columns should be identical assertEquals(rs.getInt(3), rs.getInt(4)); } } @Test(expected=TeiidSQLException.class) public void testCancelSystemQuery() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); ModelMetaData mmd = new ModelMetaData(); mmd.setName("x"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", "create view v as select 1;"); es.deployVDB("x", mmd); Connection c = es.getDriver().connect("jdbc:teiid:x", null); final Statement s = c.createStatement(); Thread t = new Thread() { @Override public void run() { try { Thread.sleep(1000); s.cancel(); } catch (InterruptedException e) { } catch (SQLException e) { } } }; t.start(); ResultSet rs = s.executeQuery("select count(*) from columns c, columns c1, columns c2, columns c3, columns c4"); rs.next(); fail(); } @Test public void testSemanticVersioning() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); ModelMetaData mmd = new ModelMetaData(); mmd.setName("x"); mmd.setModelType(Type.VIRTUAL); mmd.addSourceMetadata("ddl", "create view v as select 1;"); es.deployVDB("x.0.9.0", mmd); es.deployVDB("x.1.0.1", mmd); es.deployVDB("x.1.1.0", mmd); Connection c = es.getDriver().connect("jdbc:teiid:x", null); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("values (current_database())"); rs.next(); assertEquals("x", rs.getString(1)); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("0.9.0", rs.getString(1)); try { //v1.0.0 does not exist c = es.getDriver().connect("jdbc:teiid:x.v1.0", null); fail(); } catch (TeiidSQLException e) { } c = es.getDriver().connect("jdbc:teiid:x.1.0.1", null); s = c.createStatement(); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("1.0.1", rs.getString(1)); try { //old style non-semantic version c = es.getDriver().connect("jdbc:teiid:x.1", null); fail(); } catch (TeiidSQLException e) { } c = es.getDriver().connect("jdbc:teiid:x.1.", null); s = c.createStatement(); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("1.0.1", rs.getString(1)); c = es.getDriver().connect("jdbc:teiid:x.1.1.", null); s = c.createStatement(); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("1.1.0", rs.getString(1)); } @Test public void testSemanticVersioningAny() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); es.deployVDB(new ByteArrayInputStream(createVDB("x", "0.9").getBytes("UTF-8"))); Connection c = es.getDriver().connect("jdbc:teiid:x", null); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("values (current_database())"); rs.next(); assertEquals("x", rs.getString(1)); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("0.9.0", rs.getString(1)); es.deployVDB(new ByteArrayInputStream(createVDB("x", "1.1.1").getBytes("UTF-8"))); try { //old style non-semantic version c = es.getDriver().connect("jdbc:teiid:x.1", null); fail(); } catch (TeiidSQLException e) { } c = es.getDriver().connect("jdbc:teiid:x.1.", null); s = c.createStatement(); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("1.1.1", rs.getString(1)); c = es.getDriver().connect("jdbc:teiid:x.1.1.", null); s = c.createStatement(); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("1.1.1", rs.getString(1)); es.deployVDB(new ByteArrayInputStream(createVDB("x", "1.11.1").getBytes("UTF-8"))); es.deployVDB(new ByteArrayInputStream(createVDB("x", "1.0.1").getBytes("UTF-8"))); c = es.getDriver().connect("jdbc:teiid:x.1.1.", null); s = c.createStatement(); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("1.1.1", rs.getString(1)); c = es.getDriver().connect("jdbc:teiid:x.1.0.", null); s = c.createStatement(); rs = s.executeQuery("select version from virtualdatabases"); rs.next(); assertEquals("1.0.1", rs.getString(1)); try { c = es.getDriver().connect("jdbc:teiid:x.1.12.0", null); fail(); } catch (TeiidSQLException e) { } } private String createVDB(String name, String version) { return "<vdb name=\""+ name +"\" version=\""+version+"\"><connection-type>ANY</connection-type><model name=\"x\" type=\"VIRTUAL\"><metadata type=\"ddl\">create view v as select 1</metadata></model></vdb>"; } @Test public void testVirtualFunctions() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); es.start(ec); es.deployVDB(new ByteArrayInputStream(("<vdb name=\"ddlfunctions\" version=\"1\">" + "<model visible=\"true\" type=\"VIRTUAL\" name=\"FunctionModel\">" + " <metadata type=\"DDL\"><![CDATA[" + " CREATE VIRTUAL function f1(p1 integer) RETURNS integer as return p1;" + " CREATE VIEW TestView (c1 integer) AS SELECT f1(42) AS c1;" + " ]]>" + "</metadata></model></vdb>").getBytes())); Connection c = es.getDriver().connect("jdbc:teiid:ddlfunctions", null); Statement s = c.createStatement(); s.execute("select f1(1)"); ResultSet rs = s.getResultSet(); rs.next(); assertEquals(1, rs.getInt(1)); s.execute("select * from testview"); rs = s.getResultSet(); rs.next(); assertEquals(42, rs.getInt(1)); } @Test public void testWithPushdownChangeName() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); HardCodedExecutionFactory hcef = new HardCodedExecutionFactory() { @Override public boolean supportsCommonTableExpressions() { return true; } @Override public boolean supportsSelfJoins() { return true; } @Override public boolean supportsCompareCriteriaEquals() { return true; } @Override public boolean supportsAliasedTable() { return true; } @Override public boolean isSourceRequired() { return false; } @Override public String getExcludedCommonTableExpressionName() { return "a"; } @Override public boolean supportsInnerJoins() { return true; } }; es.addTranslator("y", hcef); hcef.addData("WITH a__2 (x) AS (SELECT g_0.e1 FROM pm1.g1 AS g_0) SELECT g_0.x FROM a__2 AS g_0, a__2 AS g_1", Arrays.asList(Arrays.asList("a"))); ModelMetaData mmd = new ModelMetaData(); mmd.setName("my-schema"); mmd.addSourceMapping("x", "y", null); mmd.addSourceMetadata("ddl", "create foreign table pm1.g1 (e1 string)"); es.deployVDB("test", mmd); TeiidDriver td = es.getDriver(); Connection c = td.connect("jdbc:teiid:test", null); Statement s = c.createStatement(); //see the correct pushdown in hcef.addData above s.execute("with a (x) as (select e1 from pm1.g1) SELECT a.x from a, a z"); //$NON-NLS-1$ } @Test public void testBatchedUpdateErrors() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); MockTransactionManager tm = new MockTransactionManager(); ec.setTransactionManager(tm); HardCodedExecutionFactory hcef = new HardCodedExecutionFactory() { @Override public boolean supportsCompareCriteriaEquals() { return true; } }; hcef.addUpdate("UPDATE pm1.g1 SET e1 = 'a' WHERE pm1.g1.e2 = 1", new int[] {1}); hcef.addUpdate("UPDATE pm1.g1 SET e1 = 'b' WHERE pm1.g1.e2 = 2", new TranslatorException("i've failed")); es.addTranslator("y", hcef); ModelMetaData mmd = new ModelMetaData(); mmd.setName("my-schema"); mmd.addSourceMapping("x", "y", null); mmd.addSourceMetadata("ddl", "create foreign table pm1.g1 (e1 string, e2 integer) options (updatable true)"); es.deployVDB("test", mmd); TeiidDriver td = es.getDriver(); Connection c = td.connect("jdbc:teiid:test", null); Statement s = c.createStatement(); s.addBatch("update pm1.g1 set e1 = 'a' where e2 = 1"); //$NON-NLS-1$ s.addBatch("update pm1.g1 set e1 = 'b' where e2 = 2"); //$NON-NLS-1$ try { s.executeBatch(); fail(); } catch (BatchUpdateException e) { int[] updateCounts = e.getUpdateCounts(); assertArrayEquals(new int[] {1}, updateCounts); assertEquals(-1, s.getUpdateCount()); } //redeploy with batch support hcef = new HardCodedExecutionFactory() { @Override public boolean supportsCompareCriteriaEquals() { return true; } @Override public boolean supportsBatchedUpdates() { return true; } }; es.addTranslator("z", hcef); es.undeployVDB("test"); mmd = new ModelMetaData(); mmd.setName("my-schema"); mmd.addSourceMetadata("ddl", "create foreign table pm1.g1 (e1 string, e2 integer) options (updatable true)"); mmd.addSourceMapping("y", "z", null); es.deployVDB("test", mmd); c = td.connect("jdbc:teiid:test", null); s = c.createStatement(); s.addBatch("update pm1.g1 set e1 = 'a' where e2 = 1"); //$NON-NLS-1$ s.addBatch("update pm1.g1 set e1 = 'b' where e2 = 2"); //$NON-NLS-1$ hcef.updateMap.clear(); hcef.addUpdate("UPDATE pm1.g1 SET e1 = 'a' WHERE pm1.g1.e2 = 1;\nUPDATE pm1.g1 SET e1 = 'b' WHERE pm1.g1.e2 = 2;", new TranslatorBatchException(new SQLException(), new int[] {1, -3})); try { s.executeBatch(); fail(); } catch (BatchUpdateException e) { int[] updateCounts = e.getUpdateCounts(); assertArrayEquals(new int[] {1, -3}, updateCounts); assertEquals(-1, s.getUpdateCount()); } } @Translator(name="dummy") public static class DummyExecutionFactory extends ExecutionFactory { static AtomicInteger INSTANCES = new AtomicInteger(); int instance = INSTANCES.getAndIncrement(); @Override public void getMetadata(MetadataFactory metadataFactory, Object conn) throws TranslatorException { Table t = metadataFactory.addTable("test"+ String.valueOf(instance)); if (this.supportsOrderBy()) { metadataFactory.addColumn("y", "integer", t); } else { metadataFactory.addColumn("x", "integer", t); } } @Override public boolean isSourceRequiredForMetadata() { return false; } }; @Test public void testTranslatorCreation() throws Exception { EmbeddedConfiguration ec = new EmbeddedConfiguration(); ec.setUseDisk(false); es.start(ec); es.addTranslator(DummyExecutionFactory.class); Map<String, String> props = new HashMap<String, String>(); props.put("supportsOrderBy", "true"); es.addTranslator("dummy-override", "dummy", props); ModelMetaData mmd = new ModelMetaData(); mmd.setName("test-one"); mmd.addSourceMapping("one", "dummy", null); ModelMetaData mmd2 = new ModelMetaData(); mmd2.setName("test-two"); mmd2.addSourceMapping("two", "dummy", null); ModelMetaData mmd3 = new ModelMetaData(); mmd3.setName("test-three"); mmd3.addSourceMapping("three", "dummy-override", null); es.deployVDB("test", mmd, mmd2, mmd3); TeiidDriver td = es.getDriver(); Connection c = td.connect("jdbc:teiid:test", null); Statement s = c.createStatement(); s.execute("select count(distinct name) from sys.tables where name like 'test%'"); s.getResultSet().next(); assertEquals(3, s.getResultSet().getInt(1)); s.execute("select count(distinct name) from sys.columns where tablename like 'test%'"); s.getResultSet().next(); assertEquals(2, s.getResultSet().getInt(1)); } @Test public void testCreateDomain() throws Exception { es.start(new EmbeddedConfiguration()); es.deployVDB(new FileInputStream(UnitTestUtil.getTestDataFile("domains-vdb.ddl")), true); Connection c = es.getDriver().connect("jdbc:teiid:domains", null); Statement s = c.createStatement(); s.execute("select * from g1"); ResultSetMetaData rsmd = s.getResultSet().getMetaData(); //for now we'll report the runtime type assertEquals("string", rsmd.getColumnTypeName(1)); ResultSet rs = c.getMetaData().getColumns(null, null, "g1", null); rs.next(); assertEquals("x", rs.getString("TYPE_NAME")); rs.next(); assertEquals("z", rs.getString("TYPE_NAME")); rs.next(); assertEquals("x[]", rs.getString("TYPE_NAME")); try { s.execute("select cast(1 as a)"); //should fail fail(); } catch (SQLException e) { } s.execute("select cast(1 as z)"); rs = s.getResultSet(); //for now we'll report the runtime type assertEquals("bigdecimal", rs.getMetaData().getColumnTypeName(1)); s.execute("select xmlcast(xmlparse(document '<a>1</a>') as z)"); s.execute("select attname, atttypid from pg_attribute where attname = 'e1'"); rs = s.getResultSet(); rs.next(); assertEquals(1043, rs.getInt(2)); //varchar s.execute("select cast((1.0,) as z[])"); rs = s.getResultSet(); rs.next(); assertArrayEquals(new BigDecimal[] {BigDecimal.valueOf(1.0)}, (BigDecimal[])rs.getArray(1).getArray()); assertEquals("bigdecimal[]", rs.getMetaData().getColumnTypeName(1)); } @Ignore("limit to/exclude not yet implemented") @Test public void testImportExcept() throws Exception { es.start(new EmbeddedConfiguration()); es.addMetadataRepository("x", new MetadataRepository() { @Override public void loadMetadata(MetadataFactory factory, ExecutionFactory executionFactory, Object connectionFactory, String text) throws TranslatorException { assertEquals("helloworld1,other", factory.getModelProperties().get("importer.excludeTables")); Table t = factory.addTable("helloworld"); t.setVirtual(true); factory.addColumn("col", "string", t); t.setSelectTransformation("select 'HELLO WORLD'"); } }); String externalDDL = "CREATE DATABASE test VERSION '1';" + "USE DATABASE test VERSION '1';" + "CREATE VIRTUAL SCHEMA test2;" + "IMPORT FOREIGN SCHEMA public except (helloworld1, other) FROM REPOSITORY x INTO test2;"; es.deployVDB(new ByteArrayInputStream(externalDDL.getBytes(Charset.forName("UTF-8"))), true); ResultSet rs = es.getDriver().connect("jdbc:teiid:test", null).createStatement().executeQuery("select * from helloworld"); rs.next(); assertEquals("HELLO WORLD", rs.getString(1)); } }