Skip to content

Building & Combining Data

Two ways to grow a dataset: concat() builds a new Object and leaves the originals untouched, while insert() appends rows to the existing table in place. copy() materializes an independent duplicate.

Copy

copy() creates a new table with the same data — a different Object backed by a different table:

original = await create_object_from_value([1, 2, 3])
print(f"Original object: {original}")
print(f"Original data: {await original.data()}")  # → [1, 2, 3]
print(f"Original table: {original.table}\n")

# Copy the object
copied = await original.copy()
print(f"Copied object: {copied}")
print(f"Copied data: {await copied.data()}")  # → [1, 2, 3]
print(f"Copied table: {copied.table}")
print(f"Tables are different: {original.table != copied.table}")

Concatenate

concat() is non-mutating: the originals are unchanged and the result is a new Object:

obj_a = await create_object_from_value([1, 2, 3])
obj_b = await create_object_from_value([4, 5, 6])

print(f"Object A: {await obj_a.data()}")  # → [1, 2, 3]
print(f"Object B: {await obj_b.data()}\n")  # → [4, 5, 6]

# Concat creates a new object
result = await obj_a.concat(obj_b)
print(f"After concat: {await result.data()}")  # → [1, 2, 3, 4, 5, 6]
print(f"Original A unchanged: {await obj_a.data()}")  # → [1, 2, 3]
print(f"Original B unchanged: {await obj_b.data()}")  # → [4, 5, 6]
print(f"Result is new object: {result.table != obj_a.table}")

Insert

insert() mutates in place — same table, more rows. Use it to accumulate data without leaving ClickHouse:

obj_x = await create_object_from_value([100, 200, 300])
obj_y = await create_object_from_value([400, 500, 600])

print(f"Object X before: {await obj_x.data()}")  # → [100, 200, 300]
print(f"Object Y: {await obj_y.data()}")  # → [400, 500, 600]
print(f"Table X before: {obj_x.table}\n")

# Insert modifies obj_x in place
await obj_x.insert(obj_y)
print(f"Object X after insert: {await obj_x.data()}")  # → [100, 200, 300, 400, 500, 600]
print(f"Table X after (same): {obj_x.table}")
print(f"Object Y unchanged: {await obj_y.data()}")  # → [400, 500, 600]

Next

Orchestration → — turn these operations into a pipeline.

See Also