Esper EPL leftouter join forwarding to other stream - esper

I have implemented ESPER for my application need of CEP. While using EPL I encountered a specific scenario which is as follows:
I have combined two events with left outer join to make sure each event from first can trigger the statement and only those from second stream which contains specific property can come along. I have created a view to store unique data based on some fields. My EPLs are
#Name ('StmtCombinedEvent')
Insert into CombinedEvent
Select S as T1,
L as T2,
From pattern[every S= bussinessObject.Type1].std:unique(S.Id) as S
left outer join
bussinessObject.Type2.std:unique(name) as L
on S.name = L.name;
#Name ('StmtGroupingEvent')
Insert into Position
Select
G.T1 as T1
G.T2 as T2
From CombinedEvent.std:unique(T1.Id) as G;
I am using java.util.Map type for CombinedEvent dataType in configuration file
Now consider test scenario
Two events of type T1 having different Id but having same name has been entered into system
One event of type T2 is entered into system
Because of the view specification both event of type T1 resides into view and when event of type T2 enters into system, NewData parameter of type Event Bean contains both event of T1 (if I was using event listener in code), but as first EPL statement specifies it to insert into second statement it finds an error of mismatched type, as it was expecting event of type T2 for 'StmtGroupingEvent' but found Event Bean instead.
So I need to handle array type of data in EPL which would be cumbersome.
On the other hand if scenario is as follows:
Only one event of type T1 is entered into system.
One event of type T2 is entered into system.
This scenario doesn’t produce any error as Event Bean was successfully type casted to type T2.
So please suggest me any alternate way of doing this.
Thanks

What does "it finds an error of mismatched type" mean? If there was an exception logged please post it and post a small test class alongside to reproduce. Also make sure you are using the latest version of Esper, if there is a bug it has likely been fixed in a newer version.
Also, use "from bussinessObject.Type1.std:unique(S.Id)" instead of
pattern[every S= bussinessObject.Type1].std:unique(S.Id)", since the latter is a straight every it is the same.

Related

Esper query for A followed by B immediately without any other events in between (no matter which event)

I have to implement the rule, that if A occurs, B hast to occur next without any event in between. Usually I could do this by just using the patter:
A->(B and not ...)
But I have to implement it very dynamical. That means that I don't know all of the possible events in advance. Does anybody know how i could implement this?
I guess I need something like:
A->(B and not any other event)
Thank you for your help. :)
See this other ticket Esper statement to check, if A is followed by B without any other As in between
It explains the match-recognize.
Here are a few path you can go down in respect to many types of events.
Create-schema with inherits plus typeof-function
create schema Parent();
create schema A() inherits Parent;
create schema B() inherits Parent;
// now you can treat all events as Parent events
select * from pattern[p=Parent(typeof(p)='A') -> ...] // or match-recognize
Variant stream
create variant schema AnyEventStream as *; // this stream can hold any type of event
insert into AnyEventStream select * from A;
insert into AnyEventStream select * from B;
select * from pattern[p=AnyEventStream(typeof(p)='A') -> ...] // or match-recognize
Normalize with insert-into
insert into CombinedStream select 'a' as type from A;
insert into CombinedStream select 'b' as type from B;
// now match on CombinedStream
select * from pattern[p=CombinedStream(type='A') -> ...] // or match-recognize
Make each event a column
create schema CombinedStream(col java.lang.Object);
insert into CombinedStream select a as col from A as a;
insert into CombinedStream select b as col from B as b;
select * from pattern[p=CombinedStream(typeof(col)='...') -> ...] // or match-recognize
You can probably combine some of these approaches. You can also use Java interfaces and abstract classes in replacement of "inherits" since the type system recognizes superclasses/interfaces.
Thank you very for your reply. I tried your suggestions and making each event a column seams to work pretty well for me.
My only problem is, that i have to get access to the properties of each event to check some conditions.
For example:
select * from CombinedStream.win:length(1) where typeof(col)='MachineFailureEvent' and id=1;
Until the id-check everything works fine, but the compiler tells me, that the property id is not valid in this stream.. do you have in idea?
Tanke you :)

Count how many times esper receives different inherit events.

I'm new using Esper and I have been able to manage with it until now. There is something that I can't find solution and I have tried to find everywhere with no success.
I have three Classes extending one to other one.
Using Esper Online:
create schema A(symbol string, price double);
create schema B() inherits A;
create schema C() inherits B;
Now I want to count how many of each events in a time window of 2 seconds I have received, using the next EPL statement:
select COALESCE(a.symbol,b.symbol,c.symbol) as symbol, count(a) as total_a, count(b) as total_b, count(c) as total_c from pattern [every a=A or every b=B or every c=C]#time(2 seconds) group by COALESCE(a.symbol,b.symbol,c.symbol);
And I run the next events:
A={symbol='X', price=1}
B={symbol='X', price=1}
C={symbol='X', price=1}
C={symbol='X', price=1}
The problem is when I send a B event, it counts a B event and an A event due to inheritance , and obviously if I send a C event it counts a C a B and also an A event.
I have used the pattern-level annotation #SuppressOverlappingMatches it works with inheritances, but Time Windows doesn't work with it.
Try this.
select count(*, typeof(a)='A') as cnt_a, count(*, typeof(a)='B') as cnt_b,
count(*, typeof(a)='C') as cnt_c from A#time(2 sec) as a

Recognize the type of the parameters of a user defined sql to be used in a Delphi TQuery at runtime

I'm writing a delphi(7 ver) application and in some place I want to execute parameterized queries (for BDE and Paradox) which will be loaded at runtime into a TQuery by the user. These queries will be stored in text files (one text file for one query). The application then, will construct for any parameter of the query, one input control (Tedit) in order to be able to accept values by the user. Also there will be a button for the execution of query. My question is how can I recognize the datatype of the query's parameter? Is there a way to get this type without of cause to be included in some way in the text file containing the query?
Create a second query from the first, but modify its where clause to ensure no rows.
SELECT * FROM MYTABLE WHERE PKFIELD IS NULL
Name your parameters so that you can establish their datatypes from the fieldtypes of this second query.
I realise this only works for relatively simple cases, but it should get you some of the way.
the advantage of using a parameter is that you don't need to know its data type.
Use the string value from the tedit
"select * from mytable where myfield = :param1"
"parambyname('param1').asstring := edit1.text"
I've made this with MySQL database. you must define some parameters, Exemple:
SELECT * FROM MyTable WHERE MyField=[ANNEE];
in this case, i have an other table, called balise, that look like this
"ID" "BALISE" "CAPTION" "DEFAULT_VALUE" "CNDT" "COMPOSANT"
"1" "ANNEE" "Année" "2014" "Properties.MaxValue=2014||Properties.MinValue=2007" 1;
in runtime, this mean that:
Make in my Panel, a TLablel that have caption Année
Make in the same line an other component type 1 (That mean in my case TcxSpinEdit), this component have défault value 2014, have Two properties Max Value=2014 and Min Value=2007, (I use RTTI to modifie this value of parameters, in Delphi ver7, use TypeInfo).
An Other Button with function called Actualise, this function have Original query, must browse an array of TBalise that i have created, take the value (In my case, take TcxSpinEdit(MyObject).Value), and replace it in the copy of my query (AnsiReplaceStr(Requete, '[ANNEE]', MyValue)), so i have the final query to execute it.
I have module in complete projet, worked with this methode, and it workk fine.

How can I remove elements from a stream

I currently have an order object. We can assume it has three fields called orderId, state and price.
class Order
{
public int orderId;
public String state;
public int filled;
}
Through out the life time of the order the state and filled quantity will change. Each time there is a field change we push it to the esper runtime via:
Order o .....;
epService.EPRuntime.SendEvent(o);
Now each time the order is added via SendEvent its a different object than the previous order object( ie not a reference). This means the old order object should no longer be in stream for statements to see
I would like statements like the one below to only operate on the most recent version of the Order in the stream, ie conceptually there should only be one order object for each physical order in the stream.
"select filled from OrderStream.win:keepall() where orderId= 1234"
Is there a way to remove old Order objects?
Can I use a reference so I just update the old order object and then push it again?
Is there another way??
I'm currently using Nesper
You could create a named window that holds unique events (older duplicates are evicted)
something like :
"create window OrderWin.std:unique(orderId) as Order"
"insert into "OrderWin select * from Order"
"select * from OrderWin where ..."
Another answer is to change the window. Keeping all events probably isn't what you wanted. Try using a different window, for example...
Let's say you only wanted the last trade per symbol. You could do the following:
select * from tradeEvent.std:unique(symbol)
This keeps only the last event for each event matching a given symbol.

How do I use TADOQuery.Parameters with integer parameter types that have to be put in two or more places in a query?

I have a complex query that contains more than one place where the same primary key value must be substituted. It looks like this:
select Foo.Id,
Foo.BearBaitId,
Foo.LinkType,
Foo.BugId,
Foo.GooNum,
Foo.WorkOrderId,
(case when Goo.ZenID is null or Goo.ZenID=0 then
IsNull(dbo.EmptyToNull(Bar.FanName),dbo.EmptyToNull(Bar.BazName))+' '+Bar.Strength else
'#'+BarZen.Description end) as Description,
Foo.Init,
Foo.DateCreated,
Foo.DateChanged,
Bug.LastName,
Bug.FirstName,
Goo.BarID,
(case when Goo.ZenID is null or Goo.ZenID=0 then
IsNull(dbo.EmptyToNull(Bar.BazName),dbo.EmptyToNull(Bar.FanName))+' '+Bar.Strength else
'#'+BarZen.Description end) as BazName,
GooTracking.Status as GooTrackingStatus
from
Foo
inner join Bug on (Foo.BugId=Bug.Id)
inner join Goo on (Foo.GooNum=Goo.GooNum)
left join Bar on (Bar.Id=Goo.BarID)
left join BarZen on (Goo.ZenID=BarZen.ID)
inner join GooTracking on(Goo.GooNum=GooTracking.GooNum )
where (BearBaitId = :aBaitid)
UNION
select Foo.Id,
Foo.BearBaitId,
Foo.LinkType,
Foo.BugId,
Foo.GooNum,
Foo.WorkOrderId,
Foo.Description,
Foo.Init,
Foo.DateCreated,
Foo.DateChanged,
Bug.LastName,
Bug.FirstName,
0,
NULL,
0
from Foo
inner join Bug on (Foo.BugId=Bug.Id)
where (LinkType=0) and (BearBaitId= :aBaitid )
order by BearBaitId,LinkType desc, GooNum
When I try to use an integer parameter on this non-trivial query, it seems impossible to me. I get this error:
Error
Incorrect syntax near ':'.
The query works fine if I take out the :aBaitid and substitute a literal 1.
Is there something else I can do to this query above? When I test with simple tests like this:
select * from foo where id = :anid
These simple cases work fine. The component is TADOQuery, and it works fine until you add any :parameters to the SQL string.
Update: when I use the following code at runtime, the parameter substitutions are actually done (some glitch in the ADO components is worked around) and a different error surfaces:
adoFooContentQuery.Parameters.FindParam('aBaitId').Value := 1;
adoFooContentQuery.Active := true;
Now the error changes to:
Incorrect syntax near the keyword 'inner''.
Note again, that this error goes away if I simply stop using the parameter substitution feature.
Update2: The accepted answer suggests I have to find two different copies of the parameter with the same name, which bothered me so I reworked the query like this:
DECLARE #aVar int;
SET #aVar = :aBaitid;
SELECT ....(long query here)
Then I used #aVar throughout the script where needed, to avoid the repeated use of :aBaitId. (If the number of times the parameter value is used changes, I don't want to have to find all parameters matching a name, and replace them).
I suppose a helper-function like this would be fine too: SetAllParamsNamed(aQuery:TAdoQuery; aName:String;aValue:Variant)
FindParam only finds one parameter, while you have two with the same name. Delphi dataset adds each parameter as a separate one to its collection of parameters.
It should work if you loop through all parameters, check if the name matches, and set the value of each one that matches, although I normally choose to give each same parameter a follow-up number to distingish between them.

Resources