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

Laurent Wouters lwouters at cenotelie.fr
Thu Jul 25 09:23:30 CEST 2019


# HG changeset patch
# User Laurent Wouters <lwouters at cenotelie.fr>
# Date 1563957074 -7200
#      Wed Jul 24 10:31:14 2019 +0200
# Node ID bd0a838704c646caa3ca41f559fe51ade19b0ea3
# Parent  549b4c20103120a7c72ecd9aeac7bbf0a78ab067
Enable answering RQL select queries with symbolic bindings

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. Because this breaks compatibility
with the 1.0 protocol, this change warrants a new version. The previous version
continues to work alongside the new one.

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.

diff -r 549b4c201031 -r bd0a838704c6 cubicweb_rqlcontroller/views.py
--- a/cubicweb_rqlcontroller/views.py	Thu Mar 14 06:24:35 2019 +0000
+++ b/cubicweb_rqlcontroller/views.py	Wed Jul 24 10:31:14 2019 +0200
@@ -128,13 +128,13 @@
         self._cw.ajax_request = True
         self._cw.set_content_type('application/json')
 
-        if self._cw.form['version'] != '1.0':
-            raise RemoteCallFailed('unknown rqlio version %r',
-                                   self._cw.form['version'])
+        version = self._cw.form['version']
+        if version not in ('1.0', '2.0'):
+            raise RemoteCallFailed('unknown rqlio version %r', version)
+
         args = self.json()
-
         try:
-            result = self.rqlio(*args)
+            result = self.rqlio(version, *args)
         except (RemoteCallFailed, DirectResponse):
             raise
         except Exception as exc:
@@ -143,7 +143,7 @@
             return b''
         return json_dumps(result).encode(self._cw.encoding)
 
-    def rqlio(self, *rql_args):
+    def rqlio(self, version, *rql_args):
         try:
             output = self._rqlio(rql_args)
         except Exception:
@@ -151,6 +151,8 @@
             raise
         else:
             self._cw.cnx.commit()
+        if version == '2.0':
+            return [{'rows': o.rows, 'variables': o.variables} for o in output]
         return [o.rows for o in output]
 
     def _rqlio(self, rql_args):



More information about the cubicweb-devel mailing list