Skip to content

Commit cfe33a8

Browse files
committed
remove update statement if table is a view
1 parent 3810d83 commit cfe33a8

2 files changed

Lines changed: 101 additions & 75 deletions

File tree

modules/core/src/main/scala/com/anymindgroup/PgCodeGen.scala

Lines changed: 92 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -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)

modules/core/src/test/resources/db/migration/V1__test.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,12 @@ CREATE MATERIALIZED VIEW public.test_materialized_view AS SELECT id,
4444
name_2,
4545
number
4646
FROM test WITH DATA;
47+
48+
49+
CREATE VIEW public.test_view AS SELECT id,
50+
created_at,
51+
name,
52+
name_2,
53+
number,
54+
numeric_default
55+
FROM test;

0 commit comments

Comments
 (0)