diff --git a/docs/pysdk_api_reference.md b/docs/pysdk_api_reference.md index 99d48348e4..4e9662bc47 100644 --- a/docs/pysdk_api_reference.md +++ b/docs/pysdk_api_reference.md @@ -451,7 +451,7 @@ This method searches for rows that satisfy the search condition and updates them Gets a query_builder by self. ```python -query_builder=table_obj.query_builder() +query_builder=table_obj.query_builder ``` ## Details diff --git a/python/infinity/remote_thrift/db.py b/python/infinity/remote_thrift/db.py index 63b9b4fc69..e935a2d675 100644 --- a/python/infinity/remote_thrift/db.py +++ b/python/infinity/remote_thrift/db.py @@ -135,7 +135,7 @@ def create_table(self, table_name: str, columns_definition: dict[str, str], opti 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 Exception(f"ERROR:{res.error_code}, {res.error_msg}") def drop_table(self, table_name, if_exists=True): check_valid_name(table_name, "Table") @@ -146,7 +146,7 @@ def list_tables(self): if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def describe_table(self, table_name): check_valid_name(table_name, "Table") @@ -155,7 +155,7 @@ def describe_table(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 Exception(f"ERROR:{res.error_code}, {res.error_msg}") def get_table(self, table_name): check_valid_name(table_name, "Table") @@ -164,11 +164,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 Exception(f"ERROR:{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 Exception(f"ERROR:{res.error_code}, {res.error_msg}") diff --git a/python/infinity/remote_thrift/infinity.py b/python/infinity/remote_thrift/infinity.py index 0c75f0b2d9..b651a61ecf 100644 --- a/python/infinity/remote_thrift/infinity.py +++ b/python/infinity/remote_thrift/infinity.py @@ -39,14 +39,14 @@ def create_database(self, db_name: str, options=None): if res.error_code == ErrorCode.OK: return RemoteDatabase(self._client, db_name) else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{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 Exception(f"ERROR:{res.error_code}, {res.error_msg}") def describe_database(self, db_name: str): check_valid_name(db_name, "DB") @@ -54,7 +54,7 @@ def describe_database(self, db_name: str): if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def drop_database(self, db_name: str, options=None): check_valid_name(db_name, "DB") @@ -62,7 +62,7 @@ def drop_database(self, db_name: str, options=None): if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def get_database(self, db_name: str): check_valid_name(db_name, "DB") @@ -70,7 +70,7 @@ def get_database(self, db_name: str): if res.error_code == ErrorCode.OK: return RemoteDatabase(self._client, db_name) else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def disconnect(self): res = self._client.disconnect() @@ -78,7 +78,7 @@ def disconnect(self): self._is_connected = False return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") @property def client(self): @@ -89,4 +89,4 @@ def show_variable(self, variable: ShowVariable): if res.error_code == ErrorCode.OK: return select_res_to_polars(res) else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") diff --git a/python/infinity/remote_thrift/table.py b/python/infinity/remote_thrift/table.py index 5ec93a0471..59b123c9a5 100644 --- a/python/infinity/remote_thrift/table.py +++ b/python/infinity/remote_thrift/table.py @@ -59,7 +59,7 @@ def create_index(self, index_name: str, index_infos: list[IndexInfo], options=No if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def drop_index(self, index_name: str): check_valid_name(index_name, "Index") @@ -68,7 +68,7 @@ def drop_index(self, index_name: str): if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def insert(self, data: Union[INSERT_DATA, list[INSERT_DATA]]): # [{"c1": 1, "c2": 1.1}, {"c1": 2, "c2": 2.2}] @@ -120,7 +120,7 @@ def insert(self, data: Union[INSERT_DATA, list[INSERT_DATA]]): if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def import_data(self, file_path: str, options=None): @@ -173,7 +173,7 @@ def import_data(self, file_path: str, options=None): if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def delete(self, cond: Optional[str] = None): match cond: @@ -186,7 +186,7 @@ def delete(self, cond: Optional[str] = None): if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def update(self, cond: Optional[str], data: Optional[list[dict[str, Union[str, int, float]]]]): # {"c1": 1, "c2": 1.1} @@ -228,7 +228,7 @@ def update(self, cond: Optional[str], data: Optional[list[dict[str, Union[str, i if res.error_code == ErrorCode.OK: return res else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def knn(self, vector_column_name: str, embedding_data: VEC, embedding_data_type: str, distance_type: str, topn: int): @@ -291,7 +291,7 @@ def _execute_query(self, query: Query) -> tuple[dict[str, list[Any]], dict[str, if res.error_code == ErrorCode.OK: return build_result(res) else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") def _explain_query(self, query: ExplainQuery) -> Any: res = self._conn.explain(db_name=self._db_name, @@ -306,4 +306,4 @@ def _explain_query(self, query: ExplainQuery) -> Any: if res.error_code == ErrorCode.OK: return select_res_to_polars(res) else: - raise Exception(f"ERROR:{res.error_code}, ", res.error_msg) + raise Exception(f"ERROR:{res.error_code}, {res.error_msg}") diff --git a/python/test/common/common_type.py b/python/test/common/common_type.py new file mode 100644 index 0000000000..c2c5618ca8 --- /dev/null +++ b/python/test/common/common_type.py @@ -0,0 +1,54 @@ +# Copyright(C) 2023 InfiniFlow, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +class CaseLabel: + """ + Testcase Levels + CI Regression: + L0: + part of CI Regression + triggered by GitHub commit + optional used for dev to verify his fix before submitting a PR(like smoke) + ~100 testcases and run in 3 mins + L1: + part of CI Regression + triggered by GitHub commit + must pass before merge + run in 15 mins + Benchmark: + L2: + E2E tests and bug-fix verification + Nightly run triggered by cron job + run in 60 mins + L3: + Stability/Performance/reliability, etc. special tests + Triggered by cron job or manually + run duration depends on test configuration + Loadbalance: + loadbalance testcases which need to be run in multi query nodes + ClusterOnly: + For functions only suitable to cluster mode + GPU: + For GPU supported cases + """ + L0 = "L0" + L1 = "L1" + L2 = "L2" + L3 = "L3" + RBAC = "RBAC" + Loadbalance = "Loadbalance" # loadbalance testcases which need to be run in multi query nodes + ClusterOnly = "ClusterOnly" # For functions only suitable to cluster mode + MultiQueryNodes = "MultiQueryNodes" # for 8 query nodes configs tests, such as resource group + GPU = "GPU" diff --git a/python/test/common_values.py b/python/test/common/common_values.py similarity index 100% rename from python/test/common_values.py rename to python/test/common/common_values.py diff --git a/python/test/test_basic.py b/python/test/test_basic.py index fe61844c2e..16e55b17fd 100644 --- a/python/test/test_basic.py +++ b/python/test/test_basic.py @@ -16,7 +16,7 @@ import pandas as pd from numpy import dtype -import common_values +from python.test.common import common_values import infinity import infinity.index as index diff --git a/python/test/test_connect.py b/python/test/test_connect.py index 4f4af86a9d..fde5453ee3 100644 --- a/python/test/test_connect.py +++ b/python/test/test_connect.py @@ -13,7 +13,7 @@ # limitations under the License. import pytest -import common_values +from python.test.common import common_values import infinity from infinity.common import NetworkAddress diff --git a/python/test/test_covert.py b/python/test/test_convert.py similarity index 64% rename from python/test/test_covert.py rename to python/test/test_convert.py index 2aa15e3cbf..152a8ee5d5 100644 --- a/python/test/test_covert.py +++ b/python/test/test_convert.py @@ -1,8 +1,8 @@ -import common_values +from python.test.common import common_values import infinity -class TestCovert: +class TestConvert: def test_to_pl(self): infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) db_obj = infinity_obj.get_database("default") @@ -36,3 +36,20 @@ def test_to_pa(self): print(res) res = table_obj.output(["c1", "c2", "c1"]).to_arrow() print(res) + + def test_to_df(self): + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_to_pa", True) + db_obj.create_table("test_to_pa", { + "c1": "int", "c2": "float"}, None) + + table_obj = db_obj.get_table("test_to_pa") + table_obj.insert([{"c1": 1, "c2": 2.0}]) + print() + res = table_obj.output(["c1", "c2"]).to_df() + print(res) + res = table_obj.output(["c1", "c1"]).to_df() + print(res) + res = table_obj.output(["c1", "c2", "c1"]).to_df() + print(res) \ No newline at end of file diff --git a/python/test/test_create_table.py b/python/test/test_create_table.py deleted file mode 100644 index cede7221a5..0000000000 --- a/python/test/test_create_table.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright(C) 2023 InfiniFlow, Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest - -import common_values -import infinity - -from infinity.errors import ErrorCode - -class TestCreateTable: - - def test_create_varchar_table(self): - """ - target: test create table with varchar column - method: create table with varchar column - expected: ok - """ - infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_varchar_table", True) - table_obj = db_obj.create_table("test_create_varchar_table", { - "c1": "varchar, primary key", "c2": "float"}, None) - assert table_obj - - db_obj.drop_table("test_create_varchar_table") - - def test_create_embedding_table(self): - """ - target: test create table with embedding column - method: create table with embedding column - expected: ok - """ - infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_embedding_table", True) - table_obj = db_obj.create_table("test_create_embedding_table", { - "c1": "vector,128,float"}, None) - assert table_obj - - db_obj.drop_table("test_create_embedding_table") - - def test_create_table_with_invalid_column_name(self): - infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) - with pytest.raises(Exception): - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_invalid_column_name", True) - table_obj = db_obj.create_table("test_create_invalid_column_name", { - "": "vector,128,float"}, None) - assert table_obj - db_obj.drop_table("test_create_invalid_column_name") - - with pytest.raises(Exception): - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_invalid_column_name", True) - table_obj = db_obj.create_table("test_create_invalid_column_name", { - " ": "vector,128,float"}, None) - assert table_obj - db_obj.drop_table("test_create_invalid_column_name") - - with pytest.raises(Exception): - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_invalid_column_name", True) - table_obj = db_obj.create_table("test_create_invalid_column_name", { - "12": "vector,128,float"}, None) - assert table_obj - db_obj.drop_table("test_create_invalid_column_name") - - with pytest.raises(Exception): - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_invalid_column_name", True) - table_obj = db_obj.create_table("test_create_invalid_column_name", { - "[]": "vector,128,float"}, None) - assert table_obj - db_obj.drop_table("test_create_invalid_column_name") - - with pytest.raises(Exception): - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_invalid_column_name", True) - table_obj = db_obj.create_table("test_create_invalid_column_name", { - "()": "vector,128,float"}, None) - assert table_obj - db_obj.drop_table("test_create_invalid_column_name") - - with pytest.raises(Exception): - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_invalid_column_name", True) - table_obj = db_obj.create_table("test_create_invalid_column_name", { - "{}": "vector,128,float"}, None) - assert table_obj - db_obj.drop_table("test_create_invalid_column_name") - - with pytest.raises(Exception): - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_invalid_column_name", True) - table_obj = db_obj.create_table("test_create_invalid_column_name", { - "1": "vector,128,float"}, None) - assert table_obj - db_obj.drop_table("test_create_invalid_column_name") - - with pytest.raises(Exception): - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("test_create_invalid_column_name", True) - table_obj = db_obj.create_table("test_create_invalid_column_name", { - "1.1": "vector,128,float"}, None) - assert table_obj - db_obj.drop_table("test_create_invalid_column_name") - - @pytest.mark.parametrize("column_name", common_values.invalid_name_array) - def test_create_table_with_invalid_column_name_python(self, column_name): - """ - target: create with invalid column name - methods: create table with invalid column name - expect: all operations throw exception on python side - """ - infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) - db_obj = infinity_obj.get_database("default") - db_obj.drop_table("my_table") - - try: - tb = db_obj.create_table("my_table", {column_name: "int"}, None) - except Exception as e: - print(e) - - # disconnect - res = infinity_obj.disconnect() - assert res.error_code == ErrorCode.OK \ No newline at end of file diff --git a/python/test/test_database.py b/python/test/test_database.py index 830afe2639..20dd2e3923 100644 --- a/python/test/test_database.py +++ b/python/test/test_database.py @@ -14,7 +14,7 @@ import threading import infinity -import common_values +from python.test.common import common_values import pytest from infinity.errors import ErrorCode from utils import trace_expected_exceptions diff --git a/python/test/test_delete.py b/python/test/test_delete.py index 4ef471aaa3..43c9857bf1 100644 --- a/python/test/test_delete.py +++ b/python/test/test_delete.py @@ -16,7 +16,7 @@ import pandas as pd import pytest from numpy import dtype -import common_values +from python.test.common import common_values import infinity from infinity.errors import ErrorCode from utils import trace_expected_exceptions @@ -121,14 +121,11 @@ def test_delete_non_existent_table(self): infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) db_obj = infinity_obj.get_database("default") - tb = db_obj.drop_table("test_delete_non_existent_table", if_exists=True) - assert tb - - tb = db_obj.create_table("test_delete_non_existent_table", {"c1": "int"}, None) - assert tb + table_obj = db_obj.drop_table("test_delete_non_existent_table", if_exists=True) + assert table_obj - table_obj = db_obj.get_table("test_delete_empty_table") - table_obj.delete() + with pytest.raises(Exception, match="ERROR:3022*"): + db_obj.get_table("test_delete_non_existent_table").delete() # disconnect res = infinity_obj.disconnect() @@ -357,3 +354,48 @@ def test_various_expression_in_where_clause(self, column_types, column_types_exa # disconnect res = infinity_obj.disconnect() assert res.error_code == ErrorCode.OK + + def test_delete_one_block_without_expression(self): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_delete_one_segment_without_expression") + table_obj = db_obj.create_table("test_delete_one_segment_without_expression", {"c1": "int"}, None) + + # insert + values = [{"c1": 1} for _ in range(8192)] + table_obj.insert(values) + insert_res = table_obj.output(["*"]).to_df() + print(insert_res) + + # delete + table_obj.delete() + delete_res = table_obj.output(["*"]).to_df() + print(delete_res) + + # disconnect + res = infinity_obj.disconnect() + assert res.error_code == ErrorCode.OK + + def test_delete_one_segment_without_expression(self): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_delete_one_segment_without_expression") + table_obj = db_obj.create_table("test_delete_one_segment_without_expression", {"c1": "int"}, None) + + # insert + for i in range(1024): + values = [{"c1": i} for _ in range(10)] + table_obj.insert(values) + insert_res = table_obj.output(["*"]).to_df() + print(insert_res) + + # delete + table_obj.delete() + delete_res = table_obj.output(["*"]).to_df() + print(delete_res) + + # disconnect + res = infinity_obj.disconnect() + assert res.error_code == ErrorCode.OK \ No newline at end of file diff --git a/python/test/test_describe.py b/python/test/test_describe.py index 4d1a7d6eae..7161834ff3 100644 --- a/python/test/test_describe.py +++ b/python/test/test_describe.py @@ -13,7 +13,7 @@ # limitations under the License. import polars as pl -import common_values +from python.test.common import common_values import infinity diff --git a/python/test/test_explain.py b/python/test/test_explain.py index 9188669865..5ec0e559d7 100644 --- a/python/test/test_explain.py +++ b/python/test/test_explain.py @@ -15,7 +15,7 @@ import polars as pl import pytest -import common_values +from python.test.common import common_values import infinity from infinity.table import ExplainType diff --git a/python/test/test_import.py b/python/test/test_import.py index 6dd3b00de8..043e13d336 100644 --- a/python/test/test_import.py +++ b/python/test/test_import.py @@ -14,7 +14,7 @@ import os import pytest -import common_values +from python.test.common import common_values import infinity from infinity.errors import ErrorCode diff --git a/python/test/test_index.py b/python/test/test_index.py index d6ad007722..f64718e71f 100644 --- a/python/test/test_index.py +++ b/python/test/test_index.py @@ -15,11 +15,12 @@ import pytest -import common_values +from python.test.common import common_values import infinity import infinity.index as index from infinity.errors import ErrorCode + TEST_DATA_DIR = "/test/data/" diff --git a/python/test/test_infinity.py b/python/test/test_infinity.py new file mode 100644 index 0000000000..2215d8b21c --- /dev/null +++ b/python/test/test_infinity.py @@ -0,0 +1,13 @@ +# Copyright(C) 2023 InfiniFlow, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/python/test/test_insert.py b/python/test/test_insert.py index 6cbe563dfe..372fb0a5ab 100644 --- a/python/test/test_insert.py +++ b/python/test/test_insert.py @@ -15,7 +15,7 @@ import pytest from numpy import dtype -import common_values +from python.test.common import common_values import infinity import infinity.index as index from infinity.errors import ErrorCode diff --git a/python/test/test_knn.py b/python/test/test_knn.py index e7384bc324..30723056c7 100644 --- a/python/test/test_knn.py +++ b/python/test/test_knn.py @@ -14,7 +14,7 @@ import pytest -import common_values +from python.test.common import common_values import infinity diff --git a/python/test/test_query.py b/python/test/test_query.py index 08a033cc22..e8acf24c6b 100644 --- a/python/test/test_query.py +++ b/python/test/test_query.py @@ -1,4 +1,19 @@ -import common_values +# Copyright(C) 2023 InfiniFlow, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from python.test.common import common_values +import infinity import infinity.index as index from infinity.errors import ErrorCode from infinity.remote_thrift.client import ThriftInfinityClient @@ -43,3 +58,12 @@ def test_query(self): query_builder.fusion('rrf') res = query_builder.to_df() print(res) + + def test_query_builder(self): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_query_builder", if_exists=True) + table_obj = db_obj.create_table("test_query_builder", {"c1": "int"}, None) + query_builder = table_obj.query_builder + query_builder.output(["*"]).to_df() diff --git a/python/test/test_select.py b/python/test/test_select.py index 3fb2d96f3c..e7627dbca9 100644 --- a/python/test/test_select.py +++ b/python/test/test_select.py @@ -14,7 +14,7 @@ import os import pandas as pd -import common_values +from python.test.common import common_values import infinity from numpy import dtype from infinity.errors import ErrorCode diff --git a/python/test/test_show_tables.py b/python/test/test_show_tables.py index ed104d3477..eee5850e86 100644 --- a/python/test/test_show_tables.py +++ b/python/test/test_show_tables.py @@ -13,7 +13,7 @@ # limitations under the License. import polars as pl -import common_values +from python.test.common import common_values import infinity diff --git a/python/test/test_show_variable.py b/python/test/test_show_variable.py index dbed9f8d65..776573d568 100644 --- a/python/test/test_show_variable.py +++ b/python/test/test_show_variable.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import common_values +from python.test.common import common_values import infinity from infinity.infinity import ShowVariable diff --git a/python/test/test_table.py b/python/test/test_table.py index 6e53e4331a..eead66e8be 100755 --- a/python/test/test_table.py +++ b/python/test/test_table.py @@ -14,7 +14,7 @@ import concurrent.futures import pytest -import common_values +from python.test.common import common_values import infinity from infinity.errors import ErrorCode from utils import trace_expected_exceptions @@ -95,6 +95,122 @@ def test_table(self): res = infinity_obj.disconnect() assert res.error_code == ErrorCode.OK + def test_create_varchar_table(self): + """ + target: test create table with varchar column + method: create table with varchar column + expected: ok + """ + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_varchar_table", True) + table_obj = db_obj.create_table("test_create_varchar_table", { + "c1": "varchar, primary key", "c2": "float"}, None) + assert table_obj + + db_obj.drop_table("test_create_varchar_table") + + def test_create_embedding_table(self): + """ + target: test create table with embedding column + method: create table with embedding column + expected: ok + """ + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_embedding_table", True) + table_obj = db_obj.create_table("test_create_embedding_table", { + "c1": "vector,128,float"}, None) + assert table_obj + + db_obj.drop_table("test_create_embedding_table") + + def test_create_table_with_invalid_column_name(self): + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + with pytest.raises(Exception): + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_invalid_column_name", True) + table_obj = db_obj.create_table("test_create_invalid_column_name", { + "": "vector,128,float"}, None) + assert table_obj + db_obj.drop_table("test_create_invalid_column_name") + + with pytest.raises(Exception): + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_invalid_column_name", True) + table_obj = db_obj.create_table("test_create_invalid_column_name", { + " ": "vector,128,float"}, None) + assert table_obj + db_obj.drop_table("test_create_invalid_column_name") + + with pytest.raises(Exception): + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_invalid_column_name", True) + table_obj = db_obj.create_table("test_create_invalid_column_name", { + "12": "vector,128,float"}, None) + assert table_obj + db_obj.drop_table("test_create_invalid_column_name") + + with pytest.raises(Exception): + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_invalid_column_name", True) + table_obj = db_obj.create_table("test_create_invalid_column_name", { + "[]": "vector,128,float"}, None) + assert table_obj + db_obj.drop_table("test_create_invalid_column_name") + + with pytest.raises(Exception): + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_invalid_column_name", True) + table_obj = db_obj.create_table("test_create_invalid_column_name", { + "()": "vector,128,float"}, None) + assert table_obj + db_obj.drop_table("test_create_invalid_column_name") + + with pytest.raises(Exception): + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_invalid_column_name", True) + table_obj = db_obj.create_table("test_create_invalid_column_name", { + "{}": "vector,128,float"}, None) + assert table_obj + db_obj.drop_table("test_create_invalid_column_name") + + with pytest.raises(Exception): + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_invalid_column_name", True) + table_obj = db_obj.create_table("test_create_invalid_column_name", { + "1": "vector,128,float"}, None) + assert table_obj + db_obj.drop_table("test_create_invalid_column_name") + + with pytest.raises(Exception): + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_invalid_column_name", True) + table_obj = db_obj.create_table("test_create_invalid_column_name", { + "1.1": "vector,128,float"}, None) + assert table_obj + db_obj.drop_table("test_create_invalid_column_name") + + @pytest.mark.parametrize("column_name", common_values.invalid_name_array) + def test_create_table_with_invalid_column_name_python(self, column_name): + """ + target: create with invalid column name + methods: create table with invalid column name + expect: all operations throw exception on python side + """ + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("my_table") + + try: + tb = db_obj.create_table("my_table", {column_name: "int"}, None) + except Exception as e: + print(e) + + # disconnect + res = infinity_obj.disconnect() + assert res.error_code == ErrorCode.OK + def test_table_with_different_column_name(self): """ target: test create/drop/describe/get valid table name with different column names @@ -572,3 +688,96 @@ def test_create_empty_column_table(self): res = infinity_obj.disconnect() assert res.error_code == ErrorCode.OK + @pytest.mark.parametrize("types", [ + "int", "int8", "int16", "int32", "int64", "integer", + "float", "float32", "double", "float64", + "varchar", + "bool", + "vector, 3, float"]) + def test_create_valid_option(self, types): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_valid_option") + + db_obj.create_table("test_valid_option", {"c1": types}, None) + + # disconnect + res = infinity_obj.disconnect() + assert res.error_code == ErrorCode.OK + + @pytest.mark.parametrize("types", [ + "int", "int8", "int16", "int32", "int64", "integer", + "float", "float32", "double", "float64", + "varchar", + "bool", + "vector, 3, float"]) + @pytest.mark.parametrize("bool", [True, False]) + def test_drop_option(self, types, bool): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_drop_option") + + db_obj.create_table("test_drop_option", {"c1": types}, None) + db_obj.drop_table("test_drop_option", if_exists=bool) + + # disconnect + res = infinity_obj.disconnect() + assert res.error_code == ErrorCode.OK + + def test_create_same_name_table(self): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_create_same_name") + + # create + db_obj.create_table("test_create_same_name", {"c1": "int"}, None) + with pytest.raises(Exception, match="ERROR:3017*"): + db_obj.create_table("test_create_same_name", {"c1": "int"}, None) + + # disconnect + res = infinity_obj.disconnect() + assert res.error_code == ErrorCode.OK + + def test_drop_same_name_table(self): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_drop_same_name") + # drop + db_obj.drop_table("test_drop_same_name") + # disconnect + res = infinity_obj.disconnect() + assert res.error_code == ErrorCode.OK + + def test_same_column_name(self): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_same_column_name") + + db_obj.create_table("test_same_column_name", {"c1": "int", + "c1":"int"}, None) + + # disconnect + res = infinity_obj.disconnect() + assert res.error_code == ErrorCode.OK + + @pytest.mark.skip(reason="May cause server kill.") + @pytest.mark.parametrize("types", [ + "int", "int8", "int16", "int32", "int64", "integer", + "float", "float32", "double", "float64", + "varchar", + "bool", + "vector, 3, float"]) + def test_column_numbers(self, types): + # connect + infinity_obj = infinity.connect(common_values.TEST_REMOTE_HOST) + db_obj = infinity_obj.get_database("default") + db_obj.drop_table("test_column_numbers") + + values = {"c" + str(i): types for i in range(pow(2, 63) - 1)} + db_obj.create_table("test_column_numbers", values, None) + diff --git a/python/test/test_update.py b/python/test/test_update.py index b7216711b9..08f767e7d5 100644 --- a/python/test/test_update.py +++ b/python/test/test_update.py @@ -17,7 +17,7 @@ import pytest from numpy import dtype -import common_values +from python.test.common import common_values import infinity from infinity.errors import ErrorCode from utils import trace_expected_exceptions diff --git a/python/test/utils.py b/python/test/utils.py index a559a5e559..d618e63409 100644 --- a/python/test/utils.py +++ b/python/test/utils.py @@ -2,10 +2,6 @@ import traceback import numpy as np -import pytest -import infinity - -import common_values # catch the expected exception