Search code examples
postgresqlslickscalatraslick-3.0

How can I get Slick 3 to produce BIGSERIAL instead of GENERATED BY DEFAULT AS IDENTITY?


I'm getting up and running with Slick 3 in a Scalatra app, with PostgreSQL. I'm able to read from a manually created table just fine, but I'm having trouble creating one via Slick. When I print out the generated SQL, I see this:

CREATE TABLE "my_table"
  (
     "id"   INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY,
     "text" VARCHAR(4096) NOT NULL
  );

that doesn't work, even manually entered into psql, generating an error:

ERROR:  syntax error at or near "GENERATED"

Ultimately this is what I think I need:

CREATE TABLE "my_table"
  (
     "id"   BIGSERIAL PRIMARY KEY,
     "text" VARCHAR(4096) NOT NULL
  );

In my build.scala, I have these dependencies:

"com.typesafe.slick" %% "slick" % "3.0.2",
"org.postgresql" % "postgresql" % "9.4-1201-jdbc41",
"com.zaxxer" % "HikariCP" % "2.4.5",

application.conf has this:

postgres {
  driver = "slick.driver.PostgresDriver$"
  db {
    url = "jdbc:postgresql://db/mydb"
    driver = org.postgresql.Driver
    connectionPool = HikariCP
    user = postgres
    password = ""
  }
}

My bootstrap code has this:

import slick.backend.{DatabaseConfig, StaticDatabaseConfig}
import slick.driver.JdbcProfile

@StaticDatabaseConfig("file:src/main/resources/application.conf#postgres")
class ScalatraBootstrap extends LifeCycle {
  val logger = LoggerFactory.getLogger(getClass)

  override def init(context: ServletContext) {
    val dbConfig = DatabaseConfig.forConfig[JdbcProfile]("postgres")
    MyDAO.db = dbConfig.db
    context.mount(new MyController, "/*")
  }
  ...
}

MyDAO has:

var db: Database = null

class MyTable(tag: Tag) extends Table[(Int, String)](tag, "my_table") {
  def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
  def text = column[String]("text", O.SqlType("varchar(4096)"))

  def * = (id, text)
}

val myTable = TableQuery[MyTable]

val createTable = myTable.schema.create

def createAllTables() = {
  createTable.statements.foreach(println)
  db.run(createTable)
}

And the controller is successfully calling that createAllTables function, without errors. I haven't confirmed the error via PostgreSQL logs directly because I'm having some fits configuring the Docker container it's running in, but I have confirmed the ability to query.

What must I tweak?


Solution

  • And as usual, I answer my own StackOverflow question within minutes of posting it. The issue was that I was importing a deprecated JdbcDriver in my data access object, where the schema.create action was being prepared. I had to replace this:

    import slick.driver.JdbcDriver.api._
    

    with this:

    import slick.driver.PostgresDriver.api._
    

    And now it's generating something PostgreSQL likes:

    CREATE TABLE "my_table" 
      ( 
         "id"   SERIAL NOT NULL PRIMARY KEY, 
         "text" VARCHAR(4096) NOT NULL 
      )