Skip to content

Commit

Permalink
Initial database schema
Browse files Browse the repository at this point in the history
Diesel is used for schema migrations (written in raw SQL; targetting
PostgreSQL at the moment) and conversions between SQL and Rust
datatypes. Structs are defined, but not used yet.
  • Loading branch information
malor committed Jul 25, 2020
1 parent f09b3d3 commit 29609be
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 14 deletions.
133 changes: 119 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ categories = [
publish = false

[dependencies]
chrono = "0.4.13"
diesel = { version = "1.4.5", features = ["postgres"] }
rocket = "0.4.5"
rocket_contrib = {version = "0.4.5", features = ["json"]}
8 changes: 8 additions & 0 deletions diesel.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# For documentation on how to configure this file,
# see diesel.rs/guides/configuring-diesel-cli

[print_schema]
file = "src/storage/sql/schema.rs"

[migrations_directory]
dir = "src/storage/sql/migrations"
3 changes: 3 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]
extern crate diesel;
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;

mod application;
mod routes;
mod storage;

fn main() {
let app = application::create_app();
Expand Down
3 changes: 3 additions & 0 deletions src/storage/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Do not fail compilation until we've started using that code
#[allow(dead_code)]
pub mod sql;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.

DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
DROP FUNCTION IF EXISTS diesel_set_updated_at();
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.




-- Sets up a trigger for the given table to automatically set a column called
-- `updated_at` whenever the row is modified (unless `updated_at` was included
-- in the modified columns)
--
-- # Example
--
-- ```sql
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
--
-- SELECT diesel_manage_updated_at('users');
-- ```
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
BEGIN
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
BEGIN
IF (
NEW IS DISTINCT FROM OLD AND
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
) THEN
NEW.updated_at := current_timestamp;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
DROP TABLE tags;
DROP TABLE changesets;
DROP TABLE snippets;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
CREATE TABLE snippets (
-- an internal autoincrementing identifier used in foreign keys.
-- Normally not visible publicly, except for the case when it is
-- used for looking legacy snippets up by id
id SERIAL PRIMARY KEY,
-- a short unique snippet identifier visible to users
slug TEXT NOT NULL,

title TEXT,
syntax TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE,

-- slugs must be unique (this will also automatically create a unique index)
CONSTRAINT uq_slug UNIQUE (slug)
);


-- will be used for pagination; slug guarantees uniqueness of the sorting key
CREATE INDEX snippets_created_at_slug ON snippets (created_at, slug);


CREATE TABLE changesets (
id SERIAL PRIMARY KEY,
snippet_id INTEGER NOT NULL,

-- numeric index used to determine the ordering of changesets for a given snippet
version INTEGER DEFAULT 0 NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE,

-- there can be multiple changesets per snippet
CONSTRAINT fk_snippet FOREIGN KEY (snippet_id) REFERENCES snippets(id),
-- but each one is supposed to have a unique version number
CONSTRAINT uq_version UNIQUE (snippet_id, version),
-- sanity check: do not allow empty changesets
CONSTRAINT check_not_empty CHECK (LENGTH(content) > 0),
-- sanity check: version numbers are non-negative integers
CONSTRAINT check_non_negative_version CHECK (version >= 0)
);


-- tags could have been associated with snippets as M:M via an auxiliary table,
-- but Diesel only supports child-parent associations, so let's do that instead
CREATE TABLE tags (
id SERIAL PRIMARY KEY,
snippet_id INTEGER NOT NULL,

value TEXT NOT NULL,

-- there can be multiple tags per snippet
CONSTRAINT fk_snippet FOREIGN KEY (snippet_id) REFERENCES snippets(id),
-- do not allow to abuse the tags for storing too much data
CONSTRAINT check_length CHECK (LENGTH(value) < 128),
-- do not allow repeated tags per snippet
CONSTRAINT uq_snippet_tag UNIQUE (snippet_id, value)
);
4 changes: 4 additions & 0 deletions src/storage/sql/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod models;
mod schema;

pub use models::{Changeset, Snippet, Tag};
Loading

0 comments on commit 29609be

Please sign in to comment.