From 3d8d0aa2fe469bc2a86a4d5d3f2243da55b3e987 Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Sat, 8 Jun 2024 12:09:33 +0200 Subject: [PATCH] Format Python examples --- docs/api/python/dbapi.md | 33 ++++++++++++++++------ docs/api/python/function.md | 56 +++++++++++++++++++++++++++++++------ docs/api/python/types.md | 21 ++++++++++---- 3 files changed, 87 insertions(+), 23 deletions(-) diff --git a/docs/api/python/dbapi.md b/docs/api/python/dbapi.md index 2ce4ae8ae04..d7574db42e6 100644 --- a/docs/api/python/dbapi.md +++ b/docs/api/python/dbapi.md @@ -92,24 +92,38 @@ The `description` property of the connection object contains the column names as DuckDB also supports [prepared statements](../../sql/query_syntax/prepared_statements) in the API with the `execute` and `executemany` methods. The values may be passed as an additional parameter after a query that contains `?` or `$1` (dollar symbol and a number) placeholders. Using the `?` notation adds the values in the same sequence as passed within the Python parameter. Using the `$` notation allows for values to be reused within the SQL statement based on the number and index of the value found within the Python parameter. Values are converted according to the [conversion rules](conversion#object-conversion-python-object-to-duckdb). -Here are some examples: +Here are some examples. First, insert a row using a [prepared statement](../../sql/query_syntax/prepared_statements): ```python -# insert a row using prepared statements con.execute("INSERT INTO items VALUES (?, ?, ?)", ["laptop", 2000, 1]) +``` + +Second, insert several rows using a [prepared statement](../../sql/query_syntax/prepared_statements): -# insert several rows using prepared statements +```python con.executemany("INSERT INTO items VALUES (?, ?, ?)", [["chainsaw", 500, 10], ["iphone", 300, 2]] ) +``` + +Query the database using a [prepared statement](../../sql/query_syntax/prepared_statements): -# query the database using a prepared statement +```python con.execute("SELECT item FROM items WHERE value > ?", [400]) print(con.fetchall()) -# [('laptop',), ('chainsaw',)] +``` + +```text +[('laptop',), ('chainsaw',)] +``` + +Query using the `$` notation for a [prepared statement](../../sql/query_syntax/prepared_statements) and reused values: -# query using $ notation for prepared statement and reused values +```python con.execute("SELECT $1, $1, $2", ["duck", "goose"]) print(con.fetchall()) -# [('duck', 'duck', 'goose')] +``` + +```text +[('duck', 'duck', 'goose')] ``` > Warning Do *not* use `executemany` to insert large amounts of data into DuckDB. See the [data ingestion page](data_ingestion) for better options. @@ -136,5 +150,8 @@ res = duckdb.execute(""" } ).fetchall() print(res) -# [(5, 'DuckDB', [42])] +``` + +```text +[(5, 'DuckDB', [42])] ``` diff --git a/docs/api/python/function.md b/docs/api/python/function.md index 0f5c81dce7b..1a96a1cd37b 100644 --- a/docs/api/python/function.md +++ b/docs/api/python/function.md @@ -20,7 +20,10 @@ def generate_random_name(): duckdb.create_function("random_name", generate_random_name, [], VARCHAR) res = duckdb.sql("SELECT random_name()").fetchall() print(res) -# [('Gerald Ashley',)] +``` + +```text +[('Gerald Ashley',)] ``` ## Creating Functions @@ -63,7 +66,7 @@ def my_function(x: int) -> str: return x duckdb.create_function("my_func", my_function) -duckdb.sql("SELECT my_func(42)") +print(duckdb.sql("SELECT my_func(42)")) ``` ```text @@ -92,13 +95,28 @@ def dont_intercept_null(x): duckdb.create_function("dont_intercept", dont_intercept_null, [BIGINT], BIGINT) res = duckdb.sql("SELECT dont_intercept(NULL)").fetchall() print(res) -# [(None,)] +``` + +```text +[(None,)] +``` + +With `null_handling="special"`: + +```python +import duckdb +from duckdb.typing import * + +def dont_intercept_null(x): + return 5 -duckdb.remove_function("dont_intercept") duckdb.create_function("dont_intercept", dont_intercept_null, [BIGINT], BIGINT, null_handling="special") res = duckdb.sql("SELECT dont_intercept(NULL)").fetchall() print(res) -# [(5,)] +``` + +```text +[(5,)] ``` ## Exception Handling @@ -122,7 +140,18 @@ except duckdb.InvalidInputException as e: duckdb.create_function("doesnt_throw", will_throw, [], BIGINT, exception_handling="return_null") res = duckdb.sql("SELECT doesnt_throw()").fetchall() print(res) -# [(None,)] +``` + +```console +Invalid Input Error: Python exception occurred while executing the UDF: ValueError: ERROR + +At: + ...(5): will_throw + ...(9): +``` + +```text +[(None,)] ``` ## Side Effects @@ -148,7 +177,10 @@ con = duckdb.connect() con.create_function("my_counter", count, side_effects = False) res = con.sql("SELECT my_counter() FROM range(10)").fetchall() print(res) -# [(0,), (0,), (0,), (0,), (0,), (0,), (0,), (0,), (0,), (0,)] +``` + +```text +[(0,), (0,), (0,), (0,), (0,), (0,), (0,), (0,), (0,), (0,)] ``` Which is obviously not the desired result, when we add `side_effects = True`, the result is as we would expect: @@ -159,7 +191,10 @@ count.counter = 0 con.create_function("my_counter", count, side_effects = True) res = con.sql("SELECT my_counter() FROM range(10)").fetchall() print(res) -# [(0,), (1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,)] +``` + +```text +[(0,), (1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,)] ``` ## Python Function Types @@ -190,5 +225,8 @@ def random_date(): duckdb.create_function("random_date", random_date, [], DATE, type="native") res = duckdb.sql("SELECT random_date()").fetchall() print(res) -# [(datetime.date(2019, 5, 15),)] +``` + +```text +[(datetime.date(2019, 5, 15),)] ``` diff --git a/docs/api/python/types.md b/docs/api/python/types.md index ca9652d7be6..9d8f96c40c7 100644 --- a/docs/api/python/types.md +++ b/docs/api/python/types.md @@ -67,8 +67,11 @@ duckdb.typing.DuckDBPyType(list[dict[Union[str, int], str]) ```python import duckdb -duckdb.typing.DuckDBPyType(dict[str, int]) -# MAP(VARCHAR, BIGINT) +print(duckdb.typing.DuckDBPyType(dict[str, int])) +``` + +```text +MAP(VARCHAR, BIGINT) ``` #### *`{'a': field_one, 'b': field_two, .., 'n': field_n}`* @@ -78,8 +81,11 @@ duckdb.typing.DuckDBPyType(dict[str, int]) ```python import duckdb -duckdb.typing.DuckDBPyType({'a': str, 'b': int}) -# STRUCT(a VARCHAR, b BIGINT) +print(duckdb.typing.DuckDBPyType({'a': str, 'b': int})) +``` + +```text +STRUCT(a VARCHAR, b BIGINT) ``` #### *`Union[⟨type_1⟩, ... ⟨type_n⟩]`* @@ -90,8 +96,11 @@ duckdb.typing.DuckDBPyType({'a': str, 'b': int}) import duckdb from typing import Union -duckdb.typing.DuckDBPyType(Union[int, str, bool, bytearray]) -# UNION(u1 BIGINT, u2 VARCHAR, u3 BOOLEAN, u4 BLOB) +print(duckdb.typing.DuckDBPyType(Union[int, str, bool, bytearray])) +``` + +```text +UNION(u1 BIGINT, u2 VARCHAR, u3 BOOLEAN, u4 BLOB) ``` ### Creation Functions