@@ -37,6 +37,7 @@ use datafusion_cli::functions::{
3737use datafusion_cli:: object_storage:: instrumented:: {
3838 InstrumentedObjectStoreMode , InstrumentedObjectStoreRegistry ,
3939} ;
40+ use datafusion_cli:: object_storage:: { StdinCarriesCommands , is_stdin_location} ;
4041use datafusion_cli:: {
4142 DATAFUSION_CLI_VERSION , exec,
4243 pool_type:: PoolType ,
@@ -158,6 +159,23 @@ struct Args {
158159 object_store_profiling : InstrumentedObjectStoreMode ,
159160}
160161
162+ impl Args {
163+ /// Without -c/-f the CLI enters the REPL, which reads its SQL from
164+ /// stdin — interactively or piped.
165+ fn repl_mode ( & self ) -> bool {
166+ self . command . is_empty ( ) && self . file . is_empty ( )
167+ }
168+
169+ /// Whether the CLI consumes stdin for its own SQL input. This covers the
170+ /// REPL (no -c/-f, reading SQL interactively or piped) as well as an
171+ /// explicit `-f /dev/stdin` (or the other stdin pseudo-paths), where the
172+ /// SQL file *is* stdin. In either case stdin is already spoken for and
173+ /// cannot also back a `LOCATION '/dev/stdin'` table.
174+ fn reads_sql_from_stdin ( & self ) -> bool {
175+ self . repl_mode ( ) || self . file . iter ( ) . any ( |f| is_stdin_location ( f) )
176+ }
177+ }
178+
161179#[ tokio:: main]
162180/// Calls [`main_inner`], then handles printing errors and returning the correct exit code
163181pub async fn main ( ) -> ExitCode {
@@ -268,6 +286,7 @@ async fn main_inner() -> Result<()> {
268286 instrumented_registry : Arc :: clone ( & instrumented_registry) ,
269287 } ;
270288
289+ let repl_mode = args. repl_mode ( ) ;
271290 let commands = args. command ;
272291 let files = args. file ;
273292 let rc = match args. rc {
@@ -285,7 +304,7 @@ async fn main_inner() -> Result<()> {
285304 }
286305 } ;
287306
288- if commands . is_empty ( ) && files . is_empty ( ) {
307+ if repl_mode {
289308 if !rc. is_empty ( ) {
290309 exec:: exec_from_files ( & ctx, rc, & print_options) . await ?;
291310 }
@@ -330,8 +349,16 @@ fn get_session_config(args: &Args) -> Result<SessionConfig> {
330349 config_options. format . null = String :: from ( "NULL" ) ;
331350 }
332351
333- let session_config =
352+ let mut session_config =
334353 SessionConfig :: from ( config_options) . with_information_schema ( true ) ;
354+
355+ if args. reads_sql_from_stdin ( ) {
356+ // When stdin carries the session's SQL — the REPL (including any rc
357+ // file run before it) or an explicit `-f /dev/stdin` — it cannot also
358+ // serve as a data source for `LOCATION '/dev/stdin'`.
359+ session_config = session_config. with_extension ( Arc :: new ( StdinCarriesCommands ) ) ;
360+ }
361+
335362 Ok ( session_config)
336363}
337364
0 commit comments