@@ -178,6 +178,15 @@ class PgCodeGen(
178178 }
179179 }
180180
181+ private def getViews (s : Session [IO ]): IO [Set [TableName ]] = {
182+ val q : Query [Void , String ] =
183+ sql """ SELECT table_name FROM information_schema.VIEWS WHERE table_schema = 'public'
184+ UNION
185+ SELECT matviewname FROM pg_matviews WHERE schemaname = 'public'; """ .query(name)
186+
187+ s.execute(q).map(_.toSet)
188+ }
189+
181190 private val postgresDBSingleSession = Session
182191 .single[IO ](
183192 host = host,
@@ -236,9 +245,9 @@ class PgCodeGen(
236245 _ <- s.execute(sql " CREATE SCHEMA public; " .command)
237246 _ <- dumbo.runMigration.void
238247 enums <- getEnums(s)
239- ((columns, indexes), constraints) <-
240- getColumns(s, enums).parProduct(getIndexes(s)).parProduct(getConstraints(s))
241- tables = toTables(columns, indexes, constraints)
248+ ((( columns, indexes), constraints), views ) <-
249+ getColumns(s, enums).parProduct(getIndexes(s)).parProduct(getConstraints(s)).parProduct(getViews(s))
250+ tables = toTables(columns, indexes, constraints, views )
242251 files = pkgFiles(tables, enums) ::: tables.flatMap { table =>
243252 rowFileContent(table) match {
244253 case None => Nil
@@ -289,6 +298,7 @@ class PgCodeGen(
289298 columns : TableMap [Column ],
290299 indexes : TableMap [Index ],
291300 constraints : TableMap [Constraint ],
301+ views : Set [TableName ],
292302 ): List [Table ] = {
293303
294304 def findAutoIncColumns (tableName : TableName ): List [Column ] =
@@ -322,6 +332,7 @@ class PgCodeGen(
322332 constraints = tableConstraints,
323333 indexes = indexes.getOrElse(tname, Nil ),
324334 autoIncFk = autoIncFk,
335+ isView = views.contains(tname),
325336 )
326337 }
327338 }
@@ -511,29 +522,32 @@ class PgCodeGen(
511522 """
512523 }
513524
514- val rowUpdateClassData = primaryUniqueConstraint match {
515- case Some (cstr) =>
516- columns.filterNot(cstr.containsColumn) match {
517- case Nil => (Nil , Nil )
518- case updateCols =>
519- val colsData = toUpdateClassPropsStr(updateCols)
520- val fragmentData = toUpdateFragment(updateCols)
521- (
522- updateCols,
523- List (
524- " " ,
525- s " final case class $rowUpdateClassName( " ,
526- s " $colsData" ,
527- " ) {" ,
528- fragmentData,
529- " }" ,
530- ),
531- )
525+ val rowUpdateClassData =
526+ if (table.isView) (Nil , Nil )
527+ else
528+ primaryUniqueConstraint match {
529+ case Some (cstr) =>
530+ columns.filterNot(cstr.containsColumn) match {
531+ case Nil => (Nil , Nil )
532+ case updateCols =>
533+ val colsData = toUpdateClassPropsStr(updateCols)
534+ val fragmentData = toUpdateFragment(updateCols)
535+ (
536+ updateCols,
537+ List (
538+ " " ,
539+ s " final case class $rowUpdateClassName( " ,
540+ s " $colsData" ,
541+ " ) {" ,
542+ fragmentData,
543+ " }" ,
544+ ),
545+ )
546+ }
547+
548+ case None => (Nil , Nil )
532549 }
533550
534- case None => (Nil , Nil )
535- }
536-
537551 def withImportsStr = rowUpdateClassData match {
538552 case (Nil , Nil ) => " "
539553 case (_, _) => List (" import skunk.implicits.*" , " import cats.implicits.*" ).mkString(" \n " )
@@ -617,64 +631,66 @@ class PgCodeGen(
617631 }
618632 }
619633
620- private def writeStatements (table : Table ): String = {
621- import table .*
634+ private def writeStatements (table : Table ): String =
635+ if (table.isView) " "
636+ else {
637+ import table .*
622638
623- val allCols = autoIncFk ::: columns
624- val allColNames = allCols.map(_.columnName).mkString(" ," )
625- val (insertScalaType, insertCodec) = queryTypesStr(table)
639+ val allCols = autoIncFk ::: columns
640+ val allColNames = allCols.map(_.columnName).mkString(" ," )
641+ val (insertScalaType, insertCodec) = queryTypesStr(table)
626642
627- val returningStatement = autoIncColumns match {
628- case Nil => " "
629- case _ => autoIncColumns.map(_.columnName).mkString(" RETURNING " , " ," , " " )
630- }
631- val returningType = autoIncColumns.map(_.scalaType).mkString(" *: " )
632- val fragmentType = autoIncColumns match {
633- case Nil => " command"
634- case _ => s " query( ${autoIncColumns.map(col => s " skunk.codec.all. ${col.pgType.name}" ).mkString(" *: " )}) "
635- }
643+ val returningStatement = autoIncColumns match {
644+ case Nil => " "
645+ case _ => autoIncColumns.map(_.columnName).mkString(" RETURNING " , " ," , " " )
646+ }
647+ val returningType = autoIncColumns.map(_.scalaType).mkString(" *: " )
648+ val fragmentType = autoIncColumns match {
649+ case Nil => " command"
650+ case _ => s " query( ${autoIncColumns.map(col => s " skunk.codec.all. ${col.pgType.name}" ).mkString(" *: " )}) "
651+ }
636652
637- val upsertQ = primaryUniqueConstraint.map { cstr =>
638- val queryType = autoIncColumns match {
639- case Nil => s " Command[ $insertScalaType *: updateFr.A *: EmptyTuple] "
640- case _ => s " Query[ $insertScalaType *: updateFr.A *: EmptyTuple, $returningType] "
653+ val upsertQ = primaryUniqueConstraint.map { cstr =>
654+ val queryType = autoIncColumns match {
655+ case Nil => s " Command[ $insertScalaType *: updateFr.A *: EmptyTuple] "
656+ case _ => s " Query[ $insertScalaType *: updateFr.A *: EmptyTuple, $returningType] "
657+ }
658+
659+ s """ | def upsertQuery(updateFr: AppliedFragment): $queryType =
660+ | sql\"\"\"INSERT INTO # $$ tableName ( $allColNames) VALUES ( $$ { $insertCodec})
661+ | ON CONFLICT ON CONSTRAINT ${cstr.name}
662+ | DO UPDATE SET $$ {updateFr.fragment} $returningStatement\"\"\". $fragmentType""" .stripMargin
641663 }
642664
643- s """ | def upsertQuery(updateFr: AppliedFragment): $queryType =
644- | sql\"\"\"INSERT INTO # $$ tableName ( $allColNames) VALUES ( $$ { $insertCodec})
645- | ON CONFLICT ON CONSTRAINT ${cstr.name}
646- | DO UPDATE SET $$ {updateFr.fragment} $returningStatement\"\"\". $fragmentType""" .stripMargin
647- }
665+ val queryType = autoIncColumns match {
666+ case Nil => s " Command[ $insertScalaType] "
667+ case _ => s " Query[ $insertScalaType, $returningType] "
668+ }
669+ val insertQ =
670+ s """ | def insertQuery(ignoreConflict: Boolean = true): $queryType = {
671+ | val onConflictFr = if (ignoreConflict) const" ON CONFLICT DO NOTHING" else const""
672+ | sql\"INSERT INTO # $$ tableName ( $allColNames) VALUES ( $$ { $insertCodec}) $$ onConflictFr $returningStatement\". $fragmentType
673+ | } """ .stripMargin
648674
649- val queryType = autoIncColumns match {
650- case Nil => s " Command[ $insertScalaType] "
651- case _ => s " Query[ $insertScalaType, $returningType] "
675+ val insertCol =
676+ s """ |
677+ | def insert[A](cols: Cols[A]): Command[A] =
678+ | sql\"INSERT INTO # $$ tableName (# $$ {cols.name}) VALUES ( $$ {cols.codec})\".command
679+ |
680+ | def insert0[A, B](cols: Cols[A], rest: Fragment[B] = sql"ON CONFLICT DO NOTHING")(implicit
681+ | ev: Void =:= B
682+ | ): Command[A] =
683+ | (sql\"INSERT INTO # $$ tableName (# $$ {cols.name}) VALUES ( $$ {cols.codec}) " ~ rest).command.contramap[A](a => (a, ev.apply(Void)))
684+ |
685+ | def insert[A, B](cols: Cols[A], rest: Fragment[B] = sql"ON CONFLICT DO NOTHING"): Command[(A, B)] =
686+ | (sql\"INSERT INTO # $$ tableName (# $$ {cols.name}) VALUES ( $$ {cols.codec})" ~ rest).command
687+ | """ .stripMargin
688+ List (
689+ upsertQ.getOrElse(" " ),
690+ insertQ,
691+ insertCol,
692+ ).mkString(" \n\n " )
652693 }
653- val insertQ =
654- s """ | def insertQuery(ignoreConflict: Boolean = true): $queryType = {
655- | val onConflictFr = if (ignoreConflict) const" ON CONFLICT DO NOTHING" else const""
656- | sql\"INSERT INTO # $$ tableName ( $allColNames) VALUES ( $$ { $insertCodec}) $$ onConflictFr $returningStatement\". $fragmentType
657- | } """ .stripMargin
658-
659- val insertCol =
660- s """ |
661- | def insert[A](cols: Cols[A]): Command[A] =
662- | sql\"INSERT INTO # $$ tableName (# $$ {cols.name}) VALUES ( $$ {cols.codec})\".command
663- |
664- | def insert0[A, B](cols: Cols[A], rest: Fragment[B] = sql"ON CONFLICT DO NOTHING")(implicit
665- | ev: Void =:= B
666- | ): Command[A] =
667- | (sql\"INSERT INTO # $$ tableName (# $$ {cols.name}) VALUES ( $$ {cols.codec}) " ~ rest).command.contramap[A](a => (a, ev.apply(Void)))
668- |
669- | def insert[A, B](cols: Cols[A], rest: Fragment[B] = sql"ON CONFLICT DO NOTHING"): Command[(A, B)] =
670- | (sql\"INSERT INTO # $$ tableName (# $$ {cols.name}) VALUES ( $$ {cols.codec})" ~ rest).command
671- | """ .stripMargin
672- List (
673- upsertQ.getOrElse(" " ),
674- insertQ,
675- insertCol,
676- ).mkString(" \n\n " )
677- }
678694
679695 private def tableColumns (table : Table ): (Option [String ], String ) = {
680696 val allCols = table.autoIncColumns ::: table.autoIncFk ::: table.columns
@@ -837,6 +853,7 @@ object PgCodeGen {
837853 constraints : List [Constraint ],
838854 indexes : List [Index ],
839855 autoIncFk : List [Column ],
856+ isView : Boolean ,
840857 ) {
841858 val tableClassName : String = toTableClassName(name)
842859 val rowClassName : String = toRowClassName(name)
0 commit comments