Skip to content

Commit feea29c

Browse files
Dev-iLclaude
andcommitted
Add docs for binary_copy_to_table and copy_records_to_table
Documents both COPY FROM STDIN methods on Connection and Transaction, including the new copy_records_to_table added in the previous commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 87bf681 commit feea29c

2 files changed

Lines changed: 151 additions & 0 deletions

File tree

docs/components/connection.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,81 @@ async def main() -> None:
245245
)
246246
```
247247

248+
### Binary Copy To Table
249+
250+
#### Parameters:
251+
252+
- `source`: bytes, bytearray, or `BytesIO` containing a PostgreSQL binary COPY stream.
253+
- `table_name`: name of the target table.
254+
- `columns`: sequence of column names to load into. When `None`, all table columns are used in their declared order.
255+
- `schema_name`: optional schema for `table_name`.
256+
257+
Stream a pre-encoded PostgreSQL binary COPY payload directly into a table.
258+
Executes `COPY table_name (<columns>) FROM STDIN (FORMAT binary)`.
259+
260+
::: warning
261+
You are responsible for encoding the bytes correctly. Passing an invalid binary COPY stream will result in a database error.
262+
:::
263+
264+
```python
265+
async def main() -> None:
266+
...
267+
connection = await db_pool.connection()
268+
with open("data.bin", "rb") as f:
269+
inserted = await connection.binary_copy_to_table(
270+
source=f.read(),
271+
table_name="users",
272+
columns=["id", "username"],
273+
)
274+
print(f"Inserted {inserted} rows")
275+
```
276+
277+
### Copy Records To Table
278+
279+
#### Parameters:
280+
281+
- `table_name`: name of the target table.
282+
- `records`: iterable of records, where each record is a sequence of column values.
283+
- `columns`: sequence of column names to load into. When `None`, all table columns are used in their declared order.
284+
- `schema_name`: optional schema for `table_name`.
285+
286+
Bulk-load plain Python records into a table via the binary `COPY FROM STDIN` protocol.
287+
Column types are introspected from the target table automatically, so each record may contain ordinary Python values — the same types accepted by `execute()`.
288+
Returns the number of inserted rows.
289+
290+
This is the ergonomic alternative to `binary_copy_to_table` when you have Python data rather than a pre-encoded binary stream.
291+
292+
```python
293+
from datetime import datetime, timezone
294+
295+
async def main() -> None:
296+
...
297+
connection = await db_pool.connection()
298+
records = [
299+
(1, "alpha", 1.5, datetime(2026, 1, 1, tzinfo=timezone.utc)),
300+
(2, "beta", 2.25, datetime(2026, 1, 2, tzinfo=timezone.utc)),
301+
(3, "gamma", None, datetime(2026, 1, 3, tzinfo=timezone.utc)),
302+
]
303+
inserted = await connection.copy_records_to_table(
304+
table_name="measurements",
305+
records=records,
306+
)
307+
print(f"Inserted {inserted} rows")
308+
```
309+
310+
You can load only a subset of columns by providing the `columns` argument:
311+
312+
```python
313+
async def main() -> None:
314+
...
315+
connection = await db_pool.connection()
316+
inserted = await connection.copy_records_to_table(
317+
table_name="measurements",
318+
records=[(1, "alpha"), (2, "beta")],
319+
columns=["id", "label"],
320+
)
321+
```
322+
248323
### Close
249324
Returns connection to the pool.
250325
It's crucial to commit all transactions and close all cursor which are made from the connection.

docs/components/transaction.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,79 @@ async def main() -> None:
426426
dict_result: List[Dict[Any, Any]] = fetched_result.result()
427427
... # do something with the result.
428428
```
429+
430+
### Binary Copy To Table
431+
432+
#### Parameters:
433+
434+
- `source`: bytes, bytearray, or `BytesIO` containing a PostgreSQL binary COPY stream.
435+
- `table_name`: name of the target table.
436+
- `columns`: sequence of column names to load into. When `None`, all table columns are used in their declared order.
437+
- `schema_name`: optional schema for `table_name`.
438+
439+
Stream a pre-encoded PostgreSQL binary COPY payload directly into a table within the transaction.
440+
Executes `COPY table_name (<columns>) FROM STDIN (FORMAT binary)`.
441+
442+
::: warning
443+
You are responsible for encoding the bytes correctly. Passing an invalid binary COPY stream will result in a database error.
444+
:::
445+
446+
```python
447+
async def main() -> None:
448+
...
449+
connection = await db_pool.connection()
450+
async with connection.transaction() as transaction:
451+
with open("data.bin", "rb") as f:
452+
inserted = await transaction.binary_copy_to_table(
453+
source=f.read(),
454+
table_name="users",
455+
columns=["id", "username"],
456+
)
457+
print(f"Inserted {inserted} rows")
458+
```
459+
460+
### Copy Records To Table
461+
462+
#### Parameters:
463+
464+
- `table_name`: name of the target table.
465+
- `records`: iterable of records, where each record is a sequence of column values.
466+
- `columns`: sequence of column names to load into. When `None`, all table columns are used in their declared order.
467+
- `schema_name`: optional schema for `table_name`.
468+
469+
Bulk-load plain Python records into a table via the binary `COPY FROM STDIN` protocol, within the transaction.
470+
Column types are introspected from the target table automatically, so each record may contain ordinary Python values — the same types accepted by `execute()`.
471+
Returns the number of inserted rows.
472+
473+
```python
474+
from datetime import datetime, timezone
475+
476+
async def main() -> None:
477+
...
478+
connection = await db_pool.connection()
479+
records = [
480+
(1, "alpha", 1.5, datetime(2026, 1, 1, tzinfo=timezone.utc)),
481+
(2, "beta", 2.25, datetime(2026, 1, 2, tzinfo=timezone.utc)),
482+
(3, "gamma", None, datetime(2026, 1, 3, tzinfo=timezone.utc)),
483+
]
484+
async with connection.transaction() as transaction:
485+
inserted = await transaction.copy_records_to_table(
486+
table_name="measurements",
487+
records=records,
488+
)
489+
print(f"Inserted {inserted} rows")
490+
```
491+
492+
You can load only a subset of columns by providing the `columns` argument:
493+
494+
```python
495+
async def main() -> None:
496+
...
497+
connection = await db_pool.connection()
498+
async with connection.transaction() as transaction:
499+
inserted = await transaction.copy_records_to_table(
500+
table_name="measurements",
501+
records=[(1, "alpha"), (2, "beta")],
502+
columns=["id", "label"],
503+
)
504+
```

0 commit comments

Comments
 (0)