use crate::{
command::{get::get_property, run::exec_psql, start::start_postgres},
CommandExecute,
};
use cargo_toml::Manifest;
use eyre::{eyre, WrapErr};
use owo_colors::OwoColorize;
use pgx_utils::createdb;
use pgx_utils::pg_config::{PgConfig, Pgx};
use std::path::PathBuf;
#[derive(clap::Args, Debug)]
#[clap(author)]
pub(crate) struct Connect {
#[clap(env = "PG_VERSION")]
pg_version: Option<String>,
#[clap(env = "DBNAME")]
dbname: Option<String>,
#[clap(from_global, parse(from_occurrences))]
verbose: usize,
#[clap(long, short)]
package: Option<String>,
#[clap(long, parse(from_os_str))]
manifest_path: Option<PathBuf>,
#[clap(env = "PGX_PGCLI", long)]
pgcli: bool,
}
impl CommandExecute for Connect {
#[tracing::instrument(level = "error", skip(self))]
fn execute(mut self) -> eyre::Result<()> {
let pgx = Pgx::from_config()?;
let pg_version = match self.pg_version {
Some(pg_version) => match pgx.get(&pg_version) {
Ok(_) => pg_version,
Err(err) => {
if self.dbname.is_some() {
return Err(err);
}
self.dbname = Some(pg_version);
let metadata =
crate::metadata::metadata(&Default::default(), self.manifest_path.as_ref())
.wrap_err("couldn't get cargo metadata")?;
crate::metadata::validate(&metadata)?;
let package_manifest_path =
crate::manifest::manifest_path(&metadata, self.package.as_ref())
.wrap_err("Couldn't get manifest path")?;
let package_manifest = Manifest::from_path(&package_manifest_path)
.wrap_err("Couldn't parse manifest")?;
let default_pg_version = crate::manifest::default_pg_version(&package_manifest)
.ok_or(eyre!("no provided `pg$VERSION` flag."))?;
default_pg_version
}
},
None => {
let metadata =
crate::metadata::metadata(&Default::default(), self.manifest_path.as_ref())
.wrap_err("couldn't get cargo metadata")?;
crate::metadata::validate(&metadata)?;
let package_manifest_path =
crate::manifest::manifest_path(&metadata, self.package.as_ref())
.wrap_err("Couldn't get manifest path")?;
let package_manifest = Manifest::from_path(&package_manifest_path)
.wrap_err("Couldn't parse manifest")?;
let default_pg_version = crate::manifest::default_pg_version(&package_manifest)
.ok_or(eyre!("no provided `pg$VERSION` flag."))?;
default_pg_version
}
};
let dbname = match self.dbname {
Some(dbname) => dbname,
None => {
let metadata =
crate::metadata::metadata(&Default::default(), self.manifest_path.as_ref())
.wrap_err("couldn't get cargo metadata")?;
crate::metadata::validate(&metadata)?;
let package_manifest_path =
crate::manifest::manifest_path(&metadata, self.package.as_ref())
.wrap_err("Couldn't get manifest path")?;
get_property(&package_manifest_path, "extname")
.wrap_err("could not determine extension name")?
.ok_or(eyre!("extname not found in control file"))?
}
};
connect_psql(Pgx::from_config()?.get(&pg_version)?, &dbname, self.pgcli)
}
}
#[tracing::instrument(level = "error", skip_all, fields(
pg_version = %pg_config.version()?,
dbname,
))]
pub(crate) fn connect_psql(pg_config: &PgConfig, dbname: &str, pgcli: bool) -> eyre::Result<()> {
start_postgres(pg_config)?;
if !createdb(pg_config, dbname, false, true)? {
println!(
"{} existing database {}",
" Re-using".bold().cyan(),
dbname
);
}
exec_psql(&pg_config, dbname, pgcli)
}