2022-08-02 12:28:52 -05:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
use once_cell::sync::OnceCell;
|
|
|
|
use sqlx::{
|
|
|
|
error::BoxDynError,
|
|
|
|
postgres::{types::Oid, PgHasArrayType, PgTypeInfo},
|
|
|
|
query_as,
|
|
|
|
types::Json,
|
|
|
|
Decode, Encode, Executor, FromRow, Postgres, Type,
|
|
|
|
};
|
|
|
|
|
2022-09-09 18:30:20 -05:00
|
|
|
use crate::index::DependencyKind;
|
|
|
|
|
2022-08-02 12:28:52 -05:00
|
|
|
#[derive(Clone, Copy, Default, Debug)]
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct PgU32(pub u32);
|
|
|
|
|
|
|
|
impl PgU32 {
|
|
|
|
fn to_i32(self) -> i32 {
|
|
|
|
i32::from_ne_bytes(self.0.to_ne_bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn from_i32(v: i32) -> Self {
|
|
|
|
Self(u32::from_ne_bytes(v.to_ne_bytes()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r> Decode<'r, Postgres> for PgU32 {
|
|
|
|
fn decode(
|
|
|
|
value: <Postgres as sqlx::database::HasValueRef<'r>>::ValueRef,
|
|
|
|
) -> Result<Self, sqlx::error::BoxDynError> {
|
|
|
|
i32::decode(value).map(Self::from_i32)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'q> Encode<'q, Postgres> for PgU32 {
|
|
|
|
fn encode_by_ref(
|
|
|
|
&self,
|
|
|
|
buf: &mut <Postgres as sqlx::database::HasArguments<'q>>::ArgumentBuffer,
|
|
|
|
) -> sqlx::encode::IsNull {
|
|
|
|
self.to_i32().encode(buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn produces(&self) -> Option<<Postgres as sqlx::Database>::TypeInfo> {
|
|
|
|
self.to_i32().produces()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn size_hint(&self) -> usize {
|
|
|
|
self.to_i32().size_hint()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Type<Postgres> for PgU32 {
|
|
|
|
fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
|
|
|
|
i32::type_info()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PgHasArrayType for PgU32 {
|
|
|
|
fn array_type_info() -> PgTypeInfo {
|
|
|
|
i32::array_type_info()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(FromRow)]
|
|
|
|
pub struct DbUser {
|
|
|
|
pub id: PgU32,
|
|
|
|
pub login: String,
|
|
|
|
pub credential: String,
|
|
|
|
pub name: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(FromRow)]
|
|
|
|
pub struct DbCrate {
|
|
|
|
pub id: PgU32,
|
|
|
|
pub name: String,
|
|
|
|
pub publisher: PgU32,
|
|
|
|
pub owners: Vec<PgU32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(FromRow)]
|
|
|
|
pub struct DbVersion {
|
|
|
|
pub id: PgU32,
|
|
|
|
pub vers: String,
|
|
|
|
pub cksum: String,
|
|
|
|
pub yanked: bool,
|
|
|
|
pub links: Option<String>,
|
|
|
|
pub crate_id: PgU32,
|
|
|
|
pub features: Vec<DbVersionFeature>,
|
|
|
|
pub authors: Vec<String>,
|
|
|
|
pub description: Option<String>,
|
|
|
|
pub documentation: Option<String>,
|
|
|
|
pub homepage: Option<String>,
|
|
|
|
pub readme: Option<String>,
|
|
|
|
pub readme_file: Option<String>,
|
|
|
|
pub keywords: Vec<String>,
|
|
|
|
pub categories: Vec<String>,
|
|
|
|
pub license: Option<String>,
|
|
|
|
pub license_file: Option<String>,
|
|
|
|
pub repository: Option<String>,
|
|
|
|
pub badges: Json<HashMap<String, HashMap<String, String>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(FromRow)]
|
|
|
|
pub struct DbDep {
|
|
|
|
pub id: PgU32,
|
|
|
|
pub name: String,
|
|
|
|
pub version_req: String,
|
|
|
|
pub optional: bool,
|
|
|
|
pub default_features: bool,
|
|
|
|
pub target: Option<String>,
|
2022-09-09 18:30:20 -05:00
|
|
|
pub kind: DependencyKind,
|
2022-08-02 12:28:52 -05:00
|
|
|
pub registry: Option<String>,
|
|
|
|
pub package: Option<String>,
|
|
|
|
pub features: Vec<String>,
|
|
|
|
pub version_id: PgU32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Type)]
|
|
|
|
#[sqlx(type_name = "version_feature")]
|
|
|
|
pub struct DbVersionFeature {
|
|
|
|
pub feature: String,
|
|
|
|
pub enables: Vec<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
static VERSION_FEATURE_ARRAY_OID: OnceCell<Oid> = OnceCell::new();
|
|
|
|
|
|
|
|
pub async fn init<'c, E: Executor<'c, Database = Postgres> + Copy>(
|
|
|
|
e: E,
|
|
|
|
) -> Result<(), BoxDynError> {
|
|
|
|
// explicitly ignore the result, since it currently throws an error if the type already exists
|
|
|
|
let _ = e.execute(include_str!("create.sql")).await;
|
|
|
|
|
|
|
|
let (oid,): (Oid,) = query_as("SELECT typarray FROM pg_type WHERE typname = 'version_feature'")
|
|
|
|
.fetch_one(e)
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
VERSION_FEATURE_ARRAY_OID
|
|
|
|
.set(oid)
|
|
|
|
.expect("db::init called multiple times");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PgHasArrayType for DbVersionFeature {
|
|
|
|
fn array_type_info() -> PgTypeInfo {
|
|
|
|
PgTypeInfo::with_oid(*VERSION_FEATURE_ARRAY_OID.get().unwrap())
|
|
|
|
}
|
|
|
|
}
|