Forum schema

I’ve been working slowly, but steadily, on the forum lately and thought I’d put up the schema I’ve been testing against for the past few weeks. This is for SQLite since it’s very simple to setup, change things and if necessary, completely scrap and start over without having to mess with a DB server.

I’ve been using the SQLite Manager plugin for Firefox to make quick changes to the schema on the go. I’ll post snippets of the rest of the script in increments when I have time to clean up and maybe I’ll post the whole thing on GitHub for the alpha release.

Maybe this will serve as a good starting point for someone else looking for ideas as well.

DROP TABLE IF EXISTS users;
CREATE TABLE users (
	id INTEGER PRIMARY KEY AUTOINCREMENT, 
	username VARCHAR NOT NULL UNIQUE, 
	password TEXT NOT NULL, 
	email VARCHAR NOT NULL UNIQUE, 
	token VARCHAR NOT NULL,
	bio TEXT, 
	pubkey TEXT, 
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 
	updated_at DATETIME NOT NULL , 
	status INTEGER NOT NULL DEFAULT 0
);

CREATE UNIQUE INDEX users_name_idx ON users (username, email);
CREATE INDEX users_activity_idx ON users (created_at, updated_at);
CREATE INDEX users_status_idx ON users (status);



DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
	id INTEGER PRIMARY KEY AUTOINCREMENT, 
	title VARCHAR,
	url VARCHAR,
	author VARCHAR NOT NULL, 
	user_id INTEGER NOT NULL DEFAULT 0, 
	summary TEXT NOT NULL, 
	body TEXT NULL, 
	reply_count INTEGER NOT NULL DEFAULT 0, 
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 
	updated_at DATETIME NOT NULL, 
	lastreply_at DATETIME NOT NULL, 
	status INTEGER NOT NULL  DEFAULT 0
);

CREATE INDEX posts_activity_idx ON posts (created_at, updated_at, lastreply_at);
CREATE INDEX posts_author_idx ON posts (author, user_id);
CREATE INDEX posts_url_idx ON posts (url) WHERE url IS NOT NULL;
CREATE INDEX posts_status_idx ON posts (status);



DROP TABLE IF EXISTS posts_family;
CREATE TABLE posts_family(
	parent_id INTEGER NOT NULL, 
	child_id INTEGER NOT NULL, 
	last_author VARCHAR NOT NULL, 
	last_id INTEGER NOT NULL, 
	lastreply_at DATETIME NOT NULL
);

CREATE INDEX posts_family_idx ON posts_family (parent_id, child_id);
CREATE INDEX posts_family_activity_idx ON posts_family 
	(last_author, last_id, lastreply_at);



DROP TABLE IF EXISTS posts_flags;
CREATE TABLE posts_flags(
	post_id INTEGER NOT NULL, 
	user_id INTEGER NOT NULL, 
	reason VARCHAR NOT NULL, 
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 
	status INTEGER NOT NULL DEFAULT 0
);

CREATE INDEX posts_flags_idx ON posts_flags (post_id, user_id);
CREATE INDEX posts_flags_created_at_idx ON posts_flags (created_at);
CREATE INDEX posts_flags_status_idx ON posts_flags (status);



DROP TABLE IF EXISTS taxonomy;
CREATE TABLE taxonomy (
	id INTEGER PRIMARY KEY AUTOINCREMENT, 
	label VARCHAR,
	term VARCHAR,
	post_count INTEGER NOT NULL DEFAULT 0, 
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	body TEXT NULL
);

CREATE INDEX taxonomy_created_at_idx ON taxonomy (created_at);
CREATE UNIQUE INDEX taxonomy_term_idx ON taxonomy (label, term);
CREATE INDEX taxonomy_count_idx ON taxonomy (post_count);



DROP TABLE IF EXISTS taxonomy_posts;
CREATE TABLE taxonomy_posts(
	taxonomy_id INTEGER NOT NULL, 
	post_id INTEGER NOT NULL
);

CREATE UNIQUE INDEX taxonomy_posts_idx ON taxonomy_posts (taxonomy_id, post_id);



DROP TABLE IF EXISTS pms;
CREATE TABLE pms (
	id INTEGER PRIMARY KEY AUTOINCREMENT, 
	title VARCHAR,
	sender_id INTEGER NOT NULL, 
	receiver_id INTEGER NOT NULL, 
	body TEXT NULL, 
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 
	status INTEGER NOT NULL  DEFAULT 0
);

CREATE INDEX pms_contact_idx ON pms (sender_id, receiver_id);
CREATE INDEX pms_created_idx ON pms (created_at);
CREATE INDEX pms_status_idx ON pms (status);



DROP TABLE IF EXISTS sessions;
CREATE TABLE sessions(
	id VARCHAR PRIMARY KEY, 
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 
	updated_at DATETIME NOT NULL,
	skey VARCHAR NOT NULL,
	data TEXT NOT NULL
);

CREATE INDEX sessions_activity_idx ON sessions (created_at, updated_at);



DROP TABLE IF EXISTS firewall;
CREATE TABLE firewall(
	id INTEGER PRIMARY KEY AUTOINCREMENT, 
	label VARCHAR,
	response VARCHAR,
	ip VARCHAR,
	ua VARCHAR,
	protocol VARCHAR,
	method VARCHAR,
	uri VARCHAR,
	headers TEXT NOT NULL, 
	request_at DATETIME NOT NULL,
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX firewall_ip_idx ON firewall (ip, label);
CREATE INDEX firewall_response_idx ON firewall (response);
CREATE INDEX firewall_activity_idx ON firewall (request_at, created_at);



DROP TABLE IF EXISTS blocklist;
CREATE TABLE blocklist(
	ip VARCHAR PRIMARY KEY, 
	label VARCHAR,
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	expires_at DATETIME NOT NULL
);

CREATE INDEX blocklist_label_idx ON blocklist (label);
CREATE INDEX blocklist_dates_idx ON blocklist (created_at, expires_at);



DROP TABLE IF EXISTS settings;
CREATE TABLE settings(
	id VARCHAR PRIMARY KEY, 
	data TEXT NOT NULL,
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX settings_created_idx ON settings (created_at);



DROP TABLE IF EXISTS history;
CREATE TABLE history(
	post_id INTEGER NOT NULL,
	user_id INTEGER NOT NULL  DEFAULT 0, 
	anon_id VARCHAR, 
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE UNIQUE INDEX history_idx ON history (post_id, user_id, anon_id);
CREATE INDEX history_created_idx ON history (created_at);



DROP TABLE IF EXISTS actions;
CREATE TABLE actions(
	post_id INTEGER NOT NULL,
	user_id INTEGER NOT NULL  DEFAULT 0, 
	anon_id VARCHAR, 
	command VARCHAR, 
	auth_key VARCHAR, 
	created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 
	expires_at DATETIME NOT NULL
);

CREATE UNIQUE INDEX actions_idx ON actions (post_id, user_id, anon_id);
CREATE INDEX actions_auth_key_idx ON actions (auth_key);
CREATE INDEX actions_activity_idx ON actions (created_at, expires_at);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s