diff --git a/partiql-ast/src/main/kotlin/org/partiql/ast/normalize/NormalizeFromSource.kt b/partiql-ast/src/main/kotlin/org/partiql/ast/normalize/NormalizeFromSource.kt
index 081321f46d..8c12807ef6 100644
--- a/partiql-ast/src/main/kotlin/org/partiql/ast/normalize/NormalizeFromSource.kt
+++ b/partiql-ast/src/main/kotlin/org/partiql/ast/normalize/NormalizeFromSource.kt
@@ -52,9 +52,19 @@ internal object NormalizeFromSource : AstPass {
 
         override fun visitFromValue(node: From.Value, ctx: Int): From {
             val expr = visitExpr(node.expr, ctx) as Expr
-            val asAlias = node.asAlias ?: expr.toBinder(ctx)
-            return if (expr !== node.expr || asAlias !== node.asAlias) {
-                node.copy(expr = expr, asAlias = asAlias)
+            var i = ctx
+            var asAlias = node.asAlias
+            var atAlias = node.atAlias
+            // derive AS alias
+            if (asAlias == null) {
+                asAlias = expr.toBinder(i++)
+            }
+            // derive AT binder
+            if (atAlias == null && node.type == From.Value.Type.UNPIVOT) {
+                atAlias = expr.toBinder(i++)
+            }
+            return if (expr !== node.expr || asAlias !== node.asAlias || atAlias !== node.atAlias) {
+                node.copy(expr = expr, asAlias = asAlias, atAlias = atAlias)
             } else {
                 node
             }
diff --git a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt
index ad535339bf..98d5dc2eab 100644
--- a/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt
+++ b/partiql-planner/src/main/kotlin/org/partiql/planner/internal/typer/PlanTyper.kt
@@ -159,17 +159,13 @@ internal class PlanTyper(private val env: Env) {
          * TODO handle NULL|STRUCT type
          */
         override fun visitRelOpUnpivot(node: Rel.Op.Unpivot, ctx: Rel.Type?): Rel {
-            // descend, with GLOBAL resolution strategy
             val rex = node.rex.type(emptyList(), outer, Scope.GLOBAL)
 
-            // key type, always a string.
             val kType = STRING
-
-            // value type, possibly coerced.
-            val vType = rex.type.allTypes.map { type ->
+            val vTypes = rex.type.allTypes.map { type ->
                 when (type) {
                     is StructType -> {
-                        if (type.contentClosed || type.constraints.contains(TupleConstraint.Open(false))) {
+                        if ((type.contentClosed || type.constraints.contains(TupleConstraint.Open(false))) && type.fields.isNotEmpty()) {
                             unionOf(type.fields.map { it.value }.toSet()).flatten()
                         } else {
                             ANY
@@ -177,9 +173,8 @@ internal class PlanTyper(private val env: Env) {
                     }
                     else -> type
                 }
-            }.let {
-                unionOf(it.toSet()).flatten()
             }
+            val vType = unionOf(vTypes.toSet()).flatten()
 
             // rewrite
             val type = ctx!!.copyWithSchema(listOf(kType, vType))
diff --git a/test/partiql-tests-runner/build.gradle.kts b/test/partiql-tests-runner/build.gradle.kts
index 9fa06449da..6f9cb78b67 100644
--- a/test/partiql-tests-runner/build.gradle.kts
+++ b/test/partiql-tests-runner/build.gradle.kts
@@ -64,8 +64,8 @@ val generateTestReport by tasks.registering(Test::class) {
     environment(Env.PARTIQL_EQUIV, file("$tests/eval-equiv/").absolutePath)
     environment("conformanceReportDir", reportDir)
     include("org/partiql/runner/ConformanceTestEval.class", "org/partiql/runner/ConformanceTestLegacy.class")
-    if (project.hasProperty("Engine")) {
-        val engine = property("Engine")!! as String
+    if (project.hasProperty("engine")) {
+        val engine = project.property("engine")!! as String
         if (engine.toLowerCase() == "legacy") {
             exclude("org/partiql/runner/ConformanceTestEval.class")
         } else if (engine.toLowerCase() == "eval") {