siddhi-io / siddhi

Stream Processing and Complex Event Processing Engine

Home Page:http://siddhi.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot find attribute type as 'null' does not exist

ida-greuelr opened this issue · comments

Description:
When trying to select a null constant as value or following Example1/2 from the official documentation of the coalesce() function the parser/execution results in an io.siddhi.query.api.exception.AttributeNotExistException: [...] Cannot find attribute type as 'null' does not exist in 'TriggerStream';

Affected Siddhi Version:
5.1.x

OS, DB, other environment details and versions:
Docker image siddhiio/siddhi-tooling:5.1.0

Steps to reproduce:
Follow the examples to run the siddhi-tooling docker image:

  • docker run -it -p 9390:9390 siddhiio/siddhi-tooling:5.1.0
  • Visit http://localhost:9390/editor in your browser
  • Click on New to create a new App
  • Enter on of the following code examples:

select null

@App:name("null-test")

@App:description("Description of the plan")

define trigger TriggerStream at every 2 sec;

from TriggerStream
    select null as value
        insert into outStream;

coalesce() documentation Example1

@App:name("null-test2")

@App:description("Description of the plan")

define trigger TriggerStream at every 2 sec;

from TriggerStream
    select coalesce('123', null, '789') as value
        insert into outStream;

coalesce() documentation Example2

@App:name("null-test3")

@App:description("Description of the plan")

define trigger TriggerStream at every 2 sec;

from TriggerStream
    select coalesce(null, 76, 567) as value
        insert into outStream;

Related Issues:

Hi @ida-greuelr ,

The examples you have pointed out have been written to depict a null event, for better readability. The samples you have mentioned above can be tried with the following Siddhi apps, by simulating events via the Event Simulator (Tick the Is Null checkbox to simulate a null).

select null

@App:name("select_null")
@App:description("Description of the plan")

define stream TriggerStream(value string);

@sink(type='log')
define stream outStream(value string);

from TriggerStream 
select value
insert into outStream;

Simulate null to the TriggerStream stream's value attribute.

coalesce() documentation Example1

@App:name("example1")
@App:description("Description of the plan")

define stream TriggerStream(val1 string, val2 string, val3 string);

@sink(type='log')
define stream outStream(value string);

from TriggerStream
select coalesce(val1, val2, val3) as value
insert into outStream;

Simulate an event with:

  • 123 to the TriggerStream stream's val1 attribute.
  • null to the TriggerStream stream's val2 attribute.
  • 789 to the TriggerStream stream's val3 attribute.

coalesce() documentation Example2

@App:name("example2")
@App:description("Description of the plan")

define stream TriggerStream(val1 int, val2 int, val3 int);

@sink(type='log')
define stream outStream(value int);

from TriggerStream
select coalesce(val1, val2, val3) as value
insert into outStream;

Simulate an event with:

  • null to the TriggerStream stream's val1 attribute.
  • 76 to the TriggerStream stream's val2 attribute.
  • 567 to the TriggerStream stream's val3 attribute.

Thanks four your reply, @senthuran16!
So is there any way, to select a "null constant" and insert it into a stream, the same way I would do it with a string constant select "foo" as value insert into outStream?
This was the origin of my request. I made some experimental apps and stumbled across the problem, that I was not able to define a constant value null.

Furhermore, null is a reserved keyword in the DSL used by the query compiler.

So, why can I write NULL as a keyword in the DSL, but the compiler fails while trying to find an relating attribute for NULL?

A formidable way of selecting a null constant would be:

define stream InputStream(dummy string);
define stream OutputStream(value string);

from InputStream
select convert(map:get(map:create(), "nonExistingKey"), "string") as value
insert into OutputStream;

This creates an empty map using the map:create() function of the siddhi-execution-map-extension, and gets value of a non-existing key in that map - using the map:get() function. Since get() with a non-existing key returns a null value in a Java Hashmap, this returns a null too.

null is a reserved keyword in the DSL, since we support is null checks. But in the examples you had initially written, when selecting from a particular stream, null is assumed as an attribute of that stream. Since that stream did not have an attribute called null, it resulted in the exception: Cannot find attribute type as 'null' does not exist in 'TriggerStream'

Thanks again @senthuran16 for your kind explanation,

while exploring the possibilities I stumbled upon a workaround like select cast(convert('','double'),'string') as value insert into outStream; to create a null value.
But to be honest, this looks very ugly and is everything but an elegant or maintainable solution. If I show this to an experienced coder or colleague he/she will not be able to understand why I'm not just writing null.

Is there a design decision which prevents siddhi from providing a null constant, which actually sometimes is a complete normal way to instantiate a variable, before using it further?

I'm trying to embed siddhi in a software workflow while aggregating database rows with possible null cells and statically created "vectors" of null/non-null values. But initializing those static vectors, when not being able to simply put a null value into, is really frustrating.

Thanks, I highly appreciate your effort.