Skip to content

Commit 03eee2f

Browse files
committed
Merge branch 'trunk' into lukim/query-method
2 parents 2d14476 + 3680b9e commit 03eee2f

52 files changed

Lines changed: 155 additions & 88 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

crates/adbc_client/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ limitations under the License.
1515
*/
1616

1717
pub mod databricks;
18+
pub mod spiceai;
1819

1920
use std::collections::HashMap;
2021

crates/adbc_client/src/spiceai.rs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
Copyright 2026 The Spice.ai OSS Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
https://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
use std::collections::HashMap;
18+
19+
use crate::{AdbcConnection, Result};
20+
21+
/// Connect to a Spice.ai Flight SQL endpoint.
22+
///
23+
/// Uses [`AdbcConnection::create`] with the `"flightsql"` ADBC driver,
24+
/// passing `uri`, `username`, and `password` options.
25+
///
26+
/// # Arguments
27+
///
28+
/// - `flight_url`: The Flight SQL endpoint URI (e.g. `"grpc://localhost:50051"`).
29+
/// - `api_key`: Optional API key (passed as the `password` option; `username` is left empty).
30+
///
31+
/// # Example
32+
///
33+
/// ```rust,no_run
34+
/// use adbc_client::spiceai;
35+
///
36+
/// let mut conn = spiceai::connect("grpc://localhost:50051", Some("my-api-key"))
37+
/// .expect("Failed to connect");
38+
///
39+
/// let batches = conn.query("SELECT 1").expect("query failed");
40+
/// ```
41+
pub fn connect(flight_url: &str, api_key: Option<&str>) -> Result<AdbcConnection> {
42+
let mut kwargs = HashMap::from([(
43+
"uri".to_string(),
44+
serde_json::Value::String(flight_url.to_string()),
45+
)]);
46+
47+
if let Some(key) = api_key {
48+
kwargs.insert(
49+
"username".to_string(),
50+
serde_json::Value::String(String::new()),
51+
);
52+
kwargs.insert(
53+
"password".to_string(),
54+
serde_json::Value::String(key.to_string()),
55+
);
56+
}
57+
58+
AdbcConnection::create("flightsql", kwargs)
59+
}
60+
61+
#[cfg(test)]
62+
mod tests {
63+
use super::*;
64+
65+
/// Requires `SPICEAI_FLIGHT_URL` and `SPICEAI_API_KEY` env vars.
66+
#[test]
67+
#[ignore = "requires Spice.ai credentials in env"]
68+
fn test_spiceai_query() {
69+
let flight_url =
70+
std::env::var("SPICEAI_FLIGHT_URL").expect("SPICEAI_FLIGHT_URL must be set");
71+
let api_key = std::env::var("SPICEAI_API_KEY").ok();
72+
73+
let mut conn =
74+
connect(&flight_url, api_key.as_deref()).expect("Failed to connect to Spice.ai");
75+
76+
let batches = conn
77+
.query("SELECT 1 AS one")
78+
.expect("Failed to execute query");
79+
80+
let total_rows: usize = batches.iter().map(|b| b.num_rows()).sum();
81+
assert!(
82+
total_rows > 0,
83+
"Expected at least one row from Spice.ai query"
84+
);
85+
}
86+
87+
/// TPC-H Q22 – Global Sales Opportunity
88+
///
89+
/// Requires `SPICEAI_FLIGHT_URL` and `SPICEAI_API_KEY` env vars.
90+
/// SPICEAI_FLIGHT_URL="grpc://127.0.0.1:50051" cargo test -p adbc_client -- --ignored
91+
#[test]
92+
#[ignore = "requires Spice.ai credentials in env"]
93+
fn test_tpch_q22() {
94+
let flight_url =
95+
std::env::var("SPICEAI_FLIGHT_URL").expect("SPICEAI_FLIGHT_URL must be set");
96+
let api_key = std::env::var("SPICEAI_API_KEY").ok();
97+
98+
let mut conn =
99+
connect(&flight_url, api_key.as_deref()).expect("Failed to connect to Spice.ai");
100+
101+
let batches = conn
102+
.query(
103+
"select \
104+
cntrycode, \
105+
count(*) as numcust, \
106+
sum(c_acctbal) as totacctbal \
107+
from \
108+
( \
109+
select \
110+
substring(c_phone from 1 for 2) as cntrycode, \
111+
c_acctbal \
112+
from \
113+
customer \
114+
where \
115+
substring(c_phone from 1 for 2) in \
116+
('13', '31', '23', '29', '30', '18', '17') \
117+
and c_acctbal > ( \
118+
select \
119+
avg(c_acctbal) \
120+
from \
121+
customer \
122+
where \
123+
c_acctbal > 0.00 \
124+
and substring(c_phone from 1 for 2) in \
125+
('13', '31', '23', '29', '30', '18', '17') \
126+
) \
127+
and not exists ( \
128+
select \
129+
* \
130+
from \
131+
orders \
132+
where \
133+
o_custkey = c_custkey \
134+
) \
135+
) as custsale \
136+
group by \
137+
cntrycode \
138+
order by \
139+
cntrycode",
140+
)
141+
.expect("Failed to execute TPC-H Q22");
142+
143+
let total_rows: usize = batches.iter().map(|b| b.num_rows()).sum();
144+
assert!(total_rows > 0, "Expected at least one row from TPC-H Q22");
145+
}
146+
}

crates/test-framework/src/queries/mod.rs

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ impl QueryOverrides {
590590
pub fn get_tpch_test_queries(overrides: Option<QueryOverrides>) -> Vec<Query> {
591591
let queries = generate_tpch_queries!(
592592
q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q16, q17, q18, q19, q20, q21,
593-
q22, simple_q1, simple_q2, simple_q3, simple_q4, simple_q5, simple_q6, simple_q7
593+
q22
594594
);
595595

596596
match overrides {
@@ -608,7 +608,7 @@ pub fn get_tpch_test_queries(overrides: Option<QueryOverrides>) -> Vec<Query> {
608608
2, // Analysis error: [UNSUPPORTED_SUBQUERY_EXPRESSION_CATEGORY.UNSUPPORTED_CORRELATED_SCALAR_SUBQUERY] Unsupported subquery expression: Correlated scalar subqueries can only be used in filters, aggregations, projections, and UPDATE/MERGE/DELETE commands
609609
17 // Analysis error: [UNSUPPORTED_SUBQUERY_EXPRESSION_CATEGORY.UNSUPPORTED_CORRELATED_SCALAR_SUBQUERY] Unsupported subquery expression: Correlated scalar subqueries can only be used in filters, aggregations, projections, and UPDATE/MERGE/DELETE commands
610610
),
611-
Some(QueryOverrides::MySQL) => remove_tpch_query!(queries, simple_q7),
611+
Some(QueryOverrides::MySQL) => queries,
612612
Some(QueryOverrides::DynamoDB) => remove_tpch_query!(
613613
queries, 6 // Unsupported Decimals
614614
),
@@ -634,19 +634,11 @@ pub fn get_tpch_test_queries(overrides: Option<QueryOverrides>) -> Vec<Query> {
634634
q19,
635635
q20,
636636
q21,
637-
q22,
638-
simple_q1,
639-
simple_q2,
640-
simple_q3,
641-
simple_q4,
642-
simple_q5,
643-
simple_q6,
644-
simple_q7
637+
q22
645638
),
646639
Some(QueryOverrides::Oracle) => generate_tpch_queries_override!(
647640
"oracle", q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q16, q17, q18,
648-
q19, q20, q21, q22, simple_q1, simple_q2, simple_q3, simple_q4, simple_q5, simple_q6,
649-
simple_q7
641+
q19, q20, q21, q22
650642
),
651643
Some(QueryOverrides::IcebergSF1) => generate_tpch_queries_override!(
652644
"iceberg_sf1",
@@ -670,19 +662,11 @@ pub fn get_tpch_test_queries(overrides: Option<QueryOverrides>) -> Vec<Query> {
670662
q19,
671663
q20,
672664
q21,
673-
q22,
674-
simple_q1,
675-
simple_q2,
676-
simple_q3,
677-
simple_q4,
678-
simple_q5,
679-
simple_q6,
680-
simple_q7
665+
q22
681666
),
682667
Some(QueryOverrides::IcebergHadoop) => generate_tpch_queries_override!(
683668
"hadoop", q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q16, q17, q18,
684-
q19, q20, q21, q22, simple_q1, simple_q2, simple_q3, simple_q4, simple_q5, simple_q6,
685-
simple_q7
669+
q19, q20, q21, q22
686670
),
687671
Some(QueryOverrides::Spicecloud) => remove_tpch_query!(
688672
queries,
@@ -713,15 +697,7 @@ pub fn get_tpch_test_queries(overrides: Option<QueryOverrides>) -> Vec<Query> {
713697
q18,
714698
q19,
715699
// q20, Binder Error; https://github.com/spiceai/spiceai/issues/7356
716-
q21,
717-
// q22, Binder Error; https://github.com/spiceai/spiceai/issues/7356
718-
simple_q1,
719-
simple_q2,
720-
simple_q3,
721-
simple_q4,
722-
simple_q5,
723-
simple_q6,
724-
simple_q7
700+
q21 // q22, Binder Error; https://github.com/spiceai/spiceai/issues/7356
725701
),
726702
Some(QueryOverrides::GlueCatalog) => generate_tpch_queries_override!(
727703
"glue_catalog",
@@ -745,14 +721,7 @@ pub fn get_tpch_test_queries(overrides: Option<QueryOverrides>) -> Vec<Query> {
745721
q19,
746722
q20,
747723
q21,
748-
q22,
749-
simple_q1,
750-
simple_q2,
751-
simple_q3,
752-
simple_q4,
753-
simple_q5,
754-
simple_q6,
755-
simple_q7
724+
q22
756725
),
757726
Some(QueryOverrides::DuckDBPartitioned) => remove_tpch_query!(
758727
queries,

crates/test-framework/src/queries/tpch/glue_catalog/simple_q1.sql

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/test-framework/src/queries/tpch/glue_catalog/simple_q2.sql

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/test-framework/src/queries/tpch/glue_catalog/simple_q3.sql

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/test-framework/src/queries/tpch/glue_catalog/simple_q4.sql

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/test-framework/src/queries/tpch/glue_catalog/simple_q5.sql

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/test-framework/src/queries/tpch/glue_catalog/simple_q6.sql

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/test-framework/src/queries/tpch/glue_catalog/simple_q7.sql

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)