|
37 | 37 | RequestUpdate, |
38 | 38 | RequestUpsert, |
39 | 39 | RequestAuthenticate, |
40 | | - RequestExecute |
| 40 | + RequestExecute, |
| 41 | + RequestProtocolVersion, |
41 | 42 | ) |
42 | 43 | from tarantool.space import Space |
43 | 44 | from tarantool.const import ( |
|
55 | 56 | REQUEST_TYPE_ERROR, |
56 | 57 | IPROTO_GREETING_SIZE, |
57 | 58 | ITERATOR_EQ, |
58 | | - ITERATOR_ALL |
| 59 | + ITERATOR_ALL, |
| 60 | + CONNECTOR_IPROTO_VERSION, |
| 61 | + CONNECTOR_FEATURES, |
| 62 | + IPROTO_FEATURE_STREAMS, |
| 63 | + IPROTO_FEATURE_TRANSACTIONS, |
| 64 | + IPROTO_FEATURE_ERROR_EXTENSION, |
| 65 | + IPROTO_FEATURE_WATCHERS, |
| 66 | + IPROTO_FEATURE_GRACEFUL_SHUTDOWN, |
59 | 67 | ) |
60 | 68 | from tarantool.error import ( |
61 | 69 | Error, |
@@ -498,6 +506,15 @@ def __init__(self, host, port, |
498 | 506 | self.ssl_cert_file = ssl_cert_file |
499 | 507 | self.ssl_ca_file = ssl_ca_file |
500 | 508 | self.ssl_ciphers = ssl_ciphers |
| 509 | + self._protocol_version = None |
| 510 | + self._features = { |
| 511 | + IPROTO_FEATURE_STREAMS: False, |
| 512 | + IPROTO_FEATURE_TRANSACTIONS: False, |
| 513 | + IPROTO_FEATURE_ERROR_EXTENSION: False, |
| 514 | + IPROTO_FEATURE_WATCHERS: False, |
| 515 | + IPROTO_FEATURE_GRACEFUL_SHUTDOWN: False, |
| 516 | + } |
| 517 | + |
501 | 518 | if connect_now: |
502 | 519 | self.connect() |
503 | 520 |
|
@@ -686,6 +703,7 @@ def connect(self): |
686 | 703 | self.wrap_socket_ssl() |
687 | 704 | self.handshake() |
688 | 705 | self.load_schema() |
| 706 | + self._check_features() |
689 | 707 | except SslError as e: |
690 | 708 | raise e |
691 | 709 | except Exception as e: |
@@ -1602,3 +1620,44 @@ def execute(self, query, params=None): |
1602 | 1620 | request = RequestExecute(self, query, params) |
1603 | 1621 | response = self._send_request(request) |
1604 | 1622 | return response |
| 1623 | + |
| 1624 | + def _check_features(self): |
| 1625 | + """ |
| 1626 | + Execute an ID request: inform the server about the protocol |
| 1627 | + version and features connector support and get server-side |
| 1628 | + information about it. |
| 1629 | +
|
| 1630 | + After executing this request, the connector will choose a |
| 1631 | + protocol version and features supported both by connector and |
| 1632 | + server. |
| 1633 | +
|
| 1634 | + :raise: :exc:`~AssertionError`, |
| 1635 | + :exc:`~tarantool.error.DatabaseError`, |
| 1636 | + :exc:`~tarantool.error.SchemaError`, |
| 1637 | + :exc:`~tarantool.error.NetworkError`, |
| 1638 | + :exc:`~tarantool.error.SslError` |
| 1639 | + """ |
| 1640 | + |
| 1641 | + try: |
| 1642 | + request = RequestProtocolVersion(self, |
| 1643 | + CONNECTOR_IPROTO_VERSION, |
| 1644 | + CONNECTOR_FEATURES) |
| 1645 | + response = self._send_request(request) |
| 1646 | + server_protocol_version = response.protocol_version |
| 1647 | + server_features = response.features |
| 1648 | + except DatabaseError as exc: |
| 1649 | + ER_UNKNOWN_REQUEST_TYPE = 48 |
| 1650 | + if exc.code == ER_UNKNOWN_REQUEST_TYPE: |
| 1651 | + server_protocol_version = None |
| 1652 | + server_features = [] |
| 1653 | + else: |
| 1654 | + raise exc |
| 1655 | + |
| 1656 | + if server_protocol_version is not None: |
| 1657 | + self._protocol_version = min(server_protocol_version, |
| 1658 | + CONNECTOR_IPROTO_VERSION) |
| 1659 | + |
| 1660 | + # Intercept lists of features |
| 1661 | + features_list = [val for val in CONNECTOR_FEATURES if val in server_features] |
| 1662 | + for val in features_list: |
| 1663 | + self._features[val] = True |
0 commit comments