Compare commits
No commits in common. "3530b4d140c877a0288c9ed5bcec1edc3573b723" and "c591c6431bef29541f4f90a060cbaae0ef474c4b" have entirely different histories.
3530b4d140
...
c591c6431b
12 changed files with 116 additions and 270 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -24,6 +24,3 @@ __MACOSX
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode
|
.vscode
|
||||||
krusty.sqlite3
|
krusty.sqlite3
|
||||||
|
|
||||||
*.sqlite3
|
|
||||||
*.db
|
|
||||||
|
|
88
app/Migrations/0010-tables.sql
Normal file
88
app/Migrations/0010-tables.sql
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS Customers (
|
||||||
|
CustomerID int PRIMARY KEY,
|
||||||
|
Name varchar(100),
|
||||||
|
Address varchar(255)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS Products (
|
||||||
|
ProductID int PRIMARY KEY,
|
||||||
|
Name varchar(100)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS Recipes (
|
||||||
|
RecipeName varchat(100),
|
||||||
|
RecipeYear Year,
|
||||||
|
ingrediences int,
|
||||||
|
ProductID int,
|
||||||
|
PRIMARY KEY (RecipeName, RecipeYear),
|
||||||
|
FOREIGN KEY (ingrediences) REFERENCES ingredience(IngredienceID),
|
||||||
|
FOREIGN KEY (ProductID) REFERENCES Products(ProductID)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ingredience (
|
||||||
|
IngredienceID int PRIMARY KEY,
|
||||||
|
RawMaterialName varchar(100),
|
||||||
|
amount int,
|
||||||
|
unit varchar(50),
|
||||||
|
FOREIGN KEY (RawMaterialName) REFERENCES RawMaterials(RawMaterialName)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS RawMaterials (
|
||||||
|
RawMaterialName varchar(100) PRIMARY KEY,
|
||||||
|
Quantity int,
|
||||||
|
LastDeliveryDateTime datetime
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS PalletsProduced (
|
||||||
|
PalletID int PRIMARY KEY,
|
||||||
|
ProductID int,
|
||||||
|
ProductionDateTime datetime,
|
||||||
|
FOREIGN KEY (ProductID) REFERENCES Products (ProductID)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS PalletsDelivered (
|
||||||
|
DeliveredID int PRIMARY KEY,
|
||||||
|
PalletID int,
|
||||||
|
DeliveryDateTime datetime,
|
||||||
|
FOREIGN KEY (PalletID) REFERENCES PalletsProduced (PalletID),
|
||||||
|
FOREIGN KEY (DeliveredID) REFERENCES Truck (Pallet)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS Truck (
|
||||||
|
truckId int PRIMARY KEY,
|
||||||
|
capacity int,
|
||||||
|
Pallet int
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS loadingBill (
|
||||||
|
LoadingbillID int PRIMARY KEY,
|
||||||
|
adress varchar(100),
|
||||||
|
customer varchar(100),
|
||||||
|
truckID int,
|
||||||
|
FOREIGN KEY (truckID) REFERENCES Truck (truckId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS Orders (
|
||||||
|
OrderID int PRIMARY KEY,
|
||||||
|
CustomerID int,
|
||||||
|
ProductID int,
|
||||||
|
Quantity int,
|
||||||
|
OrderDateTime datetime,
|
||||||
|
FOREIGN KEY (CustomerID) REFERENCES Customers (CustomerID),
|
||||||
|
FOREIGN KEY (ProductID) REFERENCES Products (ProductID)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS BlockedProducts (
|
||||||
|
BlockedProductID int PRIMARY KEY,
|
||||||
|
ProductID int,
|
||||||
|
BlockedDateTime datetime,
|
||||||
|
FOREIGN KEY (ProductID) REFERENCES Products (ProductID)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS PalletTraceability (
|
||||||
|
TraceID int PRIMARY KEY,
|
||||||
|
location varchar(100),
|
||||||
|
locationdate datetime,
|
||||||
|
PalletID int,
|
||||||
|
FOREIGN KEY (PalletID) REFERENCES PalletsProduced (PalletID)
|
||||||
|
);
|
4
app/Migrations/0020-data.sql
Normal file
4
app/Migrations/0020-data.sql
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
-- Inserts here
|
||||||
|
INSERT INTO Customers (CustomerID, Name, Address) VALUES
|
||||||
|
(1, 'John Doe', '123 Main St'),
|
||||||
|
(2, 'Jane Smith', '456 Elm St');
|
|
@ -1,83 +0,0 @@
|
||||||
--------------------------------------------
|
|
||||||
-- Recipe/Cookie related tables
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
-- Our known customers, may need more fields
|
|
||||||
CREATE TABLE IF NOT EXISTS customers (
|
|
||||||
customer_id int PRIMARY KEY,
|
|
||||||
customer_name varchar(100),
|
|
||||||
customer_address varchar(255)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Orders from customers.
|
|
||||||
-- Keep in mind that the delivery_date may be NULL
|
|
||||||
CREATE TABLE IF NOT EXISTS orders (
|
|
||||||
order_id int PRIMARY KEY,
|
|
||||||
customer_id int,
|
|
||||||
order_date date DEFAULT NOW,
|
|
||||||
delivery_date date, -- Set when the order hits the truck
|
|
||||||
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
--------------------------------------------
|
|
||||||
-- Recipe/Cookie related tables
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
-- Recipes for all the cookies (essentially a list of cookies)
|
|
||||||
CREATE TABLE IF NOT EXISTS recipes (
|
|
||||||
recipe_id int PRIMARY KEY,
|
|
||||||
recipe_name varchar(100) -- Cookie name
|
|
||||||
);
|
|
||||||
|
|
||||||
-- "The company has a raw materials warehouse in which
|
|
||||||
-- all ingredients used in their production are stored."
|
|
||||||
|
|
||||||
-- Describes ingredients and stock.
|
|
||||||
-- Each ingredient has 'amount' of 'unit' in stock
|
|
||||||
CREATE TABLE IF NOT EXISTS ingredients (
|
|
||||||
ingredient_id int PRIMARY KEY,
|
|
||||||
ingredient_name varchar(100),
|
|
||||||
amount int,
|
|
||||||
unit varchar(50)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Describes what ingredients goes into what recipe
|
|
||||||
-- Each recipe requires 'amount' of 'ingredient'
|
|
||||||
CREATE TABLE IF NOT EXISTS recipe_contents (
|
|
||||||
recipe_id int,
|
|
||||||
ingredient_id int,
|
|
||||||
amount int,
|
|
||||||
PRIMARY KEY (recipe_id, ingredient_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
--------------------------------------------
|
|
||||||
-- Pallet related tables
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
-- Pallets are used to store cookies for delivery
|
|
||||||
CREATE TABLE IF NOT EXISTS pallets (
|
|
||||||
pallet_id int PRIMARY KEY,
|
|
||||||
recipe_id int,
|
|
||||||
order_id int,
|
|
||||||
FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id),
|
|
||||||
FOREIGN KEY (order_id) REFERENCES Orders(order_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- What does the pallet contain?
|
|
||||||
CREATE TABLE IF NOT EXISTS pallet_contents (
|
|
||||||
pallet_id int,
|
|
||||||
ingredient_id int,
|
|
||||||
amount int,
|
|
||||||
PRIMARY KEY (pallet_id, ingredient_id),
|
|
||||||
FOREIGN KEY (pallet_id) REFERENCES pallets(pallet_id),
|
|
||||||
FOREIGN KEY (ingredient_id) REFERENCES ingredients(ingredient_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Has an order been delivered?
|
|
||||||
-- When the truck is loaded, a delivery is considered done
|
|
||||||
CREATE TABLE IF NOT EXISTS delivery_bill (
|
|
||||||
delivery_id int PRIMARY KEY,
|
|
||||||
order_id int,
|
|
||||||
delivery_date date DEFAULT NOW,
|
|
||||||
FOREIGN KEY (order_id) REFERENCES Orders(order_id)
|
|
||||||
);
|
|
|
@ -1,22 +0,0 @@
|
||||||
-- Inserts here
|
|
||||||
INSERT OR IGNORE INTO
|
|
||||||
customers (customer_id, customer_name, customer_address)
|
|
||||||
VALUES
|
|
||||||
(1, 'Bjudkakor AB', 'Ystad'),
|
|
||||||
(2, 'Finkakor AB', 'Helsingborg'),
|
|
||||||
(3, 'Gästkakor AB', 'Hässleholm'),
|
|
||||||
(4, 'Kaffebröd AB', 'Landskrona'),
|
|
||||||
(5, 'Kalaskakor AB', 'Trelleborg'),
|
|
||||||
(6, 'Partykakor AB', 'Kristianstad'),
|
|
||||||
(7, 'Skånekakor AB', 'Perstorp'),
|
|
||||||
(8, 'Småbröd AB', 'Malmö');
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
recipes (recipe_name)
|
|
||||||
VALUES
|
|
||||||
('Nut ring'),
|
|
||||||
('Nut cookie'),
|
|
||||||
('Amneris'),
|
|
||||||
('Tango'),
|
|
||||||
('Almond delight'),
|
|
||||||
('Berliner');
|
|
|
@ -18,8 +18,8 @@ repositories {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
|
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
|
||||||
testImplementation("org.skyscreamer:jsonassert:1.5.0") // For JSON assertions in tests.
|
// testImplementation("org.skyscreamer:jsonassert:1.5.0") // For JSON assertions in tests.
|
||||||
testImplementation("com.mashape.unirest:unirest-java:1.4.9") // For HTTP requests in tests.
|
// testImplementation("com.mashape.unirest:unirest-java:1.4.9") // For HTTP requests in tests.
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.2")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.2")
|
||||||
|
|
||||||
// implementation("com.google.guava:guava:33.1.0-jre") // Currently not used.
|
// implementation("com.google.guava:guava:33.1.0-jre") // Currently not used.
|
||||||
|
|
|
@ -8,29 +8,21 @@ import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
import java.io.BufferedReader;
|
||||||
// Likely dependencies for general operations
|
// Likely dependencies for general operations
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.ResultSet;
|
import java.io.FileReader;
|
||||||
import java.util.StringJoiner;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class Database {
|
public class Database {
|
||||||
// Here, we use an in-memory database. This string could be changed to
|
// Here, we use an in-memory database. This string could be changed to
|
||||||
// "jdbc:sqlite:<filename>.sqlite3" to use a file-based database instead.
|
// "jdbc:sqlite:<filename>.sqlite3" to use a file-based database instead.
|
||||||
// Nore that ":memory:" is an **SQLite specific** magic string that tells the
|
// Nore that ":memory:" is an **SQLite specific** magic string that tells the
|
||||||
// underlying SQLite engine to store the database in memory.
|
// underlying SQLite engine to store the database in memory.
|
||||||
// private static final String jdbcString = "jdbc:sqlite::memory:";
|
private static final String jdbcString = "jdbc:sqlite::memory:";
|
||||||
private static final String jdbcString = "jdbc:sqlite:krusty.db";
|
|
||||||
private Connection conn = null;
|
private Connection conn = null;
|
||||||
|
|
||||||
public String getCustomers(Request req, Response res) {
|
public String getCustomers(Request req, Response res) {
|
||||||
String result = selectQuery("customers", "customers", "customer_name", "customer_address");
|
return "{}";
|
||||||
result = result.replaceAll("customer_name", "name");
|
|
||||||
result = result.replaceAll("customer_address", "address");
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRawMaterials(Request req, Response res) {
|
public String getRawMaterials(Request req, Response res) {
|
||||||
|
@ -38,8 +30,7 @@ public class Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCookies(Request req, Response res) {
|
public String getCookies(Request req, Response res) {
|
||||||
String result = selectQuery("recipes", "cookies", "recipe_name");
|
return "{\"cookies\":[]}";
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRecipes(Request req, Response res) {
|
public String getRecipes(Request req, Response res) {
|
||||||
|
@ -69,64 +60,30 @@ public class Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects columns from a table and returns the result as a JSON string.
|
|
||||||
* Does _absolutely no_ query sanitization, so be careful with user input.
|
|
||||||
*/
|
|
||||||
private String selectQuery(String table, String jsonName, String... columns) {
|
|
||||||
String jsonResult = "{}"; // Valid json to return if fail
|
|
||||||
|
|
||||||
try {
|
|
||||||
Statement stmt = this.conn.createStatement();
|
|
||||||
StringBuilder query = new StringBuilder("SELECT ");
|
|
||||||
|
|
||||||
StringJoiner args = new StringJoiner(", ");
|
|
||||||
for (String column : columns) {
|
|
||||||
args.add(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
query.append(args.toString());
|
|
||||||
query.append(" FROM " + table + ";");
|
|
||||||
|
|
||||||
/* Sanitization is for cowards */
|
|
||||||
|
|
||||||
ResultSet result = stmt.executeQuery(query.toString());
|
|
||||||
jsonResult = Jsonizer.toJson(result, jsonName);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
System.out.printf("Error executing query: \n%s", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The script location is relative to the gradle
|
// The script location is relative to the gradle
|
||||||
// build script ("build.gradle.kts", in this case).
|
// build script ("build.gradle.kts", in this case).
|
||||||
/** Reads an sql script into the database */
|
/** Reads an sql script into the database */
|
||||||
public void migrateScript(String filename) throws IOException, SQLException {
|
public void migrateScript(String filename) throws IOException, SQLException {
|
||||||
try (Stream<String> lines = Files.lines(Paths.get(filename))) {
|
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
|
||||||
|
StringBuilder scriptBuilder = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
|
||||||
// Combine into one big string, with all comments and empty lines removed.
|
// Read the script file line by line
|
||||||
String[] statements = lines.filter(line -> !line.startsWith("--") && !line.isBlank())
|
while ((line = reader.readLine()) != null) {
|
||||||
.map(line -> line.replaceAll("--.*", "").replaceAll("\\s+", " ").trim())
|
scriptBuilder.append(line).append("\n");
|
||||||
.collect(Collectors.joining("\n")).split(";");
|
}
|
||||||
|
String script = scriptBuilder.toString().trim();
|
||||||
|
|
||||||
for (String query : statements) {
|
// Execute the script
|
||||||
try (Statement statement = conn.createStatement()) {
|
try (Statement statement = conn.createStatement()) {
|
||||||
statement.execute(query);
|
statement.execute(script);
|
||||||
statement.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
System.err.println("Error executing script: " + e.getMessage());
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
System.out.println(String.format("Executed script %s", filename));
|
System.out.println(String.format("Executed script %s", filename));
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Error reading script file: " + e.getMessage());
|
System.err.println("Error reading script file: " + e.getMessage());
|
||||||
throw e;
|
throw e;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
String prepend = String.format("Error executing script: %s", filename);
|
System.err.println("Error executing script: " + e.getMessage());
|
||||||
System.err.println(prepend + e.getMessage());
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
package krusty;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class DefaultRecipes {
|
|
||||||
public static List<Recipe> recipes = Arrays.asList(
|
|
||||||
new Recipe("Nut ring",
|
|
||||||
new Ingredient[] {
|
|
||||||
new Ingredient("Flour", 450, "g"),
|
|
||||||
new Ingredient("Butter", 450, "g"),
|
|
||||||
new Ingredient("Icing sugar", 190, "g"),
|
|
||||||
new Ingredient("Roasted, chopped nuts", 225, "g")
|
|
||||||
}),
|
|
||||||
new Recipe("Nut cookie",
|
|
||||||
new Ingredient[] {
|
|
||||||
new Ingredient("Fine-ground nuts", 750, "g"),
|
|
||||||
new Ingredient("Ground, roasted nuts", 625, "g"),
|
|
||||||
new Ingredient("Bread crumbs", 125, "g"),
|
|
||||||
new Ingredient("Sugar", 375, "g"),
|
|
||||||
new Ingredient("Egg Whites", 350, "ml"),
|
|
||||||
new Ingredient("Chocolate", 50, "g")
|
|
||||||
}),
|
|
||||||
new Recipe("Amneris",
|
|
||||||
new Ingredient[] {
|
|
||||||
new Ingredient("Marzipan", 750, "g"),
|
|
||||||
new Ingredient("Butter", 250, "g"),
|
|
||||||
new Ingredient("Eggs", 250, "g"),
|
|
||||||
new Ingredient("Potato starch", 25, "g"),
|
|
||||||
new Ingredient("Wheat flour", 25, "g")
|
|
||||||
}),
|
|
||||||
new Recipe("Tango",
|
|
||||||
new Ingredient[] {
|
|
||||||
new Ingredient("Butter", 200, "g"),
|
|
||||||
new Ingredient("Sugar", 250, "g"),
|
|
||||||
new Ingredient("Flour", 300, "g"),
|
|
||||||
new Ingredient("Sodium bicarbonate", 4, "g"),
|
|
||||||
new Ingredient("Vanilla", 2, "g")
|
|
||||||
}),
|
|
||||||
new Recipe("Almond delight",
|
|
||||||
new Ingredient[] {
|
|
||||||
new Ingredient("Butter", 400, "g"),
|
|
||||||
new Ingredient("Sugar", 270, "g"),
|
|
||||||
new Ingredient("Chopped almonds", 279, "g"),
|
|
||||||
new Ingredient("Flour", 400, "g"),
|
|
||||||
new Ingredient("Cinnamon", 10, "g")
|
|
||||||
}),
|
|
||||||
new Recipe("Berliner",
|
|
||||||
new Ingredient[] {
|
|
||||||
new Ingredient("Flour", 350, "g"),
|
|
||||||
new Ingredient("Butter", 250, "g"),
|
|
||||||
new Ingredient("Icing sugar", 100, "g"),
|
|
||||||
new Ingredient("Eggs", 50, "g"),
|
|
||||||
new Ingredient("Vanilla sugar", 5, "g"),
|
|
||||||
new Ingredient("Chocolate", 50, "g")
|
|
||||||
}));
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package krusty;
|
|
||||||
|
|
||||||
public class Ingredient {
|
|
||||||
public String name, unit;
|
|
||||||
public int amount;
|
|
||||||
|
|
||||||
public Ingredient(String name, int amount, String unit) {
|
|
||||||
this.name = name;
|
|
||||||
this.amount = amount;
|
|
||||||
this.unit = unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return String.format("%s: %d %s", name, amount, unit);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package krusty;
|
|
||||||
|
|
||||||
public class Recipe {
|
|
||||||
public String name;
|
|
||||||
public Ingredient ingredients[];
|
|
||||||
|
|
||||||
public Recipe(String name, Ingredient[] ingredients) {
|
|
||||||
this.name = name;
|
|
||||||
this.ingredients = ingredients;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,8 +20,8 @@ public class ServerMain {
|
||||||
|
|
||||||
// Here, we can migrate an arbitrary number of SQL scripts.
|
// Here, we can migrate an arbitrary number of SQL scripts.
|
||||||
try {
|
try {
|
||||||
db.migrateScript("Migrations/create-schema.sql");
|
db.migrateScript("Migrations/0010-tables.sql");
|
||||||
db.migrateScript("Migrations/initial-data.sql");
|
db.migrateScript("Migrations/0020-data.sql");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOError(e);
|
throw new IOError(e);
|
||||||
}
|
}
|
||||||
|
|
7
makefile
7
makefile
|
@ -10,11 +10,4 @@ clean:
|
||||||
test:
|
test:
|
||||||
./gradlew test
|
./gradlew test
|
||||||
|
|
||||||
dbdump:
|
|
||||||
sqlite3 app/krusty.db .dump
|
|
||||||
|
|
||||||
migrate:
|
|
||||||
sqlite3 app/krusty.db < app/Migrations/create-schema.sql
|
|
||||||
sqlite3 app/krusty.db < app/Migrations/initial-data.sql
|
|
||||||
|
|
||||||
.PHONY: run clean test build
|
.PHONY: run clean test build
|
Loading…
Reference in a new issue