Skip to content

Commit

Permalink
Check python SDK version when client connected with server. (#1247)
Browse files Browse the repository at this point in the history
### What problem does this PR solve?

1. Add a Python SDK version validation, when the client connected with
Infinity server.
2. Introduce an InfinityException into Python SDK, with ErrorCode and
ErrorMessage.
3. ErrorCode is same as the status code from Status structure of
Infinity server.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Refactoring
- [x] Python SDK impacted, Need to update PyPI

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
  • Loading branch information
JinHai-CN authored May 27, 2024
1 parent d0ae24e commit e7e7577
Show file tree
Hide file tree
Showing 41 changed files with 1,587 additions and 1,048 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ See [Build from Source](docs/getstarted/build_from_source.md).
`infinity-sdk` requires Python 3.10+.

```bash
pip3 install infinity-sdk==0.2.0.dev1
pip3 install infinity-sdk==0.2.0.dev2
```

### Import necessary modules
Expand Down
4 changes: 3 additions & 1 deletion benchmark/remote_infinity/remote_query_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ struct InfinityClient {
client = std::make_unique<InfinityServiceClient>(protocol);
transport->open();
CommonResponse response;
client->Connect(response);
ConnectRequest request;
request.__set_client_version(1); // 0.2.0-dev2
client->Connect(response, request);
session_id = response.session_id;
}
~InfinityClient() {
Expand Down
4 changes: 3 additions & 1 deletion client/cpp/infinity_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ Client Client::Connect(const std::string &ip_address, uint16_t port) {
std::unique_ptr<InfinityServiceClient> client = std::make_unique<InfinityServiceClient>(protocol);
transport->open();
CommonResponse response;
client->Connect(response);
ConnectRequest request;
request.__set_client_version(1); // 0.2.0-dev2
client->Connect(response, request);
return {socket, transport, protocol, std::move(client), response.session_id};
}

Expand Down
11 changes: 9 additions & 2 deletions python/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
# python-infinity

# build
# update python client

- Update "version" field of [project] chapter and client_version field of ConnectRequest message.
- build new python SDK
- upload to pypi.org
- install new python SDK

# build python SDK

```shell
rm -f dist/* && python setup.py sdist bdist_wheel
```

# install
# install python SDK
```shell
pip uninstall -y infinity-sdk && pip install dist/*.whl
```
Expand Down
4 changes: 2 additions & 2 deletions python/infinity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

__version__ = importlib.metadata.version("infinity_sdk")

from infinity.common import URI, NetworkAddress, LOCAL_HOST
from infinity.common import URI, NetworkAddress, LOCAL_HOST, InfinityException
from infinity.infinity import InfinityConnection
from infinity.remote_thrift.infinity import RemoteThriftInfinityConnection

Expand All @@ -26,4 +26,4 @@ def connect(
if isinstance(uri, NetworkAddress) and (uri.port == 9090 or uri.port == 23817 or uri.port == 9070):
return RemoteThriftInfinityConnection(uri)
else:
raise Exception(f"unknown uri: {uri}")
raise InfinityException(7016, f"Unknown uri: {uri}")
6 changes: 6 additions & 0 deletions python/infinity/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,9 @@ class ConflictType(object):
Ignore = 0
Error = 1
Replace = 2


class InfinityException(Exception):
def __init__(self, error_code=0, error_message=None):
self.error_code = error_code
self.error_message = error_message
11 changes: 10 additions & 1 deletion python/infinity/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ class ErrorCode(IntEnum):
INVALID_BYTE_SIZE = 1005,
INVALID_IP_ADDR = 1006,
INVALID_LOG_LEVEL = 1007,
INVALID_CONFIG = 1008

WRONG_PASSWD = 2001,
INSUFFICIENT_PRIVILEGE = 2002,
UNSUPPORTED_VERSION_INDEX = 2003,
CLIENT_VERSION_MISMATCH = 2004,

INVALID_USERNAME = 3001,
INVALID_PASSWD = 3002,
INVALID_DB_NAME = 3003,
INVALID_IDENTIFIER_NAME = 3003,
INVALID_TABLE_NAME = 3004,
INVALID_COLUMN_NAME = 3005,
INVALID_INDEX_NAME = 3006,
Expand Down Expand Up @@ -109,6 +112,7 @@ class ErrorCode(IntEnum):
NOT_SUPPORTED_ANALYZER = 3078,
INVALID_ANALYZER_NAME = 3079,
INVALID_ANALYZER_FILE = 3080,
INVALID_EXPLAIN_TYPE = 3081,

TXN_ROLLBACK = 4001,
TXN_CONFLICT = 4002,
Expand Down Expand Up @@ -136,6 +140,11 @@ class ErrorCode(IntEnum):
DIR_NOT_FOUND = 7009,
DATA_IO_ERROR = 7010,
UNEXPECTED_ERROR = 7011,
PARSER_ERROR = 7012,
MMAP_FILE_ERROR = 7013,
MUNMAP_FILE_ERROR = 7014,
INVALID_FILE_FLAG = 7015,
INVALID_SERVER_ADDRESS = 7016,

INVALID_ENTRY = 8001,
NOT_FOUND_ENTRY = 8002,
Expand Down
3 changes: 2 additions & 1 deletion python/infinity/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from enum import Enum

import infinity.remote_thrift.infinity_thrift_rpc.ttypes as ttypes
from infinity.common import InfinityException


class IndexType(Enum):
Expand All @@ -33,7 +34,7 @@ def to_ttype(self):
elif self == IndexType.FullText:
return ttypes.IndexType.FullText
else:
raise Exception("Unknown index type")
raise InfinityException(3060, "Unknown index type")


class InitParameter:
Expand Down
5 changes: 4 additions & 1 deletion python/infinity/remote_thrift/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ def reconnect(self):
# self.protocol = TCompactProtocol.TCompactProtocol(self.transport)
self.client = InfinityService.Client(self.protocol)
self.transport.open()
res = self.client.Connect()

# version: 0.2.0.dev2, client_version: 1
# version: 0.2.0.dev3, client_version: 2
res = self.client.Connect(ConnectRequest(client_version=1))
self.session_id = res.session_id

def create_database(self, db_name: str, conflict_type: CreateConflict = CreateConflict.Error):
Expand Down
27 changes: 14 additions & 13 deletions python/infinity/remote_thrift/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from infinity.remote_thrift.table import RemoteTable
from infinity.remote_thrift.utils import check_valid_name, name_validity_check, select_res_to_polars
from infinity.common import ConflictType
from infinity.common import InfinityException


def get_ordinary_info(column_info, column_defs, column_name, index):
Expand Down Expand Up @@ -53,7 +54,7 @@ def get_ordinary_info(column_info, column_defs, column_name, index):
elif datatype == "bool":
proto_column_type.logic_type = ttypes.LogicType.Boolean
else:
raise Exception(f"unknown datatype: {datatype}")
raise InfinityException(3051, f"Unknown datatype: {datatype}")

# process constraints
proto_column_def.data_type = proto_column_type
Expand All @@ -69,7 +70,7 @@ def get_ordinary_info(column_info, column_defs, column_name, index):
elif constraint == "unique":
proto_column_def.constraints.append(ttypes.Constraint.Unique)
else:
raise Exception(f"unknown constraint: {constraint}")
raise InfinityException(3055, f"Unknown constraint: {constraint}")

# process constant expression
default = None
Expand Down Expand Up @@ -100,7 +101,7 @@ def get_ordinary_info(column_info, column_defs, column_name, index):
constant_expression = ttypes.ConstantExpr(literal_type=ttypes.LiteralType.DoubleArray,
f64_array_value=default)
else:
raise Exception("Invalid constant expression")
raise InfinityException(3069, "Invalid constant expression")
proto_column_def.constant_expr = constant_expression
column_defs.append(proto_column_def)

Expand Down Expand Up @@ -132,7 +133,7 @@ def get_embedding_info(column_info, column_defs, column_name, index):
elif element_type == "int64":
embedding_type.element_type = ttypes.ElementType.ElementInt64
else:
raise Exception(f"unknown element type: {element_type}")
raise InfinityException(3057, f"Unknown element type: {element_type}")
embedding_type.dimension = int(length)
assert isinstance(embedding_type, ttypes.EmbeddingType)
assert embedding_type.element_type is not None
Expand Down Expand Up @@ -171,7 +172,7 @@ def get_embedding_info(column_info, column_defs, column_name, index):
constant_expression = ttypes.ConstantExpr(literal_type=ttypes.LiteralType.DoubleArray,
f64_array_value=default)
else:
raise Exception("Invalid constant expression")
raise InfinityException(3069, "Invalid constant expression")
proto_column_def.constant_expr = constant_expression

column_defs.append(proto_column_def)
Expand Down Expand Up @@ -218,7 +219,7 @@ def create_table(self, table_name: str, columns_definition,
elif conflict_type == ConflictType.Replace:
create_table_conflict = ttypes.CreateConflict.Replace
else:
raise Exception(f"ERROR:3066, Invalid conflict type")
raise InfinityException(3066, f"Invalid conflict type")

res = self._conn.create_table(db_name=self._db_name, table_name=table_name,
column_defs=column_defs,
Expand All @@ -227,7 +228,7 @@ def create_table(self, table_name: str, columns_definition,
if res.error_code == ErrorCode.OK:
return RemoteTable(self._conn, self._db_name, table_name)
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

@name_validity_check("table_name", "Table")
def drop_table(self, table_name, conflict_type: ConflictType = ConflictType.Error):
Expand All @@ -238,14 +239,14 @@ def drop_table(self, table_name, conflict_type: ConflictType = ConflictType.Erro
return self._conn.drop_table(db_name=self._db_name, table_name=table_name,
conflict_type=ttypes.DropConflict.Ignore)
else:
raise Exception(f"ERROR:3066, invalid conflict type")
raise InfinityException(3066, "nvalid conflict type")

def list_tables(self):
res = self._conn.list_tables(self._db_name)
if res.error_code == ErrorCode.OK:
return res
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

@name_validity_check("table_name", "Table")
def show_table(self, table_name):
Expand All @@ -254,7 +255,7 @@ def show_table(self, table_name):
if res.error_code == ErrorCode.OK:
return res
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

@name_validity_check("table_name", "Table")
def show_columns(self, table_name):
Expand All @@ -263,7 +264,7 @@ def show_columns(self, table_name):
if res.error_code == ErrorCode.OK:
return select_res_to_polars(res)
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

@name_validity_check("table_name", "Table")
def get_table(self, table_name):
Expand All @@ -272,11 +273,11 @@ def get_table(self, table_name):
if res.error_code == ErrorCode.OK:
return RemoteTable(self._conn, self._db_name, table_name)
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

def show_tables(self):
res = self._conn.show_tables(self._db_name)
if res.error_code == ErrorCode.OK:
return select_res_to_polars(res)
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)
18 changes: 9 additions & 9 deletions python/infinity/remote_thrift/infinity.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from infinity.remote_thrift.client import ThriftInfinityClient
from infinity.remote_thrift.db import RemoteDatabase
from infinity.remote_thrift.utils import name_validity_check, select_res_to_polars
from infinity.common import ConflictType
from infinity.common import ConflictType, InfinityException


class RemoteThriftInfinityConnection(InfinityConnection, ABC):
Expand All @@ -44,28 +44,28 @@ def create_database(self, db_name: str, conflict_type: ConflictType = ConflictTy
elif conflict_type == ConflictType.Replace:
create_database_conflict = ttypes.CreateConflict.Replace
else:
raise Exception(f"ERROR:3066, Invalid conflict type")
raise InfinityException(3066, "Invalid conflict type")

res = self._client.create_database(db_name=db_name, conflict_type=create_database_conflict)
if res.error_code == ErrorCode.OK:
return RemoteDatabase(self._client, db_name)
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

def list_databases(self):
res = self._client.list_databases()
if res.error_code == ErrorCode.OK:
return res
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

@name_validity_check("db_name", "DB")
def show_database(self, db_name: str):
res = self._client.show_database(db_name=db_name)
if res.error_code == ErrorCode.OK:
return res
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

@name_validity_check("db_name", "DB")
def drop_database(self, db_name: str, conflict_type: ConflictType = ConflictType.Error):
Expand All @@ -75,29 +75,29 @@ def drop_database(self, db_name: str, conflict_type: ConflictType = ConflictType
elif conflict_type == ConflictType.Ignore:
drop_database_conflict = ttypes.DropConflict.Ignore
else:
raise Exception(f"ERROR:3066, invalid conflict type")
raise InfinityException(3066, "Invalid conflict type")

res = self._client.drop_database(db_name=db_name, conflict_type = drop_database_conflict)
if res.error_code == ErrorCode.OK:
return res
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

@name_validity_check("db_name", "DB")
def get_database(self, db_name: str):
res = self._client.get_database(db_name)
if res.error_code == ErrorCode.OK:
return RemoteDatabase(self._client, db_name)
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

def disconnect(self):
res = self._client.disconnect()
if res.error_code == ErrorCode.OK:
self._is_connected = False
return res
else:
raise Exception(f"ERROR:{res.error_code}, {res.error_msg}")
raise InfinityException(res.error_code, res.error_msg)

@property
def client(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':
print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] [-novalidate] [-ca_certs certs] [-keyfile keyfile] [-certfile certfile] function [arg1 [arg2...]]')
print('')
print('Functions:')
print(' CommonResponse Connect()')
print(' CommonResponse Connect(ConnectRequest request)')
print(' CommonResponse Disconnect(CommonRequest request)')
print(' CommonResponse CreateDatabase(CreateDatabaseRequest request)')
print(' CommonResponse DropDatabase(DropDatabaseRequest request)')
Expand Down Expand Up @@ -133,10 +133,10 @@ client = InfinityService.Client(protocol)
transport.open()

if cmd == 'Connect':
if len(args) != 0:
print('Connect requires 0 args')
if len(args) != 1:
print('Connect requires 1 args')
sys.exit(1)
pp.pprint(client.Connect())
pp.pprint(client.Connect(eval(args[0]),))

elif cmd == 'Disconnect':
if len(args) != 1:
Expand Down
Loading

0 comments on commit e7e7577

Please sign in to comment.