use rupg_common::{Error, Result, SqlState};
use rupg_sql::nodes::{List, Node};
use crate::agg::Kind;
use crate::coerce::{AtOpt, Context};
use crate::select::{Query, Target};
use crate::{Analyzer, Env, Params, types};
pub fn param_types(names: &List, env: &dyn Env) -> Result<Vec<u32>> {
let mut analyzer = Analyzer::new(env, &Params::default());
names
.iter()
.map(|node| match node {
Some(Node::TypeName(name)) => analyzer.type_name(name).map(|(ty, _)| ty),
_ => Err(Error::new(SqlState::INTERNAL_ERROR, "a parameter of PREPARE is not a type")),
})
.collect()
}
pub fn execute_params(exprs: &List, types: &[u32], env: &dyn Env) -> Result<Query> {
let mut analyzer = Analyzer::new(env, &Params::default());
let mut targets = Vec::with_capacity(exprs.len());
for (i, (node, &ty)) in exprs.iter().zip(types).enumerate() {
let expr = analyzer.with_kind(Kind::ExecuteParameter, |an| an.transform(node.as_ref()))?;
let (given, at) = (expr.ty, expr.location);
let Some(expr) = analyzer.coerce_to_target(expr, ty, -1, Context::Assignment, at)? else {
return Err(Error::new(
SqlState::DATATYPE_MISMATCH,
format!(
"parameter ${} of type {} cannot be coerced to the expected type {}",
i + 1,
types::name(given),
types::name(ty)
),
)
.with_hint("You will need to rewrite or cast the expression.")
.at_opt(at));
};
targets.push(Target { name: "?column?".into(), expr, origin: None, junk: false });
}
Ok(Query {
relations: Vec::new(),
from: Vec::new(),
targets,
filter: None,
grouped: false,
group: Vec::new(),
grouping_sets: Vec::new(),
group_distinct: false,
having: None,
sort: Vec::new(),
distinct: Vec::new(),
distinct_on: false,
offset: None,
limit: None,
with_ties: false,
params: Vec::new(),
notices: analyzer.notices,
set_op: None,
windows: Vec::new(),
ctes: Vec::new(),
recursive: false,
row_marks: Vec::new(),
write: None,
out_args: Vec::new(),
pulled: 0,
pushed: false,
barrier: Vec::new(),
minmax: None,
constraint_deps: Vec::new(),
shown: None,
perms: Vec::new(),
funcs: Vec::new(),
})
}