@@ -21,6 +21,7 @@ use std::sync::Arc;
2121
2222use crate :: util:: { BenchmarkRun , CommonOpt , QueryResult , print_memory_stats} ;
2323
24+ use arrow:: datatypes:: Schema ;
2425use arrow:: record_batch:: RecordBatch ;
2526use arrow:: util:: pretty:: { self , pretty_format_batches} ;
2627use datafusion:: datasource:: file_format:: parquet:: ParquetFormat ;
@@ -34,7 +35,7 @@ use datafusion::physical_plan::{collect, displayable};
3435use datafusion:: prelude:: * ;
3536use datafusion_common:: instant:: Instant ;
3637use datafusion_common:: utils:: get_available_parallelism;
37- use datafusion_common:: { DEFAULT_PARQUET_EXTENSION , plan_err} ;
38+ use datafusion_common:: { Constraint , Constraints , DEFAULT_PARQUET_EXTENSION , plan_err} ;
3839
3940use clap:: Args ;
4041use log:: info;
@@ -71,6 +72,61 @@ pub const TPCDS_TABLES: &[&str] = &[
7172 "web_site" ,
7273] ;
7374
75+ static TPCDS_PRIMARY_KEYS : & [ ( & str , & [ & str ] ) ] = & [
76+ ( "call_center" , & [ "cc_call_center_sk" ] ) ,
77+ ( "catalog_page" , & [ "cp_catalog_page_sk" ] ) ,
78+ ( "catalog_returns" , & [ "cr_item_sk" , "cr_order_number" ] ) ,
79+ ( "catalog_sales" , & [ "cs_item_sk" , "cs_order_number" ] ) ,
80+ ( "customer" , & [ "c_customer_sk" ] ) ,
81+ ( "customer_address" , & [ "ca_address_sk" ] ) ,
82+ ( "customer_demographics" , & [ "cd_demo_sk" ] ) ,
83+ ( "date_dim" , & [ "d_date_sk" ] ) ,
84+ ( "household_demographics" , & [ "hd_demo_sk" ] ) ,
85+ ( "income_band" , & [ "ib_income_band_sk" ] ) ,
86+ (
87+ "inventory" ,
88+ & [ "inv_date_sk" , "inv_item_sk" , "inv_warehouse_sk" ] ,
89+ ) ,
90+ ( "item" , & [ "i_item_sk" ] ) ,
91+ ( "promotion" , & [ "p_promo_sk" ] ) ,
92+ ( "reason" , & [ "r_reason_sk" ] ) ,
93+ ( "ship_mode" , & [ "sm_ship_mode_sk" ] ) ,
94+ ( "store" , & [ "s_store_sk" ] ) ,
95+ ( "store_returns" , & [ "sr_item_sk" , "sr_ticket_number" ] ) ,
96+ ( "store_sales" , & [ "ss_item_sk" , "ss_ticket_number" ] ) ,
97+ ( "time_dim" , & [ "t_time_sk" ] ) ,
98+ ( "warehouse" , & [ "w_warehouse_sk" ] ) ,
99+ ( "web_page" , & [ "wp_web_page_sk" ] ) ,
100+ ( "web_returns" , & [ "wr_item_sk" , "wr_order_number" ] ) ,
101+ ( "web_sales" , & [ "ws_item_sk" , "ws_order_number" ] ) ,
102+ ( "web_site" , & [ "web_site_sk" ] ) ,
103+ ] ;
104+
105+ /// Get the constraints for a TPC-DS table. Only primary keys are returned;
106+ /// TPC-DS also defines foreign keys, but those are currently unsupported.
107+ fn table_constraints ( table : & str , schema : & Schema ) -> Constraints {
108+ let columns = TPCDS_PRIMARY_KEYS
109+ . iter ( )
110+ . find ( |( name, _) | * name == table)
111+ . map ( |( _, columns) | * columns)
112+ . unwrap_or_else ( || unimplemented ! ( "unknown TPC-DS table: {table}" ) ) ;
113+
114+ Constraints :: new_unverified ( vec ! [ primary_key( schema, columns) ] )
115+ }
116+
117+ fn primary_key ( schema : & Schema , column_names : & [ & str ] ) -> Constraint {
118+ let indices = column_names
119+ . iter ( )
120+ . map ( |column_name| {
121+ schema. index_of ( column_name) . unwrap_or_else ( |_| {
122+ panic ! ( "primary key column '{column_name}' not found in schema" )
123+ } )
124+ } )
125+ . collect ( ) ;
126+
127+ Constraint :: PrimaryKey ( indices)
128+ }
129+
74130/// Get the SQL statements from the specified query file
75131pub fn get_query_sql ( base_query_path : & str , query : usize ) -> Result < Vec < String > > {
76132 if query > 0 && query < 100 {
@@ -327,7 +383,9 @@ impl RunOpt {
327383 . with_file_extension ( DEFAULT_PARQUET_EXTENSION )
328384 . with_target_partitions ( target_partitions)
329385 . with_collect_stat ( state. config ( ) . collect_statistics ( ) ) ;
386+
330387 let schema = options. infer_schema ( & state, & table_path) . await ?;
388+ let constraints = table_constraints ( table, schema. as_ref ( ) ) ;
331389
332390 if self . common . debug {
333391 println ! (
@@ -347,9 +405,11 @@ impl RunOpt {
347405 . with_listing_options ( options)
348406 . with_schema ( schema) ;
349407
350- Ok ( Arc :: new ( ListingTable :: try_new ( config) ?. with_cache (
351- ctx. runtime_env ( ) . cache_manager . get_file_statistic_cache ( ) ,
352- ) ) )
408+ let provider = ListingTable :: try_new ( config) ?
409+ . with_constraints ( constraints)
410+ . with_cache ( ctx. runtime_env ( ) . cache_manager . get_file_statistic_cache ( ) ) ;
411+
412+ Ok ( Arc :: new ( provider) )
353413 }
354414
355415 fn iterations ( & self ) -> usize {
0 commit comments