QueryBuilder dependency on live cluster object breaks existing API

Description

Until now, it was possible to use the QueryBuilder in static code without having to connect to a live cluster.

The main use-case is static queries generation, for example for the Accessor interfaces in the mapper-module.

Since 2.2.0, to instantiate the QueryBuilder we need to pass in a Cluster object. Even a "non-initialized" cluster is not safe because the javadoc stated :

So in the end, users don't know exactly which methods will trigger cluster initialization and cannot use it safely.

Is it possible to find a technical work-around to avoid forcing developers to inject a cluster object in the QueryBuilder ?

I have an example that throws NPE because of strong dependency of the QueryBuilder upon CodecRegistry:

Stack-trace

The only way to make it work is to inject a real Cluster object (with contact points) so that my query string gets built:

Environment

None

Pull Requests

None

Activity

Show:
DOAN DuyHai
October 26, 2015, 10:16 AM

For simple statements the use case is less clear to me: in which situation do you need to build a simple statement if you're not going to execute it right away?

People are using the QueryBuilder to build simple statements statically and store them in map. At runtime, they will prepare those statements at startup and throw them away. Using the QueryBuilder instead of plain text is the only way to be typo-safe.

Question with the QueryBuilder constructor requiring ProtocolVersion & CodecRegistry. AFAIK, if in the query string people inject custom types requiring a codec,it will be validated by the QueryBuilder isn't it ? So it means that statically, people need to inject a non-empty CodecRegistry containing the correct codec to be used if they want their values to be validated, am I right ?

Olivier Michallat
October 30, 2015, 11:32 AM

The query builder needs codecs at query construction time: if you provide a value that can't be kept as a separate bound value, the query builder will use TypeCodec.format to append the text representation of the value to the query string.

This is the case when you explicitly require that all values be inlined (see RegularStatement#setForceNoValues), or for simple numeric values where the target CQL type is ambiguous:

That's why we need a reference to the codec registry at construction time, not only when we execute built statements.

If you choose to use QueryBuilder(ProtocolVersion protocolVersion, CodecRegistry codecRegistry), the registry you inject must handle any custom type in your built statements. You build that registry the same way as your "runtime" registry, by registering your custom codecs.

Olivier Michallat
November 13, 2015, 10:07 AM

, does the above answer your concerns?

DOAN DuyHai
November 13, 2015, 12:16 PM

Yes it is Olivier. For my needs, I can manage with runtime injection of the Cluster. For other people I don't know, guess they'll need to refactor their existing code

Olivier Michallat
November 13, 2015, 1:58 PM

Closing based on the discussion above and the available workarounds.

Not a Problem

Assignee

Unassigned

Reporter

DOAN DuyHai

Labels

None

PM Priority

A

Reproduced in

2.2.0-rc3

Affects versions

Fix versions

None

Pull Request

None

Doc Impact

None

Size

None

External issue ID

None

External issue ID

None

Components

Priority

Major
Configure