Skip to content

Commit 2e6a877

Browse files
authored
Add support for protocol 3.0 (#534)
This is basically just adding support for specifying the input language in `Parse` and `Execute`. Expose that as the new `query_sql()` and `execute_sql()` client methods.
1 parent d0b3961 commit 2e6a877

File tree

6 files changed

+78
-3
lines changed

6 files changed

+78
-3
lines changed

edgedb/abstract.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class QueryWithArgs(typing.NamedTuple):
4545
query: str
4646
args: typing.Tuple
4747
kwargs: typing.Dict[str, typing.Any]
48+
input_language: protocol.InputLanguage = protocol.InputLanguage.EDGEQL
4849

4950

5051
class QueryCache(typing.NamedTuple):
@@ -75,6 +76,7 @@ def lower(
7576
kwargs=self.query.kwargs,
7677
reg=self.cache.codecs_registry,
7778
qc=self.cache.query_cache,
79+
input_language=self.query.input_language,
7880
output_format=self.query_options.output_format,
7981
expect_one=self.query_options.expect_one,
8082
required_one=self.query_options.required_one,
@@ -98,6 +100,7 @@ def lower(
98100
kwargs=self.query.kwargs,
99101
reg=self.cache.codecs_registry,
100102
qc=self.cache.query_cache,
103+
input_language=self.query.input_language,
101104
output_format=protocol.OutputFormat.NONE,
102105
allow_capabilities=allow_capabilities,
103106
state=self.state.as_dict() if self.state else None,
@@ -109,6 +112,7 @@ class DescribeContext:
109112
query: str
110113
state: typing.Optional[options.State]
111114
inject_type_names: bool
115+
input_language: protocol.InputLanguage
112116
output_format: protocol.OutputFormat
113117
expect_one: bool
114118

@@ -121,6 +125,7 @@ def lower(
121125
kwargs=None,
122126
reg=protocol.CodecsRegistry(),
123127
qc=protocol.LRUMapping(maxsize=1),
128+
input_language=self.input_language,
124129
output_format=self.output_format,
125130
expect_one=self.expect_one,
126131
inline_typenames=self.inject_type_names,
@@ -259,6 +264,21 @@ def query_required_single_json(self, query: str, *args, **kwargs) -> str:
259264
warning_handler=self._get_warning_handler(),
260265
))
261266

267+
def query_sql(self, query: str, *args, **kwargs) -> typing.Any:
268+
return self._query(QueryContext(
269+
query=QueryWithArgs(
270+
query,
271+
args,
272+
kwargs,
273+
input_language=protocol.InputLanguage.SQL,
274+
),
275+
cache=self._get_query_cache(),
276+
query_options=_query_opts,
277+
retry_options=self._get_retry_options(),
278+
state=self._get_state(),
279+
warning_handler=self._get_warning_handler(),
280+
))
281+
262282
@abc.abstractmethod
263283
def _execute(self, execute_context: ExecuteContext):
264284
...
@@ -271,6 +291,19 @@ def execute(self, commands: str, *args, **kwargs) -> None:
271291
warning_handler=self._get_warning_handler(),
272292
))
273293

294+
def execute_sql(self, commands: str, *args, **kwargs) -> None:
295+
self._execute(ExecuteContext(
296+
query=QueryWithArgs(
297+
commands,
298+
args,
299+
kwargs,
300+
input_language=protocol.InputLanguage.SQL,
301+
),
302+
cache=self._get_query_cache(),
303+
state=self._get_state(),
304+
warning_handler=self._get_warning_handler(),
305+
))
306+
274307

275308
class Executor(ReadOnlyExecutor):
276309
"""Subclasses can execute both read-only and modification queries"""
@@ -357,6 +390,21 @@ async def query_required_single_json(
357390
warning_handler=self._get_warning_handler(),
358391
))
359392

393+
async def query_sql(self, query: str, *args, **kwargs) -> typing.Any:
394+
return await self._query(QueryContext(
395+
query=QueryWithArgs(
396+
query,
397+
args,
398+
kwargs,
399+
input_language=protocol.InputLanguage.SQL,
400+
),
401+
cache=self._get_query_cache(),
402+
query_options=_query_opts,
403+
retry_options=self._get_retry_options(),
404+
state=self._get_state(),
405+
warning_handler=self._get_warning_handler(),
406+
))
407+
360408
@abc.abstractmethod
361409
async def _execute(self, execute_context: ExecuteContext) -> None:
362410
...
@@ -369,6 +417,19 @@ async def execute(self, commands: str, *args, **kwargs) -> None:
369417
warning_handler=self._get_warning_handler(),
370418
))
371419

420+
async def execute_sql(self, commands: str, *args, **kwargs) -> None:
421+
await self._execute(ExecuteContext(
422+
query=QueryWithArgs(
423+
commands,
424+
args,
425+
kwargs,
426+
input_language=protocol.InputLanguage.SQL,
427+
),
428+
cache=self._get_query_cache(),
429+
state=self._get_state(),
430+
warning_handler=self._get_warning_handler(),
431+
))
432+
372433

373434
class AsyncIOExecutor(AsyncIOReadOnlyExecutor):
374435
"""Subclasses can execute both read-only and modification queries"""

edgedb/asyncio_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from . import errors
3131
from . import transaction
3232
from .protocol import asyncio_proto
33-
from .protocol.protocol import OutputFormat
33+
from .protocol.protocol import InputLanguage, OutputFormat
3434

3535

3636
__all__ = (
@@ -392,13 +392,15 @@ async def _describe_query(
392392
query: str,
393393
*,
394394
inject_type_names: bool = False,
395+
input_language: InputLanguage = InputLanguage.EDGEQL,
395396
output_format: OutputFormat = OutputFormat.BINARY,
396397
expect_one: bool = False,
397398
) -> abstract.DescribeResult:
398399
return await self._describe(abstract.DescribeContext(
399400
query=query,
400401
state=self._get_state(),
401402
inject_type_names=inject_type_names,
403+
input_language=input_language,
402404
output_format=output_format,
403405
expect_one=expect_one,
404406
))

edgedb/blocking_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from . import errors
3333
from . import transaction
3434
from .protocol import blocking_proto
35-
from .protocol.protocol import OutputFormat
35+
from .protocol.protocol import InputLanguage, OutputFormat
3636

3737

3838
DEFAULT_PING_BEFORE_IDLE_TIMEOUT = datetime.timedelta(seconds=5)
@@ -434,13 +434,15 @@ def _describe_query(
434434
query: str,
435435
*,
436436
inject_type_names: bool = False,
437+
input_language: InputLanguage = InputLanguage.EDGEQL,
437438
output_format: OutputFormat = OutputFormat.BINARY,
438439
expect_one: bool = False,
439440
) -> abstract.DescribeResult:
440441
return self._iter_coroutine(self._describe(abstract.DescribeContext(
441442
query=query,
442443
state=self._get_state(),
443444
inject_type_names=inject_type_names,
445+
input_language=input_language,
444446
output_format=output_format,
445447
expect_one=expect_one,
446448
)))

edgedb/protocol/consts.pxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ DEF TRANS_STATUS_IDLE = b'I'
6161
DEF TRANS_STATUS_INTRANS = b'T'
6262
DEF TRANS_STATUS_ERROR = b'E'
6363

64-
DEF PROTO_VER_MAJOR = 2
64+
DEF PROTO_VER_MAJOR = 3
6565
DEF PROTO_VER_MINOR = 0
6666

6767
DEF MIN_PROTO_VER_MAJOR = 0

edgedb/protocol/protocol.pxd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ include "./codecs/codecs.pxd"
4040
ctypedef object (*decode_row_method)(BaseCodec, FRBuffer *buf)
4141

4242

43+
cpdef enum InputLanguage:
44+
EDGEQL = 0x45 # b'E'
45+
SQL = 0x53 # b'S'
46+
47+
4348
cpdef enum OutputFormat:
4449
BINARY = 98 # b'b'
4550
JSON = 106 # b'j'
@@ -75,6 +80,7 @@ cdef class ExecuteContext:
7580
object kwargs
7681
CodecsRegistry reg
7782
LRUMapping qc
83+
InputLanguage input_language
7884
OutputFormat output_format
7985
bint expect_one
8086
bint required_one

edgedb/protocol/protocol.pyx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ cdef class ExecuteContext:
100100
kwargs,
101101
reg: CodecsRegistry,
102102
qc: LRUMapping,
103+
input_language: InputLanguage,
103104
output_format: OutputFormat,
104105
expect_one: bool = False,
105106
required_one: bool = False,
@@ -114,6 +115,7 @@ cdef class ExecuteContext:
114115
self.kwargs = kwargs
115116
self.reg = reg
116117
self.qc = qc
118+
self.input_language = input_language
117119
self.output_format = output_format
118120
self.expect_one = bool(expect_one)
119121
self.required_one = bool(required_one)
@@ -271,6 +273,8 @@ cdef class SansIOProtocol:
271273
buf.write_int64(<int64_t>ctx.allow_capabilities)
272274
buf.write_int64(<int64_t><uint64_t>compilation_flags)
273275
buf.write_int64(<int64_t>ctx.implicit_limit)
276+
if self.protocol_version >= (3, 0):
277+
buf.write_byte(ctx.input_language)
274278
buf.write_byte(ctx.output_format)
275279
buf.write_byte(CARDINALITY_ONE if ctx.expect_one else CARDINALITY_MANY)
276280
buf.write_len_prefixed_utf8(ctx.query)

0 commit comments

Comments
 (0)