This is an automated email from the ASF dual-hosted git repository. alexey pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/kudu.git
The following commit(s) were added to refs/heads/master by this push: new 1e037b03e [Python] Add support for immutable column 1e037b03e is described below commit 1e037b03e2f6ec85bbe8e31ba2b96288aa21911e Author: Marton Greber <greber...@gmail.com> AuthorDate: Sun Mar 5 15:28:43 2023 +0000 [Python] Add support for immutable column This patch is a followup on: f20dcf57ad76e9b1bb57fe60b27ea3a8f02df233, it introduces the immutable column type in the Python client. There is a slight difference compared to the C++ API. In the C++ client one can set two type of KuduColumnSpec: immutable or mutable. In the Python client there is a single mutable ColumnSpec, which accepts a boolean value. This is not a new type of difference between the clients, for example the nullability works the same way, in terms of client implementations. Change-Id: I09bc3fe54ea7b40ccefa046c668e3622794b22e9 Reviewed-on: http://gerrit.cloudera.org:8080/19586 Tested-by: Kudu Jenkins Reviewed-by: Yingchun Lai <laiyingc...@apache.org> Reviewed-by: Alexey Serbin <ale...@apache.org> --- python/kudu/libkudu_client.pxd | 3 ++ python/kudu/schema.pyx | 22 +++++++++ python/kudu/tests/test_client.py | 96 ++++++++++++++++++++++++++++++++++++++++ python/kudu/tests/test_schema.py | 14 ++++++ 4 files changed, 135 insertions(+) diff --git a/python/kudu/libkudu_client.pxd b/python/kudu/libkudu_client.pxd index f7e1950db..671aca067 100644 --- a/python/kudu/libkudu_client.pxd +++ b/python/kudu/libkudu_client.pxd @@ -173,6 +173,7 @@ cdef extern from "kudu/client/schema.h" namespace "kudu::client" nogil: string& name() c_bool is_nullable() DataType type() + c_bool is_immutable() KuduColumnTypeAttributes type_attributes() string& comment() @@ -208,6 +209,8 @@ cdef extern from "kudu/client/schema.h" namespace "kudu::client" nogil: KuduColumnSpec* NonUniquePrimaryKey() KuduColumnSpec* NotNull() KuduColumnSpec* Nullable() + KuduColumnSpec* Immutable() + KuduColumnSpec* Mutable() KuduColumnSpec* Type(DataType type_) KuduColumnSpec* Precision(int8_t precision); diff --git a/python/kudu/schema.pyx b/python/kudu/schema.pyx index 739dff1f9..00394e2b4 100644 --- a/python/kudu/schema.pyx +++ b/python/kudu/schema.pyx @@ -246,6 +246,10 @@ cdef class ColumnSchema: def __get__(self): return self.schema.is_nullable() + property mutable: + def __get__(self): + return not self.schema.is_immutable() + property type_attributes: def __get__(self): cdef ColumnTypeAttributes result = ColumnTypeAttributes() @@ -478,6 +482,24 @@ cdef class ColumnSpec: self.spec.NotNull() return self + def mutable(self, bint is_mutable=True): + """ + Set mutable (True) or immutable (False) + + Parameters + ---------- + is_mutable : boolean, default True + + Returns + ------- + self + """ + if is_mutable: + self.spec.Mutable() + else: + self.spec.Immutable() + return self + def rename(self, new_name): """ Change the column name. diff --git a/python/kudu/tests/test_client.py b/python/kudu/tests/test_client.py index be46ef4bb..ce76a87d3 100755 --- a/python/kudu/tests/test_client.py +++ b/python/kudu/tests/test_client.py @@ -341,6 +341,102 @@ class TestClient(KuduTestBase, unittest.TestCase): scanner = table.scanner().open() assert len(scanner.read_all_tuples()) == 0 + def test_insert_and_mutate_immutable_column(self): + table_name = 'insert_and_mutate_immutable_column' + try: + builder = kudu.schema_builder() + (builder.add_column('key', kudu.int32) + .nullable(False) + .primary_key()) + builder.add_column('immutable_data', kudu.string).mutable(False) + builder.add_column('mutable_data', kudu.string).mutable(True) + schema = builder.build() + + self.client.create_table( + table_name, schema, + partitioning=Partitioning().add_hash_partitions(['key'], 2)) + + table = self.client.table(table_name) + session = self.client.new_session() + op = table.new_insert() + op['key'] = 1 + op['immutable_data'] = 'text' + op['mutable_data'] = 'text' + session.apply(op) + session.flush() + + # Update the mutable columns + op = table.new_update() + op['key'] = 1 + op['mutable_data'] = 'new_text' + session.apply(op) + session.flush() + + # Update the immutable column + op = table.new_update() + op['key'] = 1 + op['immutable_data'] = 'new_text' + session.apply(op) + try: + session.flush() + except KuduBadStatus: + message = 'Immutable: UPDATE not allowed for immutable column' + errors, overflow = session.get_pending_errors() + assert not overflow + assert len(errors) == 1 + assert message in repr(errors[0]) + + # Update ignore on both mutable and immutable columns. The error is ignored. + op = table.new_update_ignore() + op['key'] = 1 + op['immutable_data'] = 'new_text' + op['mutable_data'] = 'new_text' + session.apply(op) + session.flush() + + # Update ignore the immutable column + op = table.new_update_ignore() + op['key'] = 1 + op['immutable_data'] = 'new_text' + session.apply(op) + try: + session.flush() + except KuduBadStatus: + message = 'Invalid argument: No fields updated' + errors, overflow = session.get_pending_errors() + assert not overflow + assert len(errors) == 1 + assert message in repr(errors[0]) + + # TODO: test upsert ignore, once it is supported by the Python client. + + # Upsert the mutable columns + op = table.new_upsert() + op['key'] = 1 + op['mutable_data'] = 'new_text' + session.apply(op) + session.flush() + + # Upsert the immutable column + op = table.new_upsert() + op['key'] = 1 + op['immutable_data'] = 'new_text' + session.apply(op) + try: + session.flush() + except KuduBadStatus: + message = 'Immutable: UPDATE not allowed for immutable column' + errors, overflow = session.get_pending_errors() + assert not overflow + assert len(errors) == 1 + assert message in repr(errors[0]) + + finally: + try: + self.client.delete_table(table_name) + except: + pass + def test_insert_with_auto_incrementing_column(self): table_name = 'test_insert_with_auto_incrementing_column' diff --git a/python/kudu/tests/test_schema.py b/python/kudu/tests/test_schema.py index b3ba26b2c..069201f64 100644 --- a/python/kudu/tests/test_schema.py +++ b/python/kudu/tests/test_schema.py @@ -291,6 +291,20 @@ class TestSchema(unittest.TestCase): assert schema[3].nullable assert not schema[4].nullable + def test_mutable_immutable(self): + builder = kudu.schema_builder() + (builder.add_column('key', 'int64', nullable=False) + .primary_key()) + + builder.add_column('data1', 'double').mutable(True) + builder.add_column('data2', 'double').mutable(False) + + schema = builder.build() + + assert schema[0].mutable + assert schema[1].mutable + assert not schema[2].mutable + def test_column_comment(self): comment = "test_comment" builder = kudu.schema_builder()