Skip to content

Cascading Column Names for nested Case Classes. #3148

@jmpicnic

Description

@jmpicnic

Version: 4.8.6
Module: quill-jdbc-zio
Database: postgres (but also in Mirror context)

Expected behavior

I am not sure if this is a problem, a design decision or my ignorance... so apologies if this is a dumb question. I have not found much information online. Any guidance would be greatly appreciated.

I would like to be able to use case classes with multiple nested classes without column name conflicts, this is not an uncommon situation in domains (e.g. case Person(name: String, home: Address, work: Address)) . The disambiguation should not depend on the nested case class Name but on the field name of the container class.

It seems that concatenating the "tree branch" of containment is already available somewhere b/c the nested query does precisely that already.

Actual behavior

When a case class has multiple nested classes embedded, the column names generated by querySchema and schemaMeta use only the name of the leaf field for the column, causing conflicts in column names.

Steps to reproduce the behavior

Here is the Scastie Snippet: https://scastie.scala-lang.org/jmpicnic/XKX7Cd8fSpyfi9nlpdzOvQ/1

import io.getquill.*

case class O(a: String, b: Long)
case class P(x: String, a: Int, b: Boolean, o1: O, o2: O)

val ctx = new SqlMirrorContext(MirrorSqlDialect, Literal)

import ctx.*

// inline def probeSch: Quoted[EntityQuery[P]] = quote(querySchema[P]("p_table"))
implicit val pSchM: SchemaMeta[P] = schemaMeta[P]("P_TABLE")

val rs1 = ctx.run(query[P])
rs1.string(true)

val rs2 = ctx.run(query[P].nested)
rs2.string(true)

Workaround

None that I have been able to find in a way that would scale. It is possible to override column names in the schema definition, but on a one by one basis, which is impractical for commonly used "value classes" like Adddress, Unit Of Measure, etc... that get used all over the place.

I explored using a naming strategy but the input to the columns method is only the leaf name (it seems it would be easy to implement this in almost a backwards compatible way if the naming strategy method would have a signature as def columns(path: String*): String representing the tree path from the root, with the default being the current behavior.

I tried to dig into the SchemaMeta generation, but ended up being too much.

@getquill/maintainers

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions