mz_testdrive/action/
psql.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use anyhow::{Context, bail};
11use mz_ore::option::OptionExt;
12use tokio::process::Command;
13
14use crate::action::{ControlFlow, State};
15use crate::parser::BuiltinCommand;
16use crate::util::text;
17
18pub async fn run_execute(
19    mut cmd: BuiltinCommand,
20    state: &State,
21) -> Result<ControlFlow, anyhow::Error> {
22    let command = cmd.args.string("command")?;
23    cmd.args.done()?;
24
25    let expected_output = cmd.input.join("\n");
26    let output = Command::new("psql")
27        .args([
28            // Ignore .psqlrc so that local execution of testdrive isn't
29            // affected by it.
30            "--no-psqlrc",
31            "--pset",
32            "footer=off",
33            "--command",
34            &command,
35            &format!(
36                "postgres://{}@{}",
37                state.materialize.user, state.materialize.sql_addr
38            ),
39        ])
40        .output()
41        .await
42        .context("execution of `psql` failed")?;
43    if !output.status.success() {
44        bail!(
45            "psql reported failure with exit code {}: {}",
46            output.status.code().display_or("unknown"),
47            String::from_utf8_lossy(&output.stderr),
48        );
49    }
50    let stdout = text::trim_trailing_space(&String::from_utf8_lossy(&output.stdout));
51    if expected_output != stdout {
52        text::print_diff(&expected_output, &*stdout);
53        bail!("psql returned unexpected output (diff above)");
54    }
55    Ok(ControlFlow::Continue)
56}