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

Tuple-based Tables.scala file generated by Codegen does not compile #1054

Open
ludwiggj opened this Issue Jan 24, 2015 · 0 comments

Comments

Projects
None yet
4 participants
@ludwiggj

I'm playing with slick 2 and codegen, using MySql for the database. I started with the Coffee / Suppliers example from the hello slick activator template.

I'm trying to use codegen to create a new Tables.scala file from the Coffee and Suppliers database tables, which will allow the existing client code to work e.g.

db.withSession { implicit session =>
  ...
  suppliers += (101, "Acme, Inc.", "99 Market Street", "Groundsville", "CA", "95199")
  suppliers += ( 49, "Superior Coffee", "1 Party Place", "Mendocino", "CA", "95460")
  suppliers += (150, "The High Ground", "100 Coffee Lane", "Meadows", "CA", "93966")
  ...
}

I've been posting to the slick google group for help. I've had to use a custom generator to use tuples for the rows instead of case classes:

import scala.slick.driver.MySQLDriver
import scala.slick.driver.MySQLDriver.simple._
import scala.slick.codegen.SourceCodeGenerator
import scala.slick.model.Model

object SlickAutoGen {
  def main(args: Array[String]) {

    val db = Database.forConfig("db")

    val model = db.withSession { implicit session =>
        MySQLDriver.profile.createModel()
    }

    case class SourceGen(model: Model) extends SourceCodeGenerator(model) {
      override def Table = new Table(_) {
        override lazy val EntityType = new EntityType {
          override val classEnabled: Boolean = false
        }
      }
    }

    SourceGen(model).writeToFile(
      "scala.slick.driver.MySQLDriver", "src/main/scala", "org.ludwiggj.finance.database", "Tables", "Tables.scala")
  }
}

This generates the following code for Tables.scala (relevant parts shown only):

trait Tables {
  ...
  /** Row type of table Coffees */
  type CoffeesRow = (String, Int, Double, Int, Int)
  /** Constructor for CoffeesRow providing default values if available in the database schema. */
  def CoffeesRow(name: String, supId: Int, price: Double, sales: Int, total: Int): CoffeesRow = {
    (name, supId, price, sales, total)
  }
  /** GetResult implicit for fetching CoffeesRow objects using plain SQL queries */
  implicit def GetResultCoffeesRow(implicit e0: GR[String], e1: GR[Int], e2: GR[Double]): GR[CoffeesRow] = GR{
    prs => import prs._
    CoffeesRow.tupled((<<[String], <<[Int], <<[Double], <<[Int], <<[Int]))
  }
  /** Table description of table COFFEES. Objects of this class serve as prototypes for rows in queries. */
  class Coffees(_tableTag: Tag) extends Table[CoffeesRow](_tableTag, "COFFEES") {
    def * = (name, supId, price, sales, total) <> (CoffeesRow.tupled, CoffeesRow.unapply)
    /** Maps whole row to an option. Useful for outer joins. */
    def ? = (name.?, supId.?, price.?, sales.?, total.?).shaped.<>({r=>import r._; _1.map(_=>
        CoffeesRow.tupled((_1.get, _2.get, _3.get, _4.get, _5.get)))}, (_:Any) =>
        throw new Exception("Inserting into ? projection not supported."))   
    ...
  }
  ...
}

This results in the following compilation errors:

Error:(28, 5) missing arguments for method CoffeesRow in trait Tables;
follow this method with `_' if you want to treat it as a partially applied function
CoffeesRow.tupled((<<[String], <<[Int], <<[Double], <<[Int], <<[Int]))

Error:(32, 52) missing arguments for method CoffeesRow in trait Tables;
follow this method with `_' if you want to treat it as a partially applied function
def * = (name, supId, price, sales, total) <> (CoffeesRow.tupled, CoffeesRow.unapply)

Error:(32, 71) missing arguments for method CoffeesRow in trait Tables;
follow this method with `_' if you want to treat it as a partially applied function
def * = (name, supId, price, sales, total) <> (CoffeesRow.tupled, CoffeesRow.unapply)

Error:(34, 95) missing arguments for method CoffeesRow in trait Tables;
follow this method with `_' if you want to treat it as a partially applied function
def ? = (name.?, supId.?, price.?, sales.?, total.?).shaped.<>({r=>import r._; _1.map(_=> CoffeesRow.tupled((_1.get, _2.get, _3.get, _4.get, _5.get)))}, (_:Any) =>  throw new Exception("Inserting into ? projection not supported."))

I've been advised on the forum to raise this as a bug against CodeGenerator, and that I could disable the PlainSqlMapper as follows:

case class SourceGen(model: m.Model) extends SourceCodeGenerator(model) {
    override def Table = new Table(_) {
        override lazy val EntityType = new EntityType {
            override val classEnabled: Boolean = false
        }
        override lazy val PlainSqlMapper = new PlainSqlMapper{
            override val enabled = false
        }
    }
}

Disabling the PlainSqlMapper as above removes the first compilation error, but not those connected with the incorrect definitions of the * and ? methods, so it still won't compile.

I know I can fix this code by hand, but obviously codegen should produce the correctly compiling code!

(As an aside, I also wonder why the default behaviour of the code generator is to create Tables.scala with case classes; will this change in future to generate the tuples only version, so that the existing way of populating the database works with the schema classes generated by codegen?)

@cvogt cvogt self-assigned this Jan 26, 2015

@szeiger szeiger added this to the 3.2.0 milestone Aug 26, 2015

@szeiger szeiger modified the milestones: 3.2.1, 3.2.0 Jan 24, 2017

@hvesalai hvesalai modified the milestones: 3.2.1, Next fix release Feb 28, 2018

@hvesalai hvesalai removed the effort: easy label Mar 7, 2018

@cvogt cvogt removed their assignment Mar 13, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment