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 record Attribute(String name, Class<?> type) {
public Attribute {
assert name != null;
assert type != null;
}
public Attribute rho(String newName) { public Attribute rho(String newName) {
assert newName != null;
return new Attribute(newName, type); 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.AttributeEquals;
import de.cccwi.conditions.GreaterThan; import de.cccwi.conditions.GreaterThan;
import de.cccwi.conditions.Not;
import de.cccwi.conditions.ValueEquals; import de.cccwi.conditions.ValueEquals;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
public class Main { public class Main {
public static void main(String[] args) { private static Relation createUserTable() {
var idColumn = new Attribute("id", String.class); var idColumn = new Attribute("id", String.class);
var nameColumn = new Attribute("name", String.class); var nameColumn = new Attribute("name", String.class);
var ageColumn = new Attribute("age", Integer.class); var ageColumn = new Attribute("age", Integer.class);
var enabledColumn = new Attribute("enabled", Boolean.class); var enabledColumn = new Attribute("enabled", Boolean.class);
var userTable = new Relation( return new Relation("Users", List.of(idColumn, nameColumn, ageColumn, enabledColumn), List.of())
"Users", .insert(List.of(UUID.randomUUID().toString(), "nitrix", 32, true))
List.of(idColumn, nameColumn, ageColumn, enabledColumn), .insert(List.of(UUID.randomUUID().toString(), "oxedos", 32, true))
List.of( .insert(List.of(UUID.randomUUID().toString(), "yubilee", 31, false));
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);
private static Relation createEventTable(Relation userTable) {
var idColumn = new Attribute("id", String.class);
var userIdColumn = new Attribute("userId", String.class); var userIdColumn = new Attribute("userId", String.class);
var typeColumn = new Attribute("type", String.class); var typeColumn = new Attribute("type", String.class);
var descriptionColumn = new Attribute("description", String.class); var descriptionColumn = new Attribute("description", String.class);
var eventTable = new Relation( return new Relation("Events", List.of(idColumn, userIdColumn, typeColumn, descriptionColumn), List.of())
"Events", .insert(List.of(UUID.randomUUID().toString(), userTable.tuples().getFirst().getFirst(), "login", "user logged in"))
List.of(idColumn, userIdColumn, typeColumn, descriptionColumn), .insert(List.of(UUID.randomUUID().toString(), userTable.tuples().getFirst().getFirst(), "logout", "user logged out"));
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") 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("Events");
System.out.println(eventTable); 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 var resultTable = userTable
.sigma(new GreaterThan(ageColumn, 30)) .sigma(new GreaterThan(new Attribute("age", Integer.class), 31))
.pi(List.of(nameColumn, idColumn, ageColumn)) .pi(List.of(
.rho(ageColumn.name(), "howOld"); 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(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 resultTable = userTable
.sigma(new ValueEquals(enabledColumn, false)) .sigma(new Not(new ValueEquals(new Attribute("enabled", Boolean.class), true)))
.pi(List.of(nameColumn)) .pi(List.of(new Attribute("name", String.class)))
.rho(nameColumn.name(), "enabledUsers"); .rho("name", "disabledUsers");
System.out.println(resultTable); System.out.println(resultTable);
System.out.println("SELECT * FROM Users u1 JOIN Users u2 ON u1.id = u2.id"); System.out.println("SELECT * FROM Users u1 JOIN Users u2 ON u1.id = u2.id");
var u1 = userTable.rho("u1"); resultTable = userTable
var u2 = userTable.rho("u2"); .rho("u1")
resultTable = u1.join(u2, new AttributeEquals(idColumn.rho("u1.id"), idColumn.rho("u2.id"))); .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(resultTable);
System.out.println("SELECT * FROM Users u JOIN Events e ON u.id = e.userId"); System.out.println("SELECT * FROM Users u JOIN Events e ON u.id = e.userId");
resultTable = userTable.rho("u") resultTable = userTable
.join(eventTable.rho("e"), new AttributeEquals(idColumn.rho("u.id"), userIdColumn)); .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(resultTable);
System.out.println("SELECT * FROM Users UNION Users"); System.out.println("SELECT * FROM Users UNION Users");

View File

@@ -12,7 +12,33 @@ public record Relation(
List<Attribute> attributes, List<Attribute> attributes,
List<List<Object>> tuples 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) { public Relation sigma(BiFunction<List<Attribute>, List<Object>, Boolean> condition) {
assert condition != null;
return new Relation( return new Relation(
name, name,
List.copyOf(attributes), List.copyOf(attributes),
@@ -21,11 +47,15 @@ public record Relation(
} }
public Relation pi(List<Attribute> newAttributes) { public Relation pi(List<Attribute> newAttributes) {
assert newAttributes != null && !newAttributes.isEmpty();
// find out the required indices in the correct order // find out the required indices in the correct order
var indices = newAttributes.stream() var indices = newAttributes.stream()
.map(attributes::indexOf) .map(attributes::indexOf)
.toList(); .toList();
assert indices.stream().noneMatch(idx -> idx == -1);
// filter and reorder the attributes of each row // filter and reorder the attributes of each row
var resultTuples = tuples.stream() var resultTuples = tuples.stream()
.map(t -> indices.stream().map(t::get).toList()) .map(t -> indices.stream().map(t::get).toList())
@@ -39,10 +69,15 @@ public record Relation(
} }
public Relation rho(String newRelationName) { public Relation rho(String newRelationName) {
assert newRelationName != null;
return new Relation(newRelationName, List.copyOf(attributes), List.copyOf(tuples)); return new Relation(newRelationName, List.copyOf(attributes), List.copyOf(tuples));
} }
public Relation rho(String oldAttributeName, String newAttributeName) { public Relation rho(String oldAttributeName, String newAttributeName) {
assert oldAttributeName != null;
assert newAttributeName != null;
return new Relation( return new Relation(
name, name,
List.copyOf(attributes.stream() List.copyOf(attributes.stream()
@@ -53,6 +88,7 @@ public record Relation(
} }
public Relation cross(Relation other) { public Relation cross(Relation other) {
assert other != null;
assert !this.name.equals(other.name); assert !this.name.equals(other.name);
var resultTuples = new ArrayList<List<Object>>(); var resultTuples = new ArrayList<List<Object>>();
@@ -70,10 +106,7 @@ public record Relation(
} }
public Relation union(Relation other) { public Relation union(Relation other) {
assert attributes.size() == other.attributes.size(); checkAttributesMatch(other);
for (int i = 0; i < attributes.size(); i++) {
assert attributes.get(i).equals(other.attributes.get(i));
}
return new Relation( return new Relation(
"%sU%s".formatted(name, other.name), "%sU%s".formatted(name, other.name),
@@ -83,10 +116,7 @@ public record Relation(
} }
public Relation unionAll(Relation other) { public Relation unionAll(Relation other) {
assert attributes.size() == other.attributes.size(); checkAttributesMatch(other);
for (int i = 0; i < attributes.size(); i++) {
assert attributes.get(i).equals(other.attributes.get(i));
}
return new Relation( return new Relation(
"%sU%s".formatted(name, other.name), "%sU%s".formatted(name, other.name),
@@ -96,10 +126,7 @@ public record Relation(
} }
public Relation difference(Relation other) { public Relation difference(Relation other) {
assert attributes.size() == other.attributes.size(); checkAttributesMatch(other);
for (int i = 0; i < attributes.size(); i++) {
assert attributes.get(i).equals(other.attributes.get(i));
}
return new Relation( return new Relation(
"%s-%s".formatted(name, other.name), "%s-%s".formatted(name, other.name),
@@ -138,7 +165,6 @@ public record Relation(
return line.toString(); return line.toString();
}; };
// Header // Header
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.append(formatRow.apply(attributes.stream().map(Attribute::name).map(a -> (Object) a).toList())); sb.append(formatRow.apply(attributes.stream().map(Attribute::name).map(a -> (Object) a).toList()));
@@ -187,4 +213,12 @@ public record Relation(
return resultAttributes; 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; private final Attribute rhs;
public AttributeEquals(Attribute lhs, Attribute rhs) { public AttributeEquals(Attribute lhs, Attribute rhs) {
assert lhs != null;
assert rhs != null;
assert lhs.type().equals(rhs.type()); assert lhs.type().equals(rhs.type());
this.lhs = lhs; this.lhs = lhs;
this.rhs = rhs; this.rhs = rhs;
} }
@Override @Override
public Boolean apply(List<Attribute> attributes, List<Object> rows) { public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
return rows.get(attributes.indexOf(lhs)).equals(rows.get(attributes.indexOf(rhs))); 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; private final Integer value;
public GreaterThan(Attribute attribute, Integer value) { public GreaterThan(Attribute attribute, Integer value) {
assert attribute != null && attribute.type().equals(Integer.class);
assert value != null;
this.attribute = attribute; this.attribute = attribute;
this.value = value; this.value = value;
} }
@Override @Override
public Boolean apply(List<Attribute> attributes, List<Object> rows) { public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
var columnIndex = attributes.indexOf(attribute); var attributeIndex = attributes.indexOf(attribute);
assert attributes.get(columnIndex).type().equals(Integer.class); assert attributes.get(attributeIndex).type().equals(Integer.class);
return ((Integer) rows.get(columnIndex)) > value; 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; private final Integer value;
public GreaterThanEquals(Attribute attribute, Integer value) { public GreaterThanEquals(Attribute attribute, Integer value) {
assert attribute != null && attribute.type().equals(Integer.class);
assert value != null;
this.attribute = attribute; this.attribute = attribute;
this.value = value; this.value = value;
} }
@Override @Override
public Boolean apply(List<Attribute> attributes, List<Object> rows) { public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
var columnIndex = attributes.indexOf(attribute); var attributeIndex = attributes.indexOf(attribute);
assert attributes.get(columnIndex).type().equals(Integer.class); assert attributes.get(attributeIndex).type().equals(Integer.class);
return ((Integer) rows.get(columnIndex)) >= value; 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; private final Integer value;
public LessThan(Attribute attribute, Integer value) { public LessThan(Attribute attribute, Integer value) {
assert attribute != null && attribute.type().equals(Integer.class);
assert value != null;
this.attribute = attribute; this.attribute = attribute;
this.value = value; this.value = value;
} }
@Override @Override
public Boolean apply(List<Attribute> attributes, List<Object> rows) { public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
var columnIndex = attributes.indexOf(attribute); var attributeIndex = attributes.indexOf(attribute);
assert attributes.get(columnIndex).type().equals(Integer.class); assert attributes.get(attributeIndex).type().equals(Integer.class);
return ((Integer) rows.get(columnIndex)) < value; 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; private final Integer value;
public LessThanEquals(Attribute attribute, Integer value) { public LessThanEquals(Attribute attribute, Integer value) {
assert attribute != null && attribute.type().equals(Integer.class);
assert value != null;
this.attribute = attribute; this.attribute = attribute;
this.value = value; this.value = value;
} }
@Override @Override
public Boolean apply(List<Attribute> attributes, List<Object> rows) { public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
var columnIndex = attributes.indexOf(attribute); var attributeIndex = attributes.indexOf(attribute);
assert attributes.get(columnIndex).type().equals(Integer.class); assert attributes.get(attributeIndex).type().equals(Integer.class);
return ((Integer) rows.get(columnIndex)) <= value; return ((Integer) tuple.get(attributeIndex)) <= value;
} }
} }

View File

@@ -6,14 +6,16 @@ import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
public class Not implements BiFunction<List<Attribute>, List<Object>, Boolean> { 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) { public Not(BiFunction<List<Attribute>, List<Object>, Boolean> condition) {
assert condition != null;
this.condition = condition; this.condition = condition;
} }
@Override @Override
public Boolean apply(List<Attribute> attributes, List<Object> objects) { public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
return !condition.apply(attributes, objects); 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; private final Object rhs;
public ValueEquals(Attribute lhs, Object rhs) { public ValueEquals(Attribute lhs, Object rhs) {
assert lhs != null;
assert rhs != null;
assert lhs.type().isInstance(rhs); assert lhs.type().isInstance(rhs);
this.lhs = lhs; this.lhs = lhs;
this.rhs = rhs; this.rhs = rhs;
} }
@Override @Override
public Boolean apply(List<Attribute> attributes, List<Object> rows) { public Boolean apply(List<Attribute> attributes, List<Object> tuple) {
return rows.get(attributes.indexOf(lhs)).equals(rhs); return tuple.get(attributes.indexOf(lhs)).equals(rhs);
} }
} }