CREATE TABLE users (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
username VARCHAR(30) NOT NULL,
bio VARCHAR(400),
avatar VARCHAR(200),
phone VARCHAR(25),
email VARCHAR(40),
password VARCHAR(50),
status VARCHAR(15),
-- user should have at least either phone or an email
CHECK(COALESCE(phone, email) IS NOT NULL)
);
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
url VARCHAR(200) NOT NULL,
caption VARCHAR(240),
-- lat and lng can be NULL or should meet the criteria
lat REAL CHECK(lat IS NULL OR (lat >= -90 AND lat <= 90)),
lng REAL CHECK(lng IS NULL OR (lng >= -180 AND lng <= 180)),
-- if a user is deleted, posts associated with that user_id will be deleted
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE comments (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
contents VARCHAR(240) NOT NULL,
-- if a user is deleted, comments associated with that user_id will be deleted
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
-- if a post is deleted, comments associated with that post_id will be deleted
post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE
);
CREATE TABLE likes (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE,
comment_id INTEGER REFERENCES comments(id) ON DELETE CASCADE,
-- either post_id or comment_id should exist
CHECK(
COALESCE((post_id)::BOOLEAN::INTEGER, 0)
+
COALESCE((comment_id)::BOOLEAN::INTEGER, 0)
= 1
),
-- user cannot like a post_id or a comment_id twice
UNIQUE(user_id, post_id, comment_id)
);
CREATE TABLE photo_tags (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
x INTEGER NOT NULL,
y INTEGER NOT NULL,
-- a user can be only tagged only once for one post(photo)
UNIQUE(user_id, post_id)
);
CREATE TABLE caption_tags (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
-- a user can be mentioned only once for one post(even though a person can be tagged several times)
-- the purpose of this table is to give a alert to the user, so alert shouldn't be given more than once
UNIQUE(user_id, post_id)
);
CREATE TABLE hashtags (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
title VARCHAR(20) NOT NULL UNIQUE
);
CREATE TABLE hashtags_posts (
id SERIAL PRIMARY KEY,
hashtag_id INTEGER NOT NULL REFERENCES hashtags(id) ON DELETE CASCADE,
post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
UNIQUE(hashtag_id, post_id)
);
CREATE TABLE followers (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
leader_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
follower_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
-- a user can follow a person once
UNIQUE(leader_id, follower_id)
);