Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime exception compiling query containing groupBy(x=>x) #252

Closed
ianba opened this issue Nov 15, 2013 · 8 comments
Closed

Runtime exception compiling query containing groupBy(x=>x) #252

ianba opened this issue Nov 15, 2013 · 8 comments

Comments

@ianba
Copy link

ianba commented Nov 15, 2013

I am trying to use the pattern query.groupBy(x=>x).map(_._1) to simulate a SELECT DISTINCT; however, I am hitting a runtime exception in some situations.

This pattern works if query is a TableQuery. A similar query of the form query.groupBy(_.*).map(_._1) works as expected. However, more generic queries of the form query.groupBy(x=>x).map(_._1) crash with the error:

scala.slick.SlickException: No type for symbol s2 found in {id: Int/INTEGER, a: Int/INTEGER}

I'm using the lastest milestone: 2.0.0-M3.

Example code demonstrating the issue:

import scala.slick.driver.JdbcDriver.simple._
object Test {
  class Test(tag: Tag) extends Table[(Int, Int)](tag, "test") {
    def id = column[Int]("id")
    def a = column[Int]("a")
    def * = (id, a)
  }

  val test = TableQuery[Test]

  val q1 = test.groupBy(x => x).map(_._1)
  val q2 = test.map(x => x).groupBy(_.*).map(_._1)
  val q3 = test.map(x => x).groupBy(x => x).map(_._1)
}
scala> Test.q1.selectStatement
res0: String = select x2."id", x2."a" from "test" x2 group by x2."id", x2."a"

scala> Test.q2.selectStatement
res1: String = select x2."id", x2."a" from "test" x2 group by x2."id", x2."a"

scala> Test.q3.selectStatement
scala.slick.SlickException: No type for symbol s2 found in {id: Int/INTEGER, a: Int/INTEGER}
    at scala.slick.ast.Type$class.select(Type.scala:19)
    at scala.slick.ast.StructType.scala$slick$ast$StructType$$super$select(Type.scala:42)
    at scala.slick.ast.StructType$$anonfun$select$3.apply(Type.scala:42)
    at scala.slick.ast.StructType$$anonfun$select$3.apply(Type.scala:42)
    at scala.Option.getOrElse(Option.scala:120)
    at scala.slick.ast.StructType.select(Type.scala:42)
    at scala.slick.ast.Select.buildType(Node.scala:466)
    at scala.slick.ast.SimplyTypedNode$class.nodeWithComputedType2(Node.scala:124)
    at scala.slick.ast.Select.nodeWithComputedType2(Node.scala:457)
    at scala.slick.ast.Select.nodeWithComputedType2(Node.scala:457)
    at scala.slick.ast.Node$class.nodeWithComputedType(Node.scala:110)
    at scala.slick.ast.Select.nodeWithComputedType(Node.scala:457)
    at scala.slick.ast.SimplyTypedNode$$anonfun$4.apply(Node.scala:123)
    at scala.slick.ast.SimplyTypedNode$$anonfun$4.apply(Node.scala:123)
    at scala.slick.ast.Util$$anonfun$mapOrNone$1.apply(Util.scala:15)
    at scala.slick.ast.Util$$anonfun$mapOrNone$1.apply(Util.scala:14)
    at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
    at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
    at scala.slick.ast.Util$.mapOrNone(Util.scala:14)
    at scala.slick.ast.Node$class.nodeMapChildren(Node.scala:42)
    at scala.slick.ast.StructNode.nodeMapChildren(Node.scala:187)
    at scala.slick.ast.SimplyTypedNode$class.nodeWithComputedType2(Node.scala:123)
    at scala.slick.ast.StructNode.nodeWithComputedType2(Node.scala:187)
    at scala.slick.ast.StructNode.nodeWithComputedType2(Node.scala:187)
    at scala.slick.ast.Node$class.nodeWithComputedType(Node.scala:110)
    at scala.slick.ast.StructNode.nodeWithComputedType(Node.scala:187)
    at scala.slick.ast.SimplyTypedNode$$anonfun$4.apply(Node.scala:123)
    at scala.slick.ast.SimplyTypedNode$$anonfun$4.apply(Node.scala:123)
    at scala.slick.ast.Util$$anonfun$mapOrNone$1.apply(Util.scala:15)
    at scala.slick.ast.Util$$anonfun$mapOrNone$1.apply(Util.scala:14)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.slick.ast.Util$.mapOrNone(Util.scala:14)
    at scala.slick.ast.Node$class.nodeMapChildren(Node.scala:42)
    at scala.slick.ast.Pure.nodeMapChildren(Node.scala:256)
    at scala.slick.ast.SimplyTypedNode$class.nodeWithComputedType2(Node.scala:123)
    at scala.slick.ast.Pure.nodeWithComputedType2(Node.scala:256)
    at scala.slick.ast.Pure.nodeWithComputedType2(Node.scala:256)
    at scala.slick.ast.Node$class.nodeWithComputedType(Node.scala:110)
    at scala.slick.ast.Pure.nodeWithComputedType(Node.scala:256)
    at scala.slick.ast.Bind.nodeWithComputedType2(Node.scala:428)
    at scala.slick.ast.Bind.nodeWithComputedType2(Node.scala:416)
    at scala.slick.ast.Node$class.nodeWithComputedType(Node.scala:110)
    at scala.slick.ast.Bind.nodeWithComputedType(Node.scala:416)
    at scala.slick.ast.Bind.nodeWithComputedType2(Node.scala:426)
    at scala.slick.ast.Bind.nodeWithComputedType2(Node.scala:416)
    at scala.slick.ast.Node$class.nodeWithComputedType(Node.scala:110)
    at scala.slick.ast.Bind.nodeWithComputedType(Node.scala:416)
    at scala.slick.ast.ResultSetMapping.nodeWithComputedType2(ClientSideOp.scala:52)
    at scala.slick.ast.ResultSetMapping.nodeWithComputedType2(ClientSideOp.scala:42)
    at scala.slick.ast.Node$class.nodeWithComputedType(Node.scala:110)
    at scala.slick.ast.ResultSetMapping.nodeWithComputedType(ClientSideOp.scala:42)
    at scala.slick.compiler.AssignTypes$$anonfun$apply$1.apply(AssignTypes.scala:10)
    at scala.slick.compiler.AssignTypes$$anonfun$apply$1.apply(AssignTypes.scala:10)
    at scala.slick.compiler.CompilerState.map(QueryCompiler.scala:144)
    at scala.slick.compiler.AssignTypes.apply(AssignTypes.scala:10)
    at scala.slick.compiler.QueryCompiler$$anonfun$runPhase$1.apply(QueryCompiler.scala:55)
    at scala.slick.compiler.QueryCompiler$$anonfun$runPhase$1.apply(QueryCompiler.scala:54)
    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:57)
    at scala.slick.ast.SymbolNamer.use(Symbol.scala:101)
    at scala.slick.compiler.QueryCompiler.runPhase(QueryCompiler.scala:54)
    at scala.slick.compiler.QueryCompiler$$anonfun$run$2.apply(QueryCompiler.scala:46)
    at scala.slick.compiler.QueryCompiler$$anonfun$run$2.apply(QueryCompiler.scala:46)
    at scala.collection.TraversableOnce$$anonfun$foldLeft$1.apply(TraversableOnce.scala:144)
    at scala.collection.TraversableOnce$$anonfun$foldLeft$1.apply(TraversableOnce.scala:144)
    at scala.collection.Iterator$class.foreach(Iterator.scala:727)
    at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
    at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
    at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
    at scala.collection.TraversableOnce$class.foldLeft(TraversableOnce.scala:144)
    at scala.collection.AbstractTraversable.foldLeft(Traversable.scala:105)
    at scala.slick.compiler.QueryCompiler.run(QueryCompiler.scala:46)
    at scala.slick.compiler.QueryCompiler.run(QueryCompiler.scala:41)
    at scala.slick.profile.BasicProfile$Implicits$class.queryToQueryExecutor(BasicProfile.scala:44)
    at scala.slick.driver.JdbcProfile$$anon$1.queryToQueryExecutor(JdbcProfile.scala:21)
@szeiger
Copy link
Member

szeiger commented Dec 12, 2013

Cannot reproduce. This works for me in M3.

@szeiger szeiger closed this as completed Dec 12, 2013
@ianba
Copy link
Author

ianba commented Dec 12, 2013

Hmmm... the above code definitely throws the above exception for me with the following build.sbt:

scalaVersion := "2.10.3"

libraryDependencies += "com.typesafe.slick" %% "slick" % "2.0.0-M3"

@nafg
Copy link
Member

nafg commented Dec 15, 2013

Maybe a self-contained github project that demonstrates the issue would
help?

On Thu, Dec 12, 2013 at 9:27 AM, Ian Baker notifications@github.com wrote:

Hmmm... the above code definitely throws the above exception for me with
the following build.sbt:

scalaVersion := "2.10.3"

libraryDependencies += "com.typesafe.slick" %% "slick" % "2.0.0-M3"


Reply to this email directly or view it on GitHubhttps://github.com//issues/252#issuecomment-30426109
.

ianba added a commit to ianba/slick that referenced this issue Dec 16, 2013
Adds test cases around using groupBy with an identity mapping
(i.e. .groupBy(x => x)).
@ianba
Copy link
Author

ianba commented Dec 16, 2013

Ok, I copied the code above into a test case in the slick testkit. The test fails at both 2.0.0-M3 and HEAD. Please take a look.

@szeiger szeiger reopened this Jan 7, 2014
@papauschek
Copy link

Having the same issue after upgrading from slick 1.0.1. The same query works in Slick 1. Is there a workaround compatible with Slick 2?

I'm also curious as to why this issue is postponed until Slick 2.1? Looks like a regression to me.

@szeiger
Copy link
Member

szeiger commented Jan 24, 2014

I wasn't aware that this is a regression. I assume that #565 will fix it but that PR caused other problems so it needs some more work for 2.0.1.

@papauschek
Copy link

Thanks for the quick response, looking forward to the next release.

szeiger added a commit that referenced this issue Jan 24, 2014
In inferTypes, we used to replace structural views of NominalTypes after
constructing all table types. At that point, however, type inference
(which runs before table types can be determined) may have copied a
structural view on its own (without the enclosing NominalType) into
another type. For instance, this happens in the typing of GroupBy, where
the "by" type needs to be copied purely as a structural view. In these
cases the resulting NoType could not be patched to the correct type. To
fix this problem we use a special NoTypeView(ts) with the same
TypeSymbol as the surrounding NominalType in table types, which can be
patched even after the NominalType has been lost.

Tests in AggregateTest.testGroupBy. Fixes issue #252.
szeiger added a commit that referenced this issue Feb 6, 2014
In inferTypes, we used to replace structural views of NominalTypes after
constructing all table types. At that point, however, type inference
(which runs before table types can be determined) may have copied a
structural view on its own (without the enclosing NominalType) into
another type. For instance, this happens in the typing of GroupBy, where
the "by" type needs to be copied purely as a structural view. In these
cases the resulting NoType could not be patched to the correct type. To
fix this problem we use the new type UnassignedStructuralType(ts) with
the same TypeSymbol as the surrounding NominalType in table types, which
can be patched even after the NominalType has been lost.

The only remaining use of NoType in StarAnd can be replaced by
UnassignedType, thus eliminating NoType entirely.

Tests in AggregateTest.testGroupBy. Fixes issue #252.
@szeiger szeiger modified the milestones: 2.0.1, 2.1 Feb 12, 2014
@szeiger szeiger removed the invalid label Feb 12, 2014
@szeiger
Copy link
Member

szeiger commented Feb 12, 2014

GroupBy fixes have been merged for 2.0.1. Closing.

@szeiger szeiger closed this as completed Feb 12, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants