From 129d688ae1764cb93bce0f6cc28c3cfab28161c1 Mon Sep 17 00:00:00 2001 From: Daniel Hegberg Date: Sat, 8 Feb 2025 21:50:41 -0800 Subject: [PATCH 1/3] Add documentation for prepare statements. --- docs/source/user-guide/sql/index.rst | 1 + .../user-guide/sql/prepared_statements.md | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 docs/source/user-guide/sql/prepared_statements.md diff --git a/docs/source/user-guide/sql/index.rst b/docs/source/user-guide/sql/index.rst index 0508fa12f0f3b..b7b8298f80d71 100644 --- a/docs/source/user-guide/sql/index.rst +++ b/docs/source/user-guide/sql/index.rst @@ -35,3 +35,4 @@ SQL Reference special_functions sql_status write_options + prepared_statements diff --git a/docs/source/user-guide/sql/prepared_statements.md b/docs/source/user-guide/sql/prepared_statements.md new file mode 100644 index 0000000000000..23089f04eb3bc --- /dev/null +++ b/docs/source/user-guide/sql/prepared_statements.md @@ -0,0 +1,123 @@ + + +# Prepared Statements + +The `PREPARE` statement allows for the creation and storage of a SQL statement with placeholder arguments. + +The prepared statements can then be executed repeatedly in an efficient manner. + +##### SQL Example + +Create a prepared statement `greater_than` that selects all records where column "a" is greater than the parameter: + +```sql +PREPARE greater_than(INT) AS SELECT * FROM example WHERE a > $1; +``` + +The prepared statement can then be executed with parameters as needed: + +```sql +EXECUTE greater_than(20); +``` + +##### Datafusion Example + +```rust +use datafusion::prelude::*; + +#[tokio::main] +async fn main() -> datafusion::error::Result<()> { + // Register the table + let ctx = SessionContext::new(); + ctx.register_csv("example", "tests/data/example.csv", CsvReadOptions::new()).await?; + + // Create the prepared statement `greater_than` + let prepare_sql = "PREPARE greater_than(INT) AS SELECT * FROM example WHERE a > $1"; + ctx.sql(prepare_sql).await?; + + // Execute the prepared statement `greater_than` + let execute_sql = "EXECUTE greater_than(20)"; + let df = ctx.sql(execute_sql).await?; + + // Execute and print results + df.show().await?; + Ok(()) +} +``` + +### Inferred Types + +If the parameter type is not specified, it can be inferred at execution time: + +##### SQL Example + +Create the prepared statement `greater_than` + +```sql +PREPARE greater_than AS SELECT * FROM example WHERE a > $1; +``` + +Execute the prepared statement `greater_than` + +```sql +EXECUTE greater_than(20); +``` + +##### Datafusion Example + +```rust + // Create the prepared statement `greater_than` + let prepare_sql = "PREPARE greater_than AS SELECT * FROM example WHERE a > $1"; + ctx.sql(prepare_sql).await?; + + // Execute the prepared statement `greater_than` + let execute_sql = "EXECUTE greater_than(20)"; + let df = ctx.sql(execute_sql).await?; +``` + +### Positional Arguments + +In the case of multiple parameters, prepared statements can use positional arguments: + +##### SQL Example + +Create the prepared statement `greater_than` + +```sql +PREPARE greater_than(INT, DOUBLE) AS SELECT * FROM example WHERE a > $1 AND b > $2; +``` + +Execute the prepared statement `greater_than` + +```sql +EXECUTE greater_than(20, 23.3); +``` + +##### Datafusion Example + +```rust + // Create the prepared statement `greater_than` + let prepare_sql = "PREPARE greater_than(INT, DOUBLE) AS SELECT * FROM example WHERE a > $1 AND b > $2"; + ctx.sql(prepare_sql).await?; + + // Execute the prepared statement `greater_than` + let execute_sql = "EXECUTE greater_than(20, 23.3)"; + let df = ctx.sql(execute_sql).await?; +``` From c6027646477fc5a4d2319be2cb1513ca7d0a4852 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Thu, 13 Feb 2025 06:26:18 -0500 Subject: [PATCH 2/3] Run examples --- datafusion/core/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/datafusion/core/src/lib.rs b/datafusion/core/src/lib.rs index 48ee8e46bc0f9..70b595442cea7 100644 --- a/datafusion/core/src/lib.rs +++ b/datafusion/core/src/lib.rs @@ -962,6 +962,12 @@ doc_comment::doctest!( user_guide_sql_operators ); +#[cfg(doctest)] +doc_comment::doctest!( + "../../../docs/source/user-guide/sql/prepared_statements.md", + user_guide_prepared_statements +); + #[cfg(doctest)] doc_comment::doctest!( "../../../docs/source/user-guide/sql/scalar_functions.md", From eee5175ed74fdd44d1aae568719a6a825983fc7d Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Thu, 13 Feb 2025 06:31:38 -0500 Subject: [PATCH 3/3] Fix heading and example --- .../user-guide/sql/prepared_statements.md | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/source/user-guide/sql/prepared_statements.md b/docs/source/user-guide/sql/prepared_statements.md index 23089f04eb3bc..6677b212fdf27 100644 --- a/docs/source/user-guide/sql/prepared_statements.md +++ b/docs/source/user-guide/sql/prepared_statements.md @@ -23,7 +23,7 @@ The `PREPARE` statement allows for the creation and storage of a SQL statement w The prepared statements can then be executed repeatedly in an efficient manner. -##### SQL Example +**SQL Example** Create a prepared statement `greater_than` that selects all records where column "a" is greater than the parameter: @@ -37,7 +37,7 @@ The prepared statement can then be executed with parameters as needed: EXECUTE greater_than(20); ``` -##### Datafusion Example +**Rust Example** ```rust use datafusion::prelude::*; @@ -62,11 +62,11 @@ async fn main() -> datafusion::error::Result<()> { } ``` -### Inferred Types +## Inferred Types If the parameter type is not specified, it can be inferred at execution time: -##### SQL Example +**SQL Example** Create the prepared statement `greater_than` @@ -80,23 +80,32 @@ Execute the prepared statement `greater_than` EXECUTE greater_than(20); ``` -##### Datafusion Example +**Rust Example** ```rust - // Create the prepared statement `greater_than` - let prepare_sql = "PREPARE greater_than AS SELECT * FROM example WHERE a > $1"; - ctx.sql(prepare_sql).await?; - - // Execute the prepared statement `greater_than` - let execute_sql = "EXECUTE greater_than(20)"; - let df = ctx.sql(execute_sql).await?; +# use datafusion::prelude::*; +# #[tokio::main] +# async fn main() -> datafusion::error::Result<()> { +# let ctx = SessionContext::new(); +# ctx.register_csv("example", "tests/data/example.csv", CsvReadOptions::new()).await?; +# + // Create the prepared statement `greater_than` + let prepare_sql = "PREPARE greater_than AS SELECT * FROM example WHERE a > $1"; + ctx.sql(prepare_sql).await?; + + // Execute the prepared statement `greater_than` + let execute_sql = "EXECUTE greater_than(20)"; + let df = ctx.sql(execute_sql).await?; +# +# Ok(()) +# } ``` -### Positional Arguments +## Positional Arguments In the case of multiple parameters, prepared statements can use positional arguments: -##### SQL Example +**SQL Example** Create the prepared statement `greater_than` @@ -110,9 +119,14 @@ Execute the prepared statement `greater_than` EXECUTE greater_than(20, 23.3); ``` -##### Datafusion Example +**Rust Example** ```rust +# use datafusion::prelude::*; +# #[tokio::main] +# async fn main() -> datafusion::error::Result<()> { +# let ctx = SessionContext::new(); +# ctx.register_csv("example", "tests/data/example.csv", CsvReadOptions::new()).await?; // Create the prepared statement `greater_than` let prepare_sql = "PREPARE greater_than(INT, DOUBLE) AS SELECT * FROM example WHERE a > $1 AND b > $2"; ctx.sql(prepare_sql).await?; @@ -120,4 +134,6 @@ EXECUTE greater_than(20, 23.3); // Execute the prepared statement `greater_than` let execute_sql = "EXECUTE greater_than(20, 23.3)"; let df = ctx.sql(execute_sql).await?; +# Ok(()) +# } ```