Skip to content

Commit e72df4f

Browse files
rustyconoverclaude
andcommitted
Update ConstantTableFunction to take count parameter first
Changed signature from constant_table(value) to constant_table(count, value): - count: number of rows to generate (must be >= 1) - value: the constant integer value to repeat Added batching support (BATCH_SIZE=1000) for large counts. Example usage: SELECT * FROM constant_table(3, 42) → [{"value": 42}, {"value": 42}, {"value": 42}] Updated tests for new signature and added test for large counts. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 79e7eef commit e72df4f

2 files changed

Lines changed: 63 additions & 29 deletions

File tree

tests/table/generator/test_constant_table_function.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,19 @@ class TestConstantTableFunctionInProcess:
1616
"""In-process tests for the constant_table function."""
1717

1818
def test_returns_constant_value(self) -> None:
19-
"""Constant table should return a single row with the given value."""
19+
"""Constant table should return rows with the given value."""
2020
assert_table_function_output(
2121
ConstantTableFunction,
22-
args=(42,),
23-
expected=[batch(value=[42])],
22+
args=(3, 42), # count=3, value=42
23+
expected=[batch(value=[42, 42, 42])],
24+
)
25+
26+
def test_returns_single_row(self) -> None:
27+
"""Constant table with count=1 should return one row."""
28+
assert_table_function_output(
29+
ConstantTableFunction,
30+
args=(1, 100),
31+
expected=[batch(value=[100])],
2432
)
2533

2634
def test_metadata(self) -> None:
@@ -30,19 +38,19 @@ def test_metadata(self) -> None:
3038
assert meta.max_workers == 1
3139

3240
def test_cardinality(self) -> None:
33-
"""Cardinality should always be 1."""
41+
"""Cardinality should equal the count parameter."""
3442
invocation = make_invocation(
3543
function_name="constant_table",
36-
arguments=Arguments(positional=(pa.scalar(42),)),
44+
arguments=Arguments(positional=(pa.scalar(5), pa.scalar(42))),
3745
)
3846
func = ConstantTableFunction(
3947
invocation=invocation,
4048
logger=structlog.get_logger(),
4149
)
4250
cardinality = func.cardinality
4351
assert cardinality is not None
44-
assert cardinality.estimate == 1
45-
assert cardinality.max == 1
52+
assert cardinality.estimate == 5
53+
assert cardinality.max == 5
4654

4755

4856
class TestConstantTableFunctionBothModes:
@@ -52,10 +60,22 @@ class TestConstantTableFunctionBothModes:
5260
def test_returns_value(
5361
self, run_table_function_mode: RunnerWithMode, value: int
5462
) -> None:
55-
"""Constant table should return a single row with the given value."""
63+
"""Constant table should return rows with the given value."""
64+
runner, mode = run_table_function_mode
65+
count = 3
66+
outputs, logs = runner(ConstantTableFunction, (count, value))
67+
68+
table = pa.Table.from_batches(outputs)
69+
assert table.num_rows == count
70+
assert table.column("value").to_pylist() == [value] * count
71+
72+
def test_large_count(self, run_table_function_mode: RunnerWithMode) -> None:
73+
"""Large counts should work correctly with batching."""
5674
runner, mode = run_table_function_mode
57-
outputs, logs = runner(ConstantTableFunction, (value,))
75+
count = 2500 # Larger than default BATCH_SIZE of 1000
76+
value = 7
77+
outputs, logs = runner(ConstantTableFunction, (count, value))
5878

5979
table = pa.Table.from_batches(outputs)
60-
assert table.num_rows == 1
61-
assert table.column("value").to_pylist() == [value]
80+
assert table.num_rows == count
81+
assert all(v == value for v in table.column("value").to_pylist())

vgi/examples/table.py

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -234,43 +234,53 @@ def process(self) -> OutputGenerator:
234234

235235

236236
class ConstantTableFunction(TableFunctionGenerator):
237-
"""Returns a constant single-row table with a specified value.
237+
"""Returns a table with repeated constant values.
238238
239239
USE CASE
240240
--------
241-
Testing, providing configuration values, or creating a single-row
242-
lookup table.
241+
Testing, providing repeated configuration values, or creating a
242+
lookup table with multiple rows of the same value.
243243
244244
SCHEMA
245245
------
246246
Output: {"value": int64}
247247
248248
PARALLELIZATION
249249
---------------
250-
Single worker (returns exactly one row).
250+
Single worker only (max_workers=1).
251251
252252
Example:
253253
-------
254-
SELECT * FROM constant_table(42)
255-
Returns: [{"value": 42}]
254+
SELECT * FROM constant_table(3, 42)
255+
Returns: [{"value": 42}, {"value": 42}, {"value": 42}]
256+
257+
SELECT * FROM constant_table(1, 100)
258+
Returns: [{"value": 100}]
256259
257260
"""
258261

259262
class Meta:
260263
"""Metadata for ConstantTableFunction."""
261264

262265
name = "constant_table"
263-
description = "Returns a single-row table with a constant value"
266+
description = "Returns a table with repeated constant values"
264267
categories = ["generator", "utility"]
265268
max_workers = 1
266269
examples = [
267270
FunctionExample(
268-
sql="SELECT * FROM constant_table(42)",
269-
description="Return a table with one row containing 42",
270-
)
271+
sql="SELECT * FROM constant_table(3, 42)",
272+
description="Return a table with 3 rows containing 42",
273+
),
274+
FunctionExample(
275+
sql="SELECT * FROM constant_table(1, 100)",
276+
description="Return a table with one row containing 100",
277+
),
271278
]
272279

273-
value: Annotated[int, Arg(0, doc="The constant value to return")]
280+
count: Annotated[int, Arg(0, doc="Number of rows to generate", ge=1)]
281+
value: Annotated[int, Arg(1, doc="The constant value to repeat")]
282+
283+
BATCH_SIZE: int = 1000
274284

275285
@property
276286
def output_schema(self) -> pa.Schema:
@@ -279,16 +289,20 @@ def output_schema(self) -> pa.Schema:
279289

280290
@property
281291
def cardinality(self) -> TableCardinality:
282-
"""Return cardinality of exactly one row."""
283-
return TableCardinality(estimate=1, max=1)
292+
"""Return exact cardinality since we know the count."""
293+
return TableCardinality(estimate=self.count, max=self.count)
284294

285295
def process(self) -> OutputGenerator:
286-
"""Emit a single batch with one row."""
287-
yield Output(
288-
pa.RecordBatch.from_pydict(
289-
{"value": [self.value]}, schema=self.output_schema
296+
"""Emit batches with constant values."""
297+
remaining = self.count
298+
while remaining > 0:
299+
batch_size = min(remaining, self.BATCH_SIZE)
300+
yield Output(
301+
pa.RecordBatch.from_pydict(
302+
{"value": [self.value] * batch_size}, schema=self.output_schema
303+
)
290304
)
291-
)
305+
remaining -= batch_size
292306

293307

294308
class GeneratorExceptionFunction(TableFunctionGenerator):

0 commit comments

Comments
 (0)