This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new 03848c52f0 Move basic SQL query examples to user guide (#11217)
03848c52f0 is described below

commit 03848c52f0ddc2a91c6ee26995429b384dfced04
Author: Andrew Lamb <[email protected]>
AuthorDate: Wed Jul 3 14:43:36 2024 -0400

    Move basic SQL query examples to user guide (#11217)
---
 datafusion-examples/README.md                      |   9 +-
 datafusion-examples/examples/avro_sql.rs           |  51 ------
 datafusion-examples/examples/csv_sql.rs            |  70 --------
 datafusion-examples/examples/parquet_sql.rs        |  51 ------
 datafusion/core/src/lib.rs                         |   6 +
 .../source/library-user-guide/using-the-sql-api.md | 195 +++++++++++++++++++++
 docs/source/user-guide/example-usage.md            |   7 +-
 7 files changed, 209 insertions(+), 180 deletions(-)

diff --git a/datafusion-examples/README.md b/datafusion-examples/README.md
index 1c5651ad8a..a208eee135 100644
--- a/datafusion-examples/README.md
+++ b/datafusion-examples/README.md
@@ -36,9 +36,9 @@ cd datafusion
 # Download test data
 git submodule update --init
 
-# Run the `csv_sql` example:
+# Run the `dataframe` example:
 # ... use the equivalent for other examples
-cargo run --example csv_sql
+cargo run --example dataframe
 ```
 
 ## Single Process
@@ -47,10 +47,8 @@ cargo run --example csv_sql
 - [`advanced_udf.rs`](examples/advanced_udf.rs): Define and invoke a more 
complicated User Defined Scalar Function (UDF)
 - [`advanced_udwf.rs`](examples/advanced_udwf.rs): Define and invoke a more 
complicated User Defined Window Function (UDWF)
 - [`advanced_parquet_index.rs`](examples/advanced_parquet_index.rs): Creates a 
detailed secondary index that covers the contents of several parquet files
-- [`avro_sql.rs`](examples/avro_sql.rs): Build and run a query plan from a SQL 
statement against a local AVRO file
 - [`catalog.rs`](examples/catalog.rs): Register the table into a custom catalog
 - [`composed_extension_codec`](examples/composed_extension_codec.rs): Example 
of using multiple extension codecs for serialization / deserialization
-- [`csv_sql.rs`](examples/csv_sql.rs): Build and run a query plan from a SQL 
statement against a local CSV file
 - [`csv_sql_streaming.rs`](examples/csv_sql_streaming.rs): Build and run a 
streaming query plan from a SQL statement against a local CSV file
 - [`custom_datasource.rs`](examples/custom_datasource.rs): Run queries against 
a custom datasource (TableProvider)
 - [`dataframe-to-s3.rs`](examples/external_dependency/dataframe-to-s3.rs): Run 
a query using a DataFrame against a parquet file from s3 and writing back to s3
@@ -66,12 +64,11 @@ cargo run --example csv_sql
 - [`memtable.rs`](examples/memtable.rs): Create an query data in memory using 
SQL and `RecordBatch`es
 - [`optimizer_rule.rs`](examples/optimizer_rule.rs): Use a custom 
OptimizerRule to replace certain predicates
 - [`parquet_index.rs`](examples/parquet_index.rs): Create an secondary index 
over several parquet files and use it to speed up queries
-- [`parquet_sql.rs`](examples/parquet_sql.rs): Build and run a query plan from 
a SQL statement against a local Parquet file
 - [`parquet_sql_multiple_files.rs`](examples/parquet_sql_multiple_files.rs): 
Build and run a query plan from a SQL statement against multiple local Parquet 
files
 - [`parquet_exec_visitor.rs`](examples/parquet_exec_visitor.rs): Extract 
statistics by visiting an ExecutionPlan after execution
 - [`parse_sql_expr.rs`](examples/parse_sql_expr.rs): Parse SQL text into 
Datafusion `Expr`.
 - [`plan_to_sql.rs`](examples/plan_to_sql.rs): Generate SQL from Datafusion 
`Expr` and `LogicalPlan`
-- [`pruning.rs`](examples/parquet_sql.rs): Use pruning to rule out files based 
on statistics
+- [`pruning.rs`](examples/pruning.rs): Use pruning to rule out files based on 
statistics
 - [`query-aws-s3.rs`](examples/external_dependency/query-aws-s3.rs): Configure 
`object_store` and run a query against files stored in AWS S3
 - [`query-http-csv.rs`](examples/query-http-csv.rs): Configure `object_store` 
and run a query against files vi HTTP
 - [`regexp.rs`](examples/regexp.rs): Examples of using regular expression 
functions
diff --git a/datafusion-examples/examples/avro_sql.rs 
b/datafusion-examples/examples/avro_sql.rs
deleted file mode 100644
index ac1053aa18..0000000000
--- a/datafusion-examples/examples/avro_sql.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use datafusion::arrow::util::pretty;
-
-use datafusion::error::Result;
-use datafusion::prelude::*;
-
-/// This example demonstrates executing a simple query against an Arrow data 
source (Avro) and
-/// fetching results
-#[tokio::main]
-async fn main() -> Result<()> {
-    // create local execution context
-    let ctx = SessionContext::new();
-
-    let testdata = datafusion::test_util::arrow_test_data();
-
-    // register avro file with the execution context
-    let avro_file = &format!("{testdata}/avro/alltypes_plain.avro");
-    ctx.register_avro("alltypes_plain", avro_file, AvroReadOptions::default())
-        .await?;
-
-    // execute the query
-    let df = ctx
-        .sql(
-            "SELECT int_col, double_col, CAST(date_string_col as VARCHAR) \
-        FROM alltypes_plain \
-        WHERE id > 1 AND tinyint_col < double_col",
-        )
-        .await?;
-    let results = df.collect().await?;
-
-    // print the results
-    pretty::print_batches(&results)?;
-
-    Ok(())
-}
diff --git a/datafusion-examples/examples/csv_sql.rs 
b/datafusion-examples/examples/csv_sql.rs
deleted file mode 100644
index 851fdcb626..0000000000
--- a/datafusion-examples/examples/csv_sql.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use 
datafusion::datasource::file_format::file_compression_type::FileCompressionType;
-use datafusion::error::Result;
-use datafusion::prelude::*;
-
-/// This example demonstrates executing a simple query against an Arrow data 
source (CSV) and
-/// fetching results
-#[tokio::main]
-async fn main() -> Result<()> {
-    // create local execution context
-    let ctx = SessionContext::new();
-
-    let testdata = datafusion::test_util::arrow_test_data();
-
-    // register csv file with the execution context
-    ctx.register_csv(
-        "aggregate_test_100",
-        &format!("{testdata}/csv/aggregate_test_100.csv"),
-        CsvReadOptions::new(),
-    )
-    .await?;
-
-    // execute the query
-    let df = ctx
-        .sql(
-            "SELECT c1, MIN(c12), MAX(c12) \
-        FROM aggregate_test_100 \
-        WHERE c11 > 0.1 AND c11 < 0.9 \
-        GROUP BY c1",
-        )
-        .await?;
-
-    // print the results
-    df.show().await?;
-
-    // query compressed CSV with specific options
-    let csv_options = CsvReadOptions::default()
-        .has_header(true)
-        .file_compression_type(FileCompressionType::GZIP)
-        .file_extension("csv.gz");
-    let df = ctx
-        .read_csv(
-            &format!("{testdata}/csv/aggregate_test_100.csv.gz"),
-            csv_options,
-        )
-        .await?;
-    let df = df
-        .filter(col("c1").eq(lit("a")))?
-        .select_columns(&["c2", "c3"])?;
-
-    df.show().await?;
-
-    Ok(())
-}
diff --git a/datafusion-examples/examples/parquet_sql.rs 
b/datafusion-examples/examples/parquet_sql.rs
deleted file mode 100644
index fb438a7832..0000000000
--- a/datafusion-examples/examples/parquet_sql.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use datafusion::error::Result;
-use datafusion::prelude::*;
-
-/// This example demonstrates executing a simple query against an Arrow data 
source (Parquet) and
-/// fetching results
-#[tokio::main]
-async fn main() -> Result<()> {
-    // create local session context
-    let ctx = SessionContext::new();
-
-    let testdata = datafusion::test_util::parquet_test_data();
-
-    // register parquet file with the execution context
-    ctx.register_parquet(
-        "alltypes_plain",
-        &format!("{testdata}/alltypes_plain.parquet"),
-        ParquetReadOptions::default(),
-    )
-    .await?;
-
-    // execute the query
-    let df = ctx
-        .sql(
-            "SELECT int_col, double_col, CAST(date_string_col as VARCHAR) \
-        FROM alltypes_plain \
-        WHERE id > 1 AND tinyint_col < double_col",
-        )
-        .await?;
-
-    // print the results
-    df.show().await?;
-
-    Ok(())
-}
diff --git a/datafusion/core/src/lib.rs b/datafusion/core/src/lib.rs
index 2810dca463..fb7abcd795 100644
--- a/datafusion/core/src/lib.rs
+++ b/datafusion/core/src/lib.rs
@@ -631,3 +631,9 @@ doc_comment::doctest!(
     "../../../docs/source/user-guide/expressions.md",
     user_guide_expressions
 );
+
+#[cfg(doctest)]
+doc_comment::doctest!(
+    "../../../docs/source/library-user-guide/using-the-sql-api.md",
+    library_user_guide_example_usage
+);
diff --git a/docs/source/library-user-guide/using-the-sql-api.md 
b/docs/source/library-user-guide/using-the-sql-api.md
index f4e85ee4e3..1a25f078cc 100644
--- a/docs/source/library-user-guide/using-the-sql-api.md
+++ b/docs/source/library-user-guide/using-the-sql-api.md
@@ -19,4 +19,199 @@
 
 # Using the SQL API
 
+DataFusion has a full SQL API that allows you to interact with DataFusion using
+SQL query strings. The simplest way to use the SQL API is to use the
+[`SessionContext`] struct which provides the highest-level API for executing 
SQL
+queries.
+
+To use SQL, you first register your data as a table and then run queries
+using the [`SessionContext::sql`] method. For lower level control such as
+preventing DDL, you can use [`SessionContext::sql_with_options`] or the
+[`SessionState`] APIs
+
+[`sessioncontext`]: 
https://docs.rs/datafusion/latest/datafusion/execution/context/struct.SessionContext.html
+[`sessioncontext::sql`]: 
https://docs.rs/datafusion/latest/datafusion/execution/context/struct.SessionContext.html#method.sql
+[`sessioncontext::sql_with_options`]: 
https://docs.rs/datafusion/latest/datafusion/execution/context/struct.SessionContext.html#method.sql_with_options
+[`sessionstate`]: 
https://docs.rs/datafusion/latest/datafusion/execution/session_state/struct.SessionState.html
+
+## Registering Data Sources using `SessionContext::register*`
+
+The `SessionContext::register*` methods tell DataFusion the name of
+the source and how to read data. Once registered, you can execute SQL queries
+using the `SessionContext::sql` method referring to your data source as a 
table.
+
+### Read a CSV File
+
+```rust
+use datafusion::error::Result;
+use datafusion::prelude::*;
+use arrow::record_batch::RecordBatch;
+
+#[tokio::main]
+async fn main() -> Result<()> {
+    let ctx = SessionContext::new();
+    // register the "example" table
+    ctx.register_csv("example", "tests/data/example.csv", 
CsvReadOptions::new()).await?;
+    // create a plan to run a SQL query
+    let df = ctx.sql("SELECT a, MIN(b) FROM example WHERE a <= b GROUP BY a 
LIMIT 100").await?;
+    // execute the plan and collect the results as Vec<RecordBatch>
+    let results: Vec<RecordBatch> = df.collect().await?;
+    // Use the assert_batches_eq macro to compare the results with expected 
output
+    datafusion::assert_batches_eq!(vec![
+        "+---+----------------+",
+        "| a | MIN(example.b) |",
+        "+---+----------------+",
+        "| 1 | 2              |",
+        "+---+----------------+",
+        ],
+        &results
+    );
+  Ok(())
+}
+```
+
+### Read an Apache Parquet file
+
+Similarly to CSV, you can register a Parquet file as a table using the 
`register_parquet` method.
+
+```rust
+use datafusion::error::Result;
+use datafusion::prelude::*;
+#[tokio::main]
+async fn main() -> Result<()> {
+    // create local session context
+    let ctx = SessionContext::new();
+    let testdata = datafusion::test_util::parquet_test_data();
+
+    // register parquet file with the execution context
+    ctx.register_parquet(
+        "alltypes_plain",
+        &format!("{testdata}/alltypes_plain.parquet"),
+        ParquetReadOptions::default(),
+    )
+    .await?;
+
+    // execute the query
+    let df = ctx.sql(
+        "SELECT int_col, double_col, CAST(date_string_col as VARCHAR) \
+         FROM alltypes_plain \
+         WHERE id > 1 AND tinyint_col < double_col",
+    ).await?;
+
+    // execute the plan, and compare to the expected results
+    let results = df.collect().await?;
+    datafusion::assert_batches_eq!(vec![
+        "+---------+------------+--------------------------------+",
+        "| int_col | double_col | alltypes_plain.date_string_col |",
+        "+---------+------------+--------------------------------+",
+        "| 1       | 10.1       | 03/01/09                       |",
+        "| 1       | 10.1       | 04/01/09                       |",
+        "| 1       | 10.1       | 02/01/09                       |",
+        "+---------+------------+--------------------------------+",
+        ],
+        &results
+    );
+    Ok(())
+}
+```
+
+### Read an Apache Avro file
+
+DataFusion can also read Avro files using the `register_avro` method.
+
+```rust
+use datafusion::arrow::util::pretty;
+use datafusion::error::Result;
+use datafusion::prelude::*;
+
+#[tokio::main]
+async fn main() -> Result<()> {
+    let ctx = SessionContext::new();
+    // find the path to the avro test files
+    let testdata = datafusion::test_util::arrow_test_data();
+    // register avro file with the execution context
+    let avro_file = &format!("{testdata}/avro/alltypes_plain.avro");
+    ctx.register_avro("alltypes_plain", avro_file, 
AvroReadOptions::default()).await?;
+
+    // execute the query
+    let df = ctx.sql(
+        "SELECT int_col, double_col, CAST(date_string_col as VARCHAR) \
+         FROM alltypes_plain \
+         WHERE id > 1 AND tinyint_col < double_col"
+      ).await?;
+
+    // execute the plan, and compare to the expected results
+    let results = df.collect().await?;
+    datafusion::assert_batches_eq!(vec![
+        "+---------+------------+--------------------------------+",
+        "| int_col | double_col | alltypes_plain.date_string_col |",
+        "+---------+------------+--------------------------------+",
+        "| 1       | 10.1       | 03/01/09                       |",
+        "| 1       | 10.1       | 04/01/09                       |",
+        "| 1       | 10.1       | 02/01/09                       |",
+        "+---------+------------+--------------------------------+",
+        ],
+        &results
+    );
+    Ok(())
+}
+```
+
+## Reading Multiple Files as a table
+
+It is also possible to read multiple files as a single table. This is done
+with the ListingTableProvider which takes a list of file paths and reads them
+as a single table, matching schemas as appropriate
+
 Coming Soon
+
+```rust
+
+```
+
+## Using `CREATE EXTERNAL TABLE` to register data sources via SQL
+
+You can also register files using SQL using the [`CREATE EXTERNAL TABLE`]
+statement.
+
+[`create external table`]: ../user-guide/sql/ddl.md#create-external-table
+
+```rust
+use datafusion::error::Result;
+use datafusion::prelude::*;
+#[tokio::main]
+async fn main() -> Result<()> {
+    // create local session context
+    let ctx = SessionContext::new();
+    let testdata = datafusion::test_util::parquet_test_data();
+
+    // register parquet file using SQL
+    let ddl = format!(
+        "CREATE EXTERNAL TABLE alltypes_plain \
+        STORED AS PARQUET LOCATION '{testdata}/alltypes_plain.parquet'"
+    );
+    ctx.sql(&ddl).await?;
+
+    // execute the query referring to the alltypes_plain table we just 
registered
+    let df = ctx.sql(
+        "SELECT int_col, double_col, CAST(date_string_col as VARCHAR) \
+         FROM alltypes_plain \
+         WHERE id > 1 AND tinyint_col < double_col",
+    ).await?;
+
+    // execute the plan, and compare to the expected results
+    let results = df.collect().await?;
+    datafusion::assert_batches_eq!(vec![
+        "+---------+------------+--------------------------------+",
+        "| int_col | double_col | alltypes_plain.date_string_col |",
+        "+---------+------------+--------------------------------+",
+        "| 1       | 10.1       | 03/01/09                       |",
+        "| 1       | 10.1       | 04/01/09                       |",
+        "| 1       | 10.1       | 02/01/09                       |",
+        "+---------+------------+--------------------------------+",
+        ],
+        &results
+    );
+    Ok(())
+}
+```
diff --git a/docs/source/user-guide/example-usage.md 
b/docs/source/user-guide/example-usage.md
index 71a614313e..62f09a6a99 100644
--- a/docs/source/user-guide/example-usage.md
+++ b/docs/source/user-guide/example-usage.md
@@ -56,7 +56,7 @@ datafusion = { git = "https://github.com/apache/datafusion";, 
branch = "main", de
 
 More on [Cargo 
dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies)
 
-## Run a SQL query against data stored in a CSV:
+## Run a SQL query against data stored in a CSV
 
 ```rust
 use datafusion::prelude::*;
@@ -76,7 +76,10 @@ async fn main() -> datafusion::error::Result<()> {
 }
 ```
 
-## Use the DataFrame API to process data stored in a CSV:
+See [the SQL API](../library-user-guide/using-the-sql-api.md) section of the
+library guide for more information on the SQL API.
+
+## Use the DataFrame API to process data stored in a CSV
 
 ```rust
 use datafusion::prelude::*;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to