From 17d53d1b79e302d10f9edcf09cfb67990f620ae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Raddum=20Berg?= Date: Sat, 17 Feb 2024 21:53:04 +0100 Subject: [PATCH] `selectByUnique` must select all columns (Fixes #84) --- .../production/document/DocumentRepoImpl.scala | 2 +- .../public/users/UsersRepoImpl.scala | 2 +- .../production/document/DocumentRepoImpl.scala | 2 +- .../public/users/UsersRepoImpl.scala | 2 +- .../production/document/DocumentRepoImpl.scala | 2 +- .../public/users/UsersRepoImpl.scala | 2 +- typo/src/scala/typo/internal/ComputedTable.scala | 9 +++++++-- typo/src/scala/typo/internal/RepoMethod.scala | 5 +++-- .../scala/typo/internal/codegen/DbLibAnorm.scala | 14 +++++++------- .../scala/typo/internal/codegen/DbLibDoobie.scala | 14 +++++++------- .../scala/typo/internal/codegen/DbLibZioJdbc.scala | 14 +++++++------- 11 files changed, 37 insertions(+), 31 deletions(-) diff --git a/typo-tester-anorm/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala b/typo-tester-anorm/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala index 812957b415..9c6fb0bac6 100644 --- a/typo-tester-anorm/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala +++ b/typo-tester-anorm/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala @@ -120,7 +120,7 @@ class DocumentRepoImpl extends DocumentRepo { } override def selectByUnique(rowguid: TypoUUID)(implicit c: Connection): Option[DocumentRow] = { - SQL"""select "rowguid" + SQL"""select "title", "owner", "folderflag", "filename", "fileextension", "revision", "changenumber", "status", "documentsummary", "document", "rowguid", "modifieddate"::text, "documentnode" from production.document where "rowguid" = ${ParameterValue(rowguid, null, TypoUUID.toStatement)} """.as(DocumentRow.rowParser(1).singleOpt) diff --git a/typo-tester-anorm/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala b/typo-tester-anorm/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala index 7013340f88..0354514b0e 100644 --- a/typo-tester-anorm/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala +++ b/typo-tester-anorm/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala @@ -98,7 +98,7 @@ class UsersRepoImpl extends UsersRepo { } override def selectByUnique(email: TypoUnknownCitext)(implicit c: Connection): Option[UsersRow] = { - SQL"""select "email"::text + SQL"""select "user_id", "name", "last_name", "email"::text, "password", "created_at"::text, "verified_on"::text from public.users where "email" = ${ParameterValue(email, null, TypoUnknownCitext.toStatement)} """.as(UsersRow.rowParser(1).singleOpt) diff --git a/typo-tester-doobie/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala b/typo-tester-doobie/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala index 52c7b73dbd..a86149db5c 100644 --- a/typo-tester-doobie/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala +++ b/typo-tester-doobie/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala @@ -106,7 +106,7 @@ class DocumentRepoImpl extends DocumentRepo { sql"""select "title", "owner", "folderflag", "filename", "fileextension", "revision", "changenumber", "status", "documentsummary", "document", "rowguid", "modifieddate"::text, "documentnode" from production.document where "documentnode" = ANY(${documentnodes})""".query(DocumentRow.read).stream } override def selectByUnique(rowguid: TypoUUID): ConnectionIO[Option[DocumentRow]] = { - sql"""select "rowguid" + sql"""select "title", "owner", "folderflag", "filename", "fileextension", "revision", "changenumber", "status", "documentsummary", "document", "rowguid", "modifieddate"::text, "documentnode" from production.document where "rowguid" = ${fromWrite(rowguid)(Write.fromPut(TypoUUID.put))} """.query(DocumentRow.read).option diff --git a/typo-tester-doobie/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala b/typo-tester-doobie/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala index a80930dc3d..18e3e35a32 100644 --- a/typo-tester-doobie/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala +++ b/typo-tester-doobie/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala @@ -84,7 +84,7 @@ class UsersRepoImpl extends UsersRepo { sql"""select "user_id", "name", "last_name", "email"::text, "password", "created_at"::text, "verified_on"::text from public.users where "user_id" = ANY(${userIds})""".query(UsersRow.read).stream } override def selectByUnique(email: TypoUnknownCitext): ConnectionIO[Option[UsersRow]] = { - sql"""select "email"::text + sql"""select "user_id", "name", "last_name", "email"::text, "password", "created_at"::text, "verified_on"::text from public.users where "email" = ${fromWrite(email)(Write.fromPut(TypoUnknownCitext.put))} """.query(UsersRow.read).option diff --git a/typo-tester-zio-jdbc/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala b/typo-tester-zio-jdbc/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala index 723eaf491e..7a30953178 100644 --- a/typo-tester-zio-jdbc/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala +++ b/typo-tester-zio-jdbc/generated-and-checked-in/adventureworks/production/document/DocumentRepoImpl.scala @@ -105,7 +105,7 @@ class DocumentRepoImpl extends DocumentRepo { sql"""select "title", "owner", "folderflag", "filename", "fileextension", "revision", "changenumber", "status", "documentsummary", "document", "rowguid", "modifieddate"::text, "documentnode" from production.document where "documentnode" = ANY(${Segment.paramSegment(documentnodes)(DocumentId.arraySetter)})""".query(DocumentRow.jdbcDecoder).selectStream } override def selectByUnique(rowguid: TypoUUID): ZIO[ZConnection, Throwable, Option[DocumentRow]] = { - sql"""select "rowguid" + sql"""select "title", "owner", "folderflag", "filename", "fileextension", "revision", "changenumber", "status", "documentsummary", "document", "rowguid", "modifieddate"::text, "documentnode" from production.document where "rowguid" = ${Segment.paramSegment(rowguid)(TypoUUID.setter)} """.query(DocumentRow.jdbcDecoder).selectOne diff --git a/typo-tester-zio-jdbc/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala b/typo-tester-zio-jdbc/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala index b12e7214ab..8f13ba0cbe 100644 --- a/typo-tester-zio-jdbc/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala +++ b/typo-tester-zio-jdbc/generated-and-checked-in/adventureworks/public/users/UsersRepoImpl.scala @@ -83,7 +83,7 @@ class UsersRepoImpl extends UsersRepo { sql"""select "user_id", "name", "last_name", "email"::text, "password", "created_at"::text, "verified_on"::text from public.users where "user_id" = ANY(${Segment.paramSegment(userIds)(UsersId.arraySetter)})""".query(UsersRow.jdbcDecoder).selectStream } override def selectByUnique(email: TypoUnknownCitext): ZIO[ZConnection, Throwable, Option[UsersRow]] = { - sql"""select "email"::text + sql"""select "user_id", "name", "last_name", "email"::text, "password", "created_at"::text, "verified_on"::text from public.users where "email" = ${Segment.paramSegment(email)(TypoUnknownCitext.setter)} """.query(UsersRow.jdbcDecoder).selectOne diff --git a/typo/src/scala/typo/internal/ComputedTable.scala b/typo/src/scala/typo/internal/ComputedTable.scala index 1260bc1cb9..d448b7468b 100644 --- a/typo/src/scala/typo/internal/ComputedTable.scala +++ b/typo/src/scala/typo/internal/ComputedTable.scala @@ -194,9 +194,14 @@ case class ComputedTable( ).flatten, dbTable.uniqueKeys .map { uk => - RepoMethod.SelectByUnique(dbTable.name, uk.cols.map(colName => cols.find(_.dbName == colName).get), names.RowName) + RepoMethod.SelectByUnique( + dbTable.name, + keyColumns = uk.cols.map(colName => cols.find(_.dbName == colName).get), + allColumns = cols, + rowType = names.RowName + ) } - .distinctByCompat(x => x.params.map(_.tpe)) // avoid erasure clashes + .distinctByCompat(x => x.keyColumns.map(_.tpe)) // avoid erasure clashes ) val valid = maybeMethods.flatten.filter { case _: RepoMethod.Mutator => !options.readonlyRepo.include(dbTable.name) diff --git a/typo/src/scala/typo/internal/RepoMethod.scala b/typo/src/scala/typo/internal/RepoMethod.scala index b7c7ad8e57..c55f2b0379 100644 --- a/typo/src/scala/typo/internal/RepoMethod.scala +++ b/typo/src/scala/typo/internal/RepoMethod.scala @@ -38,7 +38,8 @@ object RepoMethod { case class SelectByUnique( relName: db.RelationName, - params: NonEmptyList[ComputedColumn], + keyColumns: NonEmptyList[ComputedColumn], + allColumns: NonEmptyList[ComputedColumn], rowType: sc.Type ) extends Selector @@ -128,7 +129,7 @@ object RepoMethod { case _: SelectAll => "Select2" case _: SelectById => "Select3" case _: SelectAllByIds => "Select4" - case x: SelectByUnique => s"SelectByUnique(${x.params.map(_.name.value).mkString(", ")})" + case x: SelectByUnique => s"SelectByUnique(${x.keyColumns.map(_.name.value).mkString(", ")})" case _: SelectByFieldValues => "SelectByFieldValues" case _: UpdateFieldValues => "UpdateFieldValues" case _: Update => "Update1" diff --git a/typo/src/scala/typo/internal/codegen/DbLibAnorm.scala b/typo/src/scala/typo/internal/codegen/DbLibAnorm.scala index f94076179d..fbc454cdab 100644 --- a/typo/src/scala/typo/internal/codegen/DbLibAnorm.scala +++ b/typo/src/scala/typo/internal/codegen/DbLibAnorm.scala @@ -172,8 +172,8 @@ class DbLibAnorm(pkg: sc.QIdent, inlineImplicits: Boolean, default: ComputedDefa case _ => code"def selectByIds($idsParam)(implicit c: ${TypesJava.Connection}): ${TypesScala.List.of(rowType)}" } - case RepoMethod.SelectByUnique(_, cols, rowType) => - code"def selectByUnique(${cols.map(_.param.code).mkCode(", ")})(implicit c: ${TypesJava.Connection}): ${TypesScala.Option.of(rowType)}" + case RepoMethod.SelectByUnique(_, keyColumns, _, rowType) => + code"def selectByUnique(${keyColumns.map(_.param.code).mkCode(", ")})(implicit c: ${TypesJava.Connection}): ${TypesScala.Option.of(rowType)}" case RepoMethod.SelectByFieldValues(_, _, _, fieldValueOrIdsParam, rowType) => code"def selectByFieldValues($fieldValueOrIdsParam)(implicit c: ${TypesJava.Connection}): ${TypesScala.List.of(rowType)}" case RepoMethod.UpdateBuilder(_, fieldsType, rowType) => @@ -240,11 +240,11 @@ class DbLibAnorm(pkg: sc.QIdent, inlineImplicits: Boolean, default: ComputedDefa case RepoMethod.UpdateBuilder(relName, fieldsType, rowType) => code"${sc.Type.dsl.UpdateBuilder}(${sc.StrLit(relName.value)}, $fieldsType, $rowType.rowParser)" - case RepoMethod.SelectByUnique(relName, cols, rowType) => + case RepoMethod.SelectByUnique(relName, keyColumns, allCols, rowType) => val sql = SQL { - code"""|select ${dbNames(cols, isRead = true)} + code"""|select ${dbNames(allCols, isRead = true)} |from $relName - |where ${cols.map(c => code"${c.dbName.code} = ${runtimeInterpolateValue(c.name, c.tpe)}").mkCode(" AND ")} + |where ${keyColumns.map(c => code"${c.dbName.code} = ${runtimeInterpolateValue(c.name, c.tpe)}").mkCode(" AND ")} |""".stripMargin } @@ -466,8 +466,8 @@ class DbLibAnorm(pkg: sc.QIdent, inlineImplicits: Boolean, default: ComputedDefa code"map.get(${id.paramName})" case RepoMethod.SelectAllByIds(_, _, _, idsParam, _) => code"${idsParam.name}.flatMap(map.get).toList" - case RepoMethod.SelectByUnique(_, cols, _) => - code"map.values.find(v => ${cols.map(c => code"${c.name} == v.${c.name}").mkCode(" && ")})" + case RepoMethod.SelectByUnique(_, keyColumns, _, _) => + code"map.values.find(v => ${keyColumns.map(c => code"${c.name} == v.${c.name}").mkCode(" && ")})" case RepoMethod.SelectByFieldValues(_, cols, fieldValue, fieldValueOrIdsParam, _) => val cases = cols.map { col => diff --git a/typo/src/scala/typo/internal/codegen/DbLibDoobie.scala b/typo/src/scala/typo/internal/codegen/DbLibDoobie.scala index c1b3b616e9..199be00790 100644 --- a/typo/src/scala/typo/internal/codegen/DbLibDoobie.scala +++ b/typo/src/scala/typo/internal/codegen/DbLibDoobie.scala @@ -74,8 +74,8 @@ class DbLibDoobie(pkg: sc.QIdent, inlineImplicits: Boolean, default: ComputedDef case _ => code"def selectByIds($idsParam): ${fs2Stream.of(ConnectionIO, rowType)}" } - case RepoMethod.SelectByUnique(_, params, rowType) => - code"def selectByUnique(${params.map(_.param.code).mkCode(", ")}): ${ConnectionIO.of(TypesScala.Option.of(rowType))}" + case RepoMethod.SelectByUnique(_, keyColumns, _, rowType) => + code"def selectByUnique(${keyColumns.map(_.param.code).mkCode(", ")}): ${ConnectionIO.of(TypesScala.Option.of(rowType))}" case RepoMethod.SelectByFieldValues(_, _, _, fieldValueOrIdsParam, rowType) => code"def selectByFieldValues($fieldValueOrIdsParam): ${fs2Stream.of(ConnectionIO, rowType)}" case RepoMethod.UpdateBuilder(_, fieldsType, rowType) => @@ -135,11 +135,11 @@ class DbLibDoobie(pkg: sc.QIdent, inlineImplicits: Boolean, default: ComputedDef code"""select $joinedColNames from $relName where ${code"${unaryId.col.dbName.code} = ANY(${runtimeInterpolateValue(idsParam.name, idsParam.tpe, forbidInline = true)})"}""" ) code"""${query(sql, rowType)}.stream""" - case RepoMethod.SelectByUnique(relName, cols, rowType) => + case RepoMethod.SelectByUnique(relName, keyColumns, allColumns, rowType) => val sql = SQL { - code"""|select ${dbNames(cols, isRead = true)} + code"""|select ${dbNames(allColumns, isRead = true)} |from $relName - |where ${cols.map(c => code"${c.dbName.code} = ${runtimeInterpolateValue(c.name, c.tpe)}").mkCode(" AND ")} + |where ${keyColumns.map(c => code"${c.dbName.code} = ${runtimeInterpolateValue(c.name, c.tpe)}").mkCode(" AND ")} |""".stripMargin } code"""${query(sql, rowType)}.option""" @@ -333,8 +333,8 @@ class DbLibDoobie(pkg: sc.QIdent, inlineImplicits: Boolean, default: ComputedDef code"$delayCIO(map.get(${id.paramName}))" case RepoMethod.SelectAllByIds(_, _, _, idsParam, _) => code"$fs2Stream.emits(${idsParam.name}.flatMap(map.get).toList)" - case RepoMethod.SelectByUnique(_, cols, _) => - code"${delayCIO}(map.values.find(v => ${cols.map(c => code"${c.name} == v.${c.name}").mkCode(" && ")}))" + case RepoMethod.SelectByUnique(_, keyColumns, _, _) => + code"${delayCIO}(map.values.find(v => ${keyColumns.map(c => code"${c.name} == v.${c.name}").mkCode(" && ")}))" case RepoMethod.SelectByFieldValues(_, cols, fieldValue, fieldValueOrIdsParam, _) => val cases = cols.map { col => diff --git a/typo/src/scala/typo/internal/codegen/DbLibZioJdbc.scala b/typo/src/scala/typo/internal/codegen/DbLibZioJdbc.scala index 59ea662c94..cebe92ba8e 100644 --- a/typo/src/scala/typo/internal/codegen/DbLibZioJdbc.scala +++ b/typo/src/scala/typo/internal/codegen/DbLibZioJdbc.scala @@ -193,8 +193,8 @@ class DbLibZioJdbc(pkg: sc.QIdent, inlineImplicits: Boolean, dslEnabled: Boolean case _ => code"def selectByIds($idsParam): ${ZStream.of(ZConnection, Throwable, rowType)}" } - case RepoMethod.SelectByUnique(_, params, rowType) => - code"def selectByUnique(${params.map(_.param.code).mkCode(", ")}): ${ZIO.of(ZConnection, Throwable, TypesScala.Option.of(rowType))}" + case RepoMethod.SelectByUnique(_, keyColumns, _, rowType) => + code"def selectByUnique(${keyColumns.map(_.param.code).mkCode(", ")}): ${ZIO.of(ZConnection, Throwable, TypesScala.Option.of(rowType))}" case RepoMethod.SelectByFieldValues(_, _, _, fieldValueOrIdsParam, rowType) => code"def selectByFieldValues($fieldValueOrIdsParam): ${ZStream.of(ZConnection, Throwable, rowType)}" case RepoMethod.UpdateBuilder(_, fieldsType, rowType) => @@ -254,11 +254,11 @@ class DbLibZioJdbc(pkg: sc.QIdent, inlineImplicits: Boolean, dslEnabled: Boolean code"""select $joinedColNames from $relName where ${unaryId.col.dbName} = ANY(${runtimeInterpolateValue(idsParam.name, idsParam.tpe)})""" ) code"""$sql.query(${lookupJdbcDecoder(rowType)}).selectStream""" - case RepoMethod.SelectByUnique(relName, cols, rowType) => + case RepoMethod.SelectByUnique(relName, keyColumns, allCols, rowType) => val sql = SQL { - code"""|select ${dbNames(cols, isRead = true)} + code"""|select ${dbNames(allCols, isRead = true)} |from $relName - |where ${cols.map(c => code"${c.dbName} = ${runtimeInterpolateValue(c.name, c.tpe)}").mkCode(" AND ")} + |where ${keyColumns.map(c => code"${c.dbName} = ${runtimeInterpolateValue(c.name, c.tpe)}").mkCode(" AND ")} |""".stripMargin } code"""$sql.query(${lookupJdbcDecoder(rowType)}).selectOne""" @@ -450,8 +450,8 @@ class DbLibZioJdbc(pkg: sc.QIdent, inlineImplicits: Boolean, dslEnabled: Boolean code"$ZIO.succeed(map.get(${id.paramName}))" case RepoMethod.SelectAllByIds(_, _, _, idsParam, _) => code"$ZStream.fromIterable(${idsParam.name}.flatMap(map.get))" - case RepoMethod.SelectByUnique(_, cols, _) => - code"$ZIO.succeed(map.values.find(v => ${cols.map(c => code"${c.name} == v.${c.name}").mkCode(" && ")}))" + case RepoMethod.SelectByUnique(_, keyColumns, _, _) => + code"$ZIO.succeed(map.values.find(v => ${keyColumns.map(c => code"${c.name} == v.${c.name}").mkCode(" && ")}))" case RepoMethod.SelectByFieldValues(_, cols, fieldValue, fieldValueOrIdsParam, _) => val cases = cols.map { col =>