Skip to content

ultimaweapon/porm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Porm

Crates.io Version Crates.io Version docs.rs

Porm is a new type of ORM for PostgreSQL. Instead of defining some models in Rust, Porm parse migration scripts and generate models from it.

Warning

Porm currently in a pre-1.0 so prepare for a lot of breaking changes!

Features

  • Lightweight.
  • Database is a single source of truth.
  • Built-in schema migration.
  • Use actual parser from PostgreSQL.

How it works

Suppose you have the following migration scripts:

-- 0.sql
CREATE TABLE post (
    id serial NOT NULL,
    title text NOT NULL,
    body text NOT NULL,
    PRIMARY KEY (id)
);
-- 1.sql
ALTER TABLE post ADD published boolean NOT NULL DEFAULT FALSE;

CREATE INDEX ON post (published);

Porm will generate a corresponding struct for you:

pub struct Post<'a> {
    pub id: i32,
    pub title: Cow<'a, str>,
    pub body: Cow<'a, str>,
    pub published: bool,
}

The generated struct will have methods to query PostgreSQL based on table indexes:

impl<'a> Post<'a> {
    pub async fn find<T: GenericClient>(client: &T, id: i32) -> Result<Option<Self>, Error>;
    pub async fn select_by_published<T: GenericClient>(
        client: &T,
        published: bool,
    ) -> Result<Pin<Box<impl Stream<Item = Result<Self, Error>> + use<'a, T>>>, Error>;
}

Porm also generate a helper struct to insert a new row with default values:

pub struct PostBuilder<'a> { ... }

impl<'a> PostBuilder<'a> {
    pub fn new(title: &'a str, body: &'a str) -> Self;
    pub fn set_id(&mut self, v: i32) -> &mut Self;
    pub fn set_title(&mut self, v: &'a str) -> &mut Self;
    pub fn set_body(&mut self, v: &'a str) -> &mut Self;
    pub fn set_published(&mut self, v: bool) -> &mut Self;
    pub async fn create<T: GenericClient>(&self, client: &T) -> Result<Post<'static>, Error>;
}

Notice PostBuilder::new function that requires non-null columns without default value. The following code will insert a new row and construct Post value with id and published loaded from the database:

let post = PostBuilder::new("Foo", "Bar.").create(&pg).await.unwrap();

assert_eq!(post.id, 1); // Suppose this is the first row.
assert_eq!(post.title, "Foo");
assert_eq!(post.body, "Bar.");
assert!(!post.published);

Non-goals

  • Synchronous API.
  • Supports downgrade migration.
  • Supports other databases.

Breaking changes in parser 0.3

  • parse_for_build_script and parse have additional parameter.
  • ParseError no longer have migration version on every variants.
  • Migration version will be become a migration name if Migration::name return None.

Breaking changes in 0.2

  • Migration::name no longer optional.
  • Logger::run has new signature.
  • Error::ExecuteMigration and Error::UpdateVersion has been updated.

License

This project is licensed under either of

  • Apache License, Version 2.0
  • MIT License

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Porm by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

ORM for PostgreSQL that derive models from migration scripts

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Sponsor this project

 

Contributors

Languages