All Downloads are FREE. Search and download functionalities are using the official Maven repository.

molecule.sql.mysql.query.QueryExprSeq_mysql.scala Maven / Gradle / Ivy

The newest version!
package molecule.sql.mysql.query

import molecule.core.query.Model2Query
import molecule.sql.core.query.{QueryExprSeq, SqlQueryBase}


trait QueryExprSeq_mysql
  extends QueryExprSeq
    with LambdasSeq_mysql { self: Model2Query with SqlQueryBase =>

  // attr ----------------------------------------------------------------------

  override protected def seqAttr[T](
    col: String, res: ResSeq[T], mandatory: Boolean
  ): Unit = {
    mandatoryCast(res, mandatory)
  }

  override protected def seqOptAttr[T](
    res: ResSeq[T]
  ): Unit = {
    castStrategy.replace((row: RS, paramIndex: Int) => row.getString(paramIndex) match {
      case null | "[]" => Option.empty[Set[T]]
      case json        => Some(res.json2array(json).toList)
    })
  }

  override protected def seqHas[T](
    col: String, seq: Seq[T], one2json: T => String, res: ResSeq[T], mandatory: Boolean
  ): Unit = {
    def containsSeq(seq: Seq[T]): String = {
      val jsonValues = seq.map(one2json).mkString(", ")
      s"JSON_CONTAINS($col, JSON_ARRAY($jsonValues))"
    }
    mandatoryCast(res, mandatory)
    seq.size match {
      case 0 => where += (("FALSE", ""))
      case 1 => where += (("", s"JSON_CONTAINS($col, JSON_ARRAY(${one2json(seq.head)}))"))
      case _ => where += (("", seq.map(v => containsSeq(Seq(v))).mkString("(", " OR\n   ", ")")))
    }
  }

  override protected def seqHasNo[T](
    col: String, seq: Seq[T], one2json: T => String, res: ResSeq[T], mandatory: Boolean
  ): Unit = {
    def notContains(v: T): String = s"NOT JSON_CONTAINS($col, JSON_ARRAY(${one2json(v)}))"
    def notContainsSeq(seq: Seq[T]): String = {
      val jsonValues = seq.map(one2json).mkString(", ")
      s"NOT JSON_CONTAINS($col, JSON_ARRAY($jsonValues))"
    }
    mandatoryCast(res, mandatory)
    seq.size match {
      case 0 => ()
      case 1 => where += (("", notContains(seq.head)))
      case _ => where += (("", seq.map(v => notContainsSeq(Seq(v))).mkString("(", " AND\n   ", ")")))
    }
  }


  // filter attribute ----------------------------------------------------------

  override protected def seqFilterHas[T](
    col: String, filterAttr: String, res: ResSeq[T], mandatory: Boolean
  ): Unit = {
    where += (("", hasClause(col, filterAttr, res)))
    mandatoryCast(res, mandatory)
  }

  override protected def seqFilterHasNo[T](
    col: String, filterAttr: String, res: ResSeq[T], mandatory: Boolean
  ): Unit = {
    where += (("", s"NOT ${hasClause(col, filterAttr, res)}"))
    mandatoryCast(res, mandatory)
  }


  // helpers -------------------------------------------------------------------

  private def mandatoryCast[T](res: ResSeq[T], mandatory: Boolean): Unit = {
    if (mandatory) {
      if (isOptNested || nestedOptRef) {
        // Allow empty optional nested rows.
        // So let non-asserted Seq values (null) be checked in NestedOpt
        castStrategy.replace((row: RS, paramIndex: Int) => {
          row.getString(paramIndex) match {
            case null => null
            case s    => res.json2array(s).toList
          }
        })
      } else {
        castStrategy.replace((row: RS, paramIndex: Int) =>
          res.json2array(row.getString(paramIndex)).toList
        )
      }
    }
  }

  private def hasClause[T](col: String, filterAttr: String, res: ResSeq[T]): String = {
    res.tpe match {
      case "BigInt" =>
        s"JSON_CONTAINS($col, JSON_ARRAY(CAST($filterAttr AS CHAR)))"

      case "BigDecimal" =>
        // Compare Decimals, not Strings.
        // String representation of filterAttr pads 0's so we can't use that
        // against the truncated String representations in the json array
        s"""(
           |    SELECT count(_v) > 0
           |    FROM
           |      JSON_TABLE(
           |        $col, '$$[*]'
           |        COLUMNS(_v varchar(65) path '$$')
           |      ) AS alias
           |    WHERE CONVERT(_v, DECIMAL(65, 30)) = $filterAttr
           |  )"""

      case _ => s"JSON_CONTAINS($col, JSON_ARRAY($filterAttr))"
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy