You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by al...@apache.org on 2023/03/20 04:32:47 UTC
[kudu] branch master updated: [Python] Add support for immutable column
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 <gr...@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 <la...@apache.org>
Reviewed-by: Alexey Serbin <al...@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()