Skip to content

Commit 49b7cba

Browse files
authored
Merge pull request #100 from xsnippet/diesel
Initial database schema
2 parents f09b3d3 + 83b315f commit 49b7cba

File tree

10 files changed

+240
-14
lines changed

10 files changed

+240
-14
lines changed

.github/workflows/tests.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ jobs:
4848
toolchain: ${{ matrix.rust-version }}
4949
override: true
5050

51+
- name: Install libpq (Windows)
52+
if: matrix.os == 'windows-latest'
53+
shell: bash
54+
run: |
55+
choco install postgresql12 --force --params '/Password:root'
56+
echo '::add-path::C:\Program Files\PostgreSQL\12\bin'
57+
echo '::add-path::C:\Program Files\PostgreSQL\12\lib'
58+
5159
- uses: actions-rs/cargo@v1
5260
with:
5361
command: test

Cargo.lock

Lines changed: 119 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,7 @@ categories = [
1616
publish = false
1717

1818
[dependencies]
19+
chrono = "0.4.13"
20+
diesel = { version = "1.4.5", features = ["postgres"] }
1921
rocket = "0.4.5"
2022
rocket_contrib = {version = "0.4.5", features = ["json"]}

diesel.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# For documentation on how to configure this file,
2+
# see diesel.rs/guides/configuring-diesel-cli
3+
4+
[print_schema]
5+
file = "src/storage/sql/schema.rs"
6+
7+
[migrations_directory]
8+
dir = "src/storage/sql/migrations"

src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
66
#![feature(proc_macro_hygiene, decl_macro)]
77

8+
#[macro_use]
9+
extern crate diesel;
810
#[macro_use]
911
extern crate rocket;
1012
#[macro_use]
1113
extern crate rocket_contrib;
1214

1315
mod application;
1416
mod routes;
17+
mod storage;
1518

1619
fn main() {
1720
let app = application::create_app();

src/storage/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod sql;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DROP TABLE tags;
2+
DROP TABLE changesets;
3+
DROP TABLE snippets;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
CREATE TABLE snippets (
2+
-- an internal autoincrementing identifier used in foreign keys.
3+
-- Normally not visible publicly, except for the case when it is
4+
-- used for looking legacy snippets up by id
5+
id SERIAL PRIMARY KEY,
6+
-- a short unique snippet identifier visible to users
7+
slug VARCHAR(32) NOT NULL,
8+
9+
title TEXT,
10+
syntax TEXT,
11+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
12+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
13+
14+
-- slugs must be unique (this will also automatically create a unique index)
15+
CONSTRAINT uq_slug UNIQUE (slug)
16+
);
17+
18+
19+
-- will be used for pagination; slug guarantees uniqueness of the sorting key
20+
CREATE INDEX snippets_created_at_slug ON snippets (created_at, slug);
21+
CREATE INDEX snippets_updated_at_slug ON snippets (updated_at, slug);
22+
23+
24+
CREATE TABLE changesets (
25+
id SERIAL PRIMARY KEY,
26+
snippet_id INTEGER NOT NULL,
27+
28+
-- numeric index used to determine the ordering of changesets for a given snippet
29+
version INTEGER DEFAULT 0 NOT NULL,
30+
content TEXT NOT NULL,
31+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
32+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
33+
34+
-- there can be multiple changesets per snippet
35+
CONSTRAINT fk_snippet FOREIGN KEY (snippet_id) REFERENCES snippets(id),
36+
-- but each one is supposed to have a unique version number
37+
CONSTRAINT uq_version UNIQUE (snippet_id, version),
38+
-- sanity check: do not allow empty changesets
39+
CONSTRAINT check_not_empty CHECK (LENGTH(content) > 0),
40+
-- sanity check: version numbers are non-negative integers
41+
CONSTRAINT check_non_negative_version CHECK (version >= 0)
42+
);
43+
44+
45+
-- tags could have been associated with snippets as M:M via an auxiliary table,
46+
-- but Diesel only supports child-parent associations, so let's do that instead
47+
CREATE TABLE tags (
48+
id SERIAL PRIMARY KEY,
49+
snippet_id INTEGER NOT NULL,
50+
51+
value TEXT NOT NULL,
52+
53+
-- there can be multiple tags per snippet
54+
CONSTRAINT fk_snippet FOREIGN KEY (snippet_id) REFERENCES snippets(id),
55+
-- do not allow to abuse the tags for storing too much data
56+
CONSTRAINT check_length CHECK (LENGTH(value) < 128),
57+
-- do not allow repeated tags per snippet
58+
CONSTRAINT uq_snippet_tag UNIQUE (snippet_id, value)
59+
);

src/storage/sql/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mod schema;

src/storage/sql/schema.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// @generated automatically by Diesel CLI.
2+
3+
diesel::table! {
4+
changesets (id) {
5+
id -> Int4,
6+
snippet_id -> Int4,
7+
version -> Int4,
8+
content -> Text,
9+
created_at -> Timestamptz,
10+
updated_at -> Timestamptz,
11+
}
12+
}
13+
14+
diesel::table! {
15+
snippets (id) {
16+
id -> Int4,
17+
slug -> Varchar,
18+
title -> Nullable<Text>,
19+
syntax -> Nullable<Text>,
20+
created_at -> Timestamptz,
21+
updated_at -> Timestamptz,
22+
}
23+
}
24+
25+
diesel::table! {
26+
tags (id) {
27+
id -> Int4,
28+
snippet_id -> Int4,
29+
value -> Text,
30+
}
31+
}
32+
33+
diesel::joinable!(changesets -> snippets (snippet_id));
34+
diesel::joinable!(tags -> snippets (snippet_id));
35+
36+
diesel::allow_tables_to_appear_in_same_query!(changesets, snippets, tags,);

0 commit comments

Comments
 (0)