package com.example.user.slick.dbios import slick.jdbc.JdbcProfile import com.example.models._ import io.scalaland.chimney.dsl._ import com.example.user.slick.Tables import javax.inject.Singleton import javax.inject._ @Singleton class SlickLibraryDbio @Inject() (override val profile: JdbcProfile) extends Tables { import profile.api._ def findBookById(id: Long): DBIO[Option[BooksRow]] = Query.bookById(id).result.headOption def findBookById2(id: Long): DBIO[Option[BookWithoutId]] = Query.test(id).result.headOption def findBooksWithAuthor: DBIO[Seq[(BooksRow, AuthorsRow)]] = Query.booksWithAuthor.result def insertBook(book: Book): DBIO[BooksRow] = Query.writeBooks += bookToRow(book) def insertBook2(book: NewBook): DBIO[Long] = Query.writeBooks3 += book // def insertAuthor(author: Author): DBIO[AuthorsRow] = Query.writeAuthors += authorToRow(author) def insertAuthor2(author: NewAuthor): DBIO[Long] = Query.writeAuthors2 += author def getAuthorsForBook(bookId: Long): DBIO[Seq[(AuthorsRow, BooksRow)]] = { Query.authorOfBook(bookId).result } def authorToRow(author: Author) = author.transformInto[AuthorsRow] def bookToRow(book: Book) = book.transformInto[BooksRow] def authorsRowToAuthor(author: AuthorsRow) = author.transformInto[Author] def booksRowToBooks(book: BooksRow) = book.transformInto[Book] def booksRowToBooks2(book: BooksRow) = book.transformInto[BookWithoutId] // As mentioned under #2, we do encapsulate our queries object Query { // Return the book / author with it's auto incremented // id instead of an insert count lazy val writeBooks = Books returning Books .map(_.id) into ((book, id) => book.copy(id)) lazy val writeBooks2 = Books.map(b => (b.title, b.authorId).mapTo[BookWithoutId]) lazy val writeBooks3 = Books .map(b => (b.title, b.authorId).mapTo[NewBook]) .returning(Books.map(_.id)) lazy val writeAuthors = Authors returning Authors .map(_.id) into ((author, id) => author.copy(id)) lazy val writeAuthors2 = Authors.map(a => (a.name).mapTo[NewAuthor]) returning Authors.map(_.id) lazy val test = (givenId: Long) => Books .filter(_.id === givenId) .map(toBooksWithoutID) lazy val bookById = Books.findBy(_.id) lazy val toBooksWithoutID = (table: Books) => (table.title, table.authorId).mapTo[BookWithoutId] lazy val booksWithAuthor = for { b <- Books a <- Authors if b.authorId === a.id } yield (b, a) lazy val authorOfBook = (bookId: Long) => for { (author, book) <- Authors join Books on (_.id === _.authorId) filter { case (authors, books) => books.id === bookId } } yield (author, book) lazy val authorOfBook2 = (bookId: Long) => for { (authorId, book) <- Books .filter(_.id === bookId) .take(1) .map(b => (b.authorId, b)) author <- Authors filter (_.id === authorId) } yield (author, book) lazy val authorOfBook3 = (bookId: Long) => for { (author, book) <- Authors join Books on (_.id === _.authorId) filter { case (authors, books) => books.id === bookId } map { case (authors, books) => (authors.id, authors.name).mapTo[Author] -> ( books.title, books.authorId, books.createdAt ).mapTo[BookDTO] } } yield (author, book) lazy val authorOfBook4 = (bookId: Long) => for { book <- Books author <- book.authorsFk } yield (author, book) } case class BookWithoutId(title: String, authorId: Long) // def test() = { // val maybeBook = findBookById(1) // val x = maybeBook.map(_.map(_.title)) // db.run(x) // } }