[PATCH rqlcontroller] Enable answering RQL select queries with symbolic bindings

Nicolas Chauvat nicolas.chauvat at logilab.fr
Wed Jul 24 19:32:44 CEST 2019


Hello Laurent,

On Wed, Jul 24, 2019 at 10:31:37AM +0200, Laurent Wouters wrote:
> This introduces a version 2.0 of the rqlio protocol that is able to answer
> select RQL queries with symbolic bindings (with the names of the selected
> variables) instead of the positional rows.

Nice.

> The end result is the ability to answer the query Any X WHERE X is CWEtype with
> {'bindings': [{'X': 101}, {'X': 102}, {'X': 103}, ...]}
> instead of
> [[101], [102], [103], ...]
>
> In protocol version 2.0, when there are no variable names to build symbolic
> bindings out of, the protocol falls back to answering:
> {'rows': [[101], [102], [103], ...]}
>
> This way it is possible for a client to distinguish between results given in as
> symbolic bindings or positional rows. In addition, the value of the 'rows'
> member of the response object is exactly the same as the total response in the
> previous protocol, which should help write fallback code in client libraries.

You chose to return a JSON object with either a 'bindings' attribute
or a 'rows' attribute.

What would you think of a the following design:

   {'rows': [[101, "foo"], [102, "bar"], [103, "baz"], ...],
    'variables': ["X","N"],
    }

in return to a query like "Any X,N WHERE X is SomeType, X name N" ?

It would be a bit more compact, it would accomodate both the "rows"
and "bindings" access mode and since we provide an API on top of the
JSON returned we will slide in there the mapping from variable name to
index number.

> +        if version != '1.0' and version != '2.0':
> +            raise RemoteCallFailed('unknown rqlio version %r', version)

I would suggest:

    if version not in ('1.0', '2.0'):
        ...
	

> +    @staticmethod
> +    def _rqlio2_build_output(o):
> +        result = {}
> +        if len(o.variables) == 0:
> +            result['rows'] = o.rows
> +        else:
> +            result['bindings'] = [RqlIOController._row_to_bindings(row, o.variables) for row in o.rows]
> +        return result
> +
> +    @staticmethod
> +    def _row_to_bindings(row, variables):
> +        bindings = {}
> +        for cell, variable in zip(row, variables):
> +            bindings[variable] = cell
> +        return bindings
> +

I would suggest:

    @staticmethod
    def _rqlio2_build_output(o):
        result = {}
        if len(o.variables) == 0:
            result['rows'] = o.rows
        else:
            result['bindings'] = [dict(zip(o.variables, row)) for row in o.rows]
        return result

but if we chose a different design for version 2.0, this won't help :)

-- 
Nicolas Chauvat

logilab.fr - services en informatique scientifique et gestion de connaissances  



More information about the cubicweb-devel mailing list