/* *************************************************************************************** * Copyright (C) 2006 EsperTech, Inc. All rights reserved. * * http://www.espertech.com/esper * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * *************************************************************************************** */ package com.espertech.esper.regression.nwtable; import com.espertech.esper.client.*; import com.espertech.esper.client.scopetest.EPAssertionUtil; import com.espertech.esper.metrics.instrumentation.InstrumentationHelper; import com.espertech.esper.supportregression.bean.SupportSimpleBeanOne; import com.espertech.esper.supportregression.bean.SupportSimpleBeanTwo; import com.espertech.esper.supportregression.client.SupportConfigFactory; import com.espertech.esper.supportregression.epl.SupportQueryPlanIndexHook; import com.espertech.esper.supportregression.util.IndexAssertion; import com.espertech.esper.supportregression.util.IndexAssertionFAF; import com.espertech.esper.supportregression.util.IndexBackingTableInfo; import junit.framework.TestCase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestInfraIndexFAF extends TestCase implements IndexBackingTableInfo { private final static Logger log = LoggerFactory.getLogger(TestInfraIndexFAF.class); private EPServiceProvider epService; public void setUp() { Configuration config = SupportConfigFactory.getConfiguration(); config.getEngineDefaults().getLogging().setEnableQueryPlan(true); epService = EPServiceProviderManager.getDefaultProvider(config); epService.initialize(); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.startTest(epService, this.getClass(), getName());} SupportQueryPlanIndexHook.reset(); } public void tearDown() { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.endTest();} } public void testSelectIndexChoiceJoin() { epService.getEPAdministrator().getConfiguration().addEventType("SSB1", SupportSimpleBeanOne.class); epService.getEPAdministrator().getConfiguration().addEventType("SSB2", SupportSimpleBeanTwo.class); runAssertionSelectIndexChoiceJoin(true); runAssertionSelectIndexChoiceJoin(false); } public void testSelectIndexChoice() { epService.getEPAdministrator().getConfiguration().addEventType("SSB1", SupportSimpleBeanOne.class); epService.getEPAdministrator().getConfiguration().addEventType("SSB2", SupportSimpleBeanTwo.class); runAssertionSelectIndexChoice(true); runAssertionSelectIndexChoice(false); } private void runAssertionSelectIndexChoiceJoin(boolean namedWindow) { Object[] preloadedEventsOne = new Object[] { new SupportSimpleBeanOne("E1", 10, 1, 2), new SupportSimpleBeanOne("E2", 11, 3, 4), new SupportSimpleBeanTwo("E1", 20, 1, 2), new SupportSimpleBeanTwo("E2", 21, 3, 4), }; IndexAssertionFAF fafAssertion = new IndexAssertionFAF() { public void run(EPOnDemandQueryResult result) { String[] fields = "w1.s1,w2.s2,w1.i1,w2.i2".split(","); EPAssertionUtil.assertPropsPerRowAnyOrder(result.getArray(), fields, new Object[][]{{"E1", "E1", 10, 20}, {"E2", "E2", 11, 21}}); } }; IndexAssertion[] assertionsSingleProp = new IndexAssertion[] { new IndexAssertion(null, "s1 = s2", true, fafAssertion), new IndexAssertion(null, "s1 = s2 and l1 = l2", true, fafAssertion), new IndexAssertion(null, "l1 = l2 and s1 = s2", true, fafAssertion), new IndexAssertion(null, "d1 = d2 and l1 = l2 and s1 = s2", true, fafAssertion), new IndexAssertion(null, "d1 = d2 and l1 = l2", false, fafAssertion), }; // single prop, no index, both declared unique (named window only) if (namedWindow) { assertIndexChoiceJoin(namedWindow, new String[0], preloadedEventsOne, "std:unique(s1)", "std:unique(s2)", assertionsSingleProp); } // single prop, unique indexes, both declared keepall String[] uniqueIndex = new String[] {"create unique index W1I1 on W1(s1)", "create unique index W1I2 on W2(s2)"}; assertIndexChoiceJoin(namedWindow, uniqueIndex, preloadedEventsOne, "win:keepall()", "win:keepall()", assertionsSingleProp); // single prop, mixed indexes, both declared keepall IndexAssertion[] assertionsMultiProp = new IndexAssertion[] { new IndexAssertion(null, "s1 = s2", false, fafAssertion), new IndexAssertion(null, "s1 = s2 and l1 = l2", true, fafAssertion), new IndexAssertion(null, "l1 = l2 and s1 = s2", true, fafAssertion), new IndexAssertion(null, "d1 = d2 and l1 = l2 and s1 = s2", true, fafAssertion), new IndexAssertion(null, "d1 = d2 and l1 = l2", false, fafAssertion), }; if (namedWindow) { String[] mixedIndex = new String[] {"create index W1I1 on W1(s1, l1)", "create unique index W1I2 on W2(s2)"}; assertIndexChoiceJoin(namedWindow, mixedIndex, preloadedEventsOne, "std:unique(s1)", "win:keepall()", assertionsSingleProp); // multi prop, no index, both declared unique assertIndexChoiceJoin(namedWindow, new String[0], preloadedEventsOne, "std:unique(s1, l1)", "std:unique(s2, l2)", assertionsMultiProp); } // multi prop, unique indexes, both declared keepall String[] uniqueIndexMulti = new String[] {"create unique index W1I1 on W1(s1, l1)", "create unique index W1I2 on W2(s2, l2)"}; assertIndexChoiceJoin(namedWindow, uniqueIndexMulti, preloadedEventsOne, "win:keepall()", "win:keepall()", assertionsMultiProp); // multi prop, mixed indexes, both declared keepall if (namedWindow) { String[] mixedIndexMulti = new String[] {"create index W1I1 on W1(s1)", "create unique index W1I2 on W2(s2, l2)"}; assertIndexChoiceJoin(namedWindow, mixedIndexMulti, preloadedEventsOne, "std:unique(s1, l1)", "win:keepall()", assertionsMultiProp); } } private void assertIndexChoiceJoin(boolean namedWindow, String[] indexes, Object[] preloadedEvents, String datawindowOne, String datawindowTwo, IndexAssertion... assertions) { if (namedWindow) { epService.getEPAdministrator().createEPL("create window W1." + datawindowOne + " as SSB1"); epService.getEPAdministrator().createEPL("create window W2." + datawindowTwo + " as SSB2"); } else { epService.getEPAdministrator().createEPL("create table W1 (s1 String primary key, i1 int primary key, d1 double primary key, l1 long primary key)"); epService.getEPAdministrator().createEPL("create table W2 (s2 String primary key, i2 int primary key, d2 double primary key, l2 long primary key)"); } epService.getEPAdministrator().createEPL("insert into W1 select s1,i1,d1,l1 from SSB1"); epService.getEPAdministrator().createEPL("insert into W2 select s2,i2,d2,l2 from SSB2"); for (String index : indexes) { epService.getEPAdministrator().createEPL(index); } for (Object event : preloadedEvents) { epService.getEPRuntime().sendEvent(event); } int count = 0; for (IndexAssertion assertion : assertions) { log.info("======= Testing #" + count++); String epl = INDEX_CALLBACK_HOOK + (assertion.getHint() == null ? "" : assertion.getHint()) + "select * from W1 as w1, W2 as w2 " + "where " + assertion.getWhereClause(); EPOnDemandQueryResult result; try { result = epService.getEPRuntime().executeQuery(epl); } catch (EPStatementException ex) { log.error("Failed to process:" + ex.getMessage(), ex); if (assertion.getEventSendAssertion() == null) { // no assertion, expected assertTrue(ex.getMessage().contains("index hint busted")); continue; } throw new RuntimeException("Unexpected statement exception: " + ex.getMessage(), ex); } // assert index and access SupportQueryPlanIndexHook.assertJoinAllStreamsAndReset(assertion.getUnique()); assertion.getFafAssertion().run(result); } epService.getEPAdministrator().destroyAllStatements(); epService.getEPAdministrator().getConfiguration().removeEventType("W1", false); epService.getEPAdministrator().getConfiguration().removeEventType("W2", false); } private void runAssertionSelectIndexChoice(boolean namedWindow) { Object[] preloadedEventsOne = new Object[] {new SupportSimpleBeanOne("E1", 10, 11, 12), new SupportSimpleBeanOne("E2", 20, 21, 22)}; IndexAssertionFAF fafAssertion = new IndexAssertionFAF() { public void run(EPOnDemandQueryResult result) { String[] fields = "s1,i1".split(","); EPAssertionUtil.assertPropsPerRow(result.getArray(), fields, new Object[][]{{"E2", 20}}); } }; // single index one field (plus declared unique) String[] noindexes = new String[0]; assertIndexChoice(namedWindow, noindexes, preloadedEventsOne, "std:unique(s1)", new IndexAssertion[] { new IndexAssertion(null, "s1 = 'E2'", null, null, fafAssertion), new IndexAssertion(null, "s1 = 'E2' and l1 = 22", null, null, fafAssertion), new IndexAssertion("@Hint('index(One)')", "s1 = 'E2' and l1 = 22", null, null, fafAssertion), new IndexAssertion("@Hint('index(Two,bust)')", "s1 = 'E2' and l1 = 22"), // should bust }); // single index one field (plus declared unique) String[] indexOneField = new String[] {"create unique index One on MyInfra (s1)"}; assertIndexChoice(namedWindow, indexOneField, preloadedEventsOne, "std:unique(s1)", new IndexAssertion[] { new IndexAssertion(null, "s1 = 'E2'", "One", BACKING_SINGLE_UNIQUE, fafAssertion), new IndexAssertion(null, "s1 in ('E2')", "One", BACKING_SINGLE_UNIQUE, fafAssertion), new IndexAssertion(null, "s1 = 'E2' and l1 = 22", "One", BACKING_SINGLE_UNIQUE, fafAssertion), new IndexAssertion("@Hint('index(One)')", "s1 = 'E2' and l1 = 22", "One", BACKING_SINGLE_UNIQUE, fafAssertion), new IndexAssertion("@Hint('index(Two,bust)')", "s1 = 'E2' and l1 = 22"), // should bust }); // single index two field (plus declared unique) String[] indexTwoField = new String[] {"create unique index One on MyInfra (s1, l1)"}; assertIndexChoice(namedWindow, indexTwoField, preloadedEventsOne, "std:unique(s1)", new IndexAssertion[] { new IndexAssertion(null, "s1 = 'E2'", null, null, fafAssertion), new IndexAssertion(null, "s1 = 'E2' and l1 = 22", "One", BACKING_MULTI_UNIQUE, fafAssertion), }); // two index one unique (plus declared unique) String[] indexSetTwo = new String[] { "create index One on MyInfra (s1)", "create unique index Two on MyInfra (s1, d1)"}; assertIndexChoice(namedWindow, indexSetTwo, preloadedEventsOne, "std:unique(s1)", new IndexAssertion[] { new IndexAssertion(null, "s1 = 'E2'", "One", BACKING_SINGLE_DUPS, fafAssertion), new IndexAssertion(null, "s1 = 'E2' and l1 = 22", "One", BACKING_SINGLE_DUPS, fafAssertion), new IndexAssertion("@Hint('index(One)')", "s1 = 'E2' and l1 = 22", "One", BACKING_SINGLE_DUPS, fafAssertion), new IndexAssertion("@Hint('index(Two,One)')", "s1 = 'E2' and l1 = 22", "One", BACKING_SINGLE_DUPS, fafAssertion), new IndexAssertion("@Hint('index(Two,bust)')", "s1 = 'E2' and l1 = 22"), // busted new IndexAssertion("@Hint('index(explicit,bust)')", "s1 = 'E2' and l1 = 22", "One", BACKING_SINGLE_DUPS, fafAssertion), new IndexAssertion(null, "s1 = 'E2' and d1 = 21 and l1 = 22", "Two", BACKING_MULTI_UNIQUE, fafAssertion), new IndexAssertion("@Hint('index(explicit,bust)')", "d1 = 22 and l1 = 22"), // busted }); // range (unique) String[] indexSetThree = new String[] { "create index One on MyInfra (l1 btree)", "create index Two on MyInfra (d1 btree)"}; assertIndexChoice(namedWindow, indexSetThree, preloadedEventsOne, "std:unique(s1)", new IndexAssertion[] { new IndexAssertion(null, "l1 between 22 and 23", "One", BACKING_SORTED_COERCED, fafAssertion), new IndexAssertion(null, "d1 between 21 and 22", "Two", BACKING_SORTED_COERCED, fafAssertion), new IndexAssertion("@Hint('index(One, bust)')", "d1 between 21 and 22"), // busted }); } private void assertIndexChoice(boolean namedWindow, String[] indexes, Object[] preloadedEvents, String datawindow, IndexAssertion[] assertions) { String eplCreate = namedWindow ? "create window MyInfra." + datawindow + " as SSB1" : "create table MyInfra(s1 String primary key, i1 int primary key, d1 double primary key, l1 long primary key)"; epService.getEPAdministrator().createEPL(eplCreate); epService.getEPAdministrator().createEPL("insert into MyInfra select s1,i1,d1,l1 from SSB1"); for (String index : indexes) { epService.getEPAdministrator().createEPL(index); } for (Object event : preloadedEvents) { epService.getEPRuntime().sendEvent(event); } int count = 0; for (IndexAssertion assertion : assertions) { log.info("======= Testing #" + count++); String epl = INDEX_CALLBACK_HOOK + (assertion.getHint() == null ? "" : assertion.getHint()) + "select * from MyInfra where " + assertion.getWhereClause(); EPOnDemandQueryResult result; try { result = epService.getEPRuntime().executeQuery(epl); } catch (EPStatementException ex) { if (assertion.getEventSendAssertion() == null) { // no assertion, expected assertTrue(ex.getMessage().contains("index hint busted")); continue; } throw new RuntimeException("Unexpected statement exception: " + ex.getMessage(), ex); } // assert index and access SupportQueryPlanIndexHook.assertFAFAndReset(assertion.getExpectedIndexName(), assertion.getIndexBackingClass()); assertion.getFafAssertion().run(result); } epService.getEPAdministrator().destroyAllStatements(); epService.getEPAdministrator().getConfiguration().removeEventType("MyInfra", false); } }