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

molecule.datalog.datomic.transaction.Delete_datomic.scala Maven / Gradle / Ivy

There is a newer version: 0.12.1
Show newest version
package molecule.datalog.datomic.transaction

import datomic.Peer
import molecule.base.error.ExecutionError
import molecule.boilerplate.ast.Model._
import molecule.boilerplate.util.MoleculeLogging
import molecule.core.transaction.ResolveDelete
import molecule.core.transaction.ops.DeleteOps
import molecule.core.util.{JavaConversions, MetaModelUtils}
import molecule.datalog.core.query.Model2DatomicQuery
import molecule.datalog.datomic.facade.DatomicConn_JVM
import scala.collection.mutable

trait Delete_datomic
  extends DatomicBase_JVM
    with DeleteOps
    with MetaModelUtils
    with MoleculeLogging
    with JavaConversions { self: ResolveDelete =>

  def getData(
    conn: DatomicConn_JVM,
    elements: List[Element],
    idIndex: Int = 0,
    debug: Boolean = true
  ): Data = {
    initTxBase(elements, idIndex)

    // Resolve the delete model
    resolve(elements, true)

    val (filterQuery, inputs) = if (ids.isEmpty && filterElements.nonEmpty) {
      val filterElements1 = AttrOneManID("DummyNs", "id", V) +: filterElements
      val (query, inputs) = new Model2DatomicQuery[Any](filterElements1).getIdQueryWithInputs
      (Some(query), inputs)
    } else {
      (None, Nil)
    }

    lazy val db = conn.peerConn.db()
    val ids1 = filterQuery.fold(ids)(query =>
      Peer.q(query, db +: inputs: _*).asScala.toList.map(_.get(0))
    )

    // Add retract stmts
    ids1.foreach(addRetractEntityStmt)

    // Prevent deleting mandatory referenced entities
    if (getHasMandatoryRefs(conn.proxy.nsMap)) {
      val referrers = Peer.q(
        s"""[:find  ?ns ?attr ?refs
           | :in    $$ [?ids ...]
           | :where [?refs ?a ?ids]
           |        [?a :db/ident ?attrIdent]
           |        [(namespace ?attrIdent) ?ns]
           |        [(name ?attrIdent) ?attr]
           |]""".stripMargin, db, ids1.asJava
      )
      if (referrers.size() != 0) {
        val refIds = mutable.Map.empty[String, List[Long]]
        referrers.forEach { row =>
          val refAttr = s"${row.get(0)}.${row.get(1)}"
          refIds.get(refAttr).fold[Unit](
            refIds += refAttr -> List(row.get(2).asInstanceOf[Long])
          )(curRefIds =>
            refIds(refAttr) = curRefIds :+ row.get(2).asInstanceOf[Long]
          )
        }
        if (refIds.nonEmpty) {
          val refAttrsStr = refIds.toList.sortBy(_._1).map {
            case (refAttr, ids) => s"$refAttr: List(${ids.mkString(", ")})"
          }
          throw ExecutionError(
            s"""Can't delete entities referenced by mandatory ref attributes of other entities:
               |  ${refAttrsStr.mkString("\n  ")}
               |""".stripMargin
          )
        }
      }
    }
    if (debug) {
      val deleteStrs = "DELETE:" +: elements :+ "" :+ stmts.toArray().mkString("\n")
      logger.debug(deleteStrs.mkString("\n").trim)
    }
    stmts
  }

  override def addIds(ids1: Seq[String]): Unit = {
    ids = ids ++ ids1.map(_.toLong).asInstanceOf[Seq[AnyRef]]
  }

  override def addFilterElement(element: Element): Unit = {
    filterElements = filterElements :+ element
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy