EBD - dmfrodrigues/feup-lbaw-proj GitHub Wiki
The Conceptual Domain Model contains the identification and description of the entities of the domain and the relationships between them in an UML class diagram.
The diagram of Figure 1 presents the main organisational entities, the relationships between them, attributes and their domains, and the multiplicity of relationships for Tokyo Drift Auction House.
Figure 1: UML conceptual data model
The "diagrams.net" tool was used.
This artifact contains the Relational Schema obtained by mapping from the Conceptual Data Model. The Relational Schema includes the relation schema, attributes, domains, primary keys, foreign keys and other integrity rules: UNIQUE, DEFAULT, NOT NULL, CHECK.
Relation schemas are specified in the compact notation:
Relation reference | Relation Compact Notation |
---|---|
R01 | user(id, firstName NN, lastName NN, email EMAIL_T NN UK, username NN UK, password NN, location, about, registeredOn PASTTIMESTAMP, profileImage β image) |
R02 | global_mod(id β user) |
R03 | admin(id β user) |
R04 | seller(id β user) |
R05 | vehicle(id, owner β user NN, brand NN, model NN, condition CONDITION_T NN, year NN CK year β€ year(now), horsepower NN CK horsepower β₯ 0, description) |
R06 | auction(id, auction_name NN, vehicle_id β vehicle NN, startingBid EURO_T CK startingBid β₯ 0, creationTime PASTTIMESTAMP, startingTime CK startingTime β₯ creationTime, endingTime NN CK endingTime β₯ startingTime + 1hour, auctionType AUCTIONTYPE_T NN DF 'Public', search TSVECTOR) |
R07 | auction_mod(auction_id β auction, user_id β user) |
R08 | image(id, path NN) |
R09 | invoice(id, user_id β user NN, createdOn PASTTIMESTAMP, vatNumber VATNUMBER_T, value EURO_T CK value β₯ 0, description NN) |
R10 | vehicle_image(vehicle_id β vehicle, image_id β image, sequence_number NN CK sequence_number β₯ 0) UK(vehicle, sequence_number) |
R11 | auction_guest(user_id β User, auction_id β auction) |
R12 | favorite_auction(user_id β user, auction_id β auction) |
R13 | comment(id, user_id β user NN, auction β auction NN, time NowTimeStamp CK time β€ now, content NN) |
R14 | ban(id, user_id β user NN, createdBy β user NN, createdOn PASTTIMESTAMP, startTime FUTURETIMESTAMP CK startTime β₯ createdOn, endTime FUTURETIMESTAMP CK end > start, reason NN, banType BANTYPE_T NN, auction_id β auction) CK (banType = 'AuctionBan' β auction_id β NULL) |
R15 | bid(id, user_id β user NN, auction_id β auction NN, amount EURO_T CK amount > 0, createdOn PASTTIMESTAMP) CK user β auction.vehicle.user CK createdOn < auction.endingTime |
Specification of additional domains:
Domain Name | Domain Specification |
---|---|
PASTTIMESTAMP | TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK(VALUE <= CURRENT_TIMESTAMP) |
FUTURETIMESTAMP | TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP |
EURO_T | NUMERIC(17, 2) NOT NULL |
EMAIL_T | TEXT CHECK(VALUE LIKE '%@%.__%') |
CONDITION_T | ENUM ('Mint', 'Clean', 'Average', 'Rough') |
AUCTIONTYPE_T | ENUM ('Public', 'Private') |
BANTYPE_T | ENUM ('BuyerBan', 'SellerBan', 'AllBan', 'AuctionBan') |
Table R01 (user) | |
---|---|
Keys: { id }, { email }, { username } | |
Functional Dependencies | |
FD101 | { id } β { firstName, lastName, email, username, password, location, about, registeredOn, profileImage } |
FD102 | { email } β { id, firstName, lastName, username, password, location, about, registeredOn, profileImage } |
FD103 | { username } β { id, firstName, lastName, email, password, location, about, registeredOn, profileImage } |
NORMAL FORM | BCNF |
Table R02 (global_mod) | |
---|---|
Keys: { id } | |
NORMAL FORM | BCNF |
Table R03 (admin) | |
---|---|
Keys: { id } | |
NORMAL FORM | BCNF |
Table R04 (seller) | |
---|---|
Keys: { id } | |
NORMAL FORM | BCNF |
Table R05 (vehicle) | |
---|---|
Keys: { id } | |
Functional Dependencies | |
FD201 | { id } β { owner, brand, model, condition, year, horsepower, description } |
NORMAL FORM | BCNF |
Table R06 (auction) | |
---|---|
Keys: { id } | |
Functional Dependencies | |
FD301 | { id } β { name, vehicle_id, startingBid, startingTime, endingTime, auctionType } |
NORMAL FORM | BCNF |
Table R07 (auction_mod) | |
---|---|
Keys: { auction_id, user_id } | |
NORMAL FORM | BCNF |
Table R08 (image) | |
---|---|
Keys: { id } | |
Functional Dependencies | |
FD801 | { id } β { path } |
NORMAL FORM | BCNF |
Table R09 (invoice) | |
---|---|
Keys: { id } | |
Functional Dependencies | |
FD901 | { id } β { user_id, createdOn, vatNumber, value, description } |
NORMAL FORM | BCNF |
Table R10 (vehicle_image) | |
---|---|
Keys: { vehicle_id, image_id }, { vehicle_id, sequence_number } | |
Functional Dependencies | |
FD1001 | { vehicle_id, image_id } β { sequence_number } |
FD1002 | { vehicle_id, sequence_number } β { image_id } |
NORMAL FORM | BCNF |
Table R11 (auction_guest) | |
---|---|
Keys: { user_id, auction_id } | |
NORMAL FORM | BCNF |
Table R12 (favourite_auction) | |
---|---|
Keys: { user_id, auction_id } | |
NORMAL FORM | BCNF |
Table R13 (comment) | |
---|---|
Keys: { id } | |
Functional Dependencies | |
FD1301 | { id } β { user_id, auction_id, time, content } |
NORMAL FORM | BCNF |
Table R14 (ban) | |
---|---|
Keys: { id } | |
Functional Dependencies | |
FD1401 | { id } β { user_id, createdBy, createdOn, start, end, reason, banType, auction_id } |
NORMAL FORM | BCNF |
Table R15 (bid) | |
---|---|
Keys: { id } | |
Functional Dependencies | |
FD1401 | { id } β { user_id, auction_id, amount, time } |
NORMAL FORM | BCNF |
All relations are in the BoyceβCodd Normal Form (BCNF), because for every one of its dependencies X β Y, at least one of the following conditions hold:
X β Y is a trivial functional dependency (Y β X),
X is a superkey for schema R.
Thus, the relational schema is also in the BCNF and therefore there is no need for it to be refined using normalisation.
This artefact contains the physical schema of the database, the identification and characterization of the indexes, the support of data integrity rules with triggers, the definition of the database user-defined functions, and the identification and characterization of the database transactions. This artefact also includes the complete database creation script, including all SQL necessary to define all integrity constraints, indexes, triggers and transactions.
Relation Reference | Relation Name | Order of magnitude | Estimated growth |
---|---|---|---|
R01 | user | thousands | units per day |
R02 | global_mod | tens | units per month |
R03 | admin | tens | units per month |
R04 | seller | thousands | units per day |
R05 | vehicle | hundreds | tens per day |
R06 | auction | hundreds | tens per day |
R07 | auction_mod | tens | units per month |
R08 | image | thousands | tens per day |
R09 | profile_image | thousands | units per day |
R10 | vehicle_image | hundreds | tens per day |
R11 | auction_guest | hundreds | tens per day |
R12 | favorite_auction | thousands | hundreds per day |
R13 | auction_comment | thousands | hundreds per day |
R14 | ban | hundreds | units per month |
R15 | bid | thousands | hundreds per hour |
Query | SELECT01 |
---|---|
Description | User's Profile |
Frequency | Hundreds per Day |
SELECT *
FROM "user"
WHERE "user".email = $email;
SELECT *
FROM "user"
WHERE "user".username = $username; |
Query | SELECT02 |
---|---|
Description | Users by location |
Frequency | Dozens per Day |
SELECT *
FROM "user"
WHERE "user".location = $location; |
Query | SELECT03 |
---|---|
Description | User's Favourites |
Frequency | Hundreds per Day |
SELECT "auction".*
FROM "favourite_auction", "auction"
WHERE
favourite_auction.auction_id = "auction".id
AND favourite_auction.user_id = $user_id; |
Query | SELECT04 |
---|---|
Description | Sign in |
Frequency | Hundreds per Day |
SELECT id
FROM user
WHERE
username = $username
AND password = $hashedPassword;
SELECT id
FROM user
WHERE
email = $email
AND password = $hashedPassword; |
Query | SELECT05 |
---|---|
Description | Auction card |
Frequency | Thousands per Day |
SELECT "auction".auction_name, "auction".endingTime, "vehicle_image".image
FROM "vehicle_image", "auction"
WHERE
"auction".id = $id
AND "vehicle_image".vehicle = "auction".vehicle
AND "vehicle_image".sequence_number = 0; |
Query | SELECT06 |
---|---|
Description | Auction |
Frequency | Thousands per Day |
SELECT *
FROM "auction", "vehicle"
WHERE
"auction".vehicle = "vehicle".id
AND auction.id = $id; |
Query | SELECT07 |
---|---|
Description | Auction's guests |
Frequency | Hundreds per Day |
SELECT "user".*
FROM "user", "auction_guest"
WHERE
"auction_guest".auction_id = $auction_id
AND "user".id = "auction_guest".user_id; |
Query | SELECT08 |
---|---|
Description | Auction's info |
Frequency | Thousands per Day |
SELECT *
FROM "auction"
WHERE
"auction".id = $id; |
Query | SELECT09 |
---|---|
Description | Auction's images |
Frequency | Thousands per Day |
SELECT "vehicle_image".image, "vehicle_image".sequence_number
FROM "auction", "vehicle_image"
WHERE
"auction".id = $id
AND "vehicle_image".vehicle = "auction".vehicle; |
Query | SELECT10 |
---|---|
Description | Seller Auctions |
Frequency | Hundreds per Day |
SELECT *
FROM "auction", "vehicle"
WHERE
"auction".vehicle = "vehicle".id
AND "vehicle".owner = $seller_id; |
Query | SELECT11 |
---|---|
Description | Search by Brand |
Frequency | Dozens per Day |
SELECT *
FROM "auction", "vehicle"
WHERE
"auction".vehicle = "vehicle".id
AND "vehicle".brand = $brand; |
Query | SELECT12 |
---|---|
Description | Search by Model |
Frequency | Dozens per Day |
SELECT *
FROM "auction", "vehicle"
WHERE
"auction".vehicle = "vehicle".id
AND "vehicle".model = $model; |
Query | SELECT13 |
---|---|
Description | Auction's comments |
Frequency | Thousands per Day |
SELECT "auction_comment".*
FROM "auction_comment", "auction"
WHERE
"auction_comment".auction_id = "auction".id; |
Query | SELECT14 |
---|---|
Description | Search |
Frequency | Hundreds per Day |
SELECT *
FROM
"auction", to_tsquery($search) AS query,
to_tsvector(auction_name || ' ' || brand || model) AS textsearch
WHERE query @@ textsearch\\
ORDER BY rank DESC; |
Query | SELECT15 |
---|---|
Description | Auction's top bid |
Frequency | Thousands per Day |
SELECT *
FROM "bid", "auction"
WHERE
"bid".amount = (
SELECT MAX(amount)
FROM "bid", "auction"
WHERE "bid".auction = "auction".id) |
Query | INSERT01 |
---|---|
Description | New Comment |
Frequency | Hundreds per Day |
INSERT INTO "auction_comment" (user_id, auction_id, content)
VALUES($user_id, $auction_id, $content) |
Query | INSERT02 |
---|---|
Description | New Favourite |
Frequency | Thousands per Day |
INSERT INTO "favourite_auction" (user_id, auction_id)
VALUES($user_id, $auction_id) |
Query | INSERT03 |
---|---|
Description | New Ban |
Frequency | Units per Month |
INSERT INTO "ban" (user_id, createdBy, startTime, endTime, reason, banType, auction_id)
VALUES($user_id, $createdBy, $startTime, $endTime, $reason, $banType, $auction_id) |
Query | INSERT04 |
---|---|
Description | New Bid |
Frequency | Hundreds per Hour |
INSERT INTO "bid" (user_id, auction_id, amount)
VALUES($user_id, $auction_id , $amount) |
Query | INSERT05 |
---|---|
Description | Add Auction Guest |
Frequency | Dozens per Day |
|
Query | UPDATE01 |
---|---|
Description | Update User Profile |
Frequency | Units per Day |
UPDATE user
SET
firstName = $firstName,
lastName = $lastName,
username = $username,
email = $email,
password = $hashedPassword,
location = $location,
about = $about
WHERE id = $id; |
Query | UPDATE02 |
---|---|
Description | Update Auction info |
Frequency | Units per Day |
UPDATE auction
SET
auction_name = $auction_name,
startingTime = $startingTime,
endingTime = $endingTime,
auctionType = $auctionType
WHERE vehicle = $id;
UPDATE vehicle
SET
brand = $brand,
model = $model,
condition = $condition,
manufactureYear = $manufactureYear,
horsepower = $horsepower
WHERE id = $id; |
Query | DELETE01 |
---|---|
Description | Delete Comment |
Frequency | Units per Day |
DELETE FROM "auction_comment"
WHERE id = $id; |
Query | DELETE02 |
---|---|
Description | Delete Auction |
Frequency | Units per Day |
DELETE FROM "vehicle"
WHERE id = $id; |
Index | IDX01 |
---|---|
Related Queries | SELECT10 |
Relation | "vehicle" |
Attribute | owner |
Type | Hash |
Cardinality | Medium |
Clustering | Yes |
Justification | Table "vehicle" is very large and query SELECT10, used to search the vehicles/auctions of an user, has to be fast because it's executed many times. Doesn't need range query support. Cardinality is medium so it's a good candidate for clustering. |
CREATE INDEX user_vehicles ON "vehicle"
USING hash(owner); |
Index | IDX02 |
---|---|
Related Queries | SELECT13 |
Relation | "auction_comment" |
Attribute | auction |
Type | Hash |
Cardinality | Medium |
Clustering | Yes |
Justification | Table "auction_comment" is very large and query SELECT13, used to get all comments under an auction, has to be fast because it's executed many times. Doesn't need range query support. Cardinality is medium so it's a good candidate for clustering. |
CREATE INDEX auctions_comments ON "comment"
USING hash(auction_id); |
Index | IDX03 |
---|---|
Related Queries | SELECT12 |
Relation | "vehicle" |
Attribute | model |
Type | Hash |
Cardinality | Medium |
Clustering | Yes |
Justification | Table "vehicle" is very large and query SELECT12, which is used to get all vehicles of a given model, has to be fast because it's executed many times. Doesn't need range query support. Cardinality is medium so it's a good candidate for clustering. |
CREATE INDEX vehicle_models ON "vehicle"
USING hash(model); |
Index | IDX04 |
---|---|
Related Queries | SELECT15 |
Relation | "bid" |
Attribute | auction |
Type | Hash |
Cardinality | Medium |
Clustering | Yes |
Justification | Table "bid" is very large and query SELECT15, used to get the current top bid of an auction, has to be fast because it's executed many times. Doesn't need range query support. Cardinality is medium so it's a good candidate for clustering. |
CREATE INDEX auctions_bids ON "bid"
USING hash(auction_id); |
Index | IDX05 |
---|---|
Related Queries | SELECT06 |
Relation | "auction" |
Attribute | endingTime |
Type | B-tree |
Cardinality | Medium |
Clustering | Yes |
Justification | Query SELECT06 allows to obtain all auctions and is executed very frequently. The index allows searching auctions by ending time range faster. It's clustered to allow for quick range queries. Cardinality is medium. |
CREATE INDEX end_auction ON "auction"
USING btree (endingTime); |
Index | IDX06 |
---|---|
Related Queries | SELECT14 |
Relation | "auction" |
Attribute | auction_name |
Type | GiST |
Clustering | No |
Justification | Query SELECT14 is responsible for running full text searches while searching for auctions and their names. The index improves the performance of the search adn should use GiST because it's better for dynamic data. |
CREATE INDEX search_idx ON "auction"
USING GIST (search); |
Trigger | TRIGGER01 |
---|---|
Description | A user can only be banned from an auction by an admin, global_mod or an auction_mod of that auction. A user can only be banned as seller, buyer or totally by an admin. |
CREATE FUNCTION ban_user() RETURNS TRIGGER AS
$BODY$
BEGIN
IF NEW.banType = 'AuctionBan' THEN
IF NOT EXISTS (
SELECT * FROM "admin" WHERE "admin".id = NEW.createdBy
UNION
SELECT * FROM "global_mod" WHERE "global_mod".id = NEW.createdBy
UNION
SELECT user_id FROM "auction_mod" WHERE NEW.auction_id = "auction_mod".auction_id AND "auction_mod".user_id = NEW.createdBy
) THEN
RAISE EXCEPTION 'User must be banned by Authorised Mod or Admin';
END IF;
ELSE
IF NOT EXISTS (SELECT * FROM "admin" WHERE "admin".id = NEW.createdBy) THEN
RAISE EXCEPTION 'User must be banned by Admin';
END IF;
END IF;
RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER ban_user
BEFORE INSERT OR UPDATE ON "ban"
FOR EACH ROW
EXECUTE PROCEDURE ban_user(); |
Trigger | TRIGGER02 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Description | Auction Guest tables can only exist for private auctions. | ||||||||||||
CREATE FUNCTION private_auction_guests() RETURNS TRIGGER AS
$BODY$
BEGIN
IF NOT EXISTS(
SELECT *
FROM "auction"
WHERE NEW.auction_id = "auction".id AND "auction".auctionType = 'Private'
) THEN
RAISE EXCEPTION 'Auction is not Private';
END IF;
RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER private_auction_guests
BEFORE INSERT OR UPDATE ON "auction_guest"
FOR EACH ROW
EXECUTE PROCEDURE private_auction_guests();
|
Trigger | TRIGGER05 |
---|---|
Description | A bid can only be placed on a private auction if the user placing it is a guest of that auction. |
CREATE FUNCTION only_guests_can_bid() RETURNS TRIGGER AS
$BODY$
BEGIN
IF (
SELECT auctionType
FROM "auction"
WHERE id = NEW.auction_id
) = 'Private' AND NEW.user_id NOT IN (
SELECT user_id FROM "auction_guest" WHERE auction_id = NEW.auction_id
) THEN
RAISE EXCEPTION 'Bids can only be placed on private auctions by guests of that auction';
END IF;
RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER only_guests_can_bid
BEFORE INSERT OR UPDATE ON "bid"
FOR EACH ROW
EXECUTE PROCEDURE only_guests_can_bid(); |
Trigger | TRIGGER06 |
---|---|
Description | When a BuyerBan or AllBan is created, that user's bids are removed. |
CREATE FUNCTION banned_bids() RETURNS TRIGGER AS
$BODY$
BEGIN
IF NEW.banType = 'BuyerBan' OR NEW.banType = 'AllBan' THEN
DELETE FROM "bid" b
WHERE b.user = NEW.user
END IF;
RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER banned_bids
AFTER INSERT OR UPDATE ON "ban"
FOR EACH ROW
EXECUTE PROCEDURE banned_bids(); |
Trigger | TRIGGER07 |
---|---|
Description | When a user is removed from a private auction's guest list, it's bids are also removed. |
CREATE FUNCTION removed_from_guest_list() RETURNS TRIGGER AS
$BODY$
BEGIN
DELETE FROM "bid" b
WHERE
b.user = OLD.user AND
b.auction = OLD.auction
RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER removed_from_guest_list
AFTER DELETE ON "auction_guest"
FOR EACH ROW
EXECUTE PROCEDURE removed_from_guest_list(); |
Trigger | TRIGGER08 |
---|---|
Description | Keeps TSVECTOR in sync. |
CREATE FUNCTION update_fts() RETURNS TRIGGER AS
$BODY$
DECLARE brand TEXT = (SELECT brand FROM "vehicle" WHERE id = NEW.vehicle_id);
DECLARE model TEXT = (SELECT model FROM "vehicle" WHERE id = NEW.vehicle_id);
BEGIN
IF TG_OP = 'INSERT' THEN
NEW.search = setweight(to_tsvector ('english', NEW.auction_name), 'A') ||
setweight(to_tsvector ('english', brand), 'B') ||
setweight(to_tsvector ('english', model), 'C');
END IF;
IF TG_OP = 'UPDATE' THEN
IF NEW.auction_name <> OLD.auction_name THEN
NEW.search = setweight(to_tsvector ('english', NEW.auction_name), 'A') ||
setweight(to_tsvector ('english', brand), 'B') ||
setweight(to_tsvector ('english', model), 'C');
END IF;
END IF;
RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER update_fts
BEFORE INSERT OR UPDATE ON "auction"
FOR EACH ROW
EXECUTE PROCEDURE update_fts(); |
SQL Reference | New User |
---|---|
Justification | Creation of a user implies user, image and profile_image row insertion |
Isolation Level | Serializable |
BEGIN;
INSERT INTO "user" (firstName,lastName,email,username,password,location,about)
VALUES ($first_name, $last_name, $email, $username, $password, $location, $about);
INSERT INTO "image" (path)
VALUES ($path);
INSERT INTO "profile_image" (user_id,image)
VALUES ($user_id, $image_id);
COMMIT; |
SQL Reference | New Auction |
---|---|
Justification | Creation of an auction implies vehice, image, vehicle_image and auction row insertion |
Isolation Level | Serializable |
BEGIN;
INSERT INTO "vehicle" (owner,brand,model,condition,manufactureYear,horsepower)
VALUES ($user_id, $brand, $model, $condition, $year, $horsepower);
INSERT INTO "image" (path)
VALUES ($path);
INSERT INTO "vehicle_image" (vehicle,image,sequence_number)
VALUES ($vehicle_id, $image_id, $sequence_number);
INSERT INTO "auction" (auction_name,vehicle,startingBid,startingTime,endingTime,auctionType)
VALUES ($auction_name, $vehicle_id, $startingBid, $startingTime, $endingTime, $auctionType)
COMMIT; |
DROP DOMAIN IF EXISTS PASTTIMESTAMP CASCADE;
DROP DOMAIN IF EXISTS FUTURETIMESTAMP CASCADE;
DROP DOMAIN IF EXISTS EURO_T CASCADE;
DROP DOMAIN IF EXISTS EMAIL_T CASCADE;
DROP DOMAIN IF EXISTS VATNUMBER_T CASCADE;
DROP TYPE IF EXISTS CONDITION_T CASCADE;
DROP TYPE IF EXISTS AUCTIONTYPE_T CASCADE;
DROP TYPE IF EXISTS BANTYPE_T CASCADE;
DROP TABLE IF EXISTS "user" CASCADE;
DROP TABLE IF EXISTS "global_mod" CASCADE;
DROP TABLE IF EXISTS "admin" CASCADE;
DROP TABLE IF EXISTS "seller" CASCADE;
DROP TABLE IF EXISTS "vehicle" CASCADE;
DROP TABLE IF EXISTS "auction" CASCADE;
DROP TABLE IF EXISTS "auction_mod" CASCADE;
DROP TABLE IF EXISTS "image" CASCADE;
DROP TABLE IF EXISTS "invoice" CASCADE;
DROP TABLE IF EXISTS "vehicle_image" CASCADE;
DROP TABLE IF EXISTS "auction_guest" CASCADE;
DROP TABLE IF EXISTS "favourite_auction" CASCADE;
DROP TABLE IF EXISTS "comment" CASCADE;
DROP TABLE IF EXISTS "ban" CASCADE;
DROP TABLE IF EXISTS "bid" CASCADE;
CREATE DOMAIN PASTTIMESTAMP AS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP CHECK(VALUE <= CURRENT_TIMESTAMP);
CREATE DOMAIN FUTURETIMESTAMP AS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
CREATE DOMAIN EURO_T AS INTEGER NOT NULL;
CREATE DOMAIN EMAIL_T AS TEXT CHECK(VALUE LIKE '_%@_%.__%');
CREATE DOMAIN VATNUMBER_T AS CHAR(16);
CREATE TYPE CONDITION_T AS ENUM ('Mint', 'Clean', 'Average', 'Rough');
CREATE TYPE AUCTIONTYPE_T AS ENUM ('Public', 'Private');
CREATE TYPE BANTYPE_T AS ENUM ('BuyerBan', 'SellerBan', 'AllBan', 'AuctionBan');
CREATE TABLE "image" (
id SERIAL PRIMARY KEY,
path TEXT NOT NULL
);
CREATE TABLE "user" (
id SERIAL PRIMARY KEY,
firstName TEXT NOT NULL,
lastName TEXT NOT NULL,
email EMAIL_T NOT NULL UNIQUE,
username TEXT NOT NULL UNIQUE,
password TEXT NOT NULL,
location TEXT ,
about TEXT ,
registeredOn PASTTIMESTAMP ,
profileImage INTEGER REFERENCES "image"(id)
);
CREATE TABLE "global_mod" (
id INTEGER PRIMARY KEY REFERENCES "user"(id) ON DELETE CASCADE
);
CREATE TABLE "admin" (
id INTEGER PRIMARY KEY REFERENCES "user"(id) ON DELETE CASCADE
);
CREATE TABLE "seller" (
id INTEGER PRIMARY KEY REFERENCES "user"(id) ON DELETE CASCADE
);
CREATE TABLE "vehicle" (
id SERIAL PRIMARY KEY,
owner INTEGER REFERENCES "user"(id) NOT NULL,
brand TEXT NOT NULL,
model TEXT NOT NULL,
condition CONDITION_T NOT NULL DEFAULT 'Mint',
year INTEGER NOT NULL CHECK(year <= date_part('year', CURRENT_TIMESTAMP)),
horsepower INTEGER NOT NULL CHECK(horsepower >= 0),
description TEXT
);
CREATE TABLE "auction" (
id SERIAL PRIMARY KEY,
auction_name TEXT NOT NULL,
vehicle_id INTEGER NOT NULL REFERENCES "vehicle"(id),
startingBid EURO_T CHECK (startingBid >= 0),
creationTime PASTTIMESTAMP ,
startingTime TIMESTAMP NOT NULL CHECK (startingTime >= creationTime),
endingTime TIMESTAMP NOT NULL CHECK (endingTime >= startingTime + INTERVAL '1 hour'),
auctionType AUCTIONTYPE_T NOT NULL DEFAULT 'Public',
search TSVECTOR
);
CREATE TABLE "auction_mod" (
user_id INTEGER REFERENCES "user"(id) ON DELETE CASCADE,
auction_id INTEGER REFERENCES "auction"(id),
PRIMARY KEY(user_id, auction_id)
);
CREATE TABLE "invoice" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES "user"(id),
createdOn PASTTIMESTAMP ,
vatNumber VATNUMBER_T ,
value EURO_T CHECK(value >= 0),
description TEXT NOT NULL
);
CREATE TABLE "vehicle_image" (
vehicle_id INTEGER NOT NULL REFERENCES "vehicle"(id),
image_id INTEGER NOT NULL REFERENCES "image"(id) ON DELETE CASCADE,
sequence_number INTEGER NOT NULL CHECK(sequence_number >= 0),
PRIMARY KEY(vehicle_id, image_id),
UNIQUE(vehicle_id, sequence_number)
);
CREATE TABLE "auction_guest" (
user_id INTEGER REFERENCES "user"(id),
auction_id INTEGER REFERENCES "auction"(id),
PRIMARY KEY(user_id, auction_id)
);
CREATE TABLE "favourite_auction" (
user_id INTEGER REFERENCES "user"(id),
auction_id INTEGER REFERENCES "auction"(id),
PRIMARY KEY(user_id, auction_id)
);
CREATE TABLE "comment" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES "user"(id),
auction_id INTEGER NOT NULL REFERENCES "auction"(id),
createdOn PASTTIMESTAMP ,
content TEXT NOT NULL
);
CREATE TABLE "ban" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES "user"(id),
createdBy INTEGER NOT NULL REFERENCES "user"(id),
createdOn PASTTIMESTAMP ,
startTime FUTURETIMESTAMP CHECK(startTime >= createdOn),
endTime FUTURETIMESTAMP CHECK(endTime > startTime),
reason TEXT NOT NULL,
banType BANTYPE_T NOT NULL,
auction_id INTEGER REFERENCES "auction"(id)
CONSTRAINT auction_id CHECK ((banType != 'AuctionBan') OR (banType = 'AuctionBan' AND auction_id IS NOT NULL))
);
CREATE TABLE "bid" (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES "user"(id) NOT NULL,
auction_id INTEGER REFERENCES "auction"(id) NOT NULL,
amount EURO_T CHECK (amount > 0),
createdOn PASTTIMESTAMP
);
-- Profile Photos --
INSERT INTO "image" (id,path) VALUES
(1, 'profile_photos/1.png'),
(2, 'profile_photos/1.png'),
(3, 'profile_photos/1.png'),
(4, 'profile_photos/1.png'),
(5, 'profile_photos/1.png'),
(6, 'profile_photos/1.png'),
(7, 'profile_photos/1.png'),
(8, 'profile_photos/1.png'),
(9, 'profile_photos/1.png'),
(10, 'profile_photos/1.png'),
(11, 'profile_photos/1.png'),
(12, 'profile_photos/1.png'),
(13, 'profile_photos/1.png'),
(14, 'profile_photos/1.png'),
(15, 'profile_photos/1.png'),
(16, 'profile_photos/1.png'),
(17, 'profile_photos/1.png'),
(18, 'profile_photos/1.png'),
(19, 'profile_photos/1.png'),
(20, 'profile_photos/1.png');
-- Users --
INSERT INTO "user" (id,profileImage,firstName,lastName,email,username,password,location,about,registeredOn) VALUES
(1,1,'Roth','Hampton','[email protected]','roth_hampton','PXA24YEP6CV','Porto',
'I LOVE CARS and so I decided to build this website so I can share it with everyone else.','2021-03-30 12:38:24'),
(2,2,'Bree','Espinoza','[email protected]','bree_espinoza','ZED49VDV4VT','Muradiye',
'I love BMWs and I cant help myself when it comes to buying them. My girlfriend doesnt really approve of that so I need to sell some of them',
'2021-03-30 12:38:24'),
(3,3,'Tanek','Spence','[email protected]','tanek_spence','DTQ16ULU3HP','Barry',
'Ive been in love with cars ever since I was a 4 year old and now I want to make a living out of it.','2021-03-30 12:38:24'),
(4,4,'Fitzgerald','Cash','[email protected]','cash_fitz','UAU42EDT3XL','Perchtoldsdorf',
'Cars, cars, cars, You gotta love them.','2021-03-30 12:38:24'),
(5,5,'Aimee','Cortez','[email protected]','aimee_cortez','XXX07JUG7BH','Sargodha',
'Life without cars is like Rome without the Pope.','2021-03-30 12:38:24'),
(6,6,'Barclay','Sargent','[email protected]','barclay','KDI43MJE4FP','Maunath Bhanjan',
'Just chilling and buying cars.','2021-03-30 12:38:24'),
(7,7,'Fuller','Beck','[email protected]','fuller_beck','NAQ18MSW3TI','Pekanbaru',
'Just trying to have some fun :)','2021-03-30 12:38:24'),
(8,8,'Ulysses','Bennett','[email protected]','ulysses_bennte','CQW48UUT5TJ','Aylmer',
'Impulsive car buyer.','2021-03-30 12:38:24'),
(9,9,'Ian','Walsh','[email protected]','ian_walsh','LQG38WSJ6NO','Borgomasino',
'Im a Bad Ass.','2021-03-30 12:38:24'),
(10,10,'Valentine','Boyer','[email protected]','valentine_boyer','RIX27PKB7IJ','Sakhalin',
'Hello! Just loving cars.','2021-03-30 12:38:24'),
(11,11,'Ulysses','Hayes','[email protected]','ulysses_hayes','PPY94UIU8YF','Scala Coeli',
'Fast and Furious lover. JUst trying to bring things from the screen to real life.','2021-03-30 12:38:24'),
(12,12,'Moses','Stanton','[email protected]','moses_stanton','NPR54ONU1NS','Tallahassee',
'Im boreeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed','2021-03-30 12:38:24'),
(13,13,'Silas','Olsen','[email protected]','silas_olsen','MCH94KSM4NQ','Pishin Valley',
'what am i doing with my life?','2021-03-30 12:38:24'),
(14,14,'Abra','Carson','[email protected]','abra_carson','EWV73ABO7RD','Belogorsk',
'Fast and furious is the best and you cant change my mind','2021-03-30 12:38:24'),
(15,15,'Montana','Poole','[email protected]','montana','EXV51KVN4UG','Saint-Nazaire',
'just trying to find a nice car for my family','2021-03-30 12:38:24'),
(16,16,'Melvin','Burch','[email protected]','melvin_b','KJV18FNQ2TA','BostaniΓ§i',
'hey everyone. Im new to the car passion thing but i really want to get into business.','2021-03-30 12:38:24'),
(17,17,'Jared','Head','[email protected]','NBU44UNP0BB','head_jared','Provost',
'life is boring but cars are not','2021-03-30 12:38:24'),
(18,18,'Yvonne','Odonnell','[email protected]','odonnel_y','WYQ13QQL6SR','Saint-MΓ©dard-en-Jalles',
'Renaults are the best cars in the world.','2021-03-30 12:38:24'),
(19,19,'Palmer','Maldonado','[email protected]','paler_mal','HTJ05GKL1QF','East Linton',
'Hey hey hey hey hey hey!','2021-03-30 12:38:24'),
(20,20,'Geraldine','Farrell','[email protected]','geraldine','RTV38CTE4GF','Surat',
'wanna see me playing with cars while wearing nothing? come to this link: geraldine.naked.com','2021-03-30 12:38:24');
-- Seller Permissions --
INSERT INTO "seller" (id) VALUES (2),(3),(4),(7);
-- Vehicles --
INSERT INTO "vehicle" (id,owner,brand,model,condition,year,horsepower) VALUES
(1,2,'BMW','1 Series','Mint',2008,150),
(2,2,'BMW','3 Series','Mint',2010,200),
(3,2,'BMW','5 Series','Mint',2009,220),
(4,2,'BMW','7 Series','Mint',2012,250),
(5,2,'Mercedes','Class A','Clean',2015,180),
(6,2,'Mercedes','Class C','Average',2015,240),
(7,3,'Rolls Royce','Ghost','Mint',2016,320),
(8,3,'Rolls Royce','Ghost','Clean',2012,320),
(9,3,'Rolls Royce','Dawn','Average',2016,300),
(10,3,'Rolls Royce','Phantom','Rough',2003,380),
(11,3,'Rolls Royce','Ghost','Clean',2014,320),
(12,3,'Rolls Royce','Ghost','Clean',2014,320),
(13,3,'Rolls Royce','Dawn','Mint',2018,400),
(14,3,'Rolls Royce','Phantom','Average',2010,380),
(15,4,'Ferrari','Spider','Average',2016,6800),
(16,4,'Ford','Mustang','Rough',2008,550),
(17,4,'Jaguar','XE','Clean',2019,450),
(18,4,'Lamborguini','Aventador S','Clean',2020,740),
(19,4,'Porsche','Panamera 4 Executive','Mint',2020,450),
(20,4,'Tesla','S','Mint',2021,700);
-- Auctions --
INSERT INTO "auction" (id,auction_name,vehicle_id,startingBid,creationTime,startingTime,endingTime,auctionType) VALUES
(1,'BMW 1 Series 2008 Good State',1,8000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(2,'BMW 3 Series 2010 Mint',2,10000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(3,'BMW 5 Series Exclusive',3,15000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(4,'BMW 7 Series Great for Sports People',4,20000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(5,'Mercedes A Clean',5,10000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Private'),
(6,'Mercedes C Average',6,10000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Private'),
(7,'Awesome Rolls Royce Ghost 16',7,30000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(8,'Clean RR Ghost 12',8,25000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(9,'RR Dawn 16 Perfect for Families',9,25000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(10,'Old but never out of Style RR Phantom 03',10,20000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(11,'Clean RR Ghost 14',11,43000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(12,'Fantastic RR Ghost 14',12,48000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-05 12:00:00','Public'),
(13,'Mint RR Dawn 18',13,60000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-08 12:00:00','Public'),
(14,'10s Phantom for the fearless',14,35000,'2021-03-30 12:59:24','2021-04-03 12:00:00','2021-04-08 12:00:00','Public'),
(15,'Exclusive Ferrari Spider',15,180000,'2021-03-30 12:59:24','2021-04-04 12:00:00','2021-04-08 12:00:00','Public'),
(16,'CR7 Old Mustang',16,400000,'2021-03-30 12:59:24','2021-04-04 12:00:00','2021-04-08 12:00:00','Public'),
(17,'Roar with your new Jaguar XE',17,240000,'2021-03-30 12:59:24','2021-04-04 12:00:00','2021-04-08 12:00:00','Public'),
(18,'Luxury Aventador S',18,390000,'2021-03-30 12:59:24','2021-04-05 12:00:00','2021-04-08 12:00:00','Public'),
(19,'New Panamera 4 Executive',19,160000,'2021-03-30 12:59:24','2021-04-05 12:00:00','2021-04-08 12:00:00','Public'),
(20,'Brand New Tesla S',20,230000,'2021-03-30 12:59:24','2021-04-05 12:00:00','2021-04-08 12:00:00','Public');
-- User Permissions --
INSERT INTO "global_mod" (id) VALUES (2),(5);
INSERT INTO "auction_mod" (user_id,auction_id) VALUES (3,7),(3,8),(3,9),(3,10),(3,11),(3,12),(3,13),(3,14);
INSERT INTO "auction_mod" (user_id,auction_id) VALUES (4,15),(4,16),(4,17),(4,18),(4,19),(4,20);
INSERT INTO "auction_mod" (user_id,auction_id) VALUES (6,15),(6,16),(6,17);
INSERT INTO "admin" (id) VALUES (1);
-- Car Photos --
INSERT INTO "image" (id,path) VALUES
(21, 'car_photos/1/1.png'), (22, 'car_photos/1/2.png'), (23, 'car_photos/1/3.png'),
(24, 'car_photos/2/1.png'), (25, 'car_photos/2/2.png'),
(26, 'car_photos/3/1.png'),
(27, 'car_photos/4/1.png'), (28, 'car_photos/4/2.png'),
(29, 'car_photos/5/1.png'),
(30, 'car_photos/6/1.png'),
(31, 'car_photos/7/1.png'),
(32, 'car_photos/8/1.png'),
(33, 'car_photos/9/1.png'),
(34, 'car_photos/10/1.png'),
(35, 'car_photos/11/1.png'),
(36, 'car_photos/12/1.png'),
(37, 'car_photos/13/1.png'),
(38, 'car_photos/14/1.png'),
(39, 'car_photos/15/1.png'),
(40, 'car_photos/16/1.png'),
(41, 'car_photos/17/1.png'),
(42, 'car_photos/18/1.png'),
(43, 'car_photos/19/1.png'),
(44, 'car_photos/20/1.png');
INSERT INTO "vehicle_image" (vehicle_id,image_id,sequence_number) VALUES
(1,21,1), (1,22,2), (1,23,3),
(2,24,1),(2,25,2),
(3,26,1),
(4,27,1),(4,28,2),
(5,29,1),
(6,30,1),
(7,31,1),
(8,32,1),
(9,33,1),
(10,34,1),
(11,35,1),
(12,36,1),
(13,37,1),
(14,38,1),
(15,39,1),
(16,40,1),
(17,41,1),
(18,42,1),
(19,43,1),
(20,44,1);
-- Public Auction Guests --
INSERT INTO "auction_guest" (user_id, auction_id) VALUES
(8,5),(9,5),(10,5),(11,5),(12,5),(13,5),
(11,6),(12,6),(13,6),(14,6),(15,6);
-- Favourite Auctions --
INSERT INTO "favourite_auction" (user_id, auction_id) VALUES
(8,1),(8,2),(8,3),(8,4),(8,5),
(9,5),(9,6),(9,7),(9,8),(9,9),
(10,8),(10,9),
(11,6),(11,5),
(12,6),(12,11),(12,19),(12,17),
(13,15),(13,16);
-- Auction Comments --
INSERT INTO "comment" (id,user_id,auction_id,createdOn,content) VALUES
(1,8,1,'2021-03-31 15:27:38','Cant wait to get my hands on this car!'),
(2,9,1,'2021-03-31 17:54:38','Lovely Car! Hope I can get it!'),
(3,10,1,'2021-03-31 19:03:38','I love this BMW. It will be the perfect gift for my daughter.'),
(4,8,2,'2021-03-31 15:27:38','Cant wait to get my hands on this car!'),
(5,8,3,'2021-03-31 15:27:38','Cant wait to get my hands on this car!'),
(6,8,4,'2021-03-31 15:27:38','Cant wait to get my hands on this car!'),
(7,8,5,'2021-03-31 15:27:38','Cant wait to get my hands on this car!'),
(8,8,7,'2021-03-31 15:27:38','Cant wait to get my hands on this car!'),
(9,11,6,'2021-03-31 15:27:38','Thank you for inviting me for this auction. I really want this car!'),
(10,13,6,'2021-03-31 13:27:38','Really looking forward for this auction'),
(11,12,6,'2021-03-31 18:27:38','Great Car and great seller. Cant wait for this awesome auction.');
-- Banned Users --
INSERT INTO "ban" (id,user_id,createdBy,createdOn,startTime,endTime,reason,banType) VALUES
(1, 20, 1, '2021-03-31 15:27:38', '2021-03-31 15:27:38','2050-03-31 15:27:38',
'Is a bot.','AllBan'),
(2, 19, 1, '2021-03-31 15:27:38', '2021-03-31 15:27:38','2050-03-31 15:27:38',
'I dont trust him.','BuyerBan'),
(3, 18, 1, '2021-03-31 15:27:38', '2021-03-31 15:27:38','2050-03-31 15:27:38',
'I dont want him selling his cars in my website','SellerBan');
INSERT INTO "ban" (id,user_id,createdBy,createdOn,startTime,endTime,reason,banType,auction_id) VALUES
(4, 8, 3, '2021-03-31 15:27:38', '2021-03-31 15:27:38','2050-03-31 15:27:38',
'I dont trust him for this auction','AuctionBan',14);
-- Bids --
INSERT INTO "bid" (id,user_id,auction_id,amount,createdOn) VALUES
(1,5,1,8000,'2021-04-01 17:06:32'),
(2,6,1,8300,'2021-04-01 17:20:32'),
(3,7,1,8500,'2021-04-01 17:45:32'),
(4,5,1,8800,'2021-04-01 17:56:32'),
(5,6,2,10000,'2021-04-01 17:06:32'),
(6,8,2,10500,'2021-04-01 17:20:32'),
(7,6,2,11000,'2021-04-01 17:45:32'),
(8,8,3,15000,'2021-04-01 17:56:32'),
(9,5,4,20000,'2021-04-01 17:06:32'),
(10,7,4,21000,'2021-04-01 17:20:32'),
(11,12,5,10000,'2021-04-01 17:45:32'),
(12,15,6,10000,'2021-04-01 17:56:32'),
(13,11,7,30000,'2021-04-01 17:20:32'),
(14,12,8,25000,'2021-04-01 17:45:32'),
(15,13,9,25000,'2021-04-01 17:56:32');
-- Invoices --
INSERT INTO "invoice" (id,user_id,createdOn,vatNumber,value,description) VALUES
(1,2,'2021-02-01 00:00:10','205538451', 500, 'Seller monthly fee'),
(2,2,'2021-03-01 00:00:10','205538451', 500, 'Seller monthly fee'),
(3,2,'2021-04-01 00:00:10','205538451', 500, 'Seller monthly fee'),
(4,3,'2021-04-01 00:00:07','794830202', 500, 'Seller monthly fee'),
(5,4,'2021-04-01 00:00:08','993546321', 500, 'Seller monthly fee'),
(6,7,'2021-04-01 00:00:09','120520673', 500, 'Seller monthly fee');
Changes made to the first submission:
- ...
GROUP2174, 22/04/2021
Diogo Miguel Ferreira Rodrigues, [email protected] (Editor)
JoΓ£o AntΓ³nio Cardoso Vieira e Basto de Sousa, [email protected]
Leonor Martins de Sousa, [email protected]
Rafael Soares Ribeiro, [email protected]