use crate::{
command::{
get::get_property, install::install_extension, start::start_postgres, stop::stop_postgres,
},
CommandExecute,
};
use colored::Colorize;
use eyre::eyre;
use pgx_utils::{
createdb,
pg_config::{PgConfig, Pgx},
};
use std::{os::unix::process::CommandExt, process::Command};
#[derive(clap::Args, Debug)]
#[clap(author)]
pub(crate) struct Run {
#[clap(env = "PG_VERSION")]
pg_version: Option<String>,
dbname: Option<String>,
#[clap(env = "PROFILE", long, short)]
release: bool,
#[clap(long, short)]
no_schema: bool,
#[clap(flatten)]
features: clap_cargo::Features,
#[clap(from_global, parse(from_occurrences))]
verbose: usize,
}
impl CommandExecute for Run {
#[tracing::instrument(level = "error", skip(self))]
fn execute(mut self) -> eyre::Result<()> {
let metadata = crate::metadata::metadata(&self.features)?;
crate::metadata::validate(&metadata)?;
let manifest = crate::manifest::manifest(&metadata)?;
let pgx = Pgx::from_config()?;
let (pg_config, pg_version) = match self.pg_version {
Some(pg_version) => {
match pgx.get(&pg_version) {
Ok(pg_config) => (pg_config, pg_version),
Err(err) => {
if self.dbname.is_some() {
return Err(err);
}
self.dbname = Some(pg_version);
let default_pg_version = crate::manifest::default_pg_version(&manifest)
.ok_or(eyre!("No provided `pg$VERSION` flag."))?;
(pgx.get(&default_pg_version)?, default_pg_version)
},
}
},
None => {
let default_pg_version = crate::manifest::default_pg_version(&manifest)
.ok_or(eyre!("No provided `pg$VERSION` flag."))?;
(pgx.get(&default_pg_version)?, default_pg_version)
},
};
let features = crate::manifest::features_for_version(self.features, &manifest, &pg_version);
let dbname = match self.dbname {
Some(dbname) => dbname,
None => get_property("extname")?.ok_or(eyre!("could not determine extension name"))?,
};
run_psql(
pg_config,
&dbname,
self.release,
self.no_schema,
&features,
)
}
}
#[tracing::instrument(level = "error", skip_all, fields(
pg_version = %pg_config.version()?,
dbname,
release = is_release,
))]
pub(crate) fn run_psql(
pg_config: &PgConfig,
dbname: &str,
is_release: bool,
no_schema: bool,
features: &clap_cargo::Features,
) -> eyre::Result<()> {
stop_postgres(pg_config)?;
install_extension(pg_config, is_release, no_schema, None, features)?;
start_postgres(pg_config)?;
if !createdb(pg_config, dbname, false, true)? {
println!(
"{} existing database {}",
" Re-using".bold().cyan(),
dbname
);
}
exec_psql(pg_config, dbname)
}
pub(crate) fn exec_psql(pg_config: &PgConfig, dbname: &str) -> eyre::Result<()> {
let mut command = Command::new(pg_config.psql_path()?);
command
.env_remove("PGDATABASE")
.env_remove("PGHOST")
.env_remove("PGPORT")
.env_remove("PGUSER")
.arg("-h")
.arg(pg_config.host())
.arg("-p")
.arg(pg_config.port()?.to_string())
.arg(dbname);
panic!("{}", command.exec());
}