#![allow(clippy::result_large_err)]
use facet::Facet;
use vox::service;
#[derive(Debug, Clone, Facet)]
pub struct TableInfo {
pub name: String,
pub columns: Vec<ColumnInfo>,
pub foreign_keys: Vec<ForeignKeyInfo>,
pub indices: Vec<IndexInfo>,
pub source_file: Option<String>,
pub source_line: Option<u32>,
pub doc: Option<String>,
pub icon: Option<String>,
}
#[derive(Debug, Clone, Facet)]
pub struct ColumnInfo {
pub name: String,
pub sql_type: String,
pub rust_type: Option<String>,
pub nullable: bool,
pub default: Option<String>,
pub primary_key: bool,
pub unique: bool,
pub auto_generated: bool,
pub long: bool,
pub label: bool,
pub enum_variants: Vec<String>,
pub doc: Option<String>,
pub lang: Option<String>,
pub icon: Option<String>,
pub subtype: Option<String>,
}
#[derive(Debug, Clone, Facet)]
pub struct ForeignKeyInfo {
pub columns: Vec<String>,
pub references_table: String,
pub references_columns: Vec<String>,
}
#[derive(Debug, Clone, Facet)]
pub struct IndexColumnInfo {
pub name: String,
pub order: String,
pub nulls: String,
}
#[derive(Debug, Clone, Facet)]
pub struct IndexInfo {
pub name: String,
pub columns: Vec<IndexColumnInfo>,
pub unique: bool,
pub where_clause: Option<String>,
}
#[derive(Debug, Clone, Facet)]
pub struct SchemaInfo {
pub tables: Vec<TableInfo>,
}
#[derive(Debug, Clone, Facet)]
pub struct ChangeInfo {
pub description: String,
pub kind: ChangeKind,
}
#[derive(Debug, Clone, Copy, Facet)]
#[repr(u8)]
pub enum ChangeKind {
Add = 0,
Drop = 1,
Alter = 2,
}
#[derive(Debug, Clone, Facet)]
pub struct TableDiffInfo {
pub table: String,
pub changes: Vec<ChangeInfo>,
}
#[derive(Debug, Clone, Facet)]
pub struct DiffResult {
pub table_diffs: Vec<TableDiffInfo>,
}
#[derive(Debug, Clone, Facet)]
pub struct MigrationInfo {
pub version: String,
pub name: String,
pub applied: bool,
pub applied_at: Option<String>,
pub source_file: Option<String>,
pub source: Option<String>,
}
#[derive(Debug, Clone, Facet)]
pub struct DiffRequest {
pub database_url: String,
}
#[derive(Debug, Clone, Facet)]
pub struct MigrationStatusRequest {
pub database_url: String,
}
#[derive(Debug, Clone, Facet)]
pub struct MigrateRequest {
pub database_url: String,
pub migration: Option<String>,
}
#[derive(Debug, Clone, Facet)]
pub struct AppliedMigration {
pub version: String,
pub applied_at: String,
}
#[derive(Debug, Clone, Facet)]
pub struct RanMigration {
pub version: String,
pub duration_ms: u64,
}
#[derive(Debug, Clone, Facet)]
pub struct MigrateResult {
pub total_defined: u32,
pub already_applied: Vec<AppliedMigration>,
pub applied: Vec<RanMigration>,
pub setup_ms: u64,
pub total_time_ms: u64,
}
#[derive(Debug, Clone, Facet)]
pub struct MigrationLog {
pub level: LogLevel,
pub message: String,
pub migration: Option<String>,
}
#[derive(Debug, Clone, Copy, Facet)]
#[repr(u8)]
pub enum LogLevel {
Debug = 0,
Info = 1,
Warn = 2,
Error = 3,
}
#[derive(Debug, Clone, Facet)]
pub struct SqlError {
pub message: String,
pub sql: Option<String>,
pub position: Option<u32>,
pub hint: Option<String>,
pub detail: Option<String>,
pub caller: Option<String>,
}
#[derive(Debug, Clone, Facet)]
#[repr(u8)]
pub enum DibsError {
ConnectionFailed(String) = 0,
MigrationFailed(SqlError) = 1,
InvalidRequest(String) = 2,
UnknownTable(String) = 3,
UnknownColumn(String) = 4,
QueryError(String) = 5,
}
#[derive(Debug, Clone, Facet)]
#[repr(u8)]
pub enum Value {
Null = 0,
Bool(bool) = 1,
I16(i16) = 2,
I32(i32) = 3,
I64(i64) = 4,
F32(f32) = 5,
F64(f64) = 6,
String(String) = 7,
Bytes(Vec<u8>) = 8,
}
#[derive(Debug, Clone, Facet)]
pub struct Row {
pub fields: Vec<RowField>,
}
#[derive(Debug, Clone, Facet)]
pub struct RowField {
pub name: String,
pub value: Value,
}
#[derive(Debug, Clone, Copy, Facet)]
#[repr(u8)]
pub enum FilterOp {
Eq,
Ne,
Lt,
Lte,
Gt,
Gte,
Like,
ILike,
IsNull,
IsNotNull,
In,
JsonGet,
JsonGetText,
Contains,
KeyExists,
}
#[derive(Debug, Clone, Facet)]
pub struct Filter {
pub field: String,
pub op: FilterOp,
pub value: Value,
pub values: Vec<Value>,
}
#[derive(Debug, Clone, Copy, Facet)]
#[repr(u8)]
pub enum SortDir {
Asc = 0,
Desc = 1,
}
#[derive(Debug, Clone, Facet)]
pub struct Sort {
pub field: String,
pub dir: SortDir,
}
#[derive(Debug, Clone, Facet)]
pub struct ListRequest {
pub table: String,
pub filters: Vec<Filter>,
pub sort: Vec<Sort>,
pub limit: Option<u32>,
pub offset: Option<u32>,
pub select: Vec<String>,
}
#[derive(Debug, Clone, Facet)]
pub struct ListResponse {
pub rows: Vec<Row>,
pub total: Option<u64>,
}
#[derive(Debug, Clone, Facet)]
pub struct GetRequest {
pub table: String,
pub pk: Value,
}
#[derive(Debug, Clone, Facet)]
pub struct CreateRequest {
pub table: String,
pub data: Row,
}
#[derive(Debug, Clone, Facet)]
pub struct UpdateRequest {
pub table: String,
pub pk: Value,
pub data: Row,
}
#[derive(Debug, Clone, Facet)]
pub struct DeleteRequest {
pub table: String,
pub pk: Value,
}
#[service]
pub trait DibsService {
async fn schema(&self) -> SchemaInfo;
async fn diff(&self, request: DiffRequest) -> Result<DiffResult, DibsError>;
async fn generate_migration_sql(&self, request: DiffRequest) -> Result<String, DibsError>;
async fn migration_status(
&self,
request: MigrationStatusRequest,
) -> Result<Vec<MigrationInfo>, DibsError>;
async fn migrate(
&self,
request: MigrateRequest,
logs: vox::Tx<MigrationLog>,
) -> Result<MigrateResult, DibsError>;
}
#[service]
pub trait SquelService {
async fn schema(&self) -> SchemaInfo;
async fn list(&self, request: ListRequest) -> Result<ListResponse, DibsError>;
async fn get(&self, request: GetRequest) -> Result<Option<Row>, DibsError>;
async fn create(&self, request: CreateRequest) -> Result<Row, DibsError>;
async fn update(&self, request: UpdateRequest) -> Result<Row, DibsError>;
async fn delete(&self, request: DeleteRequest) -> Result<u64, DibsError>;
}