more stuff I did

This commit is contained in:
2025-07-13 02:36:21 +02:00
parent 867e5e2097
commit 5f9f80edbe
12 changed files with 154 additions and 95 deletions

6
.idea/vcs.xml generated Normal file
View 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>

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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");

View File

@@ -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));
}
}
}

View File

@@ -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)));
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}