eclipse-vertx/vertx-sql-client

Enable the capture of metadata for empty resultsets

Yaytay opened this issue · 8 comments

Yaytay commented

Describe the feature

Currently clients using PreparedStatements get no data back from a call to createStream if the query returns no rows.
I would like to be able to report the metadata for calls like this, even if no data is provided.

The method RowStreamImpl::handle(AsyncResult<RowSet> ar) gets called when there is no data and the RowSet that it receives seems to have the information.
I propose doing something like this:

      RowSet rowSet = ar.result();
      synchronized (this) {
        readInProgress = false;
        RowIterator<Row> it = rowSet.iterator();
        if (it.hasNext()) {
          result = it;
        }
      }
      metadataPromise.tryComplete(rowSet);
      checkPending();

With associated scaffolding to give callers access to the metadataPromise.

I'm happy with an alternative solution that achieves the aim.

Use cases

When using the data for reporting it is useful to be able to present the empty result set, rather than just nothing.

Contribution

Happy to provide a PR.

Yaytay commented

It doesn't work very nicely as a promise, so I'm currently testing with a Handler<RowSet>:

      Handler<RowSet<Row>> handler = null;
      RowSet<Row> rowset = ar.result();
      synchronized (this) {
        readInProgress = false;
        RowIterator<Row> it = rowset.iterator();
        if (!metadataHandlerCalled) {
          metadataHandlerCalled = true;
          handler = metadataHandler;
        }
        if (it.hasNext()) {
          result = it;
        }
      }
      if (handler != null) {
        handler.handle(rowset);
      }
vietj commented

can't you use the stream endHandler of the stream that will always be called ?

Yaytay commented

RowStream#endHandler(Handler endHandler)
Doesn't provide any way to access the metadata.
Unless we capture the metadata in the RowStream and provide a getMetadata method that could be accessed from the endHandler:

      RowSet<Row> rowset = ar.result();
      synchronized (this) {
        readInProgress = false;
        RowIterator<Row> it = rowset.iterator();
        this.columnDescriptors = rowset.columnDescriptors();
        if (it.hasNext()) {
          result = it;
        }
      }
      checkPending();

With a getLastColumnDescriptors on the RowStream.
I think that would work quite nicely.

vietj commented

what are the metadata you are referring to ?

vietj commented

ah the column descriptor :-)

vietj commented

I propose we add the metadata on the rowstream interface which returns the metadata of the current rowset until end is called ?

Yaytay commented

Works for me.
It'll need to be able to return it until the end handler has completed.

vietj commented

makes sense