/*
***************************************************************************************
* 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.epl;
import com.espertech.esper.client.*;
import com.espertech.esper.client.deploy.DeploymentResult;
import com.espertech.esper.client.scopetest.EPAssertionUtil;
import com.espertech.esper.client.scopetest.SupportUpdateListener;
import com.espertech.esper.client.soda.*;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.supportregression.bean.SupportBean;
import com.espertech.esper.supportregression.bean.SupportBean_S0;
import com.espertech.esper.supportregression.bean.bookexample.OrderBean;
import com.espertech.esper.supportregression.bean.bookexample.OrderBeanFactory;
import com.espertech.esper.supportregression.client.SupportConfigFactory;
import com.espertech.esper.supportregression.util.SupportMessageAssertUtil;
import com.espertech.esper.supportregression.util.SupportModelHelper;
import com.espertech.esper.util.EventRepresentationChoice;
import junit.framework.TestCase;
import org.apache.avro.generic.GenericData;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.apache.avro.SchemaBuilder.record;
public class TestSplitStream extends TestCase
{
private EPServiceProvider epService;
private SupportUpdateListener listener;
private SupportUpdateListener[] listeners;
public void setUp()
{
Configuration config = SupportConfigFactory.getConfiguration();
config.addEventType("SupportBean", SupportBean.class);
config.addEventType("S0", SupportBean_S0.class);
epService = EPServiceProviderManager.getDefaultProvider(config);
epService.initialize();
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.startTest(epService, this.getClass(), getName());}
listener = new SupportUpdateListener();
listeners = new SupportUpdateListener[10];
for (int i = 0; i < listeners.length; i++)
{
listeners[i] = new SupportUpdateListener();
}
}
protected void tearDown() throws Exception {
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.endTest();}
listener = null;
listeners = null;
}
public void testInvalid()
{
SupportMessageAssertUtil.tryInvalid(epService, "on SupportBean select * where intPrimitive=1 insert into BStream select * where 1=2",
"Error starting statement: Required insert-into clause is not provided, the clause is required for split-stream syntax");
SupportMessageAssertUtil.tryInvalid(epService, "on SupportBean insert into AStream select * where intPrimitive=1 group by string insert into BStream select * where 1=2",
"Error starting statement: A group-by clause, having-clause or order-by clause is not allowed for the split stream syntax");
SupportMessageAssertUtil.tryInvalid(epService, "on SupportBean insert into AStream select * where intPrimitive=1 insert into BStream select avg(intPrimitive) where 1=2",
"Error starting statement: Aggregation functions are not allowed in this context");
}
public void testFromClause() throws Exception {
epService.getEPAdministrator().getConfiguration().addEventType("OrderEvent", OrderBean.class);
runAssertionFromClauseBeginBodyEnd();
runAssertionFromClauseAsMultiple();
runAssertionFromClauseOutputFirstWhere();
runAssertionFromClauseDocSample();
}
public void testSplitPremptiveNamedWindow() {
for (EventRepresentationChoice rep : EventRepresentationChoice.values()) {
runAssertionSplitPremptiveNamedWindow(rep);
}
}
public void test1SplitDefault()
{
// test wildcard
String stmtOrigText = "on SupportBean insert into AStream select *";
EPStatement stmt = epService.getEPAdministrator().createEPL(stmtOrigText);
stmt.addListener(listener);
EPStatement stmtOne = epService.getEPAdministrator().createEPL("select * from AStream");
stmtOne.addListener(listeners[0]);
sendSupportBean("E1", 1);
assertReceivedSingle(0, "E1");
assertFalse(listener.isInvoked());
// test select
stmtOrigText = "on SupportBean insert into BStream select 3*intPrimitive as value";
EPStatement stmtOrig = epService.getEPAdministrator().createEPL(stmtOrigText);
stmtOne = epService.getEPAdministrator().createEPL("select value from BStream");
stmtOne.addListener(listeners[1]);
sendSupportBean("E1", 6);
assertEquals(18, listeners[1].assertOneGetNewAndReset().get("value"));
// assert type is original type
assertEquals(SupportBean.class, stmtOrig.getEventType().getUnderlyingType());
assertFalse(stmtOrig.iterator().hasNext());
}
public void test2SplitNoDefaultOutputFirst()
{
String stmtOrigText = "@Audit on SupportBean " +
"insert into AStream select * where intPrimitive=1 " +
"insert into BStream select * where intPrimitive=1 or intPrimitive=2";
EPStatement stmtOrig = epService.getEPAdministrator().createEPL(stmtOrigText);
runAssertion(stmtOrig);
// statement object model
EPStatementObjectModel model = new EPStatementObjectModel();
model.setAnnotations(Collections.singletonList(new AnnotationPart("Audit")));
model.setFromClause(FromClause.create(FilterStream.create("SupportBean")));
model.setInsertInto(InsertIntoClause.create("AStream"));
model.setSelectClause(SelectClause.createWildcard());
model.setWhereClause(Expressions.eq("intPrimitive", 1));
OnInsertSplitStreamClause clause = OnClause.createOnInsertSplitStream();
model.setOnExpr(clause);
OnInsertSplitStreamItem item = OnInsertSplitStreamItem.create(
InsertIntoClause.create("BStream"),
SelectClause.createWildcard(),
Expressions.or(Expressions.eq("intPrimitive", 1), Expressions.eq("intPrimitive", 2)));
clause.addItem(item);
assertEquals(stmtOrigText, model.toEPL());
stmtOrig = epService.getEPAdministrator().create(model);
runAssertion(stmtOrig);
EPStatementObjectModel newModel = epService.getEPAdministrator().compileEPL(stmtOrigText);
stmtOrig = epService.getEPAdministrator().create(newModel);
assertEquals(stmtOrigText, newModel.toEPL());
runAssertion(stmtOrig);
SupportModelHelper.compileCreate(epService, stmtOrigText + " output all");
}
public void testSubquery()
{
String stmtOrigText = "on SupportBean " +
"insert into AStream select (select p00 from S0#lastevent) as string where intPrimitive=(select id from S0#lastevent) " +
"insert into BStream select (select p01 from S0#lastevent) as string where intPrimitive<>(select id from S0#lastevent) or (select id from S0#lastevent) is null";
EPStatement stmtOrig = epService.getEPAdministrator().createEPL(stmtOrigText);
stmtOrig.addListener(listener);
EPStatement stmtOne = epService.getEPAdministrator().createEPL("select * from AStream");
stmtOne.addListener(listeners[0]);
EPStatement stmtTwo = epService.getEPAdministrator().createEPL("select * from BStream");
stmtTwo.addListener(listeners[1]);
sendSupportBean("E1", 1);
assertFalse(listeners[0].getAndClearIsInvoked());
assertNull(listeners[1].assertOneGetNewAndReset().get("string"));
epService.getEPRuntime().sendEvent(new SupportBean_S0(10, "x", "y"));
sendSupportBean("E2", 10);
assertEquals("x", listeners[0].assertOneGetNewAndReset().get("string"));
assertFalse(listeners[1].getAndClearIsInvoked());
sendSupportBean("E3", 9);
assertFalse(listeners[0].getAndClearIsInvoked());
assertEquals("y", listeners[1].assertOneGetNewAndReset().get("string"));
}
public void test2SplitNoDefaultOutputAll()
{
String stmtOrigText = "on SupportBean " +
"insert into AStream select theString where intPrimitive=1 " +
"insert into BStream select theString where intPrimitive=1 or intPrimitive=2 " +
"output all";
EPStatement stmtOrig = epService.getEPAdministrator().createEPL(stmtOrigText);
stmtOrig.addListener(listener);
EPStatement stmtOne = epService.getEPAdministrator().createEPL("select * from AStream");
stmtOne.addListener(listeners[0]);
EPStatement stmtTwo = epService.getEPAdministrator().createEPL("select * from BStream");
stmtTwo.addListener(listeners[1]);
assertNotSame(stmtOne.getEventType(), stmtTwo.getEventType());
assertSame(stmtOne.getEventType().getUnderlyingType(), stmtTwo.getEventType().getUnderlyingType());
sendSupportBean("E1", 1);
assertReceivedEach(new String[] {"E1", "E1"});
assertFalse(listener.isInvoked());
sendSupportBean("E2", 2);
assertReceivedEach(new String[] {null, "E2"});
assertFalse(listener.isInvoked());
sendSupportBean("E3", 1);
assertReceivedEach(new String[] {"E3", "E3"});
assertFalse(listener.isInvoked());
sendSupportBean("E4", -999);
assertReceivedEach(new String[] {null, null});
assertEquals("E4", listener.assertOneGetNewAndReset().get("theString"));
stmtOrig.destroy();
stmtOrigText = "on SupportBean " +
"insert into AStream select theString || '_1' as theString where intPrimitive in (1, 2) " +
"insert into BStream select theString || '_2' as theString where intPrimitive in (2, 3) " +
"insert into CStream select theString || '_3' as theString " +
"output all";
stmtOrig = epService.getEPAdministrator().createEPL(stmtOrigText);
stmtOrig.addListener(listener);
EPStatement stmtThree = epService.getEPAdministrator().createEPL("select * from CStream");
stmtThree.addListener(listeners[2]);
sendSupportBean("E1", 2);
assertReceivedEach(new String[] {"E1_1", "E1_2", "E1_3"});
assertFalse(listener.isInvoked());
sendSupportBean("E2", 1);
assertReceivedEach(new String[] {"E2_1", null, "E2_3"});
assertFalse(listener.isInvoked());
sendSupportBean("E3", 3);
assertReceivedEach(new String[] {null, "E3_2", "E3_3"});
assertFalse(listener.isInvoked());
sendSupportBean("E4", -999);
assertReceivedEach(new String[] {null, null, "E4_3"});
assertFalse(listener.isInvoked());
}
public void test3And4SplitDefaultOutputFirst()
{
String stmtOrigText = "on SupportBean as mystream " +
"insert into AStream select mystream.theString||'_1' as theString where intPrimitive=1 " +
"insert into BStream select mystream.theString||'_2' as theString where intPrimitive=2 " +
"insert into CStream select theString||'_3' as theString";
EPStatement stmtOrig = epService.getEPAdministrator().createEPL(stmtOrigText);
stmtOrig.addListener(listener);
EPStatement stmtOne = epService.getEPAdministrator().createEPL("select * from AStream");
stmtOne.addListener(listeners[0]);
EPStatement stmtTwo = epService.getEPAdministrator().createEPL("select * from BStream");
stmtTwo.addListener(listeners[1]);
EPStatement stmtThree = epService.getEPAdministrator().createEPL("select * from CStream");
stmtThree.addListener(listeners[2]);
assertNotSame(stmtOne.getEventType(), stmtTwo.getEventType());
assertSame(stmtOne.getEventType().getUnderlyingType(), stmtTwo.getEventType().getUnderlyingType());
sendSupportBean("E1", 1);
assertReceivedSingle(0, "E1_1");
assertFalse(listener.isInvoked());
sendSupportBean("E2", 2);
assertReceivedSingle(1, "E2_2");
assertFalse(listener.isInvoked());
sendSupportBean("E3", 1);
assertReceivedSingle(0, "E3_1");
assertFalse(listener.isInvoked());
sendSupportBean("E4", -999);
assertReceivedSingle(2, "E4_3");
assertFalse(listener.isInvoked());
stmtOrigText = "on SupportBean " +
"insert into AStream select theString||'_1' as theString where intPrimitive=10 " +
"insert into BStream select theString||'_2' as theString where intPrimitive=20 " +
"insert into CStream select theString||'_3' as theString where intPrimitive<0 " +
"insert into DStream select theString||'_4' as theString";
stmtOrig.destroy();
stmtOrig = epService.getEPAdministrator().createEPL(stmtOrigText);
stmtOrig.addListener(listener);
EPStatement stmtFour = epService.getEPAdministrator().createEPL("select * from DStream");
stmtFour.addListener(listeners[3]);
sendSupportBean("E5", -999);
assertReceivedSingle(2, "E5_3");
assertFalse(listener.isInvoked());
sendSupportBean("E6", 9999);
assertReceivedSingle(3, "E6_4");
assertFalse(listener.isInvoked());
sendSupportBean("E7", 20);
assertReceivedSingle(1, "E7_2");
assertFalse(listener.isInvoked());
sendSupportBean("E8", 10);
assertReceivedSingle(0, "E8_1");
assertFalse(listener.isInvoked());
}
private void assertReceivedEach(String[] stringValue)
{
for (int i = 0; i < stringValue.length; i++)
{
if (stringValue[i] != null)
{
assertEquals(stringValue[i], listeners[i].assertOneGetNewAndReset().get("theString"));
}
else
{
assertFalse(listeners[i].isInvoked());
}
}
}
private void assertReceivedSingle(int index, String stringValue)
{
for (int i = 0; i < listeners.length; i++)
{
if (i == index)
{
continue;
}
assertFalse(listeners[i].isInvoked());
}
assertEquals(stringValue, listeners[index].assertOneGetNewAndReset().get("theString"));
}
private void assertReceivedNone()
{
for (int i = 0; i < listeners.length; i++)
{
assertFalse(listeners[i].isInvoked());
}
}
private SupportBean sendSupportBean(String theString, int intPrimitive)
{
SupportBean bean = new SupportBean();
bean.setTheString(theString);
bean.setIntPrimitive(intPrimitive);
epService.getEPRuntime().sendEvent(bean);
return bean;
}
private void runAssertion(EPStatement stmtOrig)
{
stmtOrig.addListener(listener);
EPStatement stmtOne = epService.getEPAdministrator().createEPL("select * from AStream");
stmtOne.addListener(listeners[0]);
EPStatement stmtTwo = epService.getEPAdministrator().createEPL("select * from BStream");
stmtTwo.addListener(listeners[1]);
assertNotSame(stmtOne.getEventType(), stmtTwo.getEventType());
assertSame(stmtOne.getEventType().getUnderlyingType(), stmtTwo.getEventType().getUnderlyingType());
sendSupportBean("E1", 1);
assertReceivedSingle(0, "E1");
assertFalse(listener.isInvoked());
sendSupportBean("E2", 2);
assertReceivedSingle(1, "E2");
assertFalse(listener.isInvoked());
sendSupportBean("E3", 1);
assertReceivedSingle(0, "E3");
assertFalse(listener.isInvoked());
sendSupportBean("E4", -999);
assertReceivedNone();
assertEquals("E4", listener.assertOneGetNewAndReset().get("theString"));
stmtOrig.destroy();
stmtOne.destroy();
stmtTwo.destroy();
}
private void runAssertionSplitPremptiveNamedWindow(EventRepresentationChoice eventRepresentationEnum)
{
epService.getEPAdministrator().createEPL(eventRepresentationEnum.getAnnotationText() + " create schema TypeTwo(col2 int)");
epService.getEPAdministrator().createEPL(eventRepresentationEnum.getAnnotationText() + " create schema TypeTrigger(trigger int)");
epService.getEPAdministrator().createEPL(eventRepresentationEnum.getAnnotationText() + " create window WinTwo#keepall as TypeTwo");
String stmtOrigText = "on TypeTrigger " +
"insert into OtherStream select 1 " +
"insert into WinTwo(col2) select 2 " +
"output all";
epService.getEPAdministrator().createEPL(stmtOrigText);
EPStatement stmt = epService.getEPAdministrator().createEPL("on OtherStream select col2 from WinTwo");
stmt.addListener(listener);
// populate WinOne
epService.getEPRuntime().sendEvent(new SupportBean("E1", 2));
// fire trigger
if (eventRepresentationEnum.isObjectArrayEvent()) {
epService.getEPRuntime().getEventSender("TypeTrigger").sendEvent(new Object[] {null});
}
else if (eventRepresentationEnum.isMapEvent()){
epService.getEPRuntime().getEventSender("TypeTrigger").sendEvent(new HashMap());
}
else if (eventRepresentationEnum.isAvroEvent()){
GenericData.Record event = new GenericData.Record(record("name").fields().optionalInt("trigger").endRecord());
epService.getEPRuntime().getEventSender("TypeTrigger").sendEvent(event);
}
else {
fail();
}
assertEquals(2, listener.assertOneGetNewAndReset().get("col2"));
epService.initialize();
}
private void runAssertionFromClauseBeginBodyEnd() {
runAssertionFromClauseBeginBodyEnd(false);
runAssertionFromClauseBeginBodyEnd(true);
}
private void runAssertionFromClauseAsMultiple() {
runAssertionFromClauseAsMultiple(false);
runAssertionFromClauseAsMultiple(true);
}
private void runAssertionFromClauseAsMultiple(boolean soda) {
String epl = "on OrderEvent as oe " +
"insert into StartEvent select oe.orderdetail.orderId as oi " +
"insert into ThenEvent select * from [select oe.orderdetail.orderId as oi, itemId from orderdetail.items] as item " +
"insert into MoreEvent select oe.orderdetail.orderId as oi, item.itemId as itemId from [select oe, * from orderdetail.items] as item " +
"output all";
SupportModelHelper.createByCompileOrParse(epService, soda, epl);
epService.getEPAdministrator().createEPL("select * from StartEvent").addListener(listeners[0]);
epService.getEPAdministrator().createEPL("select * from ThenEvent").addListener(listeners[1]);
epService.getEPAdministrator().createEPL("select * from MoreEvent").addListener(listeners[2]);
epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventOne());
String[] fieldsOrderId = "oi".split(",");
String[] fieldsItems = "oi,itemId".split(",");
EPAssertionUtil.assertProps(listeners[0].assertOneGetNewAndReset(), fieldsOrderId, new Object[] {"PO200901"});
Object[][] expected = new Object[][] {{"PO200901", "A001"}, {"PO200901", "A002"}, {"PO200901", "A003"}};
EPAssertionUtil.assertPropsPerRow(listeners[1].getAndResetDataListsFlattened().getFirst(), fieldsItems, expected);
EPAssertionUtil.assertPropsPerRow(listeners[2].getAndResetDataListsFlattened().getFirst(), fieldsItems, expected);
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionFromClauseBeginBodyEnd(boolean soda) {
String epl = "on OrderEvent " +
"insert into BeginEvent select orderdetail.orderId as orderId " +
"insert into OrderItem select * from [select orderdetail.orderId as orderId, * from orderdetail.items] " +
"insert into EndEvent select orderdetail.orderId as orderId " +
"output all";
SupportModelHelper.createByCompileOrParse(epService, soda, epl);
epService.getEPAdministrator().createEPL("select * from BeginEvent").addListener(listeners[0]);
epService.getEPAdministrator().createEPL("select * from OrderItem").addListener(listeners[1]);
epService.getEPAdministrator().createEPL("select * from EndEvent").addListener(listeners[2]);
EventType typeOrderItem = epService.getEPAdministrator().getConfiguration().getEventType("OrderItem");
assertEquals("[amount, itemId, price, productId, orderId]", Arrays.toString(typeOrderItem.getPropertyNames()));
epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventOne());
assertFromClauseWContained("PO200901", new Object[][]{{"PO200901", "A001"}, {"PO200901", "A002"}, {"PO200901", "A003"}});
epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventTwo());
assertFromClauseWContained("PO200902", new Object[][]{{"PO200902", "B001"}});
epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventFour());
assertFromClauseWContained("PO200904", new Object[0][]);
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionFromClauseOutputFirstWhere() {
runAssertionFromClauseOutputFirstWhere(false);
runAssertionFromClauseOutputFirstWhere(true);
}
private void runAssertionFromClauseOutputFirstWhere(boolean soda) {
String[] fieldsOrderId = "oe.orderdetail.orderId".split(",");
String epl = "on OrderEvent as oe " +
"insert into HeaderEvent select orderdetail.orderId as orderId where 1=2 " +
"insert into StreamOne select * from [select oe, * from orderdetail.items] where productId=\"10020\" " +
"insert into StreamTwo select * from [select oe, * from orderdetail.items] where productId=\"10022\" " +
"insert into StreamThree select * from [select oe, * from orderdetail.items] where productId in (\"10020\",\"10025\",\"10022\")";
SupportModelHelper.createByCompileOrParse(epService, soda, epl);
String[] listenerEPL = new String[] {"select * from StreamOne", "select * from StreamTwo", "select * from StreamThree"};
for (int i = 0; i < listenerEPL.length; i++) {
epService.getEPAdministrator().createEPL(listenerEPL[i]).addListener(listeners[i]);
listeners[i].reset();
}
epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventOne());
EPAssertionUtil.assertProps(listeners[0].assertOneGetNewAndReset(), fieldsOrderId, new Object[] {"PO200901"});
assertFalse(listeners[1].isInvoked());
assertFalse(listeners[2].isInvoked());
epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventTwo());
assertFalse(listeners[0].isInvoked());
EPAssertionUtil.assertProps(listeners[1].assertOneGetNewAndReset(), fieldsOrderId, new Object[] {"PO200902"});
assertFalse(listeners[2].isInvoked());
epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventThree());
assertFalse(listeners[0].isInvoked());
assertFalse(listeners[1].isInvoked());
EPAssertionUtil.assertProps(listeners[2].assertOneGetNewAndReset(), fieldsOrderId, new Object[] {"PO200903"});
epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventFour());
assertFalse(listeners[0].isInvoked());
assertFalse(listeners[1].isInvoked());
assertFalse(listeners[2].isInvoked());
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionFromClauseDocSample() throws Exception {
String epl =
"create schema MyOrderItem(itemId string);\n" +
"create schema MyOrderEvent(orderId string, items MyOrderItem[]);\n" +
"on MyOrderEvent\n" +
" insert into MyOrderBeginEvent select orderId\n" +
" insert into MyOrderItemEvent select * from [select orderId, * from items]\n" +
" insert into MyOrderEndEvent select orderId\n" +
" output all;\n" +
"create context MyOrderContext \n" +
" initiated by MyOrderBeginEvent as obe\n" +
" terminated by MyOrderEndEvent(orderId = obe.orderId);\n" +
"@Name('count') context MyOrderContext select count(*) as orderItemCount from MyOrderItemEvent output when terminated;\n";
DeploymentResult result = epService.getEPAdministrator().getDeploymentAdmin().parseDeploy(epl);
listener.reset();
epService.getEPAdministrator().getStatement("count").addListener(listener);
Map<String, Object> event = new HashMap<>();
event.put("orderId", "1010");
event.put("items", new Map[] {Collections.singletonMap("itemId", "A0001")});
epService.getEPRuntime().sendEvent(event, "MyOrderEvent");
assertEquals(1L, listener.assertOneGetNewAndReset().get("orderItemCount"));
epService.getEPAdministrator().getDeploymentAdmin().undeploy(result.getDeploymentId());
}
private void assertFromClauseWContained(String orderId, Object[][] expected) {
String[] fieldsOrderId = "orderId".split(",");
String[] fieldsItems = "orderId,itemId".split(",");
EPAssertionUtil.assertProps(listeners[0].assertOneGetNewAndReset(), fieldsOrderId, new Object[] {orderId});
EPAssertionUtil.assertPropsPerRow(listeners[1].getAndResetDataListsFlattened().getFirst(), fieldsItems, expected);
EPAssertionUtil.assertProps(listeners[2].assertOneGetNewAndReset(), fieldsOrderId, new Object[] {orderId});
}
}