Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

# dependencies
/node_modules

# generated
/public/licenses.json
/.pnp
.pnp.js

Expand Down Expand Up @@ -35,6 +38,7 @@ scripts/*
!scripts/generate-language.ts
!scripts/extract-oracle.ts
!scripts/generate-erd.ts
!scripts/generate-licenses.ts
!scripts/hooks/

data/*
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 2026-06-14 - PostgreSQL engine
You can now choose between SQLite and PostgreSQL in the menu above the schema. PostgreSQL gives proper data types. The editor also gained autocomplete for table and column names.

## 2026-06-14 - Relational algebra mode
You can now answer questions with relational algebra instead of SQL. Use the SQL/RA toggle to switch. Expressions are converted to SQL and run the same way, and the generated SQL is shown for reference.

## 2026-06-14 - More varied people in the database
The database now includes people who are neither students nor teachers. Some solutions that assumed every person is a student or a teacher will no longer be accepted.

## 2026-03-19 - Changelog added
A changelog has been added to the app to keep you updated on new features and bug fixes.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SQL Validator
SQL Validator is a fully client-side web application powered by sql.js. Designed for the database course at Stockholm University, it provides an interface for students to write, format, and run SQL queries directly in their browser without the need for a database server. Results can be compared to expected results based on a question bank, and views can be created and managed using the browser's local storage.
SQL Validator is a fully client-side web application powered by sql.js. It provides an interface for writing, formatting, and running SQL queries directly in the browser without the need for a database server. Results can be compared to expected results based on a question bank, and views can be created and managed using the browser's local storage.

## Features
- **Fully Client-Side Execution**: All SQL validation and execution is performed in the browser using sql.js SQLite.
Expand Down
11 changes: 11 additions & 0 deletions data/oracle-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ export interface OracleQuestion {
* these alternatives are only used for validation.
*/
alternativeQueries?: string[];
/**
* PostgreSQL-specific reference query, using the same placeholder format.
* Used instead of `query` when generating for a PostgreSQL-engine language.
* Only needed when the query differs from the SQLite version (e.g. EXTRACT vs YEAR).
*/
pgQuery?: string;
/**
* PostgreSQL-specific alternative queries.
* Falls back to `alternativeQueries` if not provided.
*/
pgAlternativeQueries?: string[];
}

export interface OracleData {
Expand Down
Binary file modified data/oracle.enc
Binary file not shown.
53 changes: 53 additions & 0 deletions languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ const de: LanguageDefinition = {
"131017-0051",
"131017-0052",
"131017-0053",
"131017-0054",
"131017-0055",
"131017-0056",
"131017-0057",
],
postalCodes: [
"6900",
Expand All @@ -120,6 +124,10 @@ const de: LanguageDefinition = {
"4051",
"4051",
"6001",
"8002",
"6002",
"9001",
"4052",
],
phones: [
"+41 76 123 45 67",
Expand All @@ -143,6 +151,10 @@ const de: LanguageDefinition = {
"+41 78 901 23 45",
"+41 79 012 34 56",
"+41 78 250 28 55",
"+41 76 111 22 33",
"+41 77 222 33 44",
"+41 78 333 44 55",
"+41 79 444 55 66",
],

// ── Data: Courses ────────────────────────────────────────────
Expand Down Expand Up @@ -427,6 +439,47 @@ const de: LanguageDefinition = {
"Warnung: Diese Speicherdatei wurde in einer anderen Sprache erstellt ({{fileLang}}). Der Import kann zu Problemen führen..",
viewLabel: "View",
changelog: "Änderungsprotokoll",
modeSQL: "SQL",
modeRA: "Relationale Algebra",
generatedSQL: "Generiertes SQL",
raParseError: "Fehler in relationaler Algebra: {{message}}",
engineLoadFailed: "Die PostgreSQL-Engine konnte nicht geladen werden. Wechsel zurück zu SQLite.",
raPlaceholder: "-- Schreibe einen Ausdruck der relationalen Algebra\n-- Klicke auf 'RA-Referenz' für die Syntax",
raReference: "Referenz relationale Algebra",
raUnaryOps: "Unäre Operatoren",
raBinaryOps: "Binäre Operatoren",
raColOp: "Operator",
raColSyntax: "Syntax",
raColDesc: "Beschreibung",
raDescSelection: "Selektion — Zeilen filtern",
raDescProjection: "Projektion — Spalten auswählen",
raDescRename: "Spalten umbenennen",
raDescGroup: "Gruppierung mit Aggregaten",
raDescSort: "Sortierung",
raDescDistinct: "Duplikate entfernen",
raDescCross: "Kreuzprodukt",
raDescNatJoin: "Natürlicher Join",
raDescThetaJoin: "Theta-Join (bedingt)",
raDescUnion: "Vereinigung",
raDescIntersect: "Schnittmenge",
raDescMinus: "Differenz",
raDescDivide: "Division",
raNotation: "Notationsstile",
raNoteBrackets: "— eckige Klammern",
raNoteCurly: "— geschweifte Klammern",
raNoteLaTeX: "— LaTeX-Stil",
raNoteImplicit: "— ohne Klammern",
raNoteChain: "— Verkettung ohne ()",
raAssignment: "Zuweisung",
raNoteAssignment: "Die letzte Zuweisung wird automatisch zurückgegeben",
raConditions: "Bedingungen",
raNoteComparison: "Vergleichsoperatoren: = <> < > <= >=",
editorSettings: "Editor-Einstellungen",
settingAutocomplete: "Autovervollständigung",
settingLineNumbers: "Zeilennummern",
settingHighlightActiveLine: "Aktive Zeile hervorheben",
sqlReferencePostgresql: "PostgreSQL-Dokumentation",
engineMismatchWarning: "Warnung: Diese Speicherdatei wurde mit einer anderen Datenbank-Engine erstellt ({{fileEngine}}). Der Import kann zu Problemen führen.",
},
};

Expand Down
53 changes: 53 additions & 0 deletions languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ const en: LanguageDefinition = {
"EN-019",
"EN-020",
"EN-021",
"EN-022",
"EN-023",
"EN-024",
"EN-025",
],
postalCodes: [
"GU1 1AA",
Expand All @@ -120,6 +124,10 @@ const en: LanguageDefinition = {
"BA4 1AS",
"BA5 2AT",
"CB4 3AU",
"YO5 4AV",
"CB6 5AW",
"OX5 6AX",
"BA6 7AY",
],
phones: [
"01234567890",
Expand All @@ -143,6 +151,10 @@ const en: LanguageDefinition = {
"01234567908",
"01234567909",
"01234567910",
"01234567911",
"01234567912",
"01234567913",
"01234567914",
],

// ── Data: Courses ────────────────────────────────────────────
Expand Down Expand Up @@ -427,6 +439,47 @@ const en: LanguageDefinition = {
"Warning: This save file was created with a different language ({{fileLang}}). Importing may cause issues.",
viewLabel: "View",
changelog: "Changelog",
modeSQL: "SQL",
modeRA: "Relational Algebra",
generatedSQL: "Generated SQL",
raParseError: "Relational algebra error: {{message}}",
engineLoadFailed: "Failed to load the PostgreSQL engine. Falling back to SQLite.",
raPlaceholder: "-- Write a relational algebra expression\n-- Click 'RA Reference' for syntax",
raReference: "Relational Algebra Reference",
raUnaryOps: "Unary Operators",
raBinaryOps: "Binary Operators",
raColOp: "Operator",
raColSyntax: "Syntax",
raColDesc: "Description",
raDescSelection: "Selection — filter rows",
raDescProjection: "Projection — pick columns",
raDescRename: "Rename columns",
raDescGroup: "Grouping with aggregates",
raDescSort: "Sort",
raDescDistinct: "Remove duplicates",
raDescCross: "Cross product",
raDescNatJoin: "Natural join",
raDescThetaJoin: "Theta join (conditional)",
raDescUnion: "Union",
raDescIntersect: "Intersection",
raDescMinus: "Difference",
raDescDivide: "Division",
raNotation: "Notation Styles",
raNoteBrackets: "— square brackets",
raNoteCurly: "— curly braces",
raNoteLaTeX: "— LaTeX style",
raNoteImplicit: "— no brackets",
raNoteChain: "— chaining without ()",
raAssignment: "Assignment",
raNoteAssignment: "Last assignment is returned automatically",
raConditions: "Conditions",
raNoteComparison: "Comparison operators: = <> < > <= >=",
editorSettings: "Editor Settings",
settingAutocomplete: "Autocomplete",
settingLineNumbers: "Line Numbers",
settingHighlightActiveLine: "Highlight Active Line",
sqlReferencePostgresql: "PostgreSQL Documentation",
engineMismatchWarning: "Warning: This save file was created with a different database engine ({{fileEngine}}). Importing may cause issues.",
},
};

Expand Down
11 changes: 11 additions & 0 deletions languages/sv-pg.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { LanguageDefinition } from "./types";
import sv from "./sv";

const svPg: LanguageDefinition = {
...sv,
code: "sv-pg",
displayName: "Svenska (PostgreSQL)",
engine: "postgresql",
};

export default svPg;
53 changes: 53 additions & 0 deletions languages/sv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ const sv: LanguageDefinition = {
"131017-0051",
"131017-0052",
"131017-0053",
"131017-0054",
"131017-0055",
"131017-0056",
"131017-0057",
],
postalCodes: [
"19122",
Expand All @@ -120,6 +124,10 @@ const sv: LanguageDefinition = {
"16966",
"16966",
"18753",
"16955",
"17012",
"18760",
"19044",
],
phones: [
"151576",
Expand All @@ -143,6 +151,10 @@ const sv: LanguageDefinition = {
"449867",
"665844",
"770691",
"112233",
"445566",
"778899",
"223344",
],

// ── Data: Courses ────────────────────────────────────────────
Expand Down Expand Up @@ -427,6 +439,47 @@ const sv: LanguageDefinition = {
"Warning: This save file was created with a different language ({{fileLang}}). Importing may cause issues.",
viewLabel: "View",
changelog: "Changelog",
modeSQL: "SQL",
modeRA: "Relationsalgebra",
generatedSQL: "Genererad SQL",
raParseError: "Relationsalgebra-fel: {{message}}",
engineLoadFailed: "Kunde inte ladda PostgreSQL-motorn. Återgår till SQLite.",
raPlaceholder: "-- Skriv ett relationsalgebrauttryck\n-- Klicka på 'RA-referens' för syntax",
raReference: "Relationsalgebrareferens",
raUnaryOps: "Unära operatorer",
raBinaryOps: "Binära operatorer",
raColOp: "Operator",
raColSyntax: "Syntax",
raColDesc: "Beskrivning",
raDescSelection: "Selektion — filtrera rader",
raDescProjection: "Projektion — välj kolumner",
raDescRename: "Namnbyte — byt namn på kolumner",
raDescGroup: "Gruppering med aggregat",
raDescSort: "Sortering",
raDescDistinct: "Ta bort dubbletter",
raDescCross: "Korsprodukt",
raDescNatJoin: "Naturlig join",
raDescThetaJoin: "Theta-join (villkorlig)",
raDescUnion: "Union",
raDescIntersect: "Snitt",
raDescMinus: "Differens",
raDescDivide: "Division",
raNotation: "Notationsalternativ",
raNoteBrackets: "— hakparenteser",
raNoteCurly: "— klammerparenteser",
raNoteLaTeX: "— LaTeX-stil",
raNoteImplicit: "— utan parenteser",
raNoteChain: "— kedjning utan ()",
raAssignment: "Tilldelning",
raNoteAssignment: "Sista tilldelningen returneras automatiskt",
raConditions: "Villkor",
raNoteComparison: "Jämförelseoperatorer: = <> < > <= >=",
editorSettings: "Editorinställningar",
settingAutocomplete: "Autokomplettering",
settingLineNumbers: "Radnummer",
settingHighlightActiveLine: "Markera aktiv rad",
sqlReferencePostgresql: "PostgreSQL-dokumentation",
engineMismatchWarning: "Varning: Denna sparfil skapades med en annan databasmotor ({{fileEngine}}). Import kan orsaka problem.",
},
};

Expand Down
2 changes: 2 additions & 0 deletions languages/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export interface LanguageDefinition {
code: string;
/** Display name in the language itself, e.g. "Svenska", "English" */
displayName: string;
/** Database engine: "sqlite" (default) or "postgresql" */
engine?: "sqlite" | "postgresql";

// ── Data: Names ──────────────────────────────────────────────
/** First names pool (min 15, indexed by canonical person slot) */
Expand Down
Loading
Loading