Description
Background
It would be a good feature to be able to create Items from arbitrary database data using native queries not tied to Openhab persisted data.
It will allow integration with other products, using the database as the interface, i.e. a way to integrate with Iotawatt is to make queries to InfluxDB and create items with the results of that queries to have information about your power usage/consumption.
Another use case is if you want to query derived data from Openhab persisted one using some type of background process, for example InfluxDB 2 offers flux tasks. Or in general if you want to create an item from some database data that doesn't follow Openhab structure.
More about the background in original forum discussion [1]
Need justification
To cover prior use cases described in the background section my implementation idea is to write a Native Query add-on (outside core) that allows you to define Items from an arbitrary query in the native query language that uses the persistence service ( SQL, Flux,...)
Need for a query interface
As the intend of the addon is to be generic an useful for several persistence services as debated on [1], it's not scalable to have all the persistence connectors in the addon.
And the best way would be to restrict its responsibilities to define items and update them making queries to existing persistence services.
Need for the query interface to be native
As the addon must be capable to make items from arbitrary queries the current FilterCriteria
doesn't cover what is needed because it's very limited and tied to Openhab persistence format.
One possibility will be to extend FilterCriteria
adding more functionality. But I think that it's not the way to go for this issue use cases because it will be very difficult to cover all the needed cases that users can have:
- Queries can be very complex and some will could not be possible to be done with a hypothetic improvement of FilterCriteria and then limiting user experience going that way.
- Several persistence services use very different query capabilities and formats. For example, SQL and Flux are very different. And can have specific capabilities that can be very useful, for example being able to do integrals in FluxDB to calculate power consumption from last hour from instant power readings
- It can be hard to implement the new interface in all persistence services and to define a query syntax and parser to allow the user to express the queries.
In contrast, adding a native persistence interface has the following benefits:
- User can do everything that it's possible in the persistence service it uses.
- Easy to implement for the persistence services that want to have such functionality.
- Easy for the user to define queries, as it doesn't need to learn a new query syntax to make its queries, and it can use a query syntax that he could already knows or is easier for him to learn, test and experiment with persistence service tooling and documentation
Architecture considerations
I think that improving FilterCriteria to cover more use cases can be useful for some use cases like addons that offer generic functionality about Openhab own persisted data without the user having to write any query.
But for external data, that for the definition of external, the query would need to be manually given by the user, I think that is too much work to offer an abstraction or genericity that it's possible that offers less and more complex functionality for the user.
I think that the native interface doesn't break persistence service if a rule is used:
That interface should only be used for queries completely created from the end-user through configurations files and never by dynamically generated queries from the core or other addons.
That way it doesn't compromise interoperability of addons with a generic persistence service, and allow end-users to create powerful queries in an easier way for them.
Also, I think that other generic persistence services offer that option. For example in Java, the most famous generic and standard API is possibly JPA that offers a nativeQuery interface in case you need it, and it doesn't considers that breaks the abstraction. That option's not used by libraries or generic features that build on top of JPA, but allow the end-user to make use of them for uses cases than cant solve with standard API.
Proposed Interface
The proposed interface would be something like
interface NativeQuery {
List<Object[]> query(Map<String,Object> params)
}
References
[1] Original forum discussion