more stuff I did
This commit is contained in:
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -3,17 +3,14 @@ package de.cccwi;
|
||||
|
||||
public record Attribute(String name, Class<?> type) {
|
||||
|
||||
public Attribute {
|
||||
assert name != null;
|
||||
assert type != null;
|
||||
}
|
||||
|
||||
public Attribute rho(String newName) {
|
||||
assert newName != null;
|
||||
|
||||
return new Attribute(newName, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof Attribute other && name.equals(other.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package de.cccwi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Database {
|
||||
private Map<String, Relation> tables;
|
||||
|
||||
public Database(Map<String, Relation> tables) {
|
||||
this.tables = tables;
|
||||
}
|
||||
|
||||
public Relation executeQuery(String query) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -2,66 +2,83 @@ package de.cccwi;
|
||||
|
||||
import de.cccwi.conditions.AttributeEquals;
|
||||
import de.cccwi.conditions.GreaterThan;
|
||||
import de.cccwi.conditions.Not;
|
||||
import de.cccwi.conditions.ValueEquals;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
private static Relation createUserTable() {
|
||||
var idColumn = new Attribute("id", String.class);
|
||||
var nameColumn = new Attribute("name", String.class);
|
||||
var ageColumn = new Attribute("age", Integer.class);
|
||||
var enabledColumn = new Attribute("enabled", Boolean.class);
|
||||
var userTable = new Relation(
|
||||
"Users",
|
||||
List.of(idColumn, nameColumn, ageColumn, enabledColumn),
|
||||
List.of(
|
||||
List.of(UUID.randomUUID().toString(), "nitrix", 31, true),
|
||||
List.of(UUID.randomUUID().toString(), "oxedos", 27, true),
|
||||
List.of(UUID.randomUUID().toString(), "yubilee", 30, false)
|
||||
)
|
||||
);
|
||||
System.out.println("Users");
|
||||
System.out.println(userTable);
|
||||
return new Relation("Users", List.of(idColumn, nameColumn, ageColumn, enabledColumn), List.of())
|
||||
.insert(List.of(UUID.randomUUID().toString(), "nitrix", 32, true))
|
||||
.insert(List.of(UUID.randomUUID().toString(), "oxedos", 32, true))
|
||||
.insert(List.of(UUID.randomUUID().toString(), "yubilee", 31, false));
|
||||
}
|
||||
|
||||
private static Relation createEventTable(Relation userTable) {
|
||||
var idColumn = new Attribute("id", String.class);
|
||||
var userIdColumn = new Attribute("userId", String.class);
|
||||
var typeColumn = new Attribute("type", String.class);
|
||||
var descriptionColumn = new Attribute("description", String.class);
|
||||
var eventTable = new Relation(
|
||||
"Events",
|
||||
List.of(idColumn, userIdColumn, typeColumn, descriptionColumn),
|
||||
List.of(
|
||||
List.of(UUID.randomUUID(), userTable.tuples().getFirst().getFirst(), "login", "user logged in"),
|
||||
List.of(UUID.randomUUID(), userTable.tuples().getFirst().getFirst(), "logout", "user logged out")
|
||||
)
|
||||
);
|
||||
return new Relation("Events", List.of(idColumn, userIdColumn, typeColumn, descriptionColumn), List.of())
|
||||
.insert(List.of(UUID.randomUUID().toString(), userTable.tuples().getFirst().getFirst(), "login", "user logged in"))
|
||||
.insert(List.of(UUID.randomUUID().toString(), userTable.tuples().getFirst().getFirst(), "logout", "user logged out"));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
var userTable = createUserTable();
|
||||
System.out.println("Users");
|
||||
System.out.println(userTable);
|
||||
|
||||
var eventTable = createEventTable(userTable);
|
||||
System.out.println("Events");
|
||||
System.out.println(eventTable);
|
||||
|
||||
System.out.println("SELECT name, id, age AS howOld FROM Users WHERE age > 30");
|
||||
System.out.println("SELECT name, id, age AS howOld FROM Users WHERE age > 31");
|
||||
var resultTable = userTable
|
||||
.sigma(new GreaterThan(ageColumn, 30))
|
||||
.pi(List.of(nameColumn, idColumn, ageColumn))
|
||||
.rho(ageColumn.name(), "howOld");
|
||||
.sigma(new GreaterThan(new Attribute("age", Integer.class), 31))
|
||||
.pi(List.of(
|
||||
new Attribute("name", String.class),
|
||||
new Attribute("id", String.class),
|
||||
new Attribute("age", Integer.class))
|
||||
)
|
||||
.rho("age", "howOld");
|
||||
System.out.println(resultTable);
|
||||
|
||||
System.out.println("SELECT name AS enabledUsers FROM Users WHERE NOT enabled");
|
||||
System.out.println("SELECT name AS disabledUsers FROM Users WHERE enabled != true");
|
||||
resultTable = userTable
|
||||
.sigma(new ValueEquals(enabledColumn, false))
|
||||
.pi(List.of(nameColumn))
|
||||
.rho(nameColumn.name(), "enabledUsers");
|
||||
.sigma(new Not(new ValueEquals(new Attribute("enabled", Boolean.class), true)))
|
||||
.pi(List.of(new Attribute("name", String.class)))
|
||||
.rho("name", "disabledUsers");
|
||||
System.out.println(resultTable);
|
||||
|
||||
System.out.println("SELECT * FROM Users u1 JOIN Users u2 ON u1.id = u2.id");
|
||||
var u1 = userTable.rho("u1");
|
||||
var u2 = userTable.rho("u2");
|
||||
resultTable = u1.join(u2, new AttributeEquals(idColumn.rho("u1.id"), idColumn.rho("u2.id")));
|
||||
resultTable = userTable
|
||||
.rho("u1")
|
||||
.join(
|
||||
userTable.rho("u2"),
|
||||
new AttributeEquals(
|
||||
new Attribute("u1.id", String.class),
|
||||
new Attribute("u2.id", String.class)
|
||||
)
|
||||
);
|
||||
System.out.println(resultTable);
|
||||
|
||||
System.out.println("SELECT * FROM Users u JOIN Events e ON u.id = e.userId");
|
||||
resultTable = userTable.rho("u")
|
||||
.join(eventTable.rho("e"), new AttributeEquals(idColumn.rho("u.id"), userIdColumn));
|
||||
resultTable = userTable
|
||||
.rho("u")
|
||||
.join(
|
||||
eventTable.rho("e"),
|
||||
new AttributeEquals(
|
||||
new Attribute("u.id", String.class),
|
||||
new Attribute("userId", String.class)
|
||||
)
|
||||
);
|
||||
System.out.println(resultTable);
|
||||
|
||||
System.out.println("SELECT * FROM Users UNION Users");
|
||||
|
||||
@@ -12,7 +12,33 @@ public record Relation(
|
||||
List<Attribute> attributes,
|
||||
List<List<Object>> tuples
|
||||
) {
|
||||
|
||||
public Relation {
|
||||
assert name != null;
|
||||
assert attributes != null && !attributes.isEmpty();
|
||||
assert tuples != null;
|
||||
|
||||
for (var tuple : tuples) {
|
||||
assert tuple.size() == attributes.size();
|
||||
for (var i = 0; i < tuple.size(); i++) {
|
||||
assert attributes.get(i).type().isInstance(tuple.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Relation insert(List<Object> tuple) {
|
||||
assert tuple != null;
|
||||
|
||||
return new Relation(
|
||||
name,
|
||||
attributes,
|
||||
List.copyOf(Stream.concat(tuples.stream(), Stream.of(tuple)).toList())
|
||||
);
|
||||
}
|
||||
|
||||
public Relation sigma(BiFunction<List<Attribute>, List<Object>, Boolean> condition) {
|
||||
assert condition != null;
|
||||
|
||||
return new Relation(
|
||||
name,
|
||||
List.copyOf(attributes),
|
||||
@@ -21,11 +47,15 @@ public record Relation(
|
||||
}
|
||||
|
||||
public Relation pi(List<Attribute> newAttributes) {
|
||||
assert newAttributes != null && !newAttributes.isEmpty();
|
||||
|
||||
// find out the required indices in the correct order
|
||||
var indices = newAttributes.stream()
|
||||
.map(attributes::indexOf)
|
||||
.toList();
|
||||
|
||||
assert indices.stream().noneMatch(idx -> idx == -1);
|
||||
|
||||
// filter and reorder the attributes of each row
|
||||
var resultTuples = tuples.stream()
|
||||
.map(t -> indices.stream().map(t::get).toList())
|
||||
@@ -39,10 +69,15 @@ public record Relation(
|
||||
}
|
||||
|
||||
public Relation rho(String newRelationName) {
|
||||
assert newRelationName != null;
|
||||
|
||||
return new Relation(newRelationName, List.copyOf(attributes), List.copyOf(tuples));
|
||||
}
|
||||
|
||||
public Relation rho(String oldAttributeName, String newAttributeName) {
|
||||
assert oldAttributeName != null;
|
||||
assert newAttributeName != null;
|
||||
|
||||
return new Relation(
|
||||
name,
|
||||
List.copyOf(attributes.stream()
|
||||
@@ -53,6 +88,7 @@ public record Relation(
|
||||
}
|
||||
|
||||
public Relation cross(Relation other) {
|
||||
assert other != null;
|
||||
assert !this.name.equals(other.name);
|
||||
|
||||
var resultTuples = new ArrayList<List<Object>>();
|
||||
@@ -70,10 +106,7 @@ public record Relation(
|
||||
}
|
||||
|
||||
public Relation union(Relation other) {
|
||||
assert attributes.size() == other.attributes.size();
|
||||
for (int i = 0; i < attributes.size(); i++) {
|
||||
assert attributes.get(i).equals(other.attributes.get(i));
|
||||
}
|
||||
checkAttributesMatch(other);
|
||||
|
||||
return new Relation(
|
||||
"%sU%s".formatted(name, other.name),
|
||||
@@ -83,10 +116,7 @@ public record Relation(
|
||||
}
|
||||
|
||||
public Relation unionAll(Relation other) {
|
||||
assert attributes.size() == other.attributes.size();
|
||||
for (int i = 0; i < attributes.size(); i++) {
|
||||
assert attributes.get(i).equals(other.attributes.get(i));
|
||||
}
|
||||
checkAttributesMatch(other);
|
||||
|
||||
return new Relation(
|
||||
"%sU%s".formatted(name, other.name),
|
||||
@@ -96,10 +126,7 @@ public record Relation(
|
||||
}
|
||||
|
||||
public Relation difference(Relation other) {
|
||||
assert attributes.size() == other.attributes.size();
|
||||
for (int i = 0; i < attributes.size(); i++) {
|
||||
assert attributes.get(i).equals(other.attributes.get(i));
|
||||
}
|
||||
checkAttributesMatch(other);
|
||||
|
||||
return new Relation(
|
||||
"%s-%s".formatted(name, other.name),
|
||||
@@ -138,7 +165,6 @@ public record Relation(
|
||||
return line.toString();
|
||||
};
|
||||
|
||||
|
||||
// Header
|
||||
var sb = new StringBuilder();
|
||||
sb.append(formatRow.apply(attributes.stream().map(Attribute::name).map(a -> (Object) a).toList()));
|
||||
@@ -187,4 +213,12 @@ public record Relation(
|
||||
|
||||
return resultAttributes;
|
||||
}
|
||||
|
||||
private void checkAttributesMatch(Relation other) {
|
||||
assert other != null;
|
||||
assert attributes.size() == other.attributes.size();
|
||||
for (int i = 0; i < attributes.size(); i++) {
|
||||
assert attributes.get(i).equals(other.attributes.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,16 @@ public class AttributeEquals implements BiFunction<List<Attribute>, List<Object>
|
||||
private final Attribute rhs;
|
||||
|
||||
public AttributeEquals(Attribute lhs, Attribute rhs) {
|
||||
assert lhs != null;
|
||||
assert rhs != null;
|
||||
assert lhs.type().equals(rhs.type());
|
||||
|
||||
this.lhs = lhs;
|
||||
this.rhs = rhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> rows) {
|
||||
return rows.get(attributes.indexOf(lhs)).equals(rows.get(attributes.indexOf(rhs)));
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
|
||||
return tuple.get(attributes.indexOf(lhs)).equals(tuple.get(attributes.indexOf(rhs)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,17 @@ public class GreaterThan implements BiFunction<List<Attribute>, List<Object>, Bo
|
||||
private final Integer value;
|
||||
|
||||
public GreaterThan(Attribute attribute, Integer value) {
|
||||
assert attribute != null && attribute.type().equals(Integer.class);
|
||||
assert value != null;
|
||||
|
||||
this.attribute = attribute;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> rows) {
|
||||
var columnIndex = attributes.indexOf(attribute);
|
||||
assert attributes.get(columnIndex).type().equals(Integer.class);
|
||||
return ((Integer) rows.get(columnIndex)) > value;
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
|
||||
var attributeIndex = attributes.indexOf(attribute);
|
||||
assert attributes.get(attributeIndex).type().equals(Integer.class);
|
||||
return ((Integer) tuple.get(attributeIndex)) > value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,17 @@ public class GreaterThanEquals implements BiFunction<List<Attribute>, List<Objec
|
||||
private final Integer value;
|
||||
|
||||
public GreaterThanEquals(Attribute attribute, Integer value) {
|
||||
assert attribute != null && attribute.type().equals(Integer.class);
|
||||
assert value != null;
|
||||
|
||||
this.attribute = attribute;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> rows) {
|
||||
var columnIndex = attributes.indexOf(attribute);
|
||||
assert attributes.get(columnIndex).type().equals(Integer.class);
|
||||
return ((Integer) rows.get(columnIndex)) >= value;
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
|
||||
var attributeIndex = attributes.indexOf(attribute);
|
||||
assert attributes.get(attributeIndex).type().equals(Integer.class);
|
||||
return ((Integer) tuple.get(attributeIndex)) >= value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,17 @@ public class LessThan implements BiFunction<List<Attribute>, List<Object>, Boole
|
||||
private final Integer value;
|
||||
|
||||
public LessThan(Attribute attribute, Integer value) {
|
||||
assert attribute != null && attribute.type().equals(Integer.class);
|
||||
assert value != null;
|
||||
|
||||
this.attribute = attribute;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> rows) {
|
||||
var columnIndex = attributes.indexOf(attribute);
|
||||
assert attributes.get(columnIndex).type().equals(Integer.class);
|
||||
return ((Integer) rows.get(columnIndex)) < value;
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
|
||||
var attributeIndex = attributes.indexOf(attribute);
|
||||
assert attributes.get(attributeIndex).type().equals(Integer.class);
|
||||
return ((Integer) tuple.get(attributeIndex)) < value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,17 @@ public class LessThanEquals implements BiFunction<List<Attribute>, List<Object>,
|
||||
private final Integer value;
|
||||
|
||||
public LessThanEquals(Attribute attribute, Integer value) {
|
||||
assert attribute != null && attribute.type().equals(Integer.class);
|
||||
assert value != null;
|
||||
|
||||
this.attribute = attribute;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> rows) {
|
||||
var columnIndex = attributes.indexOf(attribute);
|
||||
assert attributes.get(columnIndex).type().equals(Integer.class);
|
||||
return ((Integer) rows.get(columnIndex)) <= value;
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
|
||||
var attributeIndex = attributes.indexOf(attribute);
|
||||
assert attributes.get(attributeIndex).type().equals(Integer.class);
|
||||
return ((Integer) tuple.get(attributeIndex)) <= value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,16 @@ import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class Not implements BiFunction<List<Attribute>, List<Object>, Boolean> {
|
||||
private BiFunction<List<Attribute>, List<Object>, Boolean> condition;
|
||||
private final BiFunction<List<Attribute>, List<Object>, Boolean> condition;
|
||||
|
||||
public Not(BiFunction<List<Attribute>, List<Object>, Boolean> condition) {
|
||||
assert condition != null;
|
||||
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> objects) {
|
||||
return !condition.apply(attributes, objects);
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
|
||||
return !condition.apply(attributes, tuple);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,16 @@ public class ValueEquals implements BiFunction<List<Attribute>, List<Object>, Bo
|
||||
private final Object rhs;
|
||||
|
||||
public ValueEquals(Attribute lhs, Object rhs) {
|
||||
assert lhs != null;
|
||||
assert rhs != null;
|
||||
assert lhs.type().isInstance(rhs);
|
||||
|
||||
this.lhs = lhs;
|
||||
this.rhs = rhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> rows) {
|
||||
return rows.get(attributes.indexOf(lhs)).equals(rhs);
|
||||
public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
|
||||
return tuple.get(attributes.indexOf(lhs)).equals(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user