scala - Reference compound primary key -
i'm new slick , first attempt of creating application it.
i have case class user(userid: uuid, firstname: string, lastname: string)
.
users can log in. case class logininfo(providerid: string, providerkey: string)
comes in (i'm using silhouette authentication).
i'd associate every user
logininfo
using slick table
:
class userswithlogininfos(tag:tag) extends table[(primarykey, uuid)](tag, "users_with_login_infos"){ def logininfoid = tablequery[logininfos].shaped.value.logininfoid def userid = column[uuid]("user_id") def * = (logininfoid, userid) <>(userwithlogininfo.tupled, userwithlogininfo.unapply) }
this corresponding case class userwithlogininfo(logininfoid: primarykey, userid: uuid)
.
my tables user
s , logininfo
s straightforward:
class logininfos(tag: tag) extends table[logininfo](tag, "login_infos") { // primary key of table compound: consists of provider's id , key def logininfoid = primarykey("login_info_id", (providerid, providerkey)) // "credentials" example def providerid = column[string]("provider_id") // "admin@nowhere.com" example def providerkey = column[string]("provider_key") def * = (providerid, providerkey) <>(logininfo.tupled, logininfo.unapply) } class users(tag: tag) extends table[user](tag, "users") { def id = column[uuid]("id", o.primarykey) def firstname = column[string]("first_name") def lastname = column[string]("last_name") def * = (id, firstname, lastname) <>(user.tupled, user.unapply) }
unfortunately, doesn't typecheck:
def * = (logininfoid, userid) <>(userwithlogininfo.tupled, userwithlogininfo.unapply)
expression of type mappedprojection[userwithlogininfo, (primarykey, uuid)] doesn't conform expected type provenshape[(primarykey, uuid)]
i work around introducing case class logininfowithid(info: logininfo, id: uuid)
hope away referencing logininfo
's compound primary key directly.
is there way this? or on wrong track entirely?
i'm using slick 3.0.0.
i'm not quite sure trying achieve here, if user
associated loginfinfo
(untested code ahead):
class logininfos(tag: tag) extends table[logininfo](tag, "login_infos") { def providerid = column[string]("provider_id") def providerkey = column[string]("provider_key") def * = (providerid, providerkey) <>(logininfo.tupled, logininfo.unapply) def pk = primarykey("pk_login_info_id", (providerid, providerkey)) } class users(tag: tag) extends table[user](tag, "users") { def id = column[uuid]("id", o.primarykey) def firstname = column[string]("first_name") def lastname = column[string]("last_name") def * = (id, firstname, lastname) <>(user.tupled, user.unapply) } class userswithlogininfos(tag:tag) extends table[(providerid: string, providerkey: string, uuid: string)](tag, "users_with_login_infos"){ def providerid = column[string]("user_provider_id") // column name assumption def providerkey = column[string]("user_provider_key") // column name assumption def userid = column[uuid]("user_id") def pk = primarykey("pk_user_with_login_info_id", (providerid, providerkey)) } case class userwithlogininfo(user: user, logininfo: logininfo)
you can optionally wrap tuple3
in userswithlogininfos
in case class if to. however, example query user
joined logininfo
:
def finduserwithlogininfo(providerid: string, providerkey: string): future[option[userwithlogininfo]] = { val query = (for { user <- tablequery[users] if user.providerid === providerid && user.providerkey === providerkey usertologininfo <- tablequery[userswithlogininfos] if usertologininfo.userid === user.id logininfo <- tablequery[logininfos] if usertologininfo.providerid === logininfo.providerid && usertologininfo.providerid === logininfo.providerkey } yield userwithlogininfo(user, logininfo)) db.run(query.result.headoption) }
instead of writing rather verbose query above, can define foreign key constraint described here slick documentation, constraints.
also found coming orm slick useful when started using slick. remember, slick not orm , things quite different :)
Comments
Post a Comment