clone basic database structure from zhquiz

This commit is contained in:
polv committed 2021-10-05 23:03:29 +07:00
1 parent 6be2365fc6
commit 11d44ccfd3
18 files changed
+1594

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS pgroonga;
CREATE EXTENSION IF NOT EXISTS "postgres-json-schema";
+3
View File
@@ -0,0 +1,3 @@
CREATE FUNCTION array_distinct(anyarray) RETURNS anyarray AS $f$
SELECT array_agg(DISTINCT x) FROM unnest($1) t(x);
$f$ LANGUAGE SQL IMMUTABLE;
+22
View File
@@ -0,0 +1,22 @@
CREATE TABLE "user" (
"id" UUID NOT NULL PRIMARY KEY DEFAULT uuid_generate_v4(),
"createdAt" TIMESTAMPTZ DEFAULT now(),
"updatedAt" TIMESTAMPTZ DEFAULT now(),
"identifier" TEXT UNIQUE NOT NULL,
"wk_hash" TEXT NOT NULL,
"level.min" INT DEFAULT 1,
"level.max" INT DEFAULT 3,
"level.vocabulary.showing" TEXT[],
"quiz.settings" JSONB
);
CREATE TRIGGER "t_user_updatedAt"
BEFORE UPDATE ON "user"
FOR EACH ROW
EXECUTE PROCEDURE "f_updatedAt"();
CREATE INDEX "idx_user_updatedAt" ON "user" ("updatedAt");
CREATE INDEX "idx_user_identifier" ON "user" ("identifier");
CREATE INDEX "idx_user_wk_hash" ON "user" ("wk_hash");
INSERT INTO "user" ("id", "identifier") VALUES (uuid_nil(), '');
+44
View File
@@ -0,0 +1,44 @@
CREATE TABLE "quiz" (
"id" UUID NOT NULL PRIMARY KEY DEFAULT uuid_generate_v4(),
"createdAt" TIMESTAMPTZ DEFAULT now(),
"updatedAt" TIMESTAMPTZ DEFAULT now(),
"userId" UUID NOT NULL REFERENCES "user"("id") ON DELETE CASCADE,
"entry" TEXT NOT NULL,
"type" TEXT NOT NULL,
"direction" TEXT NOT NULL,
"front" TEXT NOT NULL DEFAULT '',
"back" TEXT NOT NULL DEFAULT '',
"hint" TEXT NOT NULL DEFAULT '',
"mnemonic" TEXT NOT NULL DEFAULT '',
"srsLevel" INT,
"nextReview" TIMESTAMPTZ,
"lastRight" TIMESTAMPTZ,
"lastWrong" TIMESTAMPTZ,
"maxRight" INT,
"maxWrong" INT,
"rightStreak" INT,
"wrongStreak" INT
);
CREATE TRIGGER "t_quiz_updatedAt"
BEFORE UPDATE ON "quiz"
FOR EACH ROW
EXECUTE PROCEDURE "f_updatedAt"();
CREATE UNIQUE INDEX "idx_u_quiz" ON "quiz" ("userId", "entry", "type", "direction");
CREATE INDEX "idx_quiz_q" ON "quiz"
USING pgroonga ("front", "back", "hint", "mnemonic")
WITH (plugins='token_filters/stem', token_filters='TokenFilterStem');
CREATE INDEX "idx_quiz_entry" ON "quiz" ("entry");
CREATE INDEX "idx_quiz_updatedAt" ON "quiz" ("updatedAt");
CREATE INDEX "idx_quiz_userId" ON "quiz" ("userId");
CREATE INDEX "idx_quiz_srsLevel" ON "quiz" ("srsLevel");
CREATE INDEX "idx_quiz_nextReview" ON "quiz" ("nextReview");
CREATE INDEX "idx_quiz_lastRight" ON "quiz" ("lastRight");
CREATE INDEX "idx_quiz_lastWrong" ON "quiz" ("lastWrong");
CREATE INDEX "idx_quiz_maxRight" ON "quiz" ("maxRight");
CREATE INDEX "idx_quiz_maxWrong" ON "quiz" ("maxWrong");
CREATE INDEX "idx_quiz_rightStreak" ON "quiz" ("rightStreak");
CREATE INDEX "idx_quiz_wrongStreak" ON "quiz" ("wrongStreak");
+48
View File
@@ -0,0 +1,48 @@
CREATE OR REPLACE FUNCTION unwrap_entries (JSONB) RETURNS TEXT[] AS
$func$
DECLARE
it JSONB;
"out" TEXT[] := '{}'::text[];
BEGIN
FOR it IN (SELECT * FROM jsonb_array_elements($1))
LOOP
"out" := "out"||(it ->> 'entry');
END LOOP;
RETURN "out";
END;
$func$ LANGUAGE plpgsql IMMUTABLE;
CREATE TABLE "library" (
"id" UUID NOT NULL PRIMARY KEY DEFAULT uuid_generate_v4(),
"createdAt" TIMESTAMPTZ DEFAULT now(),
"updatedAt" TIMESTAMPTZ DEFAULT now(),
"userId" UUID NOT NULL DEFAULT uuid_nil() REFERENCES "user"("id") ON DELETE CASCADE,
"isShared" BOOLEAN,
"type" TEXT NOT NULL,
"entries" JSONB NOT NULL CHECK ("entries" -> 0 -> 'entry' IS NOT NULL),
"entry" TEXT[] GENERATED ALWAYS AS (unwrap_entries("entries")) STORED,
"title" TEXT NOT NULL,
"description" TEXT NOT NULL DEFAULT '',
"tag" TEXT[] NOT NULL DEFAULT '{}'::TEXT[]
);
CREATE TRIGGER "t_library_updatedAt"
BEFORE UPDATE ON "library"
FOR EACH ROW
EXECUTE PROCEDURE "f_updatedAt"();
CREATE INDEX "idx_library_updatedAt" ON "library" ("updatedAt");
CREATE INDEX "idx_library_userId" ON "library" ("userId");
CREATE INDEX "idx_library_isShared" ON "library" ("isShared");
CREATE INDEX "idx_library_type" ON "library" ("type");
CREATE INDEX "idx_library_entry" ON "library"
USING pgroonga("entry");
CREATE INDEX "idx_library_title_description" ON "library"
USING pgroonga(
"title",
"description"
)
WITH (plugins='token_filters/stem', token_filters='TokenFilterStem');
CREATE INDEX "idx_library_tag" ON "library" USING pgroonga ("tag");
+18
View File
@@ -0,0 +1,18 @@
CREATE TABLE "quiz_preset" (
"id" UUID NOT NULL PRIMARY KEY DEFAULT uuid_generate_v4(),
"createdAt" TIMESTAMPTZ DEFAULT now(),
"updatedAt" TIMESTAMPTZ DEFAULT now(),
"userId" UUID NOT NULL REFERENCES "user"("id") ON DELETE CASCADE,
"name" TEXT NOT NULL,
"settings" JSONB NOT NULL
);
CREATE TRIGGER "t_quiz_preset_updatedAt"
BEFORE UPDATE ON "quiz_preset"
FOR EACH ROW
EXECUTE PROCEDURE "f_updatedAt"();
CREATE INDEX "idx_quiz_preset_updatedAt" ON "quiz_preset" ("updatedAt");
CREATE INDEX "idx_quiz_preset_userId" ON "quiz_preset" ("userId");
CREATE INDEX "idx_quiz_preset_name" ON "quiz_preset"
USING pgroonga ("name");
+26
View File
@@ -0,0 +1,26 @@
CREATE TABLE radical (
"entry" TEXT NOT NULL PRIMARY KEY,
"sub" TEXT[] NOT NULL,
"sup" TEXT[] NOT NULL,
"var" TEXT[] NOT NULL
);
CREATE INDEX idx_radical_search ON radical
USING pgroonga ("entry", "sub", "sup", "var")
WITH (tokenizer='TokenUnigram');
CREATE INDEX idx_radical_synonyms ON radical
USING pgroonga ("entry" pgroonga_text_term_search_ops_v2)
WITH (tokenizer='TokenUnigram');
CREATE OR REPLACE FUNCTION character_expand (TEXT) RETURNS TEXT AS
$func$
DECLARE
exp TEXT := pgroonga_query_expand('radical',
'entry',
'var',
$1);
BEGIN
RETURN $1||' OR '||exp;
END;
$func$ LANGUAGE plpgsql IMMUTABLE;
+12
View File
@@ -0,0 +1,12 @@
-- cat ./node_modules/connect-pg-simple/table.sql
CREATE TABLE "session" (
"sid" varchar NOT NULL COLLATE "default",
"sess" json NOT NULL,
"expire" timestamp(6) NOT NULL
)
WITH (OIDS=FALSE);
ALTER TABLE "session" ADD CONSTRAINT "session_pkey" PRIMARY KEY ("sid") NOT DEFERRABLE INITIALLY IMMEDIATE;
CREATE INDEX "IDX_session_expire" ON "session" ("expire");
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
pg_ctl -o "-c listen_addresses='localhost'" -w restart
cd /app
if [[ -d "./lib" ]]; then
node ./lib/init.js
else
yarn ts ./src/init.ts
fi