/* *************************************************************************************** * 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.avro.core.AvroEventType; import com.espertech.esper.avro.util.support.SupportAvroUtil; import com.espertech.esper.client.*; import com.espertech.esper.client.scopetest.EPAssertionUtil; import com.espertech.esper.client.scopetest.SupportUpdateListener; import com.espertech.esper.metrics.instrumentation.InstrumentationHelper; import com.espertech.esper.supportregression.bean.SupportBean; import com.espertech.esper.supportregression.bean.SupportBean_A; 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.util.EventRepresentationChoice; import junit.framework.TestCase; import org.apache.avro.Schema; import org.apache.avro.generic.GenericData; import java.util.LinkedHashMap; import java.util.Map; public class TestNamedWindowOnMerge extends TestCase { private EPServiceProvider epService; private SupportUpdateListener nwListener; private SupportUpdateListener mergeListener; protected void setUp() { Configuration config = SupportConfigFactory.getConfiguration(); config.addEventType("SupportBean", SupportBean.class); config.addEventType("SupportBean_A", SupportBean_A.class); config.addEventType("SupportBean_S0", SupportBean_S0.class); epService = EPServiceProviderManager.getDefaultProvider(config); epService.initialize(); if (InstrumentationHelper.ENABLED) { InstrumentationHelper.startTest(epService, this.getClass(), getName());} nwListener = new SupportUpdateListener(); mergeListener = new SupportUpdateListener(); } protected void tearDown() throws Exception { if (InstrumentationHelper.ENABLED) { InstrumentationHelper.endTest();} nwListener = null; mergeListener = null; } public void testUpdateNonPropertySet() { epService.getEPAdministrator().getConfiguration().addPlugInSingleRowFunction("increaseIntCopyDouble", this.getClass().getName(), "increaseIntCopyDouble"); epService.getEPAdministrator().createEPL("create window MyWindow#keepall as SupportBean"); epService.getEPAdministrator().createEPL("insert into MyWindow select * from SupportBean"); EPStatement stmt = epService.getEPAdministrator().createEPL("on SupportBean_S0 as sb " + "merge MyWindow as mywin when matched then " + "update set mywin.setDoublePrimitive(id), increaseIntCopyDouble(initial, mywin)"); stmt.addListener(mergeListener); String[] fields = "intPrimitive,doublePrimitive,doubleBoxed".split(","); epService.getEPRuntime().sendEvent(makeSupportBean("E1", 10, 2)); epService.getEPRuntime().sendEvent(new SupportBean_S0(5, "E1")); EPAssertionUtil.assertProps(mergeListener.getAndResetLastNewData()[0], fields, new Object[]{11, 5d, 5d}); // try a case-statement String eplCase = "on SupportBean_S0 merge MyWindow " + "when matched then update set theString = " + "case intPrimitive when 1 then 'a' else 'b' end"; epService.getEPAdministrator().createEPL(eplCase); } public void testMergeTriggeredByAnotherWindow() { // test dispatch between named windows epService.getEPAdministrator().createEPL("@Name('A') create window A#unique(id) as (id int)"); epService.getEPAdministrator().createEPL("@Name('B') create window B#unique(id) as (id int)"); epService.getEPAdministrator().createEPL("@Name('C') on A merge B when not matched then insert select 1 as id when matched then insert select 1 as id"); epService.getEPAdministrator().createEPL("@Name('D') select * from B").addListener(nwListener); epService.getEPAdministrator().createEPL("@Name('E') insert into A select intPrimitive as id FROM SupportBean"); epService.getEPRuntime().sendEvent(new SupportBean("E1", 1)); assertTrue(nwListener.isInvoked()); epService.getEPAdministrator().destroyAllStatements(); // test insert-stream only, no remove stream String[] fields = "c0,c1".split(","); epService.getEPAdministrator().createEPL("create window W1#lastevent as SupportBean"); epService.getEPAdministrator().createEPL("insert into W1 select * from SupportBean"); epService.getEPAdministrator().createEPL("create window W2#lastevent as SupportBean"); epService.getEPAdministrator().createEPL("on W1 as a merge W2 as b when not matched then insert into OutStream " + "select a.theString as c0, istream() as c1"); epService.getEPAdministrator().createEPL("select * from OutStream").addListener(mergeListener); epService.getEPRuntime().sendEvent(new SupportBean("E1", 1)); EPAssertionUtil.assertProps(mergeListener.assertOneGetNewAndReset(), fields, new Object[] {"E1", true}); epService.getEPRuntime().sendEvent(new SupportBean("E2", 2)); EPAssertionUtil.assertProps(mergeListener.assertOneGetNewAndReset(), fields, new Object[] {"E2", true}); } public void testDocExample() throws Exception { for (EventRepresentationChoice rep : EventRepresentationChoice.values()) { runAssertionDocExample(rep); } } public void runAssertionDocExample(EventRepresentationChoice eventRepresentationEnum) throws Exception { String baseModule = eventRepresentationEnum.getAnnotationText() + " create schema OrderEvent as (orderId string, productId string, price double, quantity int, deletedFlag boolean)"; epService.getEPAdministrator().getDeploymentAdmin().parseDeploy(baseModule, null, null, null); String appModuleOne = eventRepresentationEnum.getAnnotationText() + " create schema ProductTotalRec as (productId string, totalPrice double);" + "" + eventRepresentationEnum.getAnnotationText() + " @Name('nwProd') create window ProductWindow#unique(productId) as ProductTotalRec;" + "" + "on OrderEvent oe\n" + "merge ProductWindow pw\n" + "where pw.productId = oe.productId\n" + "when matched\n" + "then update set totalPrice = totalPrice + oe.price\n" + "when not matched\n" + "then insert select productId, price as totalPrice;"; epService.getEPAdministrator().getDeploymentAdmin().parseDeploy(appModuleOne, null, null, null); String appModuleTwo = eventRepresentationEnum.getAnnotationText() + " @Name('nwOrd') create window OrderWindow#keepall as OrderEvent;" + "" + "on OrderEvent oe\n" + " merge OrderWindow pw\n" + " where pw.orderId = oe.orderId\n" + " when not matched \n" + " then insert select *\n" + " when matched and oe.deletedFlag=true\n" + " then delete\n" + " when matched\n" + " then update set pw.quantity = oe.quantity, pw.price = oe.price"; epService.getEPAdministrator().getDeploymentAdmin().parseDeploy(appModuleTwo, null, null, null); sendOrderEvent(eventRepresentationEnum, "O1", "P1", 10, 100, false); sendOrderEvent(eventRepresentationEnum, "O1", "P1", 11, 200, false); sendOrderEvent(eventRepresentationEnum, "O2", "P2", 3, 300, false); EPAssertionUtil.assertPropsPerRowAnyOrder(epService.getEPAdministrator().getStatement("nwProd").iterator(), "productId,totalPrice".split(","), new Object[][]{{"P1", 21d}, {"P2", 3d}}); EPAssertionUtil.assertPropsPerRowAnyOrder(epService.getEPAdministrator().getStatement("nwOrd").iterator(), "orderId,quantity".split(","), new Object[][]{{"O1", 200}, {"O2", 300}}); String module = "create schema StreetCarCountSchema (streetid string, carcount int);" + " create schema StreetChangeEvent (streetid string, action string);" + " create window StreetCarCountWindow#unique(streetid) as StreetCarCountSchema;" + " on StreetChangeEvent ce merge StreetCarCountWindow w where ce.streetid = w.streetid\n" + " when not matched and ce.action = 'ENTER' then insert select streetid, 1 as carcount\n" + " when matched and ce.action = 'ENTER' then update set StreetCarCountWindow.carcount = carcount + 1\n" + " when matched and ce.action = 'LEAVE' then update set StreetCarCountWindow.carcount = carcount - 1;" + " select * from StreetCarCountWindow;"; epService.getEPAdministrator().getDeploymentAdmin().parseDeploy(module, null, null, null); epService.getEPAdministrator().destroyAllStatements(); for (String name : "OrderEvent,OrderWindow,StreetCarCountSchema,StreetCarCountWindow,StreetChangeEvent,ProductWindow,ProductTotalRec".split(",")) { epService.getEPAdministrator().getConfiguration().removeEventType(name, true); } } private void sendOrderEvent(EventRepresentationChoice eventRepresentationEnum, String orderId, String productId, double price, int quantity, boolean deletedFlag) { if (eventRepresentationEnum.isObjectArrayEvent()) { epService.getEPRuntime().sendEvent(new Object[] {orderId, productId, price, quantity, deletedFlag}, "OrderEvent"); } else if (eventRepresentationEnum.isMapEvent()) { Map<String, Object> theEvent = new LinkedHashMap<String, Object>(); theEvent.put("orderId", orderId); theEvent.put("productId", productId); theEvent.put("price", price); theEvent.put("quantity", quantity); theEvent.put("deletedFlag", deletedFlag); epService.getEPRuntime().sendEvent(theEvent, "OrderEvent"); } else if (eventRepresentationEnum.isAvroEvent()) { GenericData.Record theEvent = new GenericData.Record(SupportAvroUtil.getAvroSchema(epService, "OrderEvent")); theEvent.put("orderId", orderId); theEvent.put("productId", productId); theEvent.put("price", price); theEvent.put("quantity", quantity); theEvent.put("deletedFlag", deletedFlag); epService.getEPRuntime().sendEventAvro(theEvent, "OrderEvent"); } else { fail(); } } public void testTypeReference() { ConfigurationOperations configOps = epService.getEPAdministrator().getConfiguration(); epService.getEPAdministrator().createEPL("@Name('ces') create schema EventSchema(in1 string, in2 int)"); epService.getEPAdministrator().createEPL("@Name('cnws') create schema WindowSchema(in1 string, in2 int)"); EPAssertionUtil.assertEqualsAnyOrder(new String[]{"ces"}, configOps.getEventTypeNameUsedBy("EventSchema").toArray()); EPAssertionUtil.assertEqualsAnyOrder(new String[]{"cnws"}, configOps.getEventTypeNameUsedBy("WindowSchema").toArray()); epService.getEPAdministrator().createEPL("@Name('cnw') create window MyWindow#keepall as WindowSchema"); EPAssertionUtil.assertEqualsAnyOrder("cnws,cnw".split(","), configOps.getEventTypeNameUsedBy("WindowSchema").toArray()); EPAssertionUtil.assertEqualsAnyOrder(new String[]{"cnw"}, configOps.getEventTypeNameUsedBy("MyWindow").toArray()); epService.getEPAdministrator().createEPL("@Name('om') on EventSchema merge into MyWindow " + "when not matched then insert select in1, in2"); EPAssertionUtil.assertEqualsAnyOrder("ces,om".split(","), configOps.getEventTypeNameUsedBy("EventSchema").toArray()); EPAssertionUtil.assertEqualsAnyOrder("cnws,cnw".split(","), configOps.getEventTypeNameUsedBy("WindowSchema").toArray()); } public void testPropertyEval() { epService.getEPAdministrator().getConfiguration().addEventType("OrderBean", OrderBean.class); String[] fields = "c1,c2".split(","); epService.getEPAdministrator().createEPL("create window MyWindow#keepall as (c1 string, c2 string)"); String epl = "on OrderBean[books] " + "merge MyWindow mw " + "when not matched then " + "insert select bookId as c1, title as c2 "; EPStatement stmt = epService.getEPAdministrator().createEPL(epl); stmt.addListener(mergeListener); epService.getEPRuntime().sendEvent(OrderBeanFactory.makeEventOne()); EPAssertionUtil.assertPropsPerRow(mergeListener.getLastNewData(), fields, new Object[][]{{"10020", "Enders Game"}, {"10021", "Foundation 1"}, {"10022", "Stranger in a Strange Land"}}); } public void testPropertyInsertBean() { EPStatement stmtWindow = epService.getEPAdministrator().createEPL("create window MergeWindow#unique(theString) as SupportBean"); String epl = "on SupportBean as up merge MergeWindow as mv where mv.theString=up.theString when not matched then insert select intPrimitive"; EPStatement stmtMerge = epService.getEPAdministrator().createEPL(epl); epService.getEPRuntime().sendEvent(new SupportBean("E1", 10)); EventBean theEvent = stmtWindow.iterator().next(); EPAssertionUtil.assertProps(theEvent, "theString,intPrimitive".split(","), new Object[]{null, 10}); stmtMerge.destroy(); epl = "on SupportBean as up merge MergeWindow as mv where mv.theString=up.theString when not matched then insert select theString, intPrimitive"; epService.getEPAdministrator().createEPL(epl); epService.getEPRuntime().sendEvent(new SupportBean("E2", 20)); EPAssertionUtil.assertPropsPerRow(stmtWindow.iterator(), "theString,intPrimitive".split(","), new Object[][]{{null, 10}, {"E2", 20}}); } public void testSubselect() { for (EventRepresentationChoice rep : EventRepresentationChoice.values()) { runAssertionSubselect(rep); } } private void runAssertionSubselect(EventRepresentationChoice eventRepresentationEnum) { String[] fields = "col1,col2".split(","); epService.getEPAdministrator().createEPL(eventRepresentationEnum.getAnnotationText() + " create schema MyEvent as (in1 string, in2 int)"); epService.getEPAdministrator().createEPL(eventRepresentationEnum.getAnnotationText() + " create schema MySchema as (col1 string, col2 int)"); EPStatement namedWindowStmt = epService.getEPAdministrator().createEPL(eventRepresentationEnum.getAnnotationText() + " create window MyWindow#lastevent as MySchema"); epService.getEPAdministrator().createEPL("on SupportBean_A delete from MyWindow"); String epl = "on MyEvent me " + "merge MyWindow mw " + "when not matched and (select intPrimitive>0 from SupportBean(theString like 'A%')#lastevent) then " + "insert(col1, col2) select (select theString from SupportBean(theString like 'A%')#lastevent), (select intPrimitive from SupportBean(theString like 'A%')#lastevent) " + "when matched and (select intPrimitive>0 from SupportBean(theString like 'B%')#lastevent) then " + "update set col1=(select theString from SupportBean(theString like 'B%')#lastevent), col2=(select intPrimitive from SupportBean(theString like 'B%')#lastevent) " + "when matched and (select intPrimitive>0 from SupportBean(theString like 'C%')#lastevent) then " + "delete"; epService.getEPAdministrator().createEPL(epl); // no action tests sendMyEvent(eventRepresentationEnum, "X1", 1); epService.getEPRuntime().sendEvent(new SupportBean("A1", 0)); // ignored sendMyEvent(eventRepresentationEnum, "X2", 2); epService.getEPRuntime().sendEvent(new SupportBean("A2", 20)); EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, null); sendMyEvent(eventRepresentationEnum, "X3", 3); EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, new Object[][]{{"A2", 20}}); epService.getEPRuntime().sendEvent(new SupportBean_A("Y1")); epService.getEPRuntime().sendEvent(new SupportBean("A3", 30)); EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, null); sendMyEvent(eventRepresentationEnum, "X4", 4); epService.getEPRuntime().sendEvent(new SupportBean("A4", 40)); sendMyEvent(eventRepresentationEnum, "X5", 5); // ignored as matched (no where clause, no B event) EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, new Object[][]{{"A3", 30}}); epService.getEPRuntime().sendEvent(new SupportBean("B1", 50)); sendMyEvent(eventRepresentationEnum, "X6", 6); EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, new Object[][]{{"B1", 50}}); epService.getEPRuntime().sendEvent(new SupportBean("B2", 60)); sendMyEvent(eventRepresentationEnum, "X7", 7); EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, new Object[][]{{"B2", 60}}); epService.getEPRuntime().sendEvent(new SupportBean("B2", 0)); sendMyEvent(eventRepresentationEnum, "X8", 8); EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, new Object[][]{{"B2", 60}}); epService.getEPRuntime().sendEvent(new SupportBean("C1", 1)); sendMyEvent(eventRepresentationEnum, "X9", 9); EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, null); epService.getEPRuntime().sendEvent(new SupportBean("C1", 0)); sendMyEvent(eventRepresentationEnum, "X10", 10); EPAssertionUtil.assertPropsPerRowAnyOrder(namedWindowStmt.iterator(), fields, new Object[][]{{"A4", 40}}); epService.getEPAdministrator().destroyAllStatements(); for (String name : "MyEvent,MySchema,MyWindow".split(",")) { epService.getEPAdministrator().getConfiguration().removeEventType(name, true); } } private SupportBean makeSupportBean(String theString, int intPrimitive, double doublePrimitive) { SupportBean sb = new SupportBean(theString, intPrimitive); sb.setDoublePrimitive(doublePrimitive); return sb; } private void sendMyEvent(EventRepresentationChoice eventRepresentationEnum, String in1, int in2) { if (eventRepresentationEnum.isObjectArrayEvent()) { epService.getEPRuntime().sendEvent(new Object[] {in1, in2}, "MyEvent"); } else if (eventRepresentationEnum.isMapEvent()) { Map<String, Object> theEvent = new LinkedHashMap<String, Object>(); theEvent.put("in1", in1); theEvent.put("in2", in2); epService.getEPRuntime().sendEvent(theEvent, "MyEvent"); } else if (eventRepresentationEnum.isAvroEvent()) { GenericData.Record theEvent = new GenericData.Record(SupportAvroUtil.getAvroSchema(epService, "MyEvent")); theEvent.put("in1", in1); theEvent.put("in2", in2); epService.getEPRuntime().sendEventAvro(theEvent, "MyEvent"); } else { fail(); } } public static void increaseIntCopyDouble(SupportBean initialBean, SupportBean updatedBean) { updatedBean.setIntPrimitive(initialBean.getIntPrimitive() + 1); updatedBean.setDoubleBoxed(updatedBean.getDoublePrimitive()); } }