How does one insert records into PostgreSQL using AutoInc keys with Slick mapped tables? If I use and Option for the id in my case class and set it to None, then PostgreSQL will complain on insert that the field cannot be null. This works for H2, but not for PostgreSQL:
//import scala.slick.driver.H2Driver.simple._ //import scala.slick.driver.BasicProfile.SimpleQL.Table import scala.slick.driver.PostgresDriver.simple._ import Database.threadLocalSession object TestMappedTable extends App{ case class User(id: Option[Int], first: String, last: String) object Users extends Table[User]("users") { def id = column[Int]("id", O.PrimaryKey, O.AutoInc) def first = column[String]("first") def last = column[String]("last") def * = id.? ~ first ~ last <> (User, User.unapply _) def ins1 = first ~ last returning id val findByID = createFinderBy(_.id) def autoInc = id.? ~ first ~ last <> (User, User.unapply _) returning id } // implicit val session = Database.forURL("jdbc:h2:mem:test1", driver = "org.h2.Driver").createSession() implicit val session = Database.forURL("jdbc:postgresql:test:slicktest", driver="org.postgresql.Driver", user="postgres", password="xxx") session.withTransaction{ Users.ddl.create // insert data print(Users.insert(User(None, "Jack", "Green" ))) print(Users.insert(User(None, "Joe", "Blue" ))) print(Users.insert(User(None, "John", "Purple" ))) val u = Users.insert(User(None, "Jim", "Yellow" )) // println(u.id.get) print(Users.autoInc.insert(User(None, "Johnathan", "Seagul" ))) } session.withTransaction{ val queryUsers = for { user <- Users } yield (user.id, user.first) println(queryUsers.list) Users.where(_.id between(1, 2)).foreach(println) println("ID 3 -> " + Users.findByID.first(3)) } }
Using the above with H2 succeeds, but if I comment it out and change to PostgreSQL, then I get:
[error] (run-main) org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint
PostgreSQL has the data types smallserial, serial and bigserial; these are not true types, but merely a notational convenience for creating unique identifier columns. These are similar to AUTO_INCREMENT property supported by some other databases.
Syntax for Access Tip: To specify that the "Personid" column should start at value 10 and increment by 5, change the autoincrement to AUTOINCREMENT(10,5) . VALUES ('Lars','Monsen'); The SQL statement above would insert a new record into the "Persons" table. The "Personid" column would be assigned a unique value.
Auto Increment is a field used to generate a unique number for every new record added into a table. This is generally used for the primary key column as it becomes easy for the developers to automatically generate a unique number for every new record.
This is working here:
object Application extends Table[(Long, String)]("application") { def idlApplication = column[Long]("idlapplication", O.PrimaryKey, O.AutoInc) def appName = column[String]("appname") def * = idlApplication ~ appName def autoInc = appName returning idlApplication } var id = Application.autoInc.insert("App1")
This is how my SQL looks:
CREATE TABLE application (idlapplication BIGSERIAL PRIMARY KEY, appName VARCHAR(500));
Update:
The specific problem with regard to a mapped table with User (as in the question) can be solved as follows:
def forInsert = first ~ last <> ({ (f, l) => User(None, f, l) }, { u:User => Some((u.first, u.last)) })
This is from the test cases in the Slick git repository.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With