summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-11-02 18:37:17 +0000
committerMichael Williamson <mike@zwobble.org>2026-11-02 18:37:17 +0000
commit585728b94ea1037ddb3c009a0ff18ff62a1c3db3 (patch)
tree9a22643232a6eb725dba61f41c26ace266854961 /src
parentb247d99c6950fec45199ff78f8bd16af48d5f96c (diff)
Add test around generating SQL SELECT
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGenerator.java20
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGeneratorTests.java69
2 files changed, 83 insertions, 6 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGenerator.java
index 624b3fe..456ffd8 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGenerator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGenerator.java
@@ -1,5 +1,6 @@
package org.zwobble.hobgoblin.compiler.output.generators.sql;
+import org.zwobble.hobgoblin.compiler.ast.typed.Relation;
import org.zwobble.hobgoblin.compiler.ast.typed.RelationTable;
import org.zwobble.hobgoblin.compiler.ast.typed.TypedQueryDefinitionNode;
import org.zwobble.hobgoblin.compiler.ast.typed.TypedTableDefinitionNode;
@@ -56,7 +57,11 @@ public class SqlGenerator {
TypedQueryDefinitionNode queryDefinition,
TypesInfo typesInfo
) {
- switch (queryDefinition.relation()) {
+ return generateRelation(queryDefinition.relation(), typesInfo);
+ }
+
+ SqlSelectStatement generateRelation(Relation relation, TypesInfo typesInfo) {
+ switch (relation) {
case RelationTable relationTable -> {
var table = relationTable.table();
var schemaInfo = typesInfo.databaseSchemaInfo(table.databaseSchema());
@@ -73,14 +78,17 @@ public class SqlGenerator {
})
.toList();
+ // Order by the primary key to ensure stable ordering.
+ var orderBy = List.of(
+ new SqlOrderingTerm(new SqlRef(
+ generateColumnName(tableInfo.primaryKey().name())
+ ))
+ );
+
return new SqlSelectStatement(
columns,
generateTableName(table.name()),
- List.of(
- new SqlOrderingTerm(new SqlRef(
- generateColumnName(tableInfo.primaryKey().name())
- ))
- )
+ orderBy
);
}
}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGeneratorTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGeneratorTests.java
new file mode 100644
index 0000000..0438baf
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/generators/sql/SqlGeneratorTests.java
@@ -0,0 +1,69 @@
+package org.zwobble.hobgoblin.compiler.output.generators.sql;
+
+import org.junit.jupiter.api.Test;
+import org.zwobble.hobgoblin.compiler.ast.typed.RelationTable;
+import org.zwobble.hobgoblin.compiler.builtins.NativeTypes;
+import org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlIdentifier;
+import org.zwobble.hobgoblin.compiler.sources.NullSource;
+import org.zwobble.hobgoblin.compiler.typechecker.TypesInfoInMemory;
+import org.zwobble.hobgoblin.compiler.types.*;
+import org.zwobble.hobgoblin.compiler.util.SequencedMaps;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlOrderingTermMatcher.isSqlOrderingTerm;
+import static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlRefMatcher.isSqlRef;
+import static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlResultColumnMatcher.isSqlResultColumn;
+import static org.zwobble.hobgoblin.compiler.output.lang.sql.ast.SqlSelectStatementMatcher.isSqlSelectStatement;
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.equalTo;
+import static org.zwobble.precisely.Matchers.isSequence;
+
+public class SqlGeneratorTests {
+ @Test
+ public void relationTableIsTranslatedToSelectFromTable() {
+ var namespaceName = NamespaceName.of("App");
+ var databaseSchema = new DatabaseSchema(namespaceName, "blog");
+ var table = new Table(databaseSchema, "authors");
+ var authorType = new SimpleStructType(namespaceName, "Author");
+ var authorIdField = new Field("id", NativeTypes.INT_32, NullSource.INSTANCE);
+ var authorNameField = new Field("name", NativeTypes.STRING, NullSource.INSTANCE);
+
+ var typesInfo = TypesInfoInMemory.empty();
+ var databaseSchemaInfo = new DatabaseSchemaInfo(SequencedMaps.ofEntries(
+ Map.entry("authors", new TableInfo(table, authorType, authorIdField))
+ ));
+ typesInfo.defineDatabaseSchema(databaseSchema, databaseSchemaInfo);
+ typesInfo.defineStructType(authorType, Optional.of(List.of(authorIdField, authorNameField)));
+
+ var sqlGenerator = new SqlGenerator();
+
+ var relation = RelationTable.arbitrary()
+ .withTable(table)
+ .build();
+
+ var statement = sqlGenerator.generateRelation(relation, typesInfo);
+
+ assertThat(statement, isSqlSelectStatement()
+ .withColumns(isSequence(
+ isSqlResultColumn()
+ .withExpression(isSqlRef().withName(equalTo(id("id"))))
+ .withAlias(equalTo(id("id"))),
+ isSqlResultColumn()
+ .withExpression(isSqlRef().withName(equalTo(id("name"))))
+ .withAlias(equalTo(id("name")))
+ ))
+ .withFrom(equalTo(id("authors")))
+ .withOrderBy(isSequence(
+ isSqlOrderingTerm()
+ .withExpression(isSqlRef().withName(equalTo(id("id"))))
+ ))
+ );
+ }
+
+ private SqlIdentifier id(String value) {
+ return new SqlIdentifier(value);
+ }
+}