Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions magnum/src/main/scala/com/augustnagro/magnum/ClickhouseDbType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object ClickhouseDbType extends DbType:
eElemCodecs: Seq[DbCodec[?]],
ecElemNames: Seq[String],
ecElemNamesSql: Seq[String],
idIndex: Int
idIndexes: List[Int]
)(using
eCodec: DbCodec[E],
ecCodec: DbCodec[EC],
Expand All @@ -29,20 +29,23 @@ object ClickhouseDbType extends DbType:
eClassTag.runtimeClass == ecClassTag.runtimeClass,
"ClickHouse does not support generated keys, so EC must equal E"
)
val idName = eElemNamesSql(idIndex)
val idNames = idIndexes.map(eElemNamesSql)
val idKeys = idNames.mkString("(", ", ", ")")
val selectKeys = eElemNamesSql.mkString(", ")
val ecInsertKeys = ecElemNamesSql.mkString("(", ", ", ")")
val eElemNamesAndCodecs = eElemNamesSql.lazyZip(eElemCodecs)
val idFilter = idKeys + " = " + idCodec.queryRepr

val countSql = s"SELECT count(*) FROM $tableNameSql"
val countQuery = Frag(countSql, Vector.empty, FragWriter.empty).query[Long]
val existsByIdSql =
s"SELECT 1 FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
s"SELECT 1 FROM $tableNameSql WHERE $idFilter"
val findAllSql = s"SELECT $selectKeys FROM $tableNameSql"
val findAllQuery = Frag(findAllSql, Vector.empty, FragWriter.empty).query[E]
val findByIdSql =
s"SELECT $selectKeys FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
s"SELECT $selectKeys FROM $tableNameSql WHERE $idFilter"
val deleteByIdSql =
s"DELETE FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
s"DELETE FROM $tableNameSql WHERE $idFilter"
val truncateSql = s"TRUNCATE TABLE $tableNameSql"
val truncateUpdate =
Frag(truncateSql, Vector.empty, FragWriter.empty).update
Expand All @@ -53,6 +56,12 @@ object ClickhouseDbType extends DbType:
idCodec.writeSingle(id, ps, pos)
pos + idCodec.cols.length

def entityId(entity: E): ID =
val idElems = idIndexes.map(entity.asInstanceOf[Product].productElement)
idElems match
case head :: Nil => head.asInstanceOf[ID]
case _ => idClassTag.runtimeClass.getDeclaredConstructors().head.newInstance(idElems*).asInstanceOf[ID]

new RepoDefaults[EC, E, ID]:
def count(using con: DbCon): Long = countQuery.run().head

Expand All @@ -77,12 +86,7 @@ object ClickhouseDbType extends DbType:
throw UnsupportedOperationException()

def delete(entity: E)(using DbCon): Unit =
deleteById(
entity
.asInstanceOf[Product]
.productElement(idIndex)
.asInstanceOf[ID]
)
deleteById(entityId(entity))

def deleteById(id: ID)(using DbCon): Unit =
Frag(deleteByIdSql, IArray(id), idWriter(id)).update
Expand All @@ -93,9 +97,7 @@ object ClickhouseDbType extends DbType:

def deleteAll(entities: Iterable[E])(using DbCon): BatchUpdateResult =
deleteAllById(
entities.map(e =>
e.asInstanceOf[Product].productElement(idIndex).asInstanceOf[ID]
)
entities.map(entityId)
)

def deleteAllById(ids: Iterable[ID])(using
Expand Down
2 changes: 1 addition & 1 deletion magnum/src/main/scala/com/augustnagro/magnum/DbType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait DbType:
eElemCodecs: Seq[DbCodec[?]],
ecElemNames: Seq[String],
ecElemNamesSql: Seq[String],
idIndex: Int
idIndexes: List[Int]
)(using
eCodec: DbCodec[E],
ecCodec: DbCodec[EC],
Expand Down
63 changes: 33 additions & 30 deletions magnum/src/main/scala/com/augustnagro/magnum/H2DbType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object H2DbType extends DbType:
eElemCodecs: Seq[DbCodec[?]],
ecElemNames: Seq[String],
ecElemNamesSql: Seq[String],
idIndex: Int
idIndexes: List[Int]
)(using
eCodec: DbCodec[E],
ecCodec: DbCodec[EC],
Expand All @@ -25,41 +25,46 @@ object H2DbType extends DbType:
ecClassTag: ClassTag[EC],
idClassTag: ClassTag[ID]
): RepoDefaults[EC, E, ID] =
val idName = eElemNamesSql(idIndex)
val idNames = idIndexes.map(eElemNamesSql)
val idKeys = idNames.mkString("(", ", ", ")")
val selectKeys = eElemNamesSql.mkString(", ")
val ecInsertKeys = ecElemNamesSql.mkString("(", ", ", ")")

val updateKeys: String = eElemNamesSql
.lazyZip(eElemCodecs)
val eElemNamesAndCodecs = eElemNamesSql.lazyZip(eElemCodecs)
val (idNamesAndCodecs, ecNamesAndCodecs) =
eElemNamesAndCodecs.partition((sqlName, _) => idNames.contains(sqlName))

val idFilter = idKeys + " = " + idCodec.queryRepr

val updateKeys: String = ecNamesAndCodecs
.map((sqlName, codec) => sqlName + " = " + codec.queryRepr)
.patch(idIndex, Seq.empty, 1)
.mkString(", ")

val updateCodecs = eElemCodecs
.patch(idIndex, Seq.empty, 1)
.appended(idCodec)
.asInstanceOf[Seq[DbCodec[Any]]]
val updateCodecs =
(ecNamesAndCodecs.map(_._2) ++ idNamesAndCodecs.map(_._2))
.toSeq
.asInstanceOf[Seq[DbCodec[Any]]]

val insertGenKeys: Array[String] = Array.from(eElemNamesSql)

val countSql = s"SELECT count(*) FROM $tableNameSql"
val countQuery = Frag(countSql, Vector.empty, FragWriter.empty).query[Long]
val existsByIdSql =
s"SELECT 1 FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
s"SELECT 1 FROM $tableNameSql WHERE $idFilter"
val findAllSql = s"SELECT * FROM $tableNameSql"
val findAllQuery = Frag(findAllSql, Vector.empty, FragWriter.empty).query[E]
val findByIdSql =
s"SELECT * FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
val findAllByIdSql = s"SELECT * FROM $tableNameSql WHERE $idName = ANY(?)"
s"SELECT * FROM $tableNameSql WHERE $idFilter"
val findAllByIdSql = s"SELECT * FROM $tableNameSql WHERE $idKeys = ANY(?)"
val deleteByIdSql =
s"DELETE FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
s"DELETE FROM $tableNameSql WHERE $idFilter"
val truncateSql = s"TRUNCATE TABLE $tableNameSql"
val truncateUpdate =
Frag(truncateSql, Vector.empty, FragWriter.empty).update
val insertSql =
s"INSERT INTO $tableNameSql $ecInsertKeys VALUES (${ecCodec.queryRepr})"
val updateSql =
s"UPDATE $tableNameSql SET $updateKeys WHERE $idName = ${idCodec.queryRepr}"
s"UPDATE $tableNameSql SET $updateKeys WHERE $idFilter"

val compositeId = idCodec.cols.distinct.size != 1
val idFirstTypeName = JDBCType.valueOf(idCodec.cols.head).getName
Expand All @@ -68,6 +73,12 @@ object H2DbType extends DbType:
idCodec.writeSingle(id, ps, pos)
pos + idCodec.cols.length

def entityId(entity: E): ID =
val idElems = idIndexes.map(entity.asInstanceOf[Product].productElement)
idElems match
case head :: Nil => head.asInstanceOf[ID]
case _ => idClassTag.runtimeClass.getDeclaredConstructors().head.newInstance(idElems*).asInstanceOf[ID]

new RepoDefaults[EC, E, ID]:
def count(using con: DbCon): Long = countQuery.run().head

Expand Down Expand Up @@ -111,12 +122,7 @@ object H2DbType extends DbType:
// Sql(findAllByIdSql, Vector(builder.result())).run

def delete(entity: E)(using DbCon): Unit =
deleteById(
entity
.asInstanceOf[Product]
.productElement(idIndex)
.asInstanceOf[ID]
)
deleteById(entityId(entity))

def deleteById(id: ID)(using DbCon): Unit =
Frag(deleteByIdSql, IArray(id), idWriter(id)).update.run()
Expand All @@ -125,9 +131,7 @@ object H2DbType extends DbType:

def deleteAll(entities: Iterable[E])(using DbCon): BatchUpdateResult =
deleteAllById(
entities.map(e =>
e.asInstanceOf[Product].productElement(idIndex).asInstanceOf[ID]
)
entities.map(entityId)
)

def deleteAllById(ids: Iterable[ID])(using
Expand Down Expand Up @@ -183,9 +187,9 @@ object H2DbType extends DbType:
.productIterator
.toVector
// put ID at the end
val updateValues = entityValues
.patch(idIndex, Vector.empty, 1)
.appended(entityValues(idIndex))
val (idValues, ecValues) = entityValues.zipWithIndex
.partition((_, index) => idIndexes.contains(index))
val updateValues = ecValues.map(_._1) ++ idValues.map(_._1)

var pos = 1
for (field, codec) <- updateValues.lazyZip(updateCodecs) do
Expand All @@ -204,9 +208,9 @@ object H2DbType extends DbType:
.productIterator
.toVector
// put ID at the end
val updateValues = entityValues
.patch(idIndex, Vector.empty, 1)
.appended(entityValues(idIndex))
val (idValues, ecValues) = entityValues.zipWithIndex
.partition((_, index) => idIndexes.contains(index))
val updateValues = ecValues.map(_._1) ++ idValues.map(_._1)

var pos = 1
for (field, codec) <- updateValues.lazyZip(updateCodecs) do
Expand All @@ -215,7 +219,6 @@ object H2DbType extends DbType:
ps.addBatch()

timed(batchUpdateResult(ps.executeBatch()))

end new
end buildRepoDefaults
end H2DbType
68 changes: 38 additions & 30 deletions magnum/src/main/scala/com/augustnagro/magnum/MySqlDbType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object MySqlDbType extends DbType:
eElemCodecs: Seq[DbCodec[?]],
ecElemNames: Seq[String],
ecElemNamesSql: Seq[String],
idIndex: Int
idIndexes: List[Int]
)(using
eCodec: DbCodec[E],
ecCodec: DbCodec[EC],
Expand All @@ -50,46 +50,62 @@ object MySqlDbType extends DbType:
ecClassTag: ClassTag[EC],
idClassTag: ClassTag[ID]
): RepoDefaults[EC, E, ID] =
val idName = eElemNamesSql(idIndex)
val idNames = idIndexes.map(eElemNamesSql)
val idKeys = idNames.mkString("(", ", ", ")")
val selectKeys = eElemNamesSql.mkString(", ")
val ecInsertKeys = ecElemNamesSql.mkString("(", ", ", ")")

val insertGenKeys = Array(idName)
val insertGenKeys = idNames

val updateKeys: String = eElemNamesSql
.lazyZip(eElemCodecs)
val eElemNamesAndCodecs = eElemNamesSql.lazyZip(eElemCodecs)
val (idNamesAndCodecs, ecNamesAndCodecs) =
eElemNamesAndCodecs.partition((sqlName, _) => idNames.contains(sqlName))

val idFilter = idKeys + " = " + idCodec.queryRepr

val updateKeys: String = ecNamesAndCodecs
.map((sqlName, codec) => sqlName + " = " + codec.queryRepr)
.patch(idIndex, Seq.empty, 1)
.mkString(", ")

val updateCodecs = eElemCodecs
.patch(idIndex, Seq.empty, 1)
.appended(idCodec)
.asInstanceOf[Seq[DbCodec[Any]]]
val updateCodecs =
(ecNamesAndCodecs.map(_._2) ++ idNamesAndCodecs.map(_._2))
.toSeq
.asInstanceOf[Seq[DbCodec[Any]]]

val countSql = s"SELECT count(*) FROM $tableNameSql"
val countQuery = Frag(countSql, Vector.empty, FragWriter.empty).query[Long]
val existsByIdSql =
s"SELECT 1 FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
s"SELECT 1 FROM $tableNameSql WHERE $idFilter"
val findAllSql = s"SELECT * FROM $tableNameSql"
val findAllQuery = Frag(findAllSql, Vector.empty, FragWriter.empty).query[E]
val findByIdSql =
s"SELECT * FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
s"SELECT * FROM $tableNameSql WHERE $idFilter"
val deleteByIdSql =
s"DELETE FROM $tableNameSql WHERE $idName = ${idCodec.queryRepr}"
s"DELETE FROM $tableNameSql WHERE $idFilter"
val truncateSql = s"TRUNCATE TABLE $tableNameSql"
val truncateUpdate =
Frag(truncateSql, Vector.empty, FragWriter.empty).update
val insertSql =
s"INSERT INTO $tableNameSql $ecInsertKeys VALUES (${ecCodec.queryRepr})"
val updateSql =
s"UPDATE $tableNameSql SET $updateKeys WHERE $idName = ${idCodec.queryRepr}"
s"UPDATE $tableNameSql SET $updateKeys WHERE $idFilter"
val insertAndFindByIdSql = insertSql + "\n" + findByIdSql

def idWriter(id: ID): FragWriter = (ps, pos) =>
idCodec.writeSingle(id, ps, pos)
pos + idCodec.cols.length

def entityId(entity: E): ID =
val idElems = idIndexes.map(entity.asInstanceOf[Product].productElement)
idElems match
case head :: Nil => head.asInstanceOf[ID]
case _ =>
idClassTag.runtimeClass
.getDeclaredConstructors()
.head
.newInstance(idElems*)
.asInstanceOf[ID]

new RepoDefaults[EC, E, ID]:
def count(using con: DbCon): Long = countQuery.run().head

Expand All @@ -116,12 +132,7 @@ object MySqlDbType extends DbType:
)

def delete(entity: E)(using DbCon): Unit =
deleteById(
entity
.asInstanceOf[Product]
.productElement(idIndex)
.asInstanceOf[ID]
)
deleteById(entityId(entity))

def deleteById(id: ID)(using DbCon): Unit =
Frag(deleteByIdSql, IArray(id), idWriter(id)).update
Expand All @@ -131,9 +142,7 @@ object MySqlDbType extends DbType:

def deleteAll(entities: Iterable[E])(using DbCon): BatchUpdateResult =
deleteAllById(
entities.map(e =>
e.asInstanceOf[Product].productElement(idIndex).asInstanceOf[ID]
)
entities.map(entityId)
)

def deleteAllById(ids: Iterable[ID])(using
Expand Down Expand Up @@ -175,10 +184,9 @@ object MySqlDbType extends DbType:
.productIterator
.toVector
// put ID at the end
val updateValues = entityValues
.patch(idIndex, Vector.empty, 1)
.appended(entityValues(idIndex))

val (idValues, ecValues) = entityValues.zipWithIndex
.partition((_, index) => idIndexes.contains(index))
val updateValues = ecValues.map(_._1) ++ idValues.map(_._1)
var pos = 1
for (field, codec) <- updateValues.lazyZip(updateCodecs) do
codec.writeSingle(field, ps, pos)
Expand All @@ -196,9 +204,9 @@ object MySqlDbType extends DbType:
.productIterator
.toVector
// put ID at the end
val updateValues = entityValues
.patch(idIndex, Vector.empty, 1)
.appended(entityValues(idIndex))
val (idValues, ecValues) = entityValues.zipWithIndex
.partition((_, index) => idIndexes.contains(index))
val updateValues = ecValues.map(_._1) ++ idValues.map(_._1)

var pos = 1
for (field, codec) <- updateValues.lazyZip(updateCodecs) do
Expand Down
Loading