package com.ustadmobile.core.db.dao.xapi

import androidx.paging.PagingSource
import com.ustadmobile.door.DoorDbType
import com.ustadmobile.door.DoorQuery
import com.ustadmobile.door.EntityInsertionAdapter
import com.ustadmobile.door.PreparedStatementConfig
import com.ustadmobile.door.ext.copy
import com.ustadmobile.door.ext.copyWithExtraParams
import com.ustadmobile.door.ext.createArrayOrProxyArrayOf
import com.ustadmobile.door.ext.hasListOrArrayParams
import com.ustadmobile.door.ext.prepareAndUseStatement
import com.ustadmobile.door.ext.prepareAndUseStatementAsync
import com.ustadmobile.door.flow.doorFlow
import com.ustadmobile.door.jdbc.PreparedStatement
import com.ustadmobile.door.jdbc.ext.executeQueryAsyncKmp
import com.ustadmobile.door.jdbc.ext.getBooleanNullable
import com.ustadmobile.door.jdbc.ext.getFloatNullable
import com.ustadmobile.door.jdbc.ext.getIntNullable
import com.ustadmobile.door.jdbc.ext.getLongNullable
import com.ustadmobile.door.jdbc.ext.mapNextRow
import com.ustadmobile.door.jdbc.ext.mapRows
import com.ustadmobile.door.jdbc.ext.setBooleanNullable
import com.ustadmobile.door.jdbc.ext.setFloatNullable
import com.ustadmobile.door.jdbc.ext.setIntNullable
import com.ustadmobile.door.jdbc.ext.setLongNullable
import com.ustadmobile.door.jdbc.ext.useResults
import com.ustadmobile.door.paging.DoorLimitOffsetPagingSource
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.lib.db.composites.BlockStatus
import com.ustadmobile.lib.db.composites.PersonAndPictureAndNumAttempts
import com.ustadmobile.lib.db.composites.xapi.SessionTimeAndProgressInfo
import com.ustadmobile.lib.db.composites.xapi.StatementAndActivity
import com.ustadmobile.lib.db.composites.xapi.StatementEntityAndRelated
import com.ustadmobile.lib.db.composites.xapi.StatementEntityAndVerb
import com.ustadmobile.lib.db.composites.xapi.VerbEntityAndName
import com.ustadmobile.lib.db.entities.Person
import com.ustadmobile.lib.db.entities.PersonPicture
import com.ustadmobile.lib.db.entities.StatementEntityAndDisplayDetails
import com.ustadmobile.lib.db.entities.StatementReportData
import com.ustadmobile.lib.db.entities.xapi.ActivityEntity
import com.ustadmobile.lib.db.entities.xapi.ActivityLangMapEntry
import com.ustadmobile.lib.db.entities.xapi.ActorEntity
import com.ustadmobile.lib.db.entities.xapi.GroupMemberActorJoin
import com.ustadmobile.lib.db.entities.xapi.StatementEntity
import com.ustadmobile.lib.db.entities.xapi.VerbEntity
import com.ustadmobile.lib.db.entities.xapi.VerbLangMapEntry
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

public class StatementDao_JdbcImpl(
  public val _db: RoomDatabase,
) : StatementDao() {
  public val _insertAdapterStatementEntity_ignore: EntityInsertionAdapter<StatementEntity> = object
      : EntityInsertionAdapter<StatementEntity>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT  OR IGNORE INTO StatementEntity (statementIdHi, statementIdLo, statementActorPersonUid, statementVerbUid, statementObjectType, statementObjectUid1, statementObjectUid2, statementActorUid, authorityActorUid, teamUid, resultCompletion, resultSuccess, resultScoreScaled, resultScoreRaw, resultScoreMin, resultScoreMax, resultDuration, resultResponse, timestamp, stored, contextRegistrationHi, contextRegistrationLo, contextPlatform, contextStatementRefIdHi, contextStatementRefIdLo, contextInstructorActorUid, statementLct, extensionProgress, completionOrProgress, statementContentEntryUid, statementLearnerGroupUid, statementClazzUid, statementCbUid, statementDoorNode, isSubStatement) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO StatementEntity (statementIdHi, statementIdLo, statementActorPersonUid, statementVerbUid, statementObjectType, statementObjectUid1, statementObjectUid2, statementActorUid, authorityActorUid, teamUid, resultCompletion, resultSuccess, resultScoreScaled, resultScoreRaw, resultScoreMin, resultScoreMax, resultDuration, resultResponse, timestamp, stored, contextRegistrationHi, contextRegistrationLo, contextPlatform, contextStatementRefIdHi, contextStatementRefIdLo, contextInstructorActorUid, statementLct, extensionProgress, completionOrProgress, statementContentEntryUid, statementLearnerGroupUid, statementClazzUid, statementCbUid, statementDoorNode, isSubStatement) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT (statementIdHi, statementIdLo) DO NOTHING" + if(returnsId) { " RETURNING statementIdHi" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: StatementEntity) {
      stmt.setLong(1, entity.statementIdHi)
      stmt.setLong(2, entity.statementIdLo)
      stmt.setLong(3, entity.statementActorPersonUid)
      stmt.setLong(4, entity.statementVerbUid)
      stmt.setInt(5, entity.statementObjectType)
      stmt.setLong(6, entity.statementObjectUid1)
      stmt.setLong(7, entity.statementObjectUid2)
      stmt.setLong(8, entity.statementActorUid)
      stmt.setLong(9, entity.authorityActorUid)
      stmt.setLong(10, entity.teamUid)
      stmt.setBooleanNullable(11, entity.resultCompletion)
      stmt.setBooleanNullable(12, entity.resultSuccess)
      stmt.setFloatNullable(13, entity.resultScoreScaled)
      stmt.setFloatNullable(14, entity.resultScoreRaw)
      stmt.setFloatNullable(15, entity.resultScoreMin)
      stmt.setFloatNullable(16, entity.resultScoreMax)
      stmt.setLongNullable(17, entity.resultDuration)
      stmt.setString(18, entity.resultResponse)
      stmt.setLong(19, entity.timestamp)
      stmt.setLong(20, entity.stored)
      stmt.setLong(21, entity.contextRegistrationHi)
      stmt.setLong(22, entity.contextRegistrationLo)
      stmt.setString(23, entity.contextPlatform)
      stmt.setLong(24, entity.contextStatementRefIdHi)
      stmt.setLong(25, entity.contextStatementRefIdLo)
      stmt.setLong(26, entity.contextInstructorActorUid)
      stmt.setLong(27, entity.statementLct)
      stmt.setIntNullable(28, entity.extensionProgress)
      stmt.setBoolean(29, entity.completionOrProgress)
      stmt.setLong(30, entity.statementContentEntryUid)
      stmt.setLong(31, entity.statementLearnerGroupUid)
      stmt.setLong(32, entity.statementClazzUid)
      stmt.setLong(33, entity.statementCbUid)
      stmt.setLong(34, entity.statementDoorNode)
      stmt.setBoolean(35, entity.isSubStatement)
    }
  }

  override suspend fun insertOrIgnoreListAsync(entityList: List<StatementEntity>) {
    _insertAdapterStatementEntity_ignore.insertListAsync(entityList)
  }

  override fun getOneStatement(): Flow<StatementEntity?> =
      _db.doorFlow(arrayOf("StatementEntity")) {
    _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = "SELECT * From StatementEntity LIMIT 1",
      readOnly = true,)
    ) { _stmt -> 
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapNextRow(null) {
          val _tmp_statementIdHi = _result.getLong("statementIdHi")
          val _tmp_statementIdLo = _result.getLong("statementIdLo")
          val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
          val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
          val _tmp_statementObjectType = _result.getInt("statementObjectType")
          val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
          val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
          val _tmp_statementActorUid = _result.getLong("statementActorUid")
          val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
          val _tmp_teamUid = _result.getLong("teamUid")
          val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
          val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
          val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
          val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
          val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
          val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
          val _tmp_resultDuration = _result.getLongNullable("resultDuration")
          val _tmp_resultResponse = _result.getString("resultResponse")
          val _tmp_timestamp = _result.getLong("timestamp")
          val _tmp_stored = _result.getLong("stored")
          val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
          val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
          val _tmp_contextPlatform = _result.getString("contextPlatform")
          val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
          val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
          val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
          val _tmp_statementLct = _result.getLong("statementLct")
          val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
          val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
          val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
          val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
          val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
          val _tmp_statementCbUid = _result.getLong("statementCbUid")
          val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
          val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
          StatementEntity().apply {
            this.statementIdHi = _tmp_statementIdHi
            this.statementIdLo = _tmp_statementIdLo
            this.statementActorPersonUid = _tmp_statementActorPersonUid
            this.statementVerbUid = _tmp_statementVerbUid
            this.statementObjectType = _tmp_statementObjectType
            this.statementObjectUid1 = _tmp_statementObjectUid1
            this.statementObjectUid2 = _tmp_statementObjectUid2
            this.statementActorUid = _tmp_statementActorUid
            this.authorityActorUid = _tmp_authorityActorUid
            this.teamUid = _tmp_teamUid
            this.resultCompletion = _tmp_resultCompletion
            this.resultSuccess = _tmp_resultSuccess
            this.resultScoreScaled = _tmp_resultScoreScaled
            this.resultScoreRaw = _tmp_resultScoreRaw
            this.resultScoreMin = _tmp_resultScoreMin
            this.resultScoreMax = _tmp_resultScoreMax
            this.resultDuration = _tmp_resultDuration
            this.resultResponse = _tmp_resultResponse
            this.timestamp = _tmp_timestamp
            this.stored = _tmp_stored
            this.contextRegistrationHi = _tmp_contextRegistrationHi
            this.contextRegistrationLo = _tmp_contextRegistrationLo
            this.contextPlatform = _tmp_contextPlatform
            this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
            this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
            this.contextInstructorActorUid = _tmp_contextInstructorActorUid
            this.statementLct = _tmp_statementLct
            this.extensionProgress = _tmp_extensionProgress
            this.completionOrProgress = _tmp_completionOrProgress
            this.statementContentEntryUid = _tmp_statementContentEntryUid
            this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
            this.statementClazzUid = _tmp_statementClazzUid
            this.statementCbUid = _tmp_statementCbUid
            this.statementDoorNode = _tmp_statementDoorNode
            this.isSubStatement = _tmp_isSubStatement
          }
        }
      }
    }
  }

  override suspend fun getResults(query: DoorQuery): List<StatementReportData> =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(query.sql, hasListParams =
      query.hasListOrArrayParams(), readOnly = true)
  ) { _stmt -> 
    query.bindToPreparedStmt(_stmt, _db)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_yAxis = _result.getFloat("yAxis")
        val _tmp_xAxis = _result.getString("xAxis")
        val _tmp_subgroup = _result.getString("subgroup")
        StatementReportData().apply {
          this.yAxis = _tmp_yAxis
          this.xAxis = _tmp_xAxis
          this.subgroup = _tmp_subgroup
        }
      }
    }
  }

  override fun getListResults(query: DoorQuery): PagingSource<Int, StatementEntityAndDisplayDetails>
      = object : DoorLimitOffsetPagingSource<StatementEntityAndDisplayDetails>(db = _db
  , tableNames = arrayOf("StatementEntity", "Person")
  ) {
    override suspend fun loadRows(_limit: Int, _offset: Int):
        List<StatementEntityAndDisplayDetails> {
      val query = query.copyWithExtraParams(
      sql = "SELECT * FROM (${query.sql}) AS _PagingData LIMIT ? OFFSET ?",
      extraParams = arrayOf(_limit, _offset))
      return _db.prepareAndUseStatementAsync(PreparedStatementConfig(query.sql, hasListParams =
          query.hasListOrArrayParams(), readOnly = true)
      ) { _stmt -> 
        query.bindToPreparedStmt(_stmt, _db)
        _stmt.executeQueryAsyncKmp().useResults{ _result -> 
          _result.mapRows {
            var _tmp_StatementEntity_nullCount = 0
            val _tmp_statementIdHi = _result.getLong("statementIdHi")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementIdLo = _result.getLong("statementIdLo")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementObjectType = _result.getInt("statementObjectType")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementActorUid = _result.getLong("statementActorUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_teamUid = _result.getLong("teamUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_resultDuration = _result.getLongNullable("resultDuration")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_resultResponse = _result.getString("resultResponse")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_timestamp = _result.getLong("timestamp")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_stored = _result.getLong("stored")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_contextPlatform = _result.getString("contextPlatform")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementLct = _result.getLong("statementLct")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementCbUid = _result.getLong("statementCbUid")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
            if(_result.wasNull()) _tmp_StatementEntity_nullCount++
            val _tmp_StatementEntity_isAllNull = _tmp_StatementEntity_nullCount == 35
            var _tmp_Person_nullCount = 0
            val _tmp_personUid = _result.getLong("personUid")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_username = _result.getString("username")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_firstNames = _result.getString("firstNames")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_lastName = _result.getString("lastName")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_emailAddr = _result.getString("emailAddr")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_phoneNum = _result.getString("phoneNum")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_gender = _result.getInt("gender")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_active = _result.getBoolean("active")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_isPersonalAccount = _result.getBoolean("isPersonalAccount")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_dateOfBirth = _result.getLong("dateOfBirth")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personAddress = _result.getString("personAddress")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personOrgId = _result.getString("personOrgId")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personGroupUid = _result.getLong("personGroupUid")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personLct = _result.getLong("personLct")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personCountry = _result.getString("personCountry")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personType = _result.getInt("personType")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personMasterChangeSeqNum = _result.getLong("personMasterChangeSeqNum")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personLocalChangeSeqNum = _result.getLong("personLocalChangeSeqNum")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personLastChangedBy = _result.getInt("personLastChangedBy")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_admin = _result.getBoolean("admin")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_personNotes = _result.getString("personNotes")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_fatherName = _result.getString("fatherName")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_fatherNumber = _result.getString("fatherNumber")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_motherName = _result.getString("motherName")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_motherNum = _result.getString("motherNum")
            if(_result.wasNull()) _tmp_Person_nullCount++
            val _tmp_Person_isAllNull = _tmp_Person_nullCount == 25
            StatementEntityAndDisplayDetails().apply {
              if(!_tmp_StatementEntity_isAllNull) {
                this.statement = StatementEntity().apply {
                  this.statementIdHi = _tmp_statementIdHi
                  this.statementIdLo = _tmp_statementIdLo
                  this.statementActorPersonUid = _tmp_statementActorPersonUid
                  this.statementVerbUid = _tmp_statementVerbUid
                  this.statementObjectType = _tmp_statementObjectType
                  this.statementObjectUid1 = _tmp_statementObjectUid1
                  this.statementObjectUid2 = _tmp_statementObjectUid2
                  this.statementActorUid = _tmp_statementActorUid
                  this.authorityActorUid = _tmp_authorityActorUid
                  this.teamUid = _tmp_teamUid
                  this.resultCompletion = _tmp_resultCompletion
                  this.resultSuccess = _tmp_resultSuccess
                  this.resultScoreScaled = _tmp_resultScoreScaled
                  this.resultScoreRaw = _tmp_resultScoreRaw
                  this.resultScoreMin = _tmp_resultScoreMin
                  this.resultScoreMax = _tmp_resultScoreMax
                  this.resultDuration = _tmp_resultDuration
                  this.resultResponse = _tmp_resultResponse
                  this.timestamp = _tmp_timestamp
                  this.stored = _tmp_stored
                  this.contextRegistrationHi = _tmp_contextRegistrationHi
                  this.contextRegistrationLo = _tmp_contextRegistrationLo
                  this.contextPlatform = _tmp_contextPlatform
                  this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
                  this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
                  this.contextInstructorActorUid = _tmp_contextInstructorActorUid
                  this.statementLct = _tmp_statementLct
                  this.extensionProgress = _tmp_extensionProgress
                  this.completionOrProgress = _tmp_completionOrProgress
                  this.statementContentEntryUid = _tmp_statementContentEntryUid
                  this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
                  this.statementClazzUid = _tmp_statementClazzUid
                  this.statementCbUid = _tmp_statementCbUid
                  this.statementDoorNode = _tmp_statementDoorNode
                  this.isSubStatement = _tmp_isSubStatement
                }
              }
              if(!_tmp_Person_isAllNull) {
                this.person = Person().apply {
                  this.personUid = _tmp_personUid
                  this.username = _tmp_username
                  this.firstNames = _tmp_firstNames
                  this.lastName = _tmp_lastName
                  this.emailAddr = _tmp_emailAddr
                  this.phoneNum = _tmp_phoneNum
                  this.gender = _tmp_gender
                  this.active = _tmp_active
                  this.isPersonalAccount = _tmp_isPersonalAccount
                  this.dateOfBirth = _tmp_dateOfBirth
                  this.personAddress = _tmp_personAddress
                  this.personOrgId = _tmp_personOrgId
                  this.personGroupUid = _tmp_personGroupUid
                  this.personLct = _tmp_personLct
                  this.personCountry = _tmp_personCountry
                  this.personType = _tmp_personType
                  this.personMasterChangeSeqNum = _tmp_personMasterChangeSeqNum
                  this.personLocalChangeSeqNum = _tmp_personLocalChangeSeqNum
                  this.personLastChangedBy = _tmp_personLastChangedBy
                  this.admin = _tmp_admin
                  this.personNotes = _tmp_personNotes
                  this.fatherName = _tmp_fatherName
                  this.fatherNumber = _tmp_fatherNumber
                  this.motherName = _tmp_motherName
                  this.motherNum = _tmp_motherNum
                }
              }
            }
          }
        }
      }
    }

    override suspend fun countRows(): Int {
      val query = query.copy(
      sql = "SELECT COUNT(*) FROM (${query.sql})")
      return _db.prepareAndUseStatementAsync(PreparedStatementConfig(query.sql, hasListParams =
          query.hasListOrArrayParams(), readOnly = true)
      ) { _stmt -> 
        query.bindToPreparedStmt(_stmt, _db)
        _stmt.executeQueryAsyncKmp().useResults{ _result -> 
          _result.mapNextRow(0) {
            _result.getInt(1)
          }
        }
      }
    }
  }

  override fun getPerson(): Person? = _db.prepareAndUseStatement(PreparedStatementConfig(
    sql = "SELECT * FROM PERSON LIMIT 1",
    readOnly = true,)
  ) { _stmt -> 
    _stmt.executeQuery().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_personUid = _result.getLong("personUid")
        val _tmp_username = _result.getString("username")
        val _tmp_firstNames = _result.getString("firstNames")
        val _tmp_lastName = _result.getString("lastName")
        val _tmp_emailAddr = _result.getString("emailAddr")
        val _tmp_phoneNum = _result.getString("phoneNum")
        val _tmp_gender = _result.getInt("gender")
        val _tmp_active = _result.getBoolean("active")
        val _tmp_isPersonalAccount = _result.getBoolean("isPersonalAccount")
        val _tmp_dateOfBirth = _result.getLong("dateOfBirth")
        val _tmp_personAddress = _result.getString("personAddress")
        val _tmp_personOrgId = _result.getString("personOrgId")
        val _tmp_personGroupUid = _result.getLong("personGroupUid")
        val _tmp_personLct = _result.getLong("personLct")
        val _tmp_personCountry = _result.getString("personCountry")
        val _tmp_personType = _result.getInt("personType")
        val _tmp_personMasterChangeSeqNum = _result.getLong("personMasterChangeSeqNum")
        val _tmp_personLocalChangeSeqNum = _result.getLong("personLocalChangeSeqNum")
        val _tmp_personLastChangedBy = _result.getInt("personLastChangedBy")
        val _tmp_admin = _result.getBoolean("admin")
        val _tmp_personNotes = _result.getString("personNotes")
        val _tmp_fatherName = _result.getString("fatherName")
        val _tmp_fatherNumber = _result.getString("fatherNumber")
        val _tmp_motherName = _result.getString("motherName")
        val _tmp_motherNum = _result.getString("motherNum")
        Person().apply {
          this.personUid = _tmp_personUid
          this.username = _tmp_username
          this.firstNames = _tmp_firstNames
          this.lastName = _tmp_lastName
          this.emailAddr = _tmp_emailAddr
          this.phoneNum = _tmp_phoneNum
          this.gender = _tmp_gender
          this.active = _tmp_active
          this.isPersonalAccount = _tmp_isPersonalAccount
          this.dateOfBirth = _tmp_dateOfBirth
          this.personAddress = _tmp_personAddress
          this.personOrgId = _tmp_personOrgId
          this.personGroupUid = _tmp_personGroupUid
          this.personLct = _tmp_personLct
          this.personCountry = _tmp_personCountry
          this.personType = _tmp_personType
          this.personMasterChangeSeqNum = _tmp_personMasterChangeSeqNum
          this.personLocalChangeSeqNum = _tmp_personLocalChangeSeqNum
          this.personLastChangedBy = _tmp_personLastChangedBy
          this.admin = _tmp_admin
          this.personNotes = _tmp_personNotes
          this.fatherName = _tmp_fatherName
          this.fatherNumber = _tmp_fatherNumber
          this.motherName = _tmp_motherName
          this.motherNum = _tmp_motherNum
        }
      }
    }
  }

  override suspend fun getStatements(statementIdHi: Long, statementIdLo: Long):
      List<StatementEntity> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT StatementEntity.*
    |          FROM StatementEntity
    |         WHERE (    (? = 0 AND ? = 0) 
    |                 OR (statementIdHi = ? AND statementIdLo = ?))
    |                  
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,statementIdHi)
    _stmt.setLong(2,statementIdLo)
    _stmt.setLong(3,statementIdHi)
    _stmt.setLong(4,statementIdLo)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override suspend fun findById(statementIdHi: Long, statementIdLo: Long): StatementEntity? =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT StatementEntity.*
    |          FROM StatementEntity
    |         WHERE statementIdHi = ? 
    |           AND statementIdLo = ?       
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,statementIdHi)
    _stmt.setLong(2,statementIdLo)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override suspend fun findStatusStatementsByContentEntryUid(
    contentEntryUid: Long,
    courseBlockUid: Long,
    accountPersonUid: Long,
  ): List<StatementEntity> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT StatementEntity.*
    |               
    |            
    |          FROM StatementEntity
    |         WHERE StatementEntity.statementActorPersonUid = ?
    |           AND StatementEntity.statementContentEntryUid = ?
    |           AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |           AND (? = 0 OR StatementEntity.statementCbUid = ?)
    |    
    |        AND (    (CAST(StatementEntity.resultCompletion AS INTEGER) = 1)
    |              OR (StatementEntity.extensionProgress IS NOT NULL))
    |        
    |        
    |    
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,accountPersonUid)
    _stmt.setLong(2,contentEntryUid)
    _stmt.setLong(3,courseBlockUid)
    _stmt.setLong(4,courseBlockUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override suspend fun findStatusStatementByParentContentEntryUid(parentUid: Long,
      accountPersonUid: Long): List<StatementEntity> =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT StatementEntity.*
    |               
    |        FROM StatementEntity
    |       WHERE StatementEntity.statementActorPersonUid = ?
    |         AND StatementEntity.statementContentEntryUid IN (
    |             SELECT ContentEntryParentChildJoin.cepcjChildContentEntryUid
    |               FROM ContentEntryParentChildJoin
    |              WHERE ContentEntryParentChildJoin.cepcjParentContentEntryUid = ?)
    |         AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |         AND (    (CAST(StatementEntity.resultCompletion AS INTEGER) = 1)
    |              OR (StatementEntity.extensionProgress IS NOT NULL))     
    |    
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,accountPersonUid)
    _stmt.setLong(2,parentUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override suspend fun findStatusStatementsForStudentByClazzUid(clazzUid: Long,
      accountPersonUid: Long): List<StatementEntity> =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        WITH PersonUids(personUid) AS (
    |            SELECT ? AS personUid
    |        ),
    |        
    |        
    |        -- Get the ActorUids for the PersonUids See ActoryEntity doc for info on this join relationship
    |        AgentActorUidsForPersonUid(actorUid, actorPersonUid) AS(
    |             SELECT ActorEntity.actorUid AS actorUid, 
    |                    ActorEntity.actorPersonUid AS actorPersonUid
    |               FROM ActorEntity
    |              WHERE ActorEntity.actorPersonUid IN
    |                    (SELECT PersonUids.personUid
    |                       FROM PersonUids)           
    |        ),
    |        
    |        -- Add in group actor uids
    |        ActorUidsForPersonUid(actorUid, actorPersonUid) AS (
    |             SELECT AgentActorUidsForPersonUid.actorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid     
    |              UNION 
    |             SELECT GroupMemberActorJoin.gmajGroupActorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid
    |                    JOIN GroupMemberActorJoin 
    |                         ON GroupMemberActorJoin.gmajMemberActorUid = AgentActorUidsForPersonUid.actorUid
    |        )
    |    
    |        
    |        SELECT StatementEntity.*
    |               
    |               FROM StatementEntity
    |              WHERE (
    |        (SELECT EXISTS(
    |                SELECT 1
    |                  FROM ClazzEnrolment
    |                 WHERE ClazzEnrolment.clazzEnrolmentClazzUid = ?
    |                   AND ClazzEnrolment.clazzEnrolmentPersonUid = ?
    |                   AND ClazzEnrolment.clazzEnrolmentRole = 1000))
    |    )
    |                AND StatementEntity.statementActorUid IN (
    |                    SELECT ActorUidsForPersonUid.actorUid
    |                      FROM ActorUidsForPersonUid)
    |                AND StatementEntity.statementClazzUid = ?
    |                AND (    (CAST(StatementEntity.resultCompletion AS INTEGER) = 1)
    |                      OR (StatementEntity.extensionProgress IS NOT NULL))
    |    
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,accountPersonUid)
    _stmt.setLong(2,clazzUid)
    _stmt.setLong(3,accountPersonUid)
    _stmt.setLong(4,clazzUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override suspend fun findStatusForStudentsInClazzStatements(
    clazzUid: Long,
    roleId: Int,
    sortOrder: Int,
    searchText: String?,
    filter: Int,
    accountPersonUid: Long,
    currentTime: Long,
    studentsLimit: Int,
    studentsOffset: Int,
    completionOrProgressTrueVal: Boolean,
  ): List<StatementEntityAndRelated> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        -- Get the PersonUids for those that are within the current page as per studentsLimit and 
    |        -- studentsOffset
    |        WITH 
    |        PersonUids(personUid) AS (
    |            SELECT CourseMember.personUid 
    |              FROM (SELECT Person.*,
    |                           (SELECT MIN(ClazzEnrolment.clazzEnrolmentDateJoined) 
    |                              FROM ClazzEnrolment 
    |                             WHERE Person.personUid = ClazzEnrolment.clazzEnrolmentPersonUid) AS earliestJoinDate, 
    |            
    |                           (SELECT MAX(ClazzEnrolment.clazzEnrolmentDateLeft) 
    |                              FROM ClazzEnrolment 
    |                             WHERE Person.personUid = ClazzEnrolment.clazzEnrolmentPersonUid) AS latestDateLeft, 
    |            
    |                           (SELECT ClazzEnrolment.clazzEnrolmentRole 
    |                              FROM ClazzEnrolment 
    |                             WHERE Person.personUid = ClazzEnrolment.clazzEnrolmentPersonUid 
    |                               AND ClazzEnrolment.clazzEnrolmentClazzUid = ? 
    |                               AND ClazzEnrolment.clazzEnrolmentActive
    |                          ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC
    |                             LIMIT 1) AS enrolmentRole
    |                      FROM Person
    |                     WHERE Person.personUid IN 
    |                           (SELECT DISTINCT ClazzEnrolment.clazzEnrolmentPersonUid 
    |                              FROM ClazzEnrolment 
    |                             WHERE ClazzEnrolment.clazzEnrolmentClazzUid = ? 
    |                               AND ClazzEnrolment.clazzEnrolmentActive 
    |                               AND ClazzEnrolment.clazzEnrolmentRole = ? 
    |                               AND (? != 1 
    |                                     OR (? 
    |                                          BETWEEN ClazzEnrolment.clazzEnrolmentDateJoined 
    |                                          AND ClazzEnrolment.clazzEnrolmentDateLeft))) 
    |                       /* Begin permission check */
    |                       AND (
    |                               ((
    |             /* If the accountPersonUid is the owner of the course, all permissions are granted */
    |             (COALESCE(
    |                          (SELECT _Clazz_Permission.clazzOwnerPersonUid 
    |                             FROM Clazz _Clazz_Permission
    |                            WHERE _Clazz_Permission.clazzUid = ?), 0) = ?)
    |              /* 
    |              If there is a CoursePermission entity that is for the course as per the clazzUid
    |              parameter that is granted to the person directly or to the enrolmentRole that the 
    |              person has in the course, then permission is granted.
    |              */              
    |              OR EXISTS(SELECT CoursePermission.cpUid
    |                          FROM CoursePermission
    |                               
    |        LEFT JOIN ClazzEnrolment ClazzEnrolment_ForAccountPerson 
    |                        ON CoursePermission.cpToEnrolmentRole != 0
    |                       AND ClazzEnrolment_ForAccountPerson.clazzEnrolmentUid = 
    |                           (SELECT COALESCE(
    |                                   (SELECT _ClazzEnrolment_AccountPersonInner.clazzEnrolmentUid 
    |                                      FROM ClazzEnrolment _ClazzEnrolment_AccountPersonInner
    |                                     WHERE _ClazzEnrolment_AccountPersonInner.clazzEnrolmentClazzUid = CoursePermission.cpClazzUid
    |                                       AND _ClazzEnrolment_AccountPersonInner.clazzEnrolmentPersonUid = ?
    |                                       AND _ClazzEnrolment_AccountPersonInner.clazzEnrolmentActive
    |                                  ORDER BY _ClazzEnrolment_AccountPersonInner.clazzEnrolmentDateLeft DESC   
    |                                     LIMIT 1), 0))
    |    
    |                         WHERE CoursePermission.cpClazzUid = ?
    |                           AND (CoursePermission.cpToPersonUid = ? 
    |                                OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment_ForAccountPerson.clazzEnrolmentRole)
    |                           AND (CoursePermission.cpPermissionsFlag & 
    |         128
    |                                
    |        ) > 0)
    |              OR EXISTS(SELECT SystemPermission.spUid
    |                          FROM SystemPermission
    |                         WHERE SystemPermission.spToPersonUid = ?
    |                           AND (SystemPermission.spPermissionsFlag & 
    |     128
    |                                
    |        ) > 0)
    |               )
    |    )
    |                            OR Person.personUid = ?
    |                           )  
    |                       /* End permission check */                   
    |                       AND Person.firstNames || ' ' || Person.lastName LIKE ?
    |                   GROUP BY Person.personUid) AS CourseMember
    |          ORDER BY CASE(?)
    |                    WHEN 1 THEN CourseMember.firstNames
    |                    WHEN 3 THEN CourseMember.lastName
    |                    ELSE ''
    |                END ASC,
    |                CASE(?)
    |                    WHEN 2 THEN CourseMember.firstNames
    |                    WHEN 4 THEN CourseMember.lastName
    |                    ELSE ''
    |                END DESC,
    |                CASE(?)
    |                    WHEN 7 THEN CourseMember.earliestJoinDate
    |                    WHEN 9 THEN CourseMember.latestDateLeft
    |                    ELSE 0
    |                END ASC,
    |                CASE(?)
    |                    WHEN 8 THEN CourseMember.earliestJoinDate
    |                    WHEN 10 THEN CourseMember.latestDateLeft
    |                    ELSE 0
    |                END DESC
    |             LIMIT ?
    |            OFFSET ?   
    |         )
    |    ,
    |        
    |        
    |        -- Get the ActorUids for the PersonUids See ActoryEntity doc for info on this join relationship
    |        AgentActorUidsForPersonUid(actorUid, actorPersonUid) AS(
    |             SELECT ActorEntity.actorUid AS actorUid, 
    |                    ActorEntity.actorPersonUid AS actorPersonUid
    |               FROM ActorEntity
    |              WHERE ActorEntity.actorPersonUid IN
    |                    (SELECT PersonUids.personUid
    |                       FROM PersonUids)           
    |        ),
    |        
    |        -- Add in group actor uids
    |        ActorUidsForPersonUid(actorUid, actorPersonUid) AS (
    |             SELECT AgentActorUidsForPersonUid.actorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid     
    |              UNION 
    |             SELECT GroupMemberActorJoin.gmajGroupActorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid
    |                    JOIN GroupMemberActorJoin 
    |                         ON GroupMemberActorJoin.gmajMemberActorUid = AgentActorUidsForPersonUid.actorUid
    |        )
    |    
    |
    |        
    |        -- Fetch all statements that could be completion or progress for the Gradebook report
    |        SELECT StatementEntity.*, ActorEntity.*, GroupMemberActorJoin.*
    |          FROM StatementEntity
    |               JOIN ActorEntity
    |                    ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |               LEFT JOIN GroupMemberActorJoin
    |                    ON ActorEntity.actorObjectType = 2
    |                       AND GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                       AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                           SELECT DISTINCT ActorUidsForPersonUid.actorUid
    |                             FROM ActorUidsForPersonUid)
    |         WHERE StatementEntity.statementClazzUid = ?
    |           AND StatementEntity.completionOrProgress = ?
    |           AND StatementEntity.statementActorUid IN (
    |               SELECT DISTINCT ActorUidsForPersonUid.actorUid
    |                 FROM ActorUidsForPersonUid) 
    |           AND (      StatementEntity.resultScoreScaled IS NOT NULL
    |                   OR StatementEntity.resultCompletion IS NOT NULL
    |                   OR StatementEntity.resultSuccess IS NOT NULL
    |                   OR StatementEntity.extensionProgress IS NOT NULL 
    |               )
    |    
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,clazzUid)
    _stmt.setLong(2,clazzUid)
    _stmt.setInt(3,roleId)
    _stmt.setInt(4,filter)
    _stmt.setLong(5,currentTime)
    _stmt.setLong(6,clazzUid)
    _stmt.setLong(7,accountPersonUid)
    _stmt.setLong(8,accountPersonUid)
    _stmt.setLong(9,clazzUid)
    _stmt.setLong(10,accountPersonUid)
    _stmt.setLong(11,accountPersonUid)
    _stmt.setLong(12,accountPersonUid)
    _stmt.setString(13,searchText)
    _stmt.setInt(14,sortOrder)
    _stmt.setInt(15,sortOrder)
    _stmt.setInt(16,sortOrder)
    _stmt.setInt(17,sortOrder)
    _stmt.setInt(18,studentsLimit)
    _stmt.setInt(19,studentsOffset)
    _stmt.setLong(20,clazzUid)
    _stmt.setBoolean(21,completionOrProgressTrueVal)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        var _tmp_StatementEntity_nullCount = 0
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_teamUid = _result.getLong("teamUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultResponse = _result.getString("resultResponse")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_timestamp = _result.getLong("timestamp")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_stored = _result.getLong("stored")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementLct = _result.getLong("statementLct")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_StatementEntity_isAllNull = _tmp_StatementEntity_nullCount == 35
        var _tmp_GroupMemberActorJoin_nullCount = 0
        val _tmp_gmajGroupActorUid = _result.getLong("gmajGroupActorUid")
        if(_result.wasNull()) _tmp_GroupMemberActorJoin_nullCount++
        val _tmp_gmajMemberActorUid = _result.getLong("gmajMemberActorUid")
        if(_result.wasNull()) _tmp_GroupMemberActorJoin_nullCount++
        val _tmp_gmajLastMod = _result.getLong("gmajLastMod")
        if(_result.wasNull()) _tmp_GroupMemberActorJoin_nullCount++
        val _tmp_GroupMemberActorJoin_isAllNull = _tmp_GroupMemberActorJoin_nullCount == 3
        var _tmp_ActorEntity_nullCount = 0
        val _tmp_actorUid = _result.getLong("actorUid")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorPersonUid = _result.getLong("actorPersonUid")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorName = _result.getString("actorName")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorMbox = _result.getString("actorMbox")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorMbox_sha1sum = _result.getString("actorMbox_sha1sum")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorOpenid = _result.getString("actorOpenid")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorAccountName = _result.getString("actorAccountName")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorAccountHomePage = _result.getString("actorAccountHomePage")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorEtag = _result.getLong("actorEtag")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorLct = _result.getLong("actorLct")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorObjectType = _result.getInt("actorObjectType")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_ActorEntity_isAllNull = _tmp_ActorEntity_nullCount == 11
        StatementEntityAndRelated().apply {
          if(!_tmp_StatementEntity_isAllNull) {
            this.statementEntity = StatementEntity().apply {
              this.statementIdHi = _tmp_statementIdHi
              this.statementIdLo = _tmp_statementIdLo
              this.statementActorPersonUid = _tmp_statementActorPersonUid
              this.statementVerbUid = _tmp_statementVerbUid
              this.statementObjectType = _tmp_statementObjectType
              this.statementObjectUid1 = _tmp_statementObjectUid1
              this.statementObjectUid2 = _tmp_statementObjectUid2
              this.statementActorUid = _tmp_statementActorUid
              this.authorityActorUid = _tmp_authorityActorUid
              this.teamUid = _tmp_teamUid
              this.resultCompletion = _tmp_resultCompletion
              this.resultSuccess = _tmp_resultSuccess
              this.resultScoreScaled = _tmp_resultScoreScaled
              this.resultScoreRaw = _tmp_resultScoreRaw
              this.resultScoreMin = _tmp_resultScoreMin
              this.resultScoreMax = _tmp_resultScoreMax
              this.resultDuration = _tmp_resultDuration
              this.resultResponse = _tmp_resultResponse
              this.timestamp = _tmp_timestamp
              this.stored = _tmp_stored
              this.contextRegistrationHi = _tmp_contextRegistrationHi
              this.contextRegistrationLo = _tmp_contextRegistrationLo
              this.contextPlatform = _tmp_contextPlatform
              this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
              this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
              this.contextInstructorActorUid = _tmp_contextInstructorActorUid
              this.statementLct = _tmp_statementLct
              this.extensionProgress = _tmp_extensionProgress
              this.completionOrProgress = _tmp_completionOrProgress
              this.statementContentEntryUid = _tmp_statementContentEntryUid
              this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
              this.statementClazzUid = _tmp_statementClazzUid
              this.statementCbUid = _tmp_statementCbUid
              this.statementDoorNode = _tmp_statementDoorNode
              this.isSubStatement = _tmp_isSubStatement
            }
          }
          if(!_tmp_GroupMemberActorJoin_isAllNull) {
            this.groupMemberActorJoin = GroupMemberActorJoin().apply {
              this.gmajGroupActorUid = _tmp_gmajGroupActorUid
              this.gmajMemberActorUid = _tmp_gmajMemberActorUid
              this.gmajLastMod = _tmp_gmajLastMod
            }
          }
          if(!_tmp_ActorEntity_isAllNull) {
            this.actorEntity = ActorEntity().apply {
              this.actorUid = _tmp_actorUid
              this.actorPersonUid = _tmp_actorPersonUid
              this.actorName = _tmp_actorName
              this.actorMbox = _tmp_actorMbox
              this.actorMbox_sha1sum = _tmp_actorMbox_sha1sum
              this.actorOpenid = _tmp_actorOpenid
              this.actorAccountName = _tmp_actorAccountName
              this.actorAccountHomePage = _tmp_actorAccountHomePage
              this.actorEtag = _tmp_actorEtag
              this.actorLct = _tmp_actorLct
              this.actorObjectType = _tmp_actorObjectType
            }
          }
        }
      }
    }
  }

  override suspend fun findStatusForStudentsInClazzByUidList(
    clazzUid: Long,
    studentPersonUids: List<Long>,
    completionOrProgressTrueVal: Boolean,
  ): List<StatementEntityAndRelated> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        WITH PersonUids(personUid) AS (
    |            SELECT Person.personUid
    |              FROM Person
    |             WHERE Person.personUid IN (?) 
    |        ),
    |        
    |        
    |        -- Get the ActorUids for the PersonUids See ActoryEntity doc for info on this join relationship
    |        AgentActorUidsForPersonUid(actorUid, actorPersonUid) AS(
    |             SELECT ActorEntity.actorUid AS actorUid, 
    |                    ActorEntity.actorPersonUid AS actorPersonUid
    |               FROM ActorEntity
    |              WHERE ActorEntity.actorPersonUid IN
    |                    (SELECT PersonUids.personUid
    |                       FROM PersonUids)           
    |        ),
    |        
    |        -- Add in group actor uids
    |        ActorUidsForPersonUid(actorUid, actorPersonUid) AS (
    |             SELECT AgentActorUidsForPersonUid.actorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid     
    |              UNION 
    |             SELECT GroupMemberActorJoin.gmajGroupActorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid
    |                    JOIN GroupMemberActorJoin 
    |                         ON GroupMemberActorJoin.gmajMemberActorUid = AgentActorUidsForPersonUid.actorUid
    |        )
    |    
    |        
    |        
    |        -- Fetch all statements that could be completion or progress for the Gradebook report
    |        SELECT StatementEntity.*, ActorEntity.*, GroupMemberActorJoin.*
    |          FROM StatementEntity
    |               JOIN ActorEntity
    |                    ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |               LEFT JOIN GroupMemberActorJoin
    |                    ON ActorEntity.actorObjectType = 2
    |                       AND GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                       AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                           SELECT DISTINCT ActorUidsForPersonUid.actorUid
    |                             FROM ActorUidsForPersonUid)
    |         WHERE StatementEntity.statementClazzUid = ?
    |           AND StatementEntity.completionOrProgress = ?
    |           AND StatementEntity.statementActorUid IN (
    |               SELECT DISTINCT ActorUidsForPersonUid.actorUid
    |                 FROM ActorUidsForPersonUid) 
    |           AND (      StatementEntity.resultScoreScaled IS NOT NULL
    |                   OR StatementEntity.resultCompletion IS NOT NULL
    |                   OR StatementEntity.resultSuccess IS NOT NULL
    |                   OR StatementEntity.extensionProgress IS NOT NULL 
    |               )
    |    
    |    
    """.trimMargin(),
    hasListParams = true,
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setArray(1, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
        studentPersonUids.toTypedArray()))
    _stmt.setLong(2,clazzUid)
    _stmt.setBoolean(3,completionOrProgressTrueVal)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        var _tmp_StatementEntity_nullCount = 0
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_teamUid = _result.getLong("teamUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultResponse = _result.getString("resultResponse")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_timestamp = _result.getLong("timestamp")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_stored = _result.getLong("stored")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementLct = _result.getLong("statementLct")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_StatementEntity_isAllNull = _tmp_StatementEntity_nullCount == 35
        var _tmp_GroupMemberActorJoin_nullCount = 0
        val _tmp_gmajGroupActorUid = _result.getLong("gmajGroupActorUid")
        if(_result.wasNull()) _tmp_GroupMemberActorJoin_nullCount++
        val _tmp_gmajMemberActorUid = _result.getLong("gmajMemberActorUid")
        if(_result.wasNull()) _tmp_GroupMemberActorJoin_nullCount++
        val _tmp_gmajLastMod = _result.getLong("gmajLastMod")
        if(_result.wasNull()) _tmp_GroupMemberActorJoin_nullCount++
        val _tmp_GroupMemberActorJoin_isAllNull = _tmp_GroupMemberActorJoin_nullCount == 3
        var _tmp_ActorEntity_nullCount = 0
        val _tmp_actorUid = _result.getLong("actorUid")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorPersonUid = _result.getLong("actorPersonUid")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorName = _result.getString("actorName")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorMbox = _result.getString("actorMbox")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorMbox_sha1sum = _result.getString("actorMbox_sha1sum")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorOpenid = _result.getString("actorOpenid")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorAccountName = _result.getString("actorAccountName")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorAccountHomePage = _result.getString("actorAccountHomePage")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorEtag = _result.getLong("actorEtag")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorLct = _result.getLong("actorLct")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_actorObjectType = _result.getInt("actorObjectType")
        if(_result.wasNull()) _tmp_ActorEntity_nullCount++
        val _tmp_ActorEntity_isAllNull = _tmp_ActorEntity_nullCount == 11
        StatementEntityAndRelated().apply {
          if(!_tmp_StatementEntity_isAllNull) {
            this.statementEntity = StatementEntity().apply {
              this.statementIdHi = _tmp_statementIdHi
              this.statementIdLo = _tmp_statementIdLo
              this.statementActorPersonUid = _tmp_statementActorPersonUid
              this.statementVerbUid = _tmp_statementVerbUid
              this.statementObjectType = _tmp_statementObjectType
              this.statementObjectUid1 = _tmp_statementObjectUid1
              this.statementObjectUid2 = _tmp_statementObjectUid2
              this.statementActorUid = _tmp_statementActorUid
              this.authorityActorUid = _tmp_authorityActorUid
              this.teamUid = _tmp_teamUid
              this.resultCompletion = _tmp_resultCompletion
              this.resultSuccess = _tmp_resultSuccess
              this.resultScoreScaled = _tmp_resultScoreScaled
              this.resultScoreRaw = _tmp_resultScoreRaw
              this.resultScoreMin = _tmp_resultScoreMin
              this.resultScoreMax = _tmp_resultScoreMax
              this.resultDuration = _tmp_resultDuration
              this.resultResponse = _tmp_resultResponse
              this.timestamp = _tmp_timestamp
              this.stored = _tmp_stored
              this.contextRegistrationHi = _tmp_contextRegistrationHi
              this.contextRegistrationLo = _tmp_contextRegistrationLo
              this.contextPlatform = _tmp_contextPlatform
              this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
              this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
              this.contextInstructorActorUid = _tmp_contextInstructorActorUid
              this.statementLct = _tmp_statementLct
              this.extensionProgress = _tmp_extensionProgress
              this.completionOrProgress = _tmp_completionOrProgress
              this.statementContentEntryUid = _tmp_statementContentEntryUid
              this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
              this.statementClazzUid = _tmp_statementClazzUid
              this.statementCbUid = _tmp_statementCbUid
              this.statementDoorNode = _tmp_statementDoorNode
              this.isSubStatement = _tmp_isSubStatement
            }
          }
          if(!_tmp_GroupMemberActorJoin_isAllNull) {
            this.groupMemberActorJoin = GroupMemberActorJoin().apply {
              this.gmajGroupActorUid = _tmp_gmajGroupActorUid
              this.gmajMemberActorUid = _tmp_gmajMemberActorUid
              this.gmajLastMod = _tmp_gmajLastMod
            }
          }
          if(!_tmp_ActorEntity_isAllNull) {
            this.actorEntity = ActorEntity().apply {
              this.actorUid = _tmp_actorUid
              this.actorPersonUid = _tmp_actorPersonUid
              this.actorName = _tmp_actorName
              this.actorMbox = _tmp_actorMbox
              this.actorMbox_sha1sum = _tmp_actorMbox_sha1sum
              this.actorOpenid = _tmp_actorOpenid
              this.actorAccountName = _tmp_actorAccountName
              this.actorAccountHomePage = _tmp_actorAccountHomePage
              this.actorEtag = _tmp_actorEtag
              this.actorLct = _tmp_actorLct
              this.actorObjectType = _tmp_actorObjectType
            }
          }
        }
      }
    }
  }

  override suspend fun findActorEntitiesForStudentInClazzByUidList(
    clazzUid: Long,
    studentPersonUids: List<Long>,
    accountPersonUid: Long,
  ): List<ActorEntity> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        WITH PersonUids(personUid) AS (
    |            SELECT Person.personUid
    |              FROM Person
    |             WHERE Person.personUid IN (?) 
    |        ),
    |        
    |        
    |        -- Get the ActorUids for the PersonUids See ActoryEntity doc for info on this join relationship
    |        AgentActorUidsForPersonUid(actorUid, actorPersonUid) AS(
    |             SELECT ActorEntity.actorUid AS actorUid, 
    |                    ActorEntity.actorPersonUid AS actorPersonUid
    |               FROM ActorEntity
    |              WHERE ActorEntity.actorPersonUid IN
    |                    (SELECT PersonUids.personUid
    |                       FROM PersonUids)           
    |        ),
    |        
    |        -- Add in group actor uids
    |        ActorUidsForPersonUid(actorUid, actorPersonUid) AS (
    |             SELECT AgentActorUidsForPersonUid.actorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid     
    |              UNION 
    |             SELECT GroupMemberActorJoin.gmajGroupActorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid
    |                    JOIN GroupMemberActorJoin 
    |                         ON GroupMemberActorJoin.gmajMemberActorUid = AgentActorUidsForPersonUid.actorUid
    |        )
    |    
    |        
    |        SELECT ActorEntity.*
    |          FROM ActorEntity
    |         WHERE ActorEntity.actorPersonUid IN 
    |               (SELECT PersonUids.personUid
    |                  FROM PersonUids)
    |           AND ? = ?
    |           AND ? = ?
    |    
    """.trimMargin(),
    hasListParams = true,
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setArray(1, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
        studentPersonUids.toTypedArray()))
    _stmt.setLong(2,clazzUid)
    _stmt.setLong(3,clazzUid)
    _stmt.setLong(4,accountPersonUid)
    _stmt.setLong(5,accountPersonUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_actorUid = _result.getLong("actorUid")
        val _tmp_actorPersonUid = _result.getLong("actorPersonUid")
        val _tmp_actorName = _result.getString("actorName")
        val _tmp_actorMbox = _result.getString("actorMbox")
        val _tmp_actorMbox_sha1sum = _result.getString("actorMbox_sha1sum")
        val _tmp_actorOpenid = _result.getString("actorOpenid")
        val _tmp_actorAccountName = _result.getString("actorAccountName")
        val _tmp_actorAccountHomePage = _result.getString("actorAccountHomePage")
        val _tmp_actorEtag = _result.getLong("actorEtag")
        val _tmp_actorLct = _result.getLong("actorLct")
        val _tmp_actorObjectType = _result.getInt("actorObjectType")
        ActorEntity().apply {
          this.actorUid = _tmp_actorUid
          this.actorPersonUid = _tmp_actorPersonUid
          this.actorName = _tmp_actorName
          this.actorMbox = _tmp_actorMbox
          this.actorMbox_sha1sum = _tmp_actorMbox_sha1sum
          this.actorOpenid = _tmp_actorOpenid
          this.actorAccountName = _tmp_actorAccountName
          this.actorAccountHomePage = _tmp_actorAccountHomePage
          this.actorEtag = _tmp_actorEtag
          this.actorLct = _tmp_actorLct
          this.actorObjectType = _tmp_actorObjectType
        }
      }
    }
  }

  override suspend fun findStatusForStudentsInClazz(
    clazzUid: Long,
    studentPersonUids: List<Long>,
    accountPersonUid: Long,
  ): List<BlockStatus> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        WITH PersonUids(personUid) AS (
    |             SELECT Person.personUid
    |               FROM Person
    |              WHERE Person.personUid IN (?)
    |        ),
    |        
    |        
    |        -- Get the ActorUids for the PersonUids See ActoryEntity doc for info on this join relationship
    |        AgentActorUidsForPersonUid(actorUid, actorPersonUid) AS(
    |             SELECT ActorEntity.actorUid AS actorUid, 
    |                    ActorEntity.actorPersonUid AS actorPersonUid
    |               FROM ActorEntity
    |              WHERE ActorEntity.actorPersonUid IN
    |                    (SELECT PersonUids.personUid
    |                       FROM PersonUids)           
    |        ),
    |        
    |        -- Add in group actor uids
    |        ActorUidsForPersonUid(actorUid, actorPersonUid) AS (
    |             SELECT AgentActorUidsForPersonUid.actorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid     
    |              UNION 
    |             SELECT GroupMemberActorJoin.gmajGroupActorUid AS actorUid,
    |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
    |               FROM AgentActorUidsForPersonUid
    |                    JOIN GroupMemberActorJoin 
    |                         ON GroupMemberActorJoin.gmajMemberActorUid = AgentActorUidsForPersonUid.actorUid
    |        )
    |    ,
    |        
    |        PersonUidsAndCourseBlocks(personUid, cbUid, cbType, caMarkingType) AS (
    |             SELECT Person.personUid AS personUid,
    |                    CourseBlock.cbUid AS cbUid,
    |                    CourseBlock.cbType AS cbType,
    |                    ClazzAssignment.caMarkingType AS caMarkingType
    |               FROM Person
    |                    JOIN CourseBlock
    |                         ON CourseBlock.cbClazzUid = ?
    |                    LEFT JOIN ClazzAssignment
    |                         ON CourseBlock.cbType = 103
    |                        AND ClazzAssignment.caUid = CourseBlock.cbEntityUid     
    |              WHERE Person.personUid IN (?)       
    |        )
    |        
    |        SELECT PersonUidsAndCourseBlocks.personUid AS sPersonUid,
    |               PersonUidsAndCourseBlocks.cbUid AS sCbUid,
    |               (SELECT MAX(StatementEntity.extensionProgress)
    |                  FROM StatementEntity
    |                       
    |       JOIN ActorEntity
    |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |       LEFT JOIN GroupMemberActorJoin
    |            ON ActorEntity.actorObjectType = 2
    |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
    |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
    |                          GroupMemberActorJoin.gmajMemberActorUid
    |                     FROM GroupMemberActorJoin
    |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                          SELECT ActorUidsForPersonUid.actorUid
    |                            FROM ActorUidsForPersonUid
    |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
    |    
    |                 WHERE 
    |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
    |        AND StatementEntity.statementActorUid IN (
    |            SELECT ActorUidsForPersonUid.actorUid
    |              FROM ActorUidsForPersonUid
    |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
    |                   
    |     
    |               ) AS sProgress,
    |               (SELECT EXISTS(
    |                       SELECT 1
    |                         FROM StatementEntity
    |                              
    |       JOIN ActorEntity
    |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |       LEFT JOIN GroupMemberActorJoin
    |            ON ActorEntity.actorObjectType = 2
    |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
    |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
    |                          GroupMemberActorJoin.gmajMemberActorUid
    |                     FROM GroupMemberActorJoin
    |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                          SELECT ActorUidsForPersonUid.actorUid
    |                            FROM ActorUidsForPersonUid
    |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
    |    
    |                        WHERE (
    |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
    |        AND StatementEntity.statementActorUid IN (
    |            SELECT ActorUidsForPersonUid.actorUid
    |              FROM ActorUidsForPersonUid
    |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
    |                   
    |    )
    |                          AND CAST(StatementEntity.resultCompletion AS INTEGER) = 1
    |               )) AS sIsCompleted,
    |               (SELECT CASE
    |                       /*If there is a statement marked as success, then count as successful even if
    |                        *there were subsequent failed attempts
    |                        */
    |                       WHEN (
    |                            SELECT EXISTS(
    |                                    SELECT 1
    |                                      FROM StatementEntity
    |                                           
    |       JOIN ActorEntity
    |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |       LEFT JOIN GroupMemberActorJoin
    |            ON ActorEntity.actorObjectType = 2
    |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
    |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
    |                          GroupMemberActorJoin.gmajMemberActorUid
    |                     FROM GroupMemberActorJoin
    |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                          SELECT ActorUidsForPersonUid.actorUid
    |                            FROM ActorUidsForPersonUid
    |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
    |    
    |                                    WHERE (
    |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
    |        AND StatementEntity.statementActorUid IN (
    |            SELECT ActorUidsForPersonUid.actorUid
    |              FROM ActorUidsForPersonUid
    |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
    |                   
    |    )
    |                                      AND CAST(StatementEntity.resultSuccess AS INTEGER) = 1
    |                                   )                           
    |                       ) THEN 1
    |                       /*If there are no statements marked as success, however there are statements marekd as fail,
    |                        *then count as fail 
    |                        */
    |                       WHEN (
    |                            SELECT EXISTS(
    |                                    SELECT 1
    |                                      FROM StatementEntity
    |                                           
    |       JOIN ActorEntity
    |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |       LEFT JOIN GroupMemberActorJoin
    |            ON ActorEntity.actorObjectType = 2
    |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
    |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
    |                          GroupMemberActorJoin.gmajMemberActorUid
    |                     FROM GroupMemberActorJoin
    |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                          SELECT ActorUidsForPersonUid.actorUid
    |                            FROM ActorUidsForPersonUid
    |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
    |    
    |                                    WHERE (
    |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
    |        AND StatementEntity.statementActorUid IN (
    |            SELECT ActorUidsForPersonUid.actorUid
    |              FROM ActorUidsForPersonUid
    |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
    |                   
    |    )
    |                                      AND CAST(StatementEntity.resultSuccess AS INTEGER) = 0
    |                                   )                           
    |                       ) THEN 0
    |                       /* Else there is no known success/fail result*/
    |                       ELSE NULL
    |                       END
    |               ) AS sIsSuccess,
    |               -- See ClazzGradebookScreen for info on which score is selected
    |               (SELECT CASE
    |                       -- When there is a peer marked assignment, take the average of the latest distinct ...
    |                       WHEN (     PersonUidsAndCourseBlocks.cbType = 103
    |                              AND PersonUidsAndCourseBlocks.caMarkingType = 2
    |                            ) 
    |                            THEN (SELECT AVG(StatementEntity.resultScoreScaled)
    |                                    FROM StatementEntity
    |                                         
    |       JOIN ActorEntity
    |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |       LEFT JOIN GroupMemberActorJoin
    |            ON ActorEntity.actorObjectType = 2
    |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
    |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
    |                          GroupMemberActorJoin.gmajMemberActorUid
    |                     FROM GroupMemberActorJoin
    |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                          SELECT ActorUidsForPersonUid.actorUid
    |                            FROM ActorUidsForPersonUid
    |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
    |    
    |                                   WHERE (
    |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
    |        AND StatementEntity.statementActorUid IN (
    |            SELECT ActorUidsForPersonUid.actorUid
    |              FROM ActorUidsForPersonUid
    |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
    |                   
    |    )
    |                                     AND StatementEntity.timestamp = (
    |                                         SELECT MAX(StatementEntity_Inner.timestamp)
    |                                           FROM StatementEntity StatementEntity_Inner
    |                                                
    |       JOIN ActorEntity ActorEntity_Inner
    |            ON ActorEntity_Inner.actorUid = StatementEntity_Inner.statementActorUid
    |       LEFT JOIN GroupMemberActorJoin GroupMemberActorJoin_Inner
    |            ON ActorEntity_Inner.actorObjectType = 2
    |               AND (GroupMemberActorJoin_Inner.gmajGroupActorUid, GroupMemberActorJoin_Inner.gmajMemberActorUid) IN (
    |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
    |                          GroupMemberActorJoin.gmajMemberActorUid
    |                     FROM GroupMemberActorJoin
    |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                          SELECT ActorUidsForPersonUid.actorUid
    |                            FROM ActorUidsForPersonUid
    |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
    |    
    |                                          WHERE (
    |            StatementEntity_Inner.statementCbUid = PersonUidsAndCourseBlocks.cbUid
    |        AND StatementEntity_Inner.statementActorUid IN (
    |            SELECT ActorUidsForPersonUid.actorUid
    |              FROM ActorUidsForPersonUid
    |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
    |                   
    |    )
    |                                            AND StatementEntity_Inner.contextInstructorActorUid = StatementEntity.contextInstructorActorUid)
    |                                   LIMIT 1)
    |                       -- When an assignment, but not peer marked, then the latest score     
    |                       WHEN PersonUidsAndCourseBlocks.cbType = 103
    |                            THEN (SELECT StatementEntity.resultScoreScaled
    |                                    FROM StatementEntity
    |                                         
    |       JOIN ActorEntity
    |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |       LEFT JOIN GroupMemberActorJoin
    |            ON ActorEntity.actorObjectType = 2
    |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
    |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
    |                          GroupMemberActorJoin.gmajMemberActorUid
    |                     FROM GroupMemberActorJoin
    |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                          SELECT ActorUidsForPersonUid.actorUid
    |                            FROM ActorUidsForPersonUid
    |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
    |    
    |                                   WHERE (
    |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
    |        AND StatementEntity.statementActorUid IN (
    |            SELECT ActorUidsForPersonUid.actorUid
    |              FROM ActorUidsForPersonUid
    |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
    |                   
    |    )
    |                                ORDER BY StatementEntity.timestamp DESC
    |                                   LIMIT 1)
    |                       -- else the best score accomplished so far            
    |                       ELSE (SELECT MAX(StatementEntity.resultScoreScaled) 
    |                               FROM StatementEntity
    |                                    
    |       JOIN ActorEntity
    |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
    |       LEFT JOIN GroupMemberActorJoin
    |            ON ActorEntity.actorObjectType = 2
    |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
    |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
    |                          GroupMemberActorJoin.gmajMemberActorUid
    |                     FROM GroupMemberActorJoin
    |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
    |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
    |                          SELECT ActorUidsForPersonUid.actorUid
    |                            FROM ActorUidsForPersonUid
    |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
    |    
    |                              WHERE (
    |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
    |        AND StatementEntity.statementActorUid IN (
    |            SELECT ActorUidsForPersonUid.actorUid
    |              FROM ActorUidsForPersonUid
    |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
    |                   
    |    ))            
    |                       END
    |               ) AS sScoreScaled
    |          FROM PersonUidsAndCourseBlocks
    |         WHERE ? = ? 
    |    
    """.trimMargin(),
    hasListParams = true,
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setArray(1, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
        studentPersonUids.toTypedArray()))
    _stmt.setLong(2,clazzUid)
    _stmt.setArray(3, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
        studentPersonUids.toTypedArray()))
    _stmt.setLong(4,accountPersonUid)
    _stmt.setLong(5,accountPersonUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_sPersonUid = _result.getLong("sPersonUid")
        val _tmp_sCbUid = _result.getLong("sCbUid")
        val _tmp_sProgress = _result.getIntNullable("sProgress")
        val _tmp_sIsCompleted = _result.getBoolean("sIsCompleted")
        val _tmp_sIsSuccess = _result.getBooleanNullable("sIsSuccess")
        val _tmp_sScoreScaled = _result.getFloatNullable("sScoreScaled")
        BlockStatus().apply {
          this.sPersonUid = _tmp_sPersonUid
          this.sCbUid = _tmp_sCbUid
          this.sProgress = _tmp_sProgress
          this.sIsCompleted = _tmp_sIsCompleted
          this.sIsSuccess = _tmp_sIsSuccess
          this.sScoreScaled = _tmp_sScoreScaled
        }
      }
    }
  }

  override fun findStatusForStudentsInClazzAsFlow(
    clazzUid: Long,
    studentPersonUids: List<Long>,
    accountPersonUid: Long,
  ): Flow<List<BlockStatus>> = _db.doorFlow(arrayOf("ClazzAssignment", "CourseBlock", "Person",
      "GroupMemberActorJoin", "ActorEntity", "StatementEntity")) {
    _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |
      |        WITH PersonUids(personUid) AS (
      |             SELECT Person.personUid
      |               FROM Person
      |              WHERE Person.personUid IN (?)
      |        ),
      |        
      |        
      |        -- Get the ActorUids for the PersonUids See ActoryEntity doc for info on this join relationship
      |        AgentActorUidsForPersonUid(actorUid, actorPersonUid) AS(
      |             SELECT ActorEntity.actorUid AS actorUid, 
      |                    ActorEntity.actorPersonUid AS actorPersonUid
      |               FROM ActorEntity
      |              WHERE ActorEntity.actorPersonUid IN
      |                    (SELECT PersonUids.personUid
      |                       FROM PersonUids)           
      |        ),
      |        
      |        -- Add in group actor uids
      |        ActorUidsForPersonUid(actorUid, actorPersonUid) AS (
      |             SELECT AgentActorUidsForPersonUid.actorUid AS actorUid,
      |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
      |               FROM AgentActorUidsForPersonUid     
      |              UNION 
      |             SELECT GroupMemberActorJoin.gmajGroupActorUid AS actorUid,
      |                    AgentActorUidsForPersonUid.actorPersonUid AS actorPersonUid
      |               FROM AgentActorUidsForPersonUid
      |                    JOIN GroupMemberActorJoin 
      |                         ON GroupMemberActorJoin.gmajMemberActorUid = AgentActorUidsForPersonUid.actorUid
      |        )
      |    ,
      |        
      |        PersonUidsAndCourseBlocks(personUid, cbUid, cbType, caMarkingType) AS (
      |             SELECT Person.personUid AS personUid,
      |                    CourseBlock.cbUid AS cbUid,
      |                    CourseBlock.cbType AS cbType,
      |                    ClazzAssignment.caMarkingType AS caMarkingType
      |               FROM Person
      |                    JOIN CourseBlock
      |                         ON CourseBlock.cbClazzUid = ?
      |                    LEFT JOIN ClazzAssignment
      |                         ON CourseBlock.cbType = 103
      |                        AND ClazzAssignment.caUid = CourseBlock.cbEntityUid     
      |              WHERE Person.personUid IN (?)       
      |        )
      |        
      |        SELECT PersonUidsAndCourseBlocks.personUid AS sPersonUid,
      |               PersonUidsAndCourseBlocks.cbUid AS sCbUid,
      |               (SELECT MAX(StatementEntity.extensionProgress)
      |                  FROM StatementEntity
      |                       
      |       JOIN ActorEntity
      |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
      |       LEFT JOIN GroupMemberActorJoin
      |            ON ActorEntity.actorObjectType = 2
      |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
      |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
      |                          GroupMemberActorJoin.gmajMemberActorUid
      |                     FROM GroupMemberActorJoin
      |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
      |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
      |                          SELECT ActorUidsForPersonUid.actorUid
      |                            FROM ActorUidsForPersonUid
      |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
      |    
      |                 WHERE 
      |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
      |        AND StatementEntity.statementActorUid IN (
      |            SELECT ActorUidsForPersonUid.actorUid
      |              FROM ActorUidsForPersonUid
      |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
      |                   
      |     
      |               ) AS sProgress,
      |               (SELECT EXISTS(
      |                       SELECT 1
      |                         FROM StatementEntity
      |                              
      |       JOIN ActorEntity
      |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
      |       LEFT JOIN GroupMemberActorJoin
      |            ON ActorEntity.actorObjectType = 2
      |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
      |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
      |                          GroupMemberActorJoin.gmajMemberActorUid
      |                     FROM GroupMemberActorJoin
      |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
      |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
      |                          SELECT ActorUidsForPersonUid.actorUid
      |                            FROM ActorUidsForPersonUid
      |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
      |    
      |                        WHERE (
      |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
      |        AND StatementEntity.statementActorUid IN (
      |            SELECT ActorUidsForPersonUid.actorUid
      |              FROM ActorUidsForPersonUid
      |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
      |                   
      |    )
      |                          AND CAST(StatementEntity.resultCompletion AS INTEGER) = 1
      |               )) AS sIsCompleted,
      |               (SELECT CASE
      |                       /*If there is a statement marked as success, then count as successful even if
      |                        *there were subsequent failed attempts
      |                        */
      |                       WHEN (
      |                            SELECT EXISTS(
      |                                    SELECT 1
      |                                      FROM StatementEntity
      |                                           
      |       JOIN ActorEntity
      |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
      |       LEFT JOIN GroupMemberActorJoin
      |            ON ActorEntity.actorObjectType = 2
      |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
      |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
      |                          GroupMemberActorJoin.gmajMemberActorUid
      |                     FROM GroupMemberActorJoin
      |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
      |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
      |                          SELECT ActorUidsForPersonUid.actorUid
      |                            FROM ActorUidsForPersonUid
      |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
      |    
      |                                    WHERE (
      |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
      |        AND StatementEntity.statementActorUid IN (
      |            SELECT ActorUidsForPersonUid.actorUid
      |              FROM ActorUidsForPersonUid
      |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
      |                   
      |    )
      |                                      AND CAST(StatementEntity.resultSuccess AS INTEGER) = 1
      |                                   )                           
      |                       ) THEN 1
      |                       /*If there are no statements marked as success, however there are statements marekd as fail,
      |                        *then count as fail 
      |                        */
      |                       WHEN (
      |                            SELECT EXISTS(
      |                                    SELECT 1
      |                                      FROM StatementEntity
      |                                           
      |       JOIN ActorEntity
      |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
      |       LEFT JOIN GroupMemberActorJoin
      |            ON ActorEntity.actorObjectType = 2
      |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
      |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
      |                          GroupMemberActorJoin.gmajMemberActorUid
      |                     FROM GroupMemberActorJoin
      |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
      |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
      |                          SELECT ActorUidsForPersonUid.actorUid
      |                            FROM ActorUidsForPersonUid
      |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
      |    
      |                                    WHERE (
      |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
      |        AND StatementEntity.statementActorUid IN (
      |            SELECT ActorUidsForPersonUid.actorUid
      |              FROM ActorUidsForPersonUid
      |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
      |                   
      |    )
      |                                      AND CAST(StatementEntity.resultSuccess AS INTEGER) = 0
      |                                   )                           
      |                       ) THEN 0
      |                       /* Else there is no known success/fail result*/
      |                       ELSE NULL
      |                       END
      |               ) AS sIsSuccess,
      |               -- See ClazzGradebookScreen for info on which score is selected
      |               (SELECT CASE
      |                       -- When there is a peer marked assignment, take the average of the latest distinct ...
      |                       WHEN (     PersonUidsAndCourseBlocks.cbType = 103
      |                              AND PersonUidsAndCourseBlocks.caMarkingType = 2
      |                            ) 
      |                            THEN (SELECT AVG(StatementEntity.resultScoreScaled)
      |                                    FROM StatementEntity
      |                                         
      |       JOIN ActorEntity
      |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
      |       LEFT JOIN GroupMemberActorJoin
      |            ON ActorEntity.actorObjectType = 2
      |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
      |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
      |                          GroupMemberActorJoin.gmajMemberActorUid
      |                     FROM GroupMemberActorJoin
      |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
      |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
      |                          SELECT ActorUidsForPersonUid.actorUid
      |                            FROM ActorUidsForPersonUid
      |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
      |    
      |                                   WHERE (
      |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
      |        AND StatementEntity.statementActorUid IN (
      |            SELECT ActorUidsForPersonUid.actorUid
      |              FROM ActorUidsForPersonUid
      |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
      |                   
      |    )
      |                                     AND StatementEntity.timestamp = (
      |                                         SELECT MAX(StatementEntity_Inner.timestamp)
      |                                           FROM StatementEntity StatementEntity_Inner
      |                                                
      |       JOIN ActorEntity ActorEntity_Inner
      |            ON ActorEntity_Inner.actorUid = StatementEntity_Inner.statementActorUid
      |       LEFT JOIN GroupMemberActorJoin GroupMemberActorJoin_Inner
      |            ON ActorEntity_Inner.actorObjectType = 2
      |               AND (GroupMemberActorJoin_Inner.gmajGroupActorUid, GroupMemberActorJoin_Inner.gmajMemberActorUid) IN (
      |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
      |                          GroupMemberActorJoin.gmajMemberActorUid
      |                     FROM GroupMemberActorJoin
      |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
      |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
      |                          SELECT ActorUidsForPersonUid.actorUid
      |                            FROM ActorUidsForPersonUid
      |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
      |    
      |                                          WHERE (
      |            StatementEntity_Inner.statementCbUid = PersonUidsAndCourseBlocks.cbUid
      |        AND StatementEntity_Inner.statementActorUid IN (
      |            SELECT ActorUidsForPersonUid.actorUid
      |              FROM ActorUidsForPersonUid
      |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
      |                   
      |    )
      |                                            AND StatementEntity_Inner.contextInstructorActorUid = StatementEntity.contextInstructorActorUid)
      |                                   LIMIT 1)
      |                       -- When an assignment, but not peer marked, then the latest score     
      |                       WHEN PersonUidsAndCourseBlocks.cbType = 103
      |                            THEN (SELECT StatementEntity.resultScoreScaled
      |                                    FROM StatementEntity
      |                                         
      |       JOIN ActorEntity
      |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
      |       LEFT JOIN GroupMemberActorJoin
      |            ON ActorEntity.actorObjectType = 2
      |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
      |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
      |                          GroupMemberActorJoin.gmajMemberActorUid
      |                     FROM GroupMemberActorJoin
      |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
      |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
      |                          SELECT ActorUidsForPersonUid.actorUid
      |                            FROM ActorUidsForPersonUid
      |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
      |    
      |                                   WHERE (
      |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
      |        AND StatementEntity.statementActorUid IN (
      |            SELECT ActorUidsForPersonUid.actorUid
      |              FROM ActorUidsForPersonUid
      |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
      |                   
      |    )
      |                                ORDER BY StatementEntity.timestamp DESC
      |                                   LIMIT 1)
      |                       -- else the best score accomplished so far            
      |                       ELSE (SELECT MAX(StatementEntity.resultScoreScaled) 
      |                               FROM StatementEntity
      |                                    
      |       JOIN ActorEntity
      |            ON ActorEntity.actorUid = StatementEntity.statementActorUid
      |       LEFT JOIN GroupMemberActorJoin
      |            ON ActorEntity.actorObjectType = 2
      |               AND (GroupMemberActorJoin.gmajGroupActorUid, GroupMemberActorJoin.gmajMemberActorUid) IN (
      |                   SELECT GroupMemberActorJoin.gmajGroupActorUid, 
      |                          GroupMemberActorJoin.gmajMemberActorUid
      |                     FROM GroupMemberActorJoin
      |                    WHERE GroupMemberActorJoin.gmajGroupActorUid = StatementEntity.statementActorUid
      |                      AND GroupMemberActorJoin.gmajMemberActorUid IN (
      |                          SELECT ActorUidsForPersonUid.actorUid
      |                            FROM ActorUidsForPersonUid
      |                           WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid))
      |    
      |                              WHERE (
      |            StatementEntity.statementCbUid = PersonUidsAndCourseBlocks.cbUid
      |        AND StatementEntity.statementActorUid IN (
      |            SELECT ActorUidsForPersonUid.actorUid
      |              FROM ActorUidsForPersonUid
      |             WHERE ActorUidsForPersonUid.actorPersonUid = PersonUidsAndCourseBlocks.personUid)  
      |                   
      |    ))            
      |                       END
      |               ) AS sScoreScaled
      |          FROM PersonUidsAndCourseBlocks
      |         WHERE ? = ? 
      |    
      """.trimMargin(),
      hasListParams = true,
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setArray(1, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
          studentPersonUids.toTypedArray()))
      _stmt.setLong(2,clazzUid)
      _stmt.setArray(3, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
          studentPersonUids.toTypedArray()))
      _stmt.setLong(4,accountPersonUid)
      _stmt.setLong(5,accountPersonUid)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapRows {
          val _tmp_sPersonUid = _result.getLong("sPersonUid")
          val _tmp_sCbUid = _result.getLong("sCbUid")
          val _tmp_sProgress = _result.getIntNullable("sProgress")
          val _tmp_sIsCompleted = _result.getBoolean("sIsCompleted")
          val _tmp_sIsSuccess = _result.getBooleanNullable("sIsSuccess")
          val _tmp_sScoreScaled = _result.getFloatNullable("sScoreScaled")
          BlockStatus().apply {
            this.sPersonUid = _tmp_sPersonUid
            this.sCbUid = _tmp_sCbUid
            this.sProgress = _tmp_sProgress
            this.sIsCompleted = _tmp_sIsCompleted
            this.sIsSuccess = _tmp_sIsSuccess
            this.sScoreScaled = _tmp_sScoreScaled
          }
        }
      }
    }
  }

  override suspend fun findResumableRegistration(
    activityUid: Long,
    accountPersonUid: Long,
    actorUid: Long,
  ): StatementEntity? = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        WITH MostRecentRegistration(statementIdHi, statementIdLo, contextRegistrationHi, contextRegistrationLo) AS (
    |             SELECT StatementEntity.statementIdHi, StatementEntity.contextRegistrationLo,
    |                    StatementEntity.contextRegistrationHi, StatementEntity.contextRegistrationLo
    |               FROM StatementEntity
    |              WHERE StatementEntity.statementActorUid = ?
    |                AND StatementEntity.statementObjectUid1 = ?
    |                AND StatementEntity.contextRegistrationHi != 0
    |           ORDER BY StatementEntity.timestamp DESC
    |              LIMIT 1
    |        )
    |        
    |        SELECT StatementEntity.*
    |          FROM StatementEntity
    |         WHERE StatementEntity.statementIdHi = (SELECT statementIdHi FROM MostRecentRegistration)
    |           AND StatementEntity.statementIdLo = (SELECT statementIdLo FROM MostRecentRegistration)
    |           AND NOT EXISTS(
    |                   SELECT 1
    |                     FROM StatementEntity StatementEntity_Inner
    |                    WHERE StatementEntity_Inner.statementActorUid = ?
    |                      AND StatementEntity_Inner.statementObjectUid1 = ?
    |                      AND StatementEntity_Inner.contextRegistrationHi = (SELECT contextRegistrationHi FROM MostRecentRegistration)
    |                      AND StatementEntity_Inner.contextRegistrationLo = (SELECT contextRegistrationLo FROM MostRecentRegistration)
    |                      AND CAST(StatementEntity_Inner.completionOrProgress AS INTEGER) = 1
    |                      AND (     StatementEntity_Inner.resultCompletion IS NOT NULL 
    |                            AND CAST(StatementEntity_Inner.resultCompletion AS INTEGER) = 1)
    |                     )
    |           AND ? IN 
    |               (SELECT ActorEntity.actorPersonUid
    |                  FROM ActorEntity
    |                 WHERE ActorEntity.actorUid = ?)          
    |                     
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,actorUid)
    _stmt.setLong(2,activityUid)
    _stmt.setLong(3,actorUid)
    _stmt.setLong(4,activityUid)
    _stmt.setLong(5,accountPersonUid)
    _stmt.setLong(6,actorUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override suspend fun findPersonsWithAttemptsStatements(
    contentEntryUid: Long,
    accountPersonUid: Long,
    searchText: String?,
  ): List<StatementEntity> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT StatementEntity.*
    |          FROM Person
    |               JOIN StatementEntity
    |                    ON (StatementEntity.statementIdHi, StatementEntity.statementIdLo) IN
    |                            (SELECT StatementEntity.statementIdHi, StatementEntity.statementIdLo
    |                               FROM StatementEntity
    |                              WHERE StatementEntity.statementContentEntryUid = ?
    |                                AND StatementEntity.statementActorPersonUid = Person.personUid
    |                                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |                           ORDER BY StatementEntity.extensionProgress DESC
    |                              LIMIT 1)
    |                    OR (StatementEntity.statementIdHi, StatementEntity.statementIdLo) IN    
    |                          (SELECT StatementEntity.statementIdHi, StatementEntity.statementIdLo
    |                           FROM StatementEntity
    |                          WHERE StatementEntity.statementContentEntryUid = ?
    |                            AND StatementEntity.statementActorPersonUid = Person.personUid
    |                            AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |                       ORDER BY StatementEntity.resultScoreScaled DESC
    |                       LIMIT 1)
    |                    OR (StatementEntity.statementIdHi, StatementEntity.statementIdLo) IN    
    |                          (SELECT StatementEntity.statementIdHi, StatementEntity.statementIdLo
    |                           FROM StatementEntity
    |                          WHERE StatementEntity.statementContentEntryUid = ?
    |                            AND StatementEntity.statementActorPersonUid = Person.personUid
    |                       ORDER BY StatementEntity.timestamp DESC
    |                       LIMIT 1)    
    |         WHERE Person.personUid IN
    |            (SELECT DISTINCT StatementEntity.statementActorPersonUid
    |                    
    |        FROM StatementEntity
    |                    LEFT JOIN ClazzEnrolment 
    |                         ON ClazzEnrolment.clazzEnrolmentUid =
    |                           COALESCE(
    |                            (SELECT ClazzEnrolment.clazzEnrolmentUid 
    |                               FROM ClazzEnrolment
    |                              WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
    |                                AND ClazzEnrolment.clazzEnrolmentActive
    |                                AND ClazzEnrolment.clazzEnrolmentClazzUid = StatementEntity.statementClazzUid 
    |                           ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
    |                              LIMIT 1), 0)
    |              WHERE StatementEntity.statementContentEntryUid = ?
    |                /* permission check */
    |                AND (    StatementEntity.statementActorPersonUid = ?
    |                      OR EXISTS(SELECT CoursePermission.cpUid
    |                                  FROM CoursePermission
    |                                 WHERE CoursePermission.cpClazzUid = StatementEntity.statementClazzUid
    |                                   AND (   CoursePermission.cpToPersonUid = ? 
    |                                        OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole )
    |                                   AND (CoursePermission.cpPermissionsFlag & 128) > 0 
    |                                   AND NOT CoursePermission.cpIsDeleted)
    |                      OR (
    |        EXISTS(SELECT 1
    |                 FROM SystemPermission
    |                WHERE ? != 0 
    |                  AND SystemPermission.spToPersonUid = ?
    |                  AND (SystemPermission.spPermissionsFlag &
    |    
    |                          128
    |                          
    |        ) > 0
    |                  AND NOT SystemPermission.spIsDeleted)
    |    ))
    |    )      
    |            AND (   ? = '%' 
    |                 OR Person.firstNames || ' ' || Person.lastName LIKE ?) 
    |                          
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,contentEntryUid)
    _stmt.setLong(2,contentEntryUid)
    _stmt.setLong(3,contentEntryUid)
    _stmt.setLong(4,accountPersonUid)
    _stmt.setLong(5,contentEntryUid)
    _stmt.setLong(6,accountPersonUid)
    _stmt.setLong(7,accountPersonUid)
    _stmt.setLong(8,accountPersonUid)
    _stmt.setLong(9,accountPersonUid)
    _stmt.setString(10,searchText)
    _stmt.setString(11,searchText)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override fun findPersonsWithAttempts(
    contentEntryUid: Long,
    accountPersonUid: Long,
    searchText: String?,
    sortOrder: Int,
  ): PagingSource<Int, PersonAndPictureAndNumAttempts> = object :
      DoorLimitOffsetPagingSource<PersonAndPictureAndNumAttempts>(db = _db
  , tableNames = arrayOf("SystemPermission", "ClazzEnrolment", "Person", "PersonPicture",
      "StatementEntity", "CoursePermission")
  ) {
    override suspend fun loadRows(_limit: Int, _offset: Int): List<PersonAndPictureAndNumAttempts> =
        _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |SELECT * FROM (
      |     SELECT Person.*, PersonPicture.*,
      |            (SELECT COUNT(*)
      |               FROM (SELECT DISTINCT StatementEntity.contextRegistrationHi, StatementEntity.contextRegistrationLo
      |                       FROM StatementEntity
      |                      WHERE StatementEntity.statementContentEntryUid = ?
      |                        AND StatementEntity.statementActorPersonUid = Person.personUid
      |                    ) AS DistinctRegistrations) AS numAttempts,
      |            (SELECT EXISTS(
      |                    SELECT 1
      |                      FROM StatementEntity
      |                     WHERE StatementEntity.statementContentEntryUid = ?
      |                       AND StatementEntity.statementActorPersonUid = Person.personUid
      |                       AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                       AND CAST(StatementEntity.resultCompletion AS INTEGER) = 1)) AS isCompleted,
      |            (SELECT CASE
      |                    WHEN EXISTS(
      |                         SELECT 1
      |                           FROM StatementEntity
      |                          WHERE StatementEntity.statementContentEntryUid = ?
      |                            AND StatementEntity.statementActorPersonUid = Person.personUid
      |                            AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                            AND CAST(StatementEntity.resultSuccess AS INTEGER) = 1) THEN 1
      |                    WHEN EXISTS(
      |                         SELECT 1
      |                           FROM StatementEntity
      |                          WHERE StatementEntity.statementContentEntryUid = ?
      |                            AND StatementEntity.statementActorPersonUid = Person.personUid
      |                            AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                            AND StatementEntity.resultSuccess IS NOT NULL
      |                            AND CAST(StatementEntity.resultSuccess AS INTEGER) = 1) THEN 0
      |                    ELSE NULL
      |                    END) AS isSuccessful,
      |            (
      |             SELECT MAX(StatementEntity.extensionProgress)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    ) AS maxProgress,
      |            (
      |             SELECT MAX(StatementEntity.resultScoreScaled)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    ) AS maxScore,
      |            
      |            (
      |        SELECT MAX(StatementEntity.timestamp)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |    ) AS mostRecentAttemptTime    
      |       FROM Person
      |            LEFT JOIN PersonPicture
      |                 ON PersonPicture.personPictureUid = Person.personUid
      |      WHERE Person.personUid IN
      |            (SELECT DISTINCT StatementEntity.statementActorPersonUid
      |                    
      |        FROM StatementEntity
      |                    LEFT JOIN ClazzEnrolment 
      |                         ON ClazzEnrolment.clazzEnrolmentUid =
      |                           COALESCE(
      |                            (SELECT ClazzEnrolment.clazzEnrolmentUid 
      |                               FROM ClazzEnrolment
      |                              WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
      |                                AND ClazzEnrolment.clazzEnrolmentActive
      |                                AND ClazzEnrolment.clazzEnrolmentClazzUid = StatementEntity.statementClazzUid 
      |                           ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
      |                              LIMIT 1), 0)
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                /* permission check */
      |                AND (    StatementEntity.statementActorPersonUid = ?
      |                      OR EXISTS(SELECT CoursePermission.cpUid
      |                                  FROM CoursePermission
      |                                 WHERE CoursePermission.cpClazzUid = StatementEntity.statementClazzUid
      |                                   AND (   CoursePermission.cpToPersonUid = ? 
      |                                        OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole )
      |                                   AND (CoursePermission.cpPermissionsFlag & 128) > 0 
      |                                   AND NOT CoursePermission.cpIsDeleted)
      |                      OR (
      |        EXISTS(SELECT 1
      |                 FROM SystemPermission
      |                WHERE ? != 0 
      |                  AND SystemPermission.spToPersonUid = ?
      |                  AND (SystemPermission.spPermissionsFlag &
      |    
      |                          128
      |                          
      |        ) > 0
      |                  AND NOT SystemPermission.spIsDeleted)
      |    ))
      |    )      
      |            AND (   ? = '%' 
      |                 OR Person.firstNames || ' ' || Person.lastName LIKE ?)
      |     ORDER BY 
      |    CASE 
      |        WHEN ? = 5 THEN (
      |             SELECT MAX(StatementEntity.resultScoreScaled)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    )
      |        WHEN ? = 7 THEN (
      |             SELECT MAX(StatementEntity.extensionProgress)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    )
      |        WHEN ? = 9 THEN (
      |        SELECT MAX(StatementEntity.timestamp)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |    )
      |        ELSE 0
      |    END ASC,
      |    CASE 
      |        WHEN ? = 1 THEN Person.firstNames
      |        WHEN ? = 3 THEN Person.lastName
      |        ELSE ''
      |    END ASC,    
      |    CASE 
      |        WHEN ? = 6 THEN (
      |             SELECT MAX(StatementEntity.resultScoreScaled)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    )
      |        WHEN ? = 8 THEN (
      |             SELECT MAX(StatementEntity.extensionProgress)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    )
      |        WHEN ? = 10 THEN (
      |        SELECT MAX(StatementEntity.timestamp)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |    )
      |        ELSE 0
      |    END DESC,
      |    CASE
      |        WHEN ? = 2 THEN Person.firstNames
      |        WHEN ? = 4 THEN Person.lastName
      |    END DESC    
      |) AS _PagingData LIMIT ? OFFSET ?
      """.trimMargin(),
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,contentEntryUid)
      _stmt.setLong(2,contentEntryUid)
      _stmt.setLong(3,contentEntryUid)
      _stmt.setLong(4,contentEntryUid)
      _stmt.setLong(5,contentEntryUid)
      _stmt.setLong(6,contentEntryUid)
      _stmt.setLong(7,contentEntryUid)
      _stmt.setLong(8,accountPersonUid)
      _stmt.setLong(9,contentEntryUid)
      _stmt.setLong(10,accountPersonUid)
      _stmt.setLong(11,accountPersonUid)
      _stmt.setLong(12,accountPersonUid)
      _stmt.setLong(13,accountPersonUid)
      _stmt.setString(14,searchText)
      _stmt.setString(15,searchText)
      _stmt.setInt(16,sortOrder)
      _stmt.setLong(17,contentEntryUid)
      _stmt.setInt(18,sortOrder)
      _stmt.setLong(19,contentEntryUid)
      _stmt.setInt(20,sortOrder)
      _stmt.setLong(21,contentEntryUid)
      _stmt.setInt(22,sortOrder)
      _stmt.setInt(23,sortOrder)
      _stmt.setInt(24,sortOrder)
      _stmt.setLong(25,contentEntryUid)
      _stmt.setInt(26,sortOrder)
      _stmt.setLong(27,contentEntryUid)
      _stmt.setInt(28,sortOrder)
      _stmt.setLong(29,contentEntryUid)
      _stmt.setInt(30,sortOrder)
      _stmt.setInt(31,sortOrder)
      _stmt.setInt(32,_limit)
      _stmt.setInt(33,_offset)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapRows {
          val _tmp_numAttempts = _result.getInt("numAttempts")
          val _tmp_isCompleted = _result.getBoolean("isCompleted")
          val _tmp_isSuccessful = _result.getBooleanNullable("isSuccessful")
          val _tmp_maxScore = _result.getFloatNullable("maxScore")
          val _tmp_maxProgress = _result.getIntNullable("maxProgress")
          var _tmp_Person_nullCount = 0
          val _tmp_personUid = _result.getLong("personUid")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_username = _result.getString("username")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_firstNames = _result.getString("firstNames")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_lastName = _result.getString("lastName")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_emailAddr = _result.getString("emailAddr")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_phoneNum = _result.getString("phoneNum")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_gender = _result.getInt("gender")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_active = _result.getBoolean("active")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_isPersonalAccount = _result.getBoolean("isPersonalAccount")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_dateOfBirth = _result.getLong("dateOfBirth")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personAddress = _result.getString("personAddress")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personOrgId = _result.getString("personOrgId")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personGroupUid = _result.getLong("personGroupUid")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personLct = _result.getLong("personLct")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personCountry = _result.getString("personCountry")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personType = _result.getInt("personType")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personMasterChangeSeqNum = _result.getLong("personMasterChangeSeqNum")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personLocalChangeSeqNum = _result.getLong("personLocalChangeSeqNum")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personLastChangedBy = _result.getInt("personLastChangedBy")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_admin = _result.getBoolean("admin")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_personNotes = _result.getString("personNotes")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_fatherName = _result.getString("fatherName")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_fatherNumber = _result.getString("fatherNumber")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_motherName = _result.getString("motherName")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_motherNum = _result.getString("motherNum")
          if(_result.wasNull()) _tmp_Person_nullCount++
          val _tmp_Person_isAllNull = _tmp_Person_nullCount == 25
          var _tmp_PersonPicture_nullCount = 0
          val _tmp_personPictureUid = _result.getLong("personPictureUid")
          if(_result.wasNull()) _tmp_PersonPicture_nullCount++
          val _tmp_personPictureLct = _result.getLong("personPictureLct")
          if(_result.wasNull()) _tmp_PersonPicture_nullCount++
          val _tmp_personPictureUri = _result.getString("personPictureUri")
          if(_result.wasNull()) _tmp_PersonPicture_nullCount++
          val _tmp_personPictureThumbnailUri = _result.getString("personPictureThumbnailUri")
          if(_result.wasNull()) _tmp_PersonPicture_nullCount++
          val _tmp_fileSize = _result.getInt("fileSize")
          if(_result.wasNull()) _tmp_PersonPicture_nullCount++
          val _tmp_personPictureActive = _result.getBoolean("personPictureActive")
          if(_result.wasNull()) _tmp_PersonPicture_nullCount++
          val _tmp_PersonPicture_isAllNull = _tmp_PersonPicture_nullCount == 6
          PersonAndPictureAndNumAttempts().apply {
            this.numAttempts = _tmp_numAttempts
            this.isCompleted = _tmp_isCompleted
            this.isSuccessful = _tmp_isSuccessful
            this.maxScore = _tmp_maxScore
            this.maxProgress = _tmp_maxProgress
            if(!_tmp_Person_isAllNull) {
              this.person = Person().apply {
                this.personUid = _tmp_personUid
                this.username = _tmp_username
                this.firstNames = _tmp_firstNames
                this.lastName = _tmp_lastName
                this.emailAddr = _tmp_emailAddr
                this.phoneNum = _tmp_phoneNum
                this.gender = _tmp_gender
                this.active = _tmp_active
                this.isPersonalAccount = _tmp_isPersonalAccount
                this.dateOfBirth = _tmp_dateOfBirth
                this.personAddress = _tmp_personAddress
                this.personOrgId = _tmp_personOrgId
                this.personGroupUid = _tmp_personGroupUid
                this.personLct = _tmp_personLct
                this.personCountry = _tmp_personCountry
                this.personType = _tmp_personType
                this.personMasterChangeSeqNum = _tmp_personMasterChangeSeqNum
                this.personLocalChangeSeqNum = _tmp_personLocalChangeSeqNum
                this.personLastChangedBy = _tmp_personLastChangedBy
                this.admin = _tmp_admin
                this.personNotes = _tmp_personNotes
                this.fatherName = _tmp_fatherName
                this.fatherNumber = _tmp_fatherNumber
                this.motherName = _tmp_motherName
                this.motherNum = _tmp_motherNum
              }
            }
            if(!_tmp_PersonPicture_isAllNull) {
              this.picture = PersonPicture().apply {
                this.personPictureUid = _tmp_personPictureUid
                this.personPictureLct = _tmp_personPictureLct
                this.personPictureUri = _tmp_personPictureUri
                this.personPictureThumbnailUri = _tmp_personPictureThumbnailUri
                this.fileSize = _tmp_fileSize
                this.personPictureActive = _tmp_personPictureActive
              }
            }
          }
        }
      }
    }

    override suspend fun countRows(): Int = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |SELECT COUNT(*) FROM (
      |     SELECT Person.*, PersonPicture.*,
      |            (SELECT COUNT(*)
      |               FROM (SELECT DISTINCT StatementEntity.contextRegistrationHi, StatementEntity.contextRegistrationLo
      |                       FROM StatementEntity
      |                      WHERE StatementEntity.statementContentEntryUid = ?
      |                        AND StatementEntity.statementActorPersonUid = Person.personUid
      |                    ) AS DistinctRegistrations) AS numAttempts,
      |            (SELECT EXISTS(
      |                    SELECT 1
      |                      FROM StatementEntity
      |                     WHERE StatementEntity.statementContentEntryUid = ?
      |                       AND StatementEntity.statementActorPersonUid = Person.personUid
      |                       AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                       AND CAST(StatementEntity.resultCompletion AS INTEGER) = 1)) AS isCompleted,
      |            (SELECT CASE
      |                    WHEN EXISTS(
      |                         SELECT 1
      |                           FROM StatementEntity
      |                          WHERE StatementEntity.statementContentEntryUid = ?
      |                            AND StatementEntity.statementActorPersonUid = Person.personUid
      |                            AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                            AND CAST(StatementEntity.resultSuccess AS INTEGER) = 1) THEN 1
      |                    WHEN EXISTS(
      |                         SELECT 1
      |                           FROM StatementEntity
      |                          WHERE StatementEntity.statementContentEntryUid = ?
      |                            AND StatementEntity.statementActorPersonUid = Person.personUid
      |                            AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                            AND StatementEntity.resultSuccess IS NOT NULL
      |                            AND CAST(StatementEntity.resultSuccess AS INTEGER) = 1) THEN 0
      |                    ELSE NULL
      |                    END) AS isSuccessful,
      |            (
      |             SELECT MAX(StatementEntity.extensionProgress)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    ) AS maxProgress,
      |            (
      |             SELECT MAX(StatementEntity.resultScoreScaled)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    ) AS maxScore,
      |            
      |            (
      |        SELECT MAX(StatementEntity.timestamp)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |    ) AS mostRecentAttemptTime    
      |       FROM Person
      |            LEFT JOIN PersonPicture
      |                 ON PersonPicture.personPictureUid = Person.personUid
      |      WHERE Person.personUid IN
      |            (SELECT DISTINCT StatementEntity.statementActorPersonUid
      |                    
      |        FROM StatementEntity
      |                    LEFT JOIN ClazzEnrolment 
      |                         ON ClazzEnrolment.clazzEnrolmentUid =
      |                           COALESCE(
      |                            (SELECT ClazzEnrolment.clazzEnrolmentUid 
      |                               FROM ClazzEnrolment
      |                              WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
      |                                AND ClazzEnrolment.clazzEnrolmentActive
      |                                AND ClazzEnrolment.clazzEnrolmentClazzUid = StatementEntity.statementClazzUid 
      |                           ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
      |                              LIMIT 1), 0)
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                /* permission check */
      |                AND (    StatementEntity.statementActorPersonUid = ?
      |                      OR EXISTS(SELECT CoursePermission.cpUid
      |                                  FROM CoursePermission
      |                                 WHERE CoursePermission.cpClazzUid = StatementEntity.statementClazzUid
      |                                   AND (   CoursePermission.cpToPersonUid = ? 
      |                                        OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole )
      |                                   AND (CoursePermission.cpPermissionsFlag & 128) > 0 
      |                                   AND NOT CoursePermission.cpIsDeleted)
      |                      OR (
      |        EXISTS(SELECT 1
      |                 FROM SystemPermission
      |                WHERE ? != 0 
      |                  AND SystemPermission.spToPersonUid = ?
      |                  AND (SystemPermission.spPermissionsFlag &
      |    
      |                          128
      |                          
      |        ) > 0
      |                  AND NOT SystemPermission.spIsDeleted)
      |    ))
      |    )      
      |            AND (   ? = '%' 
      |                 OR Person.firstNames || ' ' || Person.lastName LIKE ?)
      |     ORDER BY 
      |    CASE 
      |        WHEN ? = 5 THEN (
      |             SELECT MAX(StatementEntity.resultScoreScaled)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    )
      |        WHEN ? = 7 THEN (
      |             SELECT MAX(StatementEntity.extensionProgress)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    )
      |        WHEN ? = 9 THEN (
      |        SELECT MAX(StatementEntity.timestamp)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |    )
      |        ELSE 0
      |    END ASC,
      |    CASE 
      |        WHEN ? = 1 THEN Person.firstNames
      |        WHEN ? = 3 THEN Person.lastName
      |        ELSE ''
      |    END ASC,    
      |    CASE 
      |        WHEN ? = 6 THEN (
      |             SELECT MAX(StatementEntity.resultScoreScaled)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    )
      |        WHEN ? = 8 THEN (
      |             SELECT MAX(StatementEntity.extensionProgress)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |                AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |    )
      |        WHEN ? = 10 THEN (
      |        SELECT MAX(StatementEntity.timestamp)
      |               FROM StatementEntity
      |              WHERE StatementEntity.statementContentEntryUid = ?
      |                AND StatementEntity.statementActorPersonUid = Person.personUid
      |    )
      |        ELSE 0
      |    END DESC,
      |    CASE
      |        WHEN ? = 2 THEN Person.firstNames
      |        WHEN ? = 4 THEN Person.lastName
      |    END DESC    
      |) AS _PagingCount
      """.trimMargin(),
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,contentEntryUid)
      _stmt.setLong(2,contentEntryUid)
      _stmt.setLong(3,contentEntryUid)
      _stmt.setLong(4,contentEntryUid)
      _stmt.setLong(5,contentEntryUid)
      _stmt.setLong(6,contentEntryUid)
      _stmt.setLong(7,contentEntryUid)
      _stmt.setLong(8,accountPersonUid)
      _stmt.setLong(9,contentEntryUid)
      _stmt.setLong(10,accountPersonUid)
      _stmt.setLong(11,accountPersonUid)
      _stmt.setLong(12,accountPersonUid)
      _stmt.setLong(13,accountPersonUid)
      _stmt.setString(14,searchText)
      _stmt.setString(15,searchText)
      _stmt.setInt(16,sortOrder)
      _stmt.setLong(17,contentEntryUid)
      _stmt.setInt(18,sortOrder)
      _stmt.setLong(19,contentEntryUid)
      _stmt.setInt(20,sortOrder)
      _stmt.setLong(21,contentEntryUid)
      _stmt.setInt(22,sortOrder)
      _stmt.setInt(23,sortOrder)
      _stmt.setInt(24,sortOrder)
      _stmt.setLong(25,contentEntryUid)
      _stmt.setInt(26,sortOrder)
      _stmt.setLong(27,contentEntryUid)
      _stmt.setInt(28,sortOrder)
      _stmt.setLong(29,contentEntryUid)
      _stmt.setInt(30,sortOrder)
      _stmt.setInt(31,sortOrder)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapNextRow(0) {
          _result.getInt(1)
        }
      }
    }
  }

  override suspend fun findSessionsByPersonAndContentStatements(
    contentEntryUid: Long,
    personUid: Long,
    accountPersonUid: Long,
  ): List<StatementEntity> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        WITH 
    |             DistinctRegistrationUids(contextRegistrationHi, contextRegistrationLo, statementClazzUid) AS (
    |      SELECT DISTINCT StatementEntity.contextRegistrationHi, 
    |                     StatementEntity.contextRegistrationLo,
    |                     StatementEntity.statementClazzUid
    |                 FROM StatementEntity
    |                WHERE StatementEntity.statementContentEntryUid = ?
    |                  AND StatementEntity.statementActorPersonUid = ?)
    |    
    |        SELECT StatementEntity.*
    |          FROM DistinctRegistrationUids
    |               JOIN StatementEntity 
    |                    ON (StatementEntity.statementIdHi, StatementEntity.statementIdLo) IN 
    |                        -- Statement for time started
    |                        (SELECT StatementEntity.statementIdHi, StatementEntity.statementIdLo 
    |                           FROM StatementEntity
    |                          WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
    |                            AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
    |                       ORDER BY StatementEntity.timestamp ASC
    |                          LIMIT 1)
    |                          
    |                       --statement for max progress   
    |                    OR (StatementEntity.statementIdHi, StatementEntity.statementIdLo) IN 
    |                       (SELECT StatementEntity.statementIdHi, StatementEntity.statementIdLo 
    |                          FROM StatementEntity
    |                         WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
    |                           AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
    |                           AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |                      ORDER BY StatementEntity.extensionProgress DESC
    |                         LIMIT 1) 
    |                         
    |                       --statement for max score  
    |                    OR (StatementEntity.statementIdHi, StatementEntity.statementIdLo) IN 
    |                       (SELECT StatementEntity.statementIdHi, StatementEntity.statementIdLo 
    |                          FROM StatementEntity
    |                         WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
    |                           AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
    |                           AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |                      ORDER BY StatementEntity.resultScoreScaled DESC
    |                         LIMIT 1)
    |                         
    |                        --statement with completion  
    |                    OR (StatementEntity.statementIdHi, StatementEntity.statementIdLo) IN 
    |                       (SELECT StatementEntity.statementIdHi, StatementEntity.statementIdLo 
    |                          FROM StatementEntity
    |                         WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
    |                           AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
    |                           AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |                           AND CAST(StatementEntity.resultCompletion AS INTEGER) = 1
    |                         LIMIT 1)
    |         WHERE (
    |            ? = ? 
    |                OR EXISTS(
    |                    SELECT CoursePermission.cpUid
    |                      FROM CoursePermission
    |                           LEFT JOIN ClazzEnrolment 
    |                                ON ClazzEnrolment.clazzEnrolmentUid =
    |                                  COALESCE(
    |                                   (SELECT ClazzEnrolment.clazzEnrolmentUid 
    |                                      FROM ClazzEnrolment
    |                                     WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
    |                                       AND ClazzEnrolment.clazzEnrolmentActive
    |                                       AND ClazzEnrolment.clazzEnrolmentClazzUid = DistinctRegistrationUids.statementClazzUid 
    |                                  ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
    |                                     LIMIT 1), 0)
    |                     WHERE CoursePermission.cpClazzUid = DistinctRegistrationUids.statementClazzUid
    |                       AND (   CoursePermission.cpToPersonUid = ? 
    |                            OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole )
    |                       AND (CoursePermission.cpPermissionsFlag & 128) > 0 
    |                       AND NOT CoursePermission.cpIsDeleted)
    |                OR (
    |        EXISTS(SELECT 1
    |                 FROM SystemPermission
    |                WHERE ? != 0 
    |                  AND SystemPermission.spToPersonUid = ?
    |                  AND (SystemPermission.spPermissionsFlag &
    |    
    |                    128
    |                    
    |        ) > 0
    |                  AND NOT SystemPermission.spIsDeleted)
    |    )
    |    )
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,contentEntryUid)
    _stmt.setLong(2,personUid)
    _stmt.setLong(3,personUid)
    _stmt.setLong(4,accountPersonUid)
    _stmt.setLong(5,accountPersonUid)
    _stmt.setLong(6,accountPersonUid)
    _stmt.setLong(7,accountPersonUid)
    _stmt.setLong(8,accountPersonUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override fun findSessionsByPersonAndContent(
    contentEntryUid: Long,
    personUid: Long,
    accountPersonUid: Long,
    sortOrder: Int,
  ): PagingSource<Int, SessionTimeAndProgressInfo> = object :
      DoorLimitOffsetPagingSource<SessionTimeAndProgressInfo>(db = _db
  , tableNames = arrayOf("SystemPermission", "ClazzEnrolment", "StatementEntity",
      "CoursePermission")
  ) {
    override suspend fun loadRows(_limit: Int, _offset: Int): List<SessionTimeAndProgressInfo> =
        _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |SELECT * FROM (
      | WITH 
      |             DistinctRegistrationUids(contextRegistrationHi, contextRegistrationLo, statementClazzUid) AS (
      |      SELECT DISTINCT StatementEntity.contextRegistrationHi, 
      |                     StatementEntity.contextRegistrationLo,
      |                     StatementEntity.statementClazzUid
      |                 FROM StatementEntity
      |                WHERE StatementEntity.statementContentEntryUid = ?
      |                  AND StatementEntity.statementActorPersonUid = ?)
      |    ,
      |      SessionsByPerson(contextRegistrationHi, contextRegistrationLo, timeStarted, maxProgress, maxScore, isCompleted, isSuccessful, resultDuration) AS (
      |       SELECT DistinctRegistrationUids.contextRegistrationHi AS contextRegistrationHi,
      |              DistinctRegistrationUids.contextRegistrationLo AS contextRegistrationLo,
      |              (SELECT MIN(StatementEntity.timestamp)
      |                 FROM StatementEntity
      |                WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                  AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                  AND StatementEntity.statementActorPersonUid = ?
      |                  AND StatementEntity.statementContentEntryUid = ?
      |              ) AS timeStarted,
      |              
      |              (SELECT MAX(StatementEntity.extensionProgress)
      |                 FROM StatementEntity
      |                WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                  AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                  AND StatementEntity.statementActorPersonUid = ?
      |                  AND StatementEntity.statementContentEntryUid = ?
      |                  AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |               ) AS maxProgress,
      |               
      |              (SELECT MAX(StatementEntity.resultScoreScaled)
      |                 FROM StatementEntity
      |                WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                  AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                  AND StatementEntity.statementActorPersonUid = ?
      |                  AND StatementEntity.statementContentEntryUid = ?
      |                  AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |               ) AS maxScore,
      |               
      |              (SELECT EXISTS(
      |                      SELECT 1 
      |                        FROM StatementEntity
      |                       WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                         AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                         AND StatementEntity.statementActorPersonUid = ?
      |                         AND StatementEntity.statementContentEntryUid = ?
      |                         AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                         AND CAST(StatementEntity.resultCompletion AS INTEGER) = 1
      |              )) AS isCompleted,
      |              (SELECT CASE 
      |                      WHEN EXISTS(
      |                           SELECT 1 
      |                             FROM StatementEntity
      |                            WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                              AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                              AND StatementEntity.statementActorPersonUid = ?
      |                              AND StatementEntity.statementContentEntryUid = ?
      |                              AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                              AND CAST(StatementEntity.resultSuccess AS INTEGER) = 1) THEN 1
      |                      WHEN EXISTS(
      |                           SELECT 1 
      |                             FROM StatementEntity
      |                            WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                              AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                              AND StatementEntity.statementActorPersonUid = ?
      |                              AND StatementEntity.statementContentEntryUid = ?
      |                              AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                              AND StatementEntity.resultSuccess IS NOT NULL
      |                              AND CAST(StatementEntity.resultSuccess AS INTEGER) = 0) THEN 0
      |                      ELSE NULL
      |                      END) AS isSuccessful,
      |                      (SELECT MAX(StatementEntity.resultDuration)
      |                         FROM StatementEntity
      |                        WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                          AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                          AND StatementEntity.statementActorPersonUid = ?
      |                          AND StatementEntity.statementContentEntryUid = ?) AS resultDuration
      |         FROM DistinctRegistrationUids
      |         WHERE (
      |            ? = ? 
      |                OR EXISTS(
      |                    SELECT CoursePermission.cpUid
      |                      FROM CoursePermission
      |                           LEFT JOIN ClazzEnrolment 
      |                                ON ClazzEnrolment.clazzEnrolmentUid =
      |                                  COALESCE(
      |                                   (SELECT ClazzEnrolment.clazzEnrolmentUid 
      |                                      FROM ClazzEnrolment
      |                                     WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
      |                                       AND ClazzEnrolment.clazzEnrolmentActive
      |                                       AND ClazzEnrolment.clazzEnrolmentClazzUid = DistinctRegistrationUids.statementClazzUid 
      |                                  ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
      |                                     LIMIT 1), 0)
      |                     WHERE CoursePermission.cpClazzUid = DistinctRegistrationUids.statementClazzUid
      |                       AND (   CoursePermission.cpToPersonUid = ? 
      |                            OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole )
      |                       AND (CoursePermission.cpPermissionsFlag & 128) > 0 
      |                       AND NOT CoursePermission.cpIsDeleted)
      |                OR (
      |        EXISTS(SELECT 1
      |                 FROM SystemPermission
      |                WHERE ? != 0 
      |                  AND SystemPermission.spToPersonUid = ?
      |                  AND (SystemPermission.spPermissionsFlag &
      |    
      |                    128
      |                    
      |        ) > 0
      |                  AND NOT SystemPermission.spIsDeleted)
      |    )
      |    )) 
      |      SELECT SessionsByPerson.*
      |        FROM SessionsByPerson
      |    ORDER BY  
      |        CASE ?
      |            WHEN 1 THEN timeStarted
      |            ELSE NULL
      |        END DESC,
      |        CASE ?
      |            WHEN 2 THEN timeStarted
      |            ELSE NULL
      |        END ASC,
      |        CASE ?
      |            WHEN 4 THEN maxScore
      |            ELSE NULL
      |        END DESC,
      |        CASE ?
      |            WHEN 3 THEN maxScore
      |            ELSE NULL
      |        END ASC,
      |        CASE ?
      |            WHEN 6 THEN maxProgress
      |            ELSE NULL
      |        END DESC,
      |        CASE ?
      |            WHEN 5 THEN maxProgress
      |            ELSE NULL
      |        END ASC
      |   ) AS _PagingData LIMIT ? OFFSET ?
      """.trimMargin(),
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,contentEntryUid)
      _stmt.setLong(2,personUid)
      _stmt.setLong(3,personUid)
      _stmt.setLong(4,contentEntryUid)
      _stmt.setLong(5,personUid)
      _stmt.setLong(6,contentEntryUid)
      _stmt.setLong(7,personUid)
      _stmt.setLong(8,contentEntryUid)
      _stmt.setLong(9,personUid)
      _stmt.setLong(10,contentEntryUid)
      _stmt.setLong(11,personUid)
      _stmt.setLong(12,contentEntryUid)
      _stmt.setLong(13,personUid)
      _stmt.setLong(14,contentEntryUid)
      _stmt.setLong(15,personUid)
      _stmt.setLong(16,contentEntryUid)
      _stmt.setLong(17,personUid)
      _stmt.setLong(18,accountPersonUid)
      _stmt.setLong(19,accountPersonUid)
      _stmt.setLong(20,accountPersonUid)
      _stmt.setLong(21,accountPersonUid)
      _stmt.setLong(22,accountPersonUid)
      _stmt.setInt(23,sortOrder)
      _stmt.setInt(24,sortOrder)
      _stmt.setInt(25,sortOrder)
      _stmt.setInt(26,sortOrder)
      _stmt.setInt(27,sortOrder)
      _stmt.setInt(28,sortOrder)
      _stmt.setInt(29,_limit)
      _stmt.setInt(30,_offset)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapRows {
          val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
          val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
          val _tmp_timeStarted = _result.getLong("timeStarted")
          val _tmp_maxProgress = _result.getIntNullable("maxProgress")
          val _tmp_maxScore = _result.getFloatNullable("maxScore")
          val _tmp_isCompleted = _result.getBoolean("isCompleted")
          val _tmp_isSuccessful = _result.getBooleanNullable("isSuccessful")
          val _tmp_resultDuration = _result.getLong("resultDuration")
          SessionTimeAndProgressInfo().apply {
            this.contextRegistrationHi = _tmp_contextRegistrationHi
            this.contextRegistrationLo = _tmp_contextRegistrationLo
            this.timeStarted = _tmp_timeStarted
            this.maxProgress = _tmp_maxProgress
            this.maxScore = _tmp_maxScore
            this.isCompleted = _tmp_isCompleted
            this.isSuccessful = _tmp_isSuccessful
            this.resultDuration = _tmp_resultDuration
          }
        }
      }
    }

    override suspend fun countRows(): Int = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |SELECT COUNT(*) FROM (
      | WITH 
      |             DistinctRegistrationUids(contextRegistrationHi, contextRegistrationLo, statementClazzUid) AS (
      |      SELECT DISTINCT StatementEntity.contextRegistrationHi, 
      |                     StatementEntity.contextRegistrationLo,
      |                     StatementEntity.statementClazzUid
      |                 FROM StatementEntity
      |                WHERE StatementEntity.statementContentEntryUid = ?
      |                  AND StatementEntity.statementActorPersonUid = ?)
      |    ,
      |      SessionsByPerson(contextRegistrationHi, contextRegistrationLo, timeStarted, maxProgress, maxScore, isCompleted, isSuccessful, resultDuration) AS (
      |       SELECT DistinctRegistrationUids.contextRegistrationHi AS contextRegistrationHi,
      |              DistinctRegistrationUids.contextRegistrationLo AS contextRegistrationLo,
      |              (SELECT MIN(StatementEntity.timestamp)
      |                 FROM StatementEntity
      |                WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                  AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                  AND StatementEntity.statementActorPersonUid = ?
      |                  AND StatementEntity.statementContentEntryUid = ?
      |              ) AS timeStarted,
      |              
      |              (SELECT MAX(StatementEntity.extensionProgress)
      |                 FROM StatementEntity
      |                WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                  AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                  AND StatementEntity.statementActorPersonUid = ?
      |                  AND StatementEntity.statementContentEntryUid = ?
      |                  AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |               ) AS maxProgress,
      |               
      |              (SELECT MAX(StatementEntity.resultScoreScaled)
      |                 FROM StatementEntity
      |                WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                  AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                  AND StatementEntity.statementActorPersonUid = ?
      |                  AND StatementEntity.statementContentEntryUid = ?
      |                  AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |               ) AS maxScore,
      |               
      |              (SELECT EXISTS(
      |                      SELECT 1 
      |                        FROM StatementEntity
      |                       WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                         AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                         AND StatementEntity.statementActorPersonUid = ?
      |                         AND StatementEntity.statementContentEntryUid = ?
      |                         AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                         AND CAST(StatementEntity.resultCompletion AS INTEGER) = 1
      |              )) AS isCompleted,
      |              (SELECT CASE 
      |                      WHEN EXISTS(
      |                           SELECT 1 
      |                             FROM StatementEntity
      |                            WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                              AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                              AND StatementEntity.statementActorPersonUid = ?
      |                              AND StatementEntity.statementContentEntryUid = ?
      |                              AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                              AND CAST(StatementEntity.resultSuccess AS INTEGER) = 1) THEN 1
      |                      WHEN EXISTS(
      |                           SELECT 1 
      |                             FROM StatementEntity
      |                            WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                              AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                              AND StatementEntity.statementActorPersonUid = ?
      |                              AND StatementEntity.statementContentEntryUid = ?
      |                              AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
      |                              AND StatementEntity.resultSuccess IS NOT NULL
      |                              AND CAST(StatementEntity.resultSuccess AS INTEGER) = 0) THEN 0
      |                      ELSE NULL
      |                      END) AS isSuccessful,
      |                      (SELECT MAX(StatementEntity.resultDuration)
      |                         FROM StatementEntity
      |                        WHERE StatementEntity.contextRegistrationHi = DistinctRegistrationUids.contextRegistrationHi
      |                          AND StatementEntity.contextRegistrationLo = DistinctRegistrationUids.contextRegistrationLo
      |                          AND StatementEntity.statementActorPersonUid = ?
      |                          AND StatementEntity.statementContentEntryUid = ?) AS resultDuration
      |         FROM DistinctRegistrationUids
      |         WHERE (
      |            ? = ? 
      |                OR EXISTS(
      |                    SELECT CoursePermission.cpUid
      |                      FROM CoursePermission
      |                           LEFT JOIN ClazzEnrolment 
      |                                ON ClazzEnrolment.clazzEnrolmentUid =
      |                                  COALESCE(
      |                                   (SELECT ClazzEnrolment.clazzEnrolmentUid 
      |                                      FROM ClazzEnrolment
      |                                     WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
      |                                       AND ClazzEnrolment.clazzEnrolmentActive
      |                                       AND ClazzEnrolment.clazzEnrolmentClazzUid = DistinctRegistrationUids.statementClazzUid 
      |                                  ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
      |                                     LIMIT 1), 0)
      |                     WHERE CoursePermission.cpClazzUid = DistinctRegistrationUids.statementClazzUid
      |                       AND (   CoursePermission.cpToPersonUid = ? 
      |                            OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole )
      |                       AND (CoursePermission.cpPermissionsFlag & 128) > 0 
      |                       AND NOT CoursePermission.cpIsDeleted)
      |                OR (
      |        EXISTS(SELECT 1
      |                 FROM SystemPermission
      |                WHERE ? != 0 
      |                  AND SystemPermission.spToPersonUid = ?
      |                  AND (SystemPermission.spPermissionsFlag &
      |    
      |                    128
      |                    
      |        ) > 0
      |                  AND NOT SystemPermission.spIsDeleted)
      |    )
      |    )) 
      |      SELECT SessionsByPerson.*
      |        FROM SessionsByPerson
      |    ORDER BY  
      |        CASE ?
      |            WHEN 1 THEN timeStarted
      |            ELSE NULL
      |        END DESC,
      |        CASE ?
      |            WHEN 2 THEN timeStarted
      |            ELSE NULL
      |        END ASC,
      |        CASE ?
      |            WHEN 4 THEN maxScore
      |            ELSE NULL
      |        END DESC,
      |        CASE ?
      |            WHEN 3 THEN maxScore
      |            ELSE NULL
      |        END ASC,
      |        CASE ?
      |            WHEN 6 THEN maxProgress
      |            ELSE NULL
      |        END DESC,
      |        CASE ?
      |            WHEN 5 THEN maxProgress
      |            ELSE NULL
      |        END ASC
      |   ) AS _PagingCount
      """.trimMargin(),
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,contentEntryUid)
      _stmt.setLong(2,personUid)
      _stmt.setLong(3,personUid)
      _stmt.setLong(4,contentEntryUid)
      _stmt.setLong(5,personUid)
      _stmt.setLong(6,contentEntryUid)
      _stmt.setLong(7,personUid)
      _stmt.setLong(8,contentEntryUid)
      _stmt.setLong(9,personUid)
      _stmt.setLong(10,contentEntryUid)
      _stmt.setLong(11,personUid)
      _stmt.setLong(12,contentEntryUid)
      _stmt.setLong(13,personUid)
      _stmt.setLong(14,contentEntryUid)
      _stmt.setLong(15,personUid)
      _stmt.setLong(16,contentEntryUid)
      _stmt.setLong(17,personUid)
      _stmt.setLong(18,accountPersonUid)
      _stmt.setLong(19,accountPersonUid)
      _stmt.setLong(20,accountPersonUid)
      _stmt.setLong(21,accountPersonUid)
      _stmt.setLong(22,accountPersonUid)
      _stmt.setInt(23,sortOrder)
      _stmt.setInt(24,sortOrder)
      _stmt.setInt(25,sortOrder)
      _stmt.setInt(26,sortOrder)
      _stmt.setInt(27,sortOrder)
      _stmt.setInt(28,sortOrder)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapNextRow(0) {
          _result.getInt(1)
        }
      }
    }
  }

  override suspend fun findActivityEntryLangMapsForStatementsBySession(registrationHi: Long,
      registrationLo: Long): List<ActivityLangMapEntry> =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT ActivityLangMapEntry.*
    |          FROM ActivityLangMapEntry
    |         WHERE ActivityLangMapEntry.almeActivityUid IN (
    |               SELECT DISTINCT StatementEntity.statementObjectUid1
    |                 FROM StatementEntity
    |                WHERE StatementEntity.contextRegistrationHi = ?
    |                  AND StatementEntity.contextRegistrationLo = ?)
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,registrationHi)
    _stmt.setLong(2,registrationLo)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_almeActivityUid = _result.getLong("almeActivityUid")
        val _tmp_almeHash = _result.getLong("almeHash")
        val _tmp_almeLangCode = _result.getString("almeLangCode")
        val _tmp_almePropName = _result.getString("almePropName")
        val _tmp_almeValue = _result.getString("almeValue")
        val _tmp_almeAieHash = _result.getLong("almeAieHash")
        val _tmp_almeLastMod = _result.getLong("almeLastMod")
        ActivityLangMapEntry().apply {
          this.almeActivityUid = _tmp_almeActivityUid
          this.almeHash = _tmp_almeHash
          this.almeLangCode = _tmp_almeLangCode
          this.almePropName = _tmp_almePropName
          this.almeValue = _tmp_almeValue
          this.almeAieHash = _tmp_almeAieHash
          this.almeLastMod = _tmp_almeLastMod
        }
      }
    }
  }

  override fun findStatementsBySession(
    registrationHi: Long,
    registrationLo: Long,
    accountPersonUid: Long,
    selectedPersonUid: Long,
    contentEntryUid: Long,
    searchText: String,
    sortOrder: Int,
    deSelectedVerbUids: List<Long>,
  ): PagingSource<Int, StatementEntityAndVerb> = object :
      DoorLimitOffsetPagingSource<StatementEntityAndVerb>(db = _db
  , tableNames = arrayOf("SystemPermission", "ActivityEntity", "VerbEntity", "ActivityLangMapEntry",
      "ClazzEnrolment", "VerbLangMapEntry", "StatementEntity", "CoursePermission")
  ) {
    override suspend fun loadRows(_limit: Int, _offset: Int): List<StatementEntityAndVerb> =
        _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |SELECT * FROM (
      |    SELECT StatementEntity.*, VerbEntity.*, VerbLangMapEntry.*, ActivityEntity.*,
      |           ActivityLangMapEntry.*,
      |           ActivityLangMapDescription.almeValue AS statementActivityDescription
      |    FROM StatementEntity
      |    LEFT JOIN VerbEntity
      |        ON StatementEntity.statementVerbUid = VerbEntity.verbUid
      |    LEFT JOIN VerbLangMapEntry 
      |        ON (VerbLangMapEntry.vlmeVerbUid, VerbLangMapEntry.vlmeLangHash) = 
      |            (SELECT VerbLangMapEntry.vlmeVerbUid, VerbLangMapEntry.vlmeLangHash
      |            FROM VerbLangMapEntry
      |            WHERE VerbLangMapEntry.vlmeVerbUid = VerbEntity.verbUid
      |            ORDER BY VerbLangMapEntry.vlmeLastModified DESC
      |            LIMIT 1)
      |    LEFT JOIN ActivityEntity
      |              ON ActivityEntity.actUid = StatementEntity.statementObjectUid1
      |    LEFT JOIN ActivityLangMapEntry
      |              ON (ActivityLangMapEntry.almeActivityUid, ActivityLangMapEntry.almeHash) = 
      |                 (SELECT ActivityLangMapEntry.almeActivityUid, ActivityLangMapEntry.almeHash
      |                    FROM ActivityLangMapEntry
      |                   WHERE ActivityLangMapEntry.almeActivityUid = StatementEntity.statementObjectUid1
      |                     AND ActivityLangMapEntry.almePropName = 'name'
      |                   LIMIT 1)
      |    LEFT JOIN ActivityLangMapEntry ActivityLangMapDescription
      |              ON (ActivityLangMapDescription.almeActivityUid, ActivityLangMapDescription.almeHash) = 
      |                 (SELECT ActivityLangMapDescription.almeActivityUid, ActivityLangMapDescription.almeHash
      |                    FROM ActivityLangMapEntry ActivityLangMapDescription
      |                   WHERE ActivityLangMapDescription.almeActivityUid = StatementEntity.statementObjectUid1
      |                     AND ActivityLangMapDescription.almePropName = 'description'
      |                   LIMIT 1)
      |    LEFT JOIN ClazzEnrolment 
      |        ON ClazzEnrolment.clazzEnrolmentUid =
      |            COALESCE(
      |                (SELECT ClazzEnrolment.clazzEnrolmentUid 
      |                FROM ClazzEnrolment
      |                WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
      |                    AND ClazzEnrolment.clazzEnrolmentActive
      |                    AND ClazzEnrolment.clazzEnrolmentClazzUid = StatementEntity.statementClazzUid 
      |                ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
      |                LIMIT 1), 0)
      |    WHERE StatementEntity.contextRegistrationHi = ?
      |    AND StatementEntity.contextRegistrationLo = ?  
      |    AND StatementEntity.statementActorPersonUid = ?
      |    AND StatementEntity.statementContentEntryUid = ?
      |    AND (? = '%' OR VerbEntity.verbUrlId LIKE ?)
      |    AND StatementEntity.statementVerbUid NOT IN (?)
      |    /* Permission check */
      |    AND (
      |        ? = ? 
      |        OR EXISTS(
      |            SELECT CoursePermission.cpUid
      |            FROM CoursePermission
      |            WHERE CoursePermission.cpClazzUid = StatementEntity.statementClazzUid
      |            AND (
      |                CoursePermission.cpToPersonUid = ? 
      |                OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole
      |            )
      |            AND (CoursePermission.cpPermissionsFlag & 128) > 0 
      |            AND NOT CoursePermission.cpIsDeleted
      |        )
      |        OR (
      |            
      |        EXISTS(SELECT 1
      |                 FROM SystemPermission
      |                WHERE ? != 0 
      |                  AND SystemPermission.spToPersonUid = ?
      |                  AND (SystemPermission.spPermissionsFlag &
      |    
      |            128
      |            
      |        ) > 0
      |                  AND NOT SystemPermission.spIsDeleted)
      |    
      |        )
      |    )
      |    ORDER BY 
      |    CASE ?
      |        WHEN 1 THEN StatementEntity.timestamp
      |        ELSE NULL
      |    END DESC,
      |    CASE ?
      |        WHEN 2 THEN StatementEntity.timestamp
      |        ELSE NULL
      |    END ASC,
      |    CASE ?
      |        WHEN 3 THEN StatementEntity.resultScoreRaw
      |        ELSE NULL
      |    END DESC,
      |    CASE ?
      |        WHEN 4 THEN StatementEntity.resultScoreRaw
      |        ELSE NULL
      |    END ASC
      |) AS _PagingData LIMIT ? OFFSET ?
      """.trimMargin(),
      hasListParams = true,
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,accountPersonUid)
      _stmt.setLong(2,registrationHi)
      _stmt.setLong(3,registrationLo)
      _stmt.setLong(4,selectedPersonUid)
      _stmt.setLong(5,contentEntryUid)
      _stmt.setString(6,searchText)
      _stmt.setString(7,searchText)
      _stmt.setArray(8, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
          deSelectedVerbUids.toTypedArray()))
      _stmt.setLong(9,accountPersonUid)
      _stmt.setLong(10,selectedPersonUid)
      _stmt.setLong(11,accountPersonUid)
      _stmt.setLong(12,accountPersonUid)
      _stmt.setLong(13,accountPersonUid)
      _stmt.setInt(14,sortOrder)
      _stmt.setInt(15,sortOrder)
      _stmt.setInt(16,sortOrder)
      _stmt.setInt(17,sortOrder)
      _stmt.setInt(18,_limit)
      _stmt.setInt(19,_offset)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapRows {
          val _tmp_statementActivityDescription = _result.getString("statementActivityDescription")
          var _tmp_StatementEntity_nullCount = 0
          val _tmp_statementIdHi = _result.getLong("statementIdHi")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementIdLo = _result.getLong("statementIdLo")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementObjectType = _result.getInt("statementObjectType")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementActorUid = _result.getLong("statementActorUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_teamUid = _result.getLong("teamUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_resultDuration = _result.getLongNullable("resultDuration")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_resultResponse = _result.getString("resultResponse")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_timestamp = _result.getLong("timestamp")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_stored = _result.getLong("stored")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_contextPlatform = _result.getString("contextPlatform")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementLct = _result.getLong("statementLct")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementCbUid = _result.getLong("statementCbUid")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
          if(_result.wasNull()) _tmp_StatementEntity_nullCount++
          val _tmp_StatementEntity_isAllNull = _tmp_StatementEntity_nullCount == 35
          var _tmp_VerbEntity_nullCount = 0
          val _tmp_verbUid = _result.getLong("verbUid")
          if(_result.wasNull()) _tmp_VerbEntity_nullCount++
          val _tmp_verbUrlId = _result.getString("verbUrlId")
          if(_result.wasNull()) _tmp_VerbEntity_nullCount++
          val _tmp_verbDeleted = _result.getBoolean("verbDeleted")
          if(_result.wasNull()) _tmp_VerbEntity_nullCount++
          val _tmp_verbLct = _result.getLong("verbLct")
          if(_result.wasNull()) _tmp_VerbEntity_nullCount++
          val _tmp_VerbEntity_isAllNull = _tmp_VerbEntity_nullCount == 4
          var _tmp_VerbLangMapEntry_nullCount = 0
          val _tmp_vlmeVerbUid = _result.getLong("vlmeVerbUid")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_vlmeLangHash = _result.getLong("vlmeLangHash")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_vlmeLangCode = _result.getString("vlmeLangCode")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_vlmeEntryString = _result.getString("vlmeEntryString")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_vlmeLastModified = _result.getLong("vlmeLastModified")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_VerbLangMapEntry_isAllNull = _tmp_VerbLangMapEntry_nullCount == 5
          var _tmp_ActivityEntity_nullCount = 0
          val _tmp_actUid = _result.getLong("actUid")
          if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
          val _tmp_actIdIri = _result.getString("actIdIri")
          if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
          val _tmp_actType = _result.getString("actType")
          if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
          val _tmp_actMoreInfo = _result.getString("actMoreInfo")
          if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
          val _tmp_actInteractionType = _result.getInt("actInteractionType")
          if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
          val _tmp_actCorrectResponsePatterns = _result.getString("actCorrectResponsePatterns")
          if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
          val _tmp_actLct = _result.getLong("actLct")
          if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
          val _tmp_ActivityEntity_isAllNull = _tmp_ActivityEntity_nullCount == 7
          var _tmp_ActivityLangMapEntry_nullCount = 0
          val _tmp_almeActivityUid = _result.getLong("almeActivityUid")
          if(_result.wasNull()) _tmp_ActivityLangMapEntry_nullCount++
          val _tmp_almeHash = _result.getLong("almeHash")
          if(_result.wasNull()) _tmp_ActivityLangMapEntry_nullCount++
          val _tmp_almeLangCode = _result.getString("almeLangCode")
          if(_result.wasNull()) _tmp_ActivityLangMapEntry_nullCount++
          val _tmp_almePropName = _result.getString("almePropName")
          if(_result.wasNull()) _tmp_ActivityLangMapEntry_nullCount++
          val _tmp_almeValue = _result.getString("almeValue")
          if(_result.wasNull()) _tmp_ActivityLangMapEntry_nullCount++
          val _tmp_almeAieHash = _result.getLong("almeAieHash")
          if(_result.wasNull()) _tmp_ActivityLangMapEntry_nullCount++
          val _tmp_almeLastMod = _result.getLong("almeLastMod")
          if(_result.wasNull()) _tmp_ActivityLangMapEntry_nullCount++
          val _tmp_ActivityLangMapEntry_isAllNull = _tmp_ActivityLangMapEntry_nullCount == 7
          StatementEntityAndVerb().apply {
            this.statementActivityDescription = _tmp_statementActivityDescription
            if(!_tmp_StatementEntity_isAllNull) {
              this.statementEntity = StatementEntity().apply {
                this.statementIdHi = _tmp_statementIdHi
                this.statementIdLo = _tmp_statementIdLo
                this.statementActorPersonUid = _tmp_statementActorPersonUid
                this.statementVerbUid = _tmp_statementVerbUid
                this.statementObjectType = _tmp_statementObjectType
                this.statementObjectUid1 = _tmp_statementObjectUid1
                this.statementObjectUid2 = _tmp_statementObjectUid2
                this.statementActorUid = _tmp_statementActorUid
                this.authorityActorUid = _tmp_authorityActorUid
                this.teamUid = _tmp_teamUid
                this.resultCompletion = _tmp_resultCompletion
                this.resultSuccess = _tmp_resultSuccess
                this.resultScoreScaled = _tmp_resultScoreScaled
                this.resultScoreRaw = _tmp_resultScoreRaw
                this.resultScoreMin = _tmp_resultScoreMin
                this.resultScoreMax = _tmp_resultScoreMax
                this.resultDuration = _tmp_resultDuration
                this.resultResponse = _tmp_resultResponse
                this.timestamp = _tmp_timestamp
                this.stored = _tmp_stored
                this.contextRegistrationHi = _tmp_contextRegistrationHi
                this.contextRegistrationLo = _tmp_contextRegistrationLo
                this.contextPlatform = _tmp_contextPlatform
                this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
                this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
                this.contextInstructorActorUid = _tmp_contextInstructorActorUid
                this.statementLct = _tmp_statementLct
                this.extensionProgress = _tmp_extensionProgress
                this.completionOrProgress = _tmp_completionOrProgress
                this.statementContentEntryUid = _tmp_statementContentEntryUid
                this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
                this.statementClazzUid = _tmp_statementClazzUid
                this.statementCbUid = _tmp_statementCbUid
                this.statementDoorNode = _tmp_statementDoorNode
                this.isSubStatement = _tmp_isSubStatement
              }
            }
            if(!_tmp_VerbEntity_isAllNull) {
              this.verb = VerbEntity().apply {
                this.verbUid = _tmp_verbUid
                this.verbUrlId = _tmp_verbUrlId
                this.verbDeleted = _tmp_verbDeleted
                this.verbLct = _tmp_verbLct
              }
            }
            if(!_tmp_VerbLangMapEntry_isAllNull) {
              this.verbDisplay = VerbLangMapEntry().apply {
                this.vlmeVerbUid = _tmp_vlmeVerbUid
                this.vlmeLangHash = _tmp_vlmeLangHash
                this.vlmeLangCode = _tmp_vlmeLangCode
                this.vlmeEntryString = _tmp_vlmeEntryString
                this.vlmeLastModified = _tmp_vlmeLastModified
              }
            }
            if(!_tmp_ActivityEntity_isAllNull) {
              this.activity = ActivityEntity().apply {
                this.actUid = _tmp_actUid
                this.actIdIri = _tmp_actIdIri
                this.actType = _tmp_actType
                this.actMoreInfo = _tmp_actMoreInfo
                this.actInteractionType = _tmp_actInteractionType
                this.actCorrectResponsePatterns = _tmp_actCorrectResponsePatterns
                this.actLct = _tmp_actLct
              }
            }
            if(!_tmp_ActivityLangMapEntry_isAllNull) {
              this.activityLangMapEntry = ActivityLangMapEntry().apply {
                this.almeActivityUid = _tmp_almeActivityUid
                this.almeHash = _tmp_almeHash
                this.almeLangCode = _tmp_almeLangCode
                this.almePropName = _tmp_almePropName
                this.almeValue = _tmp_almeValue
                this.almeAieHash = _tmp_almeAieHash
                this.almeLastMod = _tmp_almeLastMod
              }
            }
          }
        }
      }
    }

    override suspend fun countRows(): Int = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |SELECT COUNT(*) FROM (
      |    SELECT StatementEntity.*, VerbEntity.*, VerbLangMapEntry.*, ActivityEntity.*,
      |           ActivityLangMapEntry.*,
      |           ActivityLangMapDescription.almeValue AS statementActivityDescription
      |    FROM StatementEntity
      |    LEFT JOIN VerbEntity
      |        ON StatementEntity.statementVerbUid = VerbEntity.verbUid
      |    LEFT JOIN VerbLangMapEntry 
      |        ON (VerbLangMapEntry.vlmeVerbUid, VerbLangMapEntry.vlmeLangHash) = 
      |            (SELECT VerbLangMapEntry.vlmeVerbUid, VerbLangMapEntry.vlmeLangHash
      |            FROM VerbLangMapEntry
      |            WHERE VerbLangMapEntry.vlmeVerbUid = VerbEntity.verbUid
      |            ORDER BY VerbLangMapEntry.vlmeLastModified DESC
      |            LIMIT 1)
      |    LEFT JOIN ActivityEntity
      |              ON ActivityEntity.actUid = StatementEntity.statementObjectUid1
      |    LEFT JOIN ActivityLangMapEntry
      |              ON (ActivityLangMapEntry.almeActivityUid, ActivityLangMapEntry.almeHash) = 
      |                 (SELECT ActivityLangMapEntry.almeActivityUid, ActivityLangMapEntry.almeHash
      |                    FROM ActivityLangMapEntry
      |                   WHERE ActivityLangMapEntry.almeActivityUid = StatementEntity.statementObjectUid1
      |                     AND ActivityLangMapEntry.almePropName = 'name'
      |                   LIMIT 1)
      |    LEFT JOIN ActivityLangMapEntry ActivityLangMapDescription
      |              ON (ActivityLangMapDescription.almeActivityUid, ActivityLangMapDescription.almeHash) = 
      |                 (SELECT ActivityLangMapDescription.almeActivityUid, ActivityLangMapDescription.almeHash
      |                    FROM ActivityLangMapEntry ActivityLangMapDescription
      |                   WHERE ActivityLangMapDescription.almeActivityUid = StatementEntity.statementObjectUid1
      |                     AND ActivityLangMapDescription.almePropName = 'description'
      |                   LIMIT 1)
      |    LEFT JOIN ClazzEnrolment 
      |        ON ClazzEnrolment.clazzEnrolmentUid =
      |            COALESCE(
      |                (SELECT ClazzEnrolment.clazzEnrolmentUid 
      |                FROM ClazzEnrolment
      |                WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
      |                    AND ClazzEnrolment.clazzEnrolmentActive
      |                    AND ClazzEnrolment.clazzEnrolmentClazzUid = StatementEntity.statementClazzUid 
      |                ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
      |                LIMIT 1), 0)
      |    WHERE StatementEntity.contextRegistrationHi = ?
      |    AND StatementEntity.contextRegistrationLo = ?  
      |    AND StatementEntity.statementActorPersonUid = ?
      |    AND StatementEntity.statementContentEntryUid = ?
      |    AND (? = '%' OR VerbEntity.verbUrlId LIKE ?)
      |    AND StatementEntity.statementVerbUid NOT IN (?)
      |    /* Permission check */
      |    AND (
      |        ? = ? 
      |        OR EXISTS(
      |            SELECT CoursePermission.cpUid
      |            FROM CoursePermission
      |            WHERE CoursePermission.cpClazzUid = StatementEntity.statementClazzUid
      |            AND (
      |                CoursePermission.cpToPersonUid = ? 
      |                OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole
      |            )
      |            AND (CoursePermission.cpPermissionsFlag & 128) > 0 
      |            AND NOT CoursePermission.cpIsDeleted
      |        )
      |        OR (
      |            
      |        EXISTS(SELECT 1
      |                 FROM SystemPermission
      |                WHERE ? != 0 
      |                  AND SystemPermission.spToPersonUid = ?
      |                  AND (SystemPermission.spPermissionsFlag &
      |    
      |            128
      |            
      |        ) > 0
      |                  AND NOT SystemPermission.spIsDeleted)
      |    
      |        )
      |    )
      |    ORDER BY 
      |    CASE ?
      |        WHEN 1 THEN StatementEntity.timestamp
      |        ELSE NULL
      |    END DESC,
      |    CASE ?
      |        WHEN 2 THEN StatementEntity.timestamp
      |        ELSE NULL
      |    END ASC,
      |    CASE ?
      |        WHEN 3 THEN StatementEntity.resultScoreRaw
      |        ELSE NULL
      |    END DESC,
      |    CASE ?
      |        WHEN 4 THEN StatementEntity.resultScoreRaw
      |        ELSE NULL
      |    END ASC
      |) AS _PagingCount
      """.trimMargin(),
      hasListParams = true,
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,accountPersonUid)
      _stmt.setLong(2,registrationHi)
      _stmt.setLong(3,registrationLo)
      _stmt.setLong(4,selectedPersonUid)
      _stmt.setLong(5,contentEntryUid)
      _stmt.setString(6,searchText)
      _stmt.setString(7,searchText)
      _stmt.setArray(8, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
          deSelectedVerbUids.toTypedArray()))
      _stmt.setLong(9,accountPersonUid)
      _stmt.setLong(10,selectedPersonUid)
      _stmt.setLong(11,accountPersonUid)
      _stmt.setLong(12,accountPersonUid)
      _stmt.setLong(13,accountPersonUid)
      _stmt.setInt(14,sortOrder)
      _stmt.setInt(15,sortOrder)
      _stmt.setInt(16,sortOrder)
      _stmt.setInt(17,sortOrder)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapNextRow(0) {
          _result.getInt(1)
        }
      }
    }
  }

  override fun getUniqueVerbsForSession(
    registrationHi: Long,
    registrationLo: Long,
    selectedPersonUid: Long,
    contentEntryUid: Long,
  ): Flow<List<VerbEntityAndName>> = _db.doorFlow(arrayOf("VerbEntity", "VerbLangMapEntry",
      "StatementEntity")) {
    _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |
      |    WITH DistinctVerbUrls(statementVerbUid) AS (
      |        SELECT DISTINCT StatementEntity.statementVerbUid
      |        FROM StatementEntity
      |        WHERE StatementEntity.contextRegistrationHi = ?
      |            AND StatementEntity.contextRegistrationLo = ?
      |            AND StatementEntity.statementActorPersonUid = ?
      |            AND StatementEntity.statementContentEntryUid = ?
      |    )
      |    
      |    SELECT VerbEntity.*,
      |           VerbLangMapEntry.*
      |    FROM DistinctVerbUrls
      |         JOIN VerbEntity 
      |              ON VerbEntity.verbUid = DistinctVerbUrls.statementVerbUid
      |         LEFT JOIN VerbLangMapEntry
      |                  ON (VerbLangMapEntry.vlmeVerbUid, VerbLangMapEntry.vlmeLangHash) = 
      |                     (SELECT VerbLangMapEntry.vlmeVerbUid, VerbLangMapEntry.vlmeLangHash
      |                      FROM VerbLangMapEntry
      |                      WHERE VerbLangMapEntry.vlmeVerbUid = DistinctVerbUrls.statementVerbUid
      |                      ORDER BY VerbLangMapEntry.vlmeLastModified DESC
      |                      LIMIT 1)
      |""".trimMargin(),
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,registrationHi)
      _stmt.setLong(2,registrationLo)
      _stmt.setLong(3,selectedPersonUid)
      _stmt.setLong(4,contentEntryUid)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapRows {
          var _tmp_VerbEntity_nullCount = 0
          val _tmp_verbUid = _result.getLong("verbUid")
          if(_result.wasNull()) _tmp_VerbEntity_nullCount++
          val _tmp_verbUrlId = _result.getString("verbUrlId")
          if(_result.wasNull()) _tmp_VerbEntity_nullCount++
          val _tmp_verbDeleted = _result.getBoolean("verbDeleted")
          if(_result.wasNull()) _tmp_VerbEntity_nullCount++
          val _tmp_verbLct = _result.getLong("verbLct")
          if(_result.wasNull()) _tmp_VerbEntity_nullCount++
          val _tmp_VerbEntity_isAllNull = _tmp_VerbEntity_nullCount == 4
          var _tmp_VerbLangMapEntry_nullCount = 0
          val _tmp_vlmeVerbUid = _result.getLong("vlmeVerbUid")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_vlmeLangHash = _result.getLong("vlmeLangHash")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_vlmeLangCode = _result.getString("vlmeLangCode")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_vlmeEntryString = _result.getString("vlmeEntryString")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_vlmeLastModified = _result.getLong("vlmeLastModified")
          if(_result.wasNull()) _tmp_VerbLangMapEntry_nullCount++
          val _tmp_VerbLangMapEntry_isAllNull = _tmp_VerbLangMapEntry_nullCount == 5
          VerbEntityAndName().apply {
            if(!_tmp_VerbEntity_isAllNull) {
              this.verbEntity = VerbEntity().apply {
                this.verbUid = _tmp_verbUid
                this.verbUrlId = _tmp_verbUrlId
                this.verbDeleted = _tmp_verbDeleted
                this.verbLct = _tmp_verbLct
              }
            }
            if(!_tmp_VerbLangMapEntry_isAllNull) {
              this.verbName = VerbLangMapEntry().apply {
                this.vlmeVerbUid = _tmp_vlmeVerbUid
                this.vlmeLangHash = _tmp_vlmeLangHash
                this.vlmeLangCode = _tmp_vlmeLangCode
                this.vlmeEntryString = _tmp_vlmeEntryString
                this.vlmeLastModified = _tmp_vlmeLastModified
              }
            }
          }
        }
      }
    }
  }

  override suspend fun scoreOrProgressDataExistsForContent(contentEntryUid: Long,
      accountPersonUid: Long): List<StatementEntity> =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT * 
    |          FROM (SELECT StatementEntity.*
    |                 
    |        FROM StatementEntity
    |                    LEFT JOIN ClazzEnrolment 
    |                         ON ClazzEnrolment.clazzEnrolmentUid =
    |                           COALESCE(
    |                            (SELECT ClazzEnrolment.clazzEnrolmentUid 
    |                               FROM ClazzEnrolment
    |                              WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
    |                                AND ClazzEnrolment.clazzEnrolmentActive
    |                                AND ClazzEnrolment.clazzEnrolmentClazzUid = StatementEntity.statementClazzUid 
    |                           ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
    |                              LIMIT 1), 0)
    |              WHERE StatementEntity.statementContentEntryUid = ?
    |                /* permission check */
    |                AND (    StatementEntity.statementActorPersonUid = ?
    |                      OR EXISTS(SELECT CoursePermission.cpUid
    |                                  FROM CoursePermission
    |                                 WHERE CoursePermission.cpClazzUid = StatementEntity.statementClazzUid
    |                                   AND (   CoursePermission.cpToPersonUid = ? 
    |                                        OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole )
    |                                   AND (CoursePermission.cpPermissionsFlag & 128) > 0 
    |                                   AND NOT CoursePermission.cpIsDeleted)
    |                      OR (
    |        EXISTS(SELECT 1
    |                 FROM SystemPermission
    |                WHERE ? != 0 
    |                  AND SystemPermission.spToPersonUid = ?
    |                  AND (SystemPermission.spPermissionsFlag &
    |    
    |                          128
    |                          
    |        ) > 0
    |                  AND NOT SystemPermission.spIsDeleted)
    |    ))
    |    
    |                   AND (     StatementEntity.extensionProgress IS NOT NULL
    |                         AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1)
    |                 LIMIT 1) AS ProgressStatements
    |        UNION
    |        SELECT * 
    |          FROM (SELECT StatementEntity.*
    |                 
    |        FROM StatementEntity
    |                    LEFT JOIN ClazzEnrolment 
    |                         ON ClazzEnrolment.clazzEnrolmentUid =
    |                           COALESCE(
    |                            (SELECT ClazzEnrolment.clazzEnrolmentUid 
    |                               FROM ClazzEnrolment
    |                              WHERE ClazzEnrolment.clazzEnrolmentPersonUid = ?
    |                                AND ClazzEnrolment.clazzEnrolmentActive
    |                                AND ClazzEnrolment.clazzEnrolmentClazzUid = StatementEntity.statementClazzUid 
    |                           ORDER BY ClazzEnrolment.clazzEnrolmentDateLeft DESC   
    |                              LIMIT 1), 0)
    |              WHERE StatementEntity.statementContentEntryUid = ?
    |                /* permission check */
    |                AND (    StatementEntity.statementActorPersonUid = ?
    |                      OR EXISTS(SELECT CoursePermission.cpUid
    |                                  FROM CoursePermission
    |                                 WHERE CoursePermission.cpClazzUid = StatementEntity.statementClazzUid
    |                                   AND (   CoursePermission.cpToPersonUid = ? 
    |                                        OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment.clazzEnrolmentRole )
    |                                   AND (CoursePermission.cpPermissionsFlag & 128) > 0 
    |                                   AND NOT CoursePermission.cpIsDeleted)
    |                      OR (
    |        EXISTS(SELECT 1
    |                 FROM SystemPermission
    |                WHERE ? != 0 
    |                  AND SystemPermission.spToPersonUid = ?
    |                  AND (SystemPermission.spPermissionsFlag &
    |    
    |                          128
    |                          
    |        ) > 0
    |                  AND NOT SystemPermission.spIsDeleted)
    |    ))
    |    
    |                   AND (     StatementEntity.resultScoreScaled IS NOT NULL
    |                         AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1)
    |                 LIMIT 1) AS ScoreStatements
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,accountPersonUid)
    _stmt.setLong(2,contentEntryUid)
    _stmt.setLong(3,accountPersonUid)
    _stmt.setLong(4,accountPersonUid)
    _stmt.setLong(5,accountPersonUid)
    _stmt.setLong(6,accountPersonUid)
    _stmt.setLong(7,accountPersonUid)
    _stmt.setLong(8,contentEntryUid)
    _stmt.setLong(9,accountPersonUid)
    _stmt.setLong(10,accountPersonUid)
    _stmt.setLong(11,accountPersonUid)
    _stmt.setLong(12,accountPersonUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        val _tmp_teamUid = _result.getLong("teamUid")
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        val _tmp_resultResponse = _result.getString("resultResponse")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_stored = _result.getLong("stored")
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        val _tmp_statementLct = _result.getLong("statementLct")
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        StatementEntity().apply {
          this.statementIdHi = _tmp_statementIdHi
          this.statementIdLo = _tmp_statementIdLo
          this.statementActorPersonUid = _tmp_statementActorPersonUid
          this.statementVerbUid = _tmp_statementVerbUid
          this.statementObjectType = _tmp_statementObjectType
          this.statementObjectUid1 = _tmp_statementObjectUid1
          this.statementObjectUid2 = _tmp_statementObjectUid2
          this.statementActorUid = _tmp_statementActorUid
          this.authorityActorUid = _tmp_authorityActorUid
          this.teamUid = _tmp_teamUid
          this.resultCompletion = _tmp_resultCompletion
          this.resultSuccess = _tmp_resultSuccess
          this.resultScoreScaled = _tmp_resultScoreScaled
          this.resultScoreRaw = _tmp_resultScoreRaw
          this.resultScoreMin = _tmp_resultScoreMin
          this.resultScoreMax = _tmp_resultScoreMax
          this.resultDuration = _tmp_resultDuration
          this.resultResponse = _tmp_resultResponse
          this.timestamp = _tmp_timestamp
          this.stored = _tmp_stored
          this.contextRegistrationHi = _tmp_contextRegistrationHi
          this.contextRegistrationLo = _tmp_contextRegistrationLo
          this.contextPlatform = _tmp_contextPlatform
          this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
          this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
          this.contextInstructorActorUid = _tmp_contextInstructorActorUid
          this.statementLct = _tmp_statementLct
          this.extensionProgress = _tmp_extensionProgress
          this.completionOrProgress = _tmp_completionOrProgress
          this.statementContentEntryUid = _tmp_statementContentEntryUid
          this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
          this.statementClazzUid = _tmp_statementClazzUid
          this.statementCbUid = _tmp_statementCbUid
          this.statementDoorNode = _tmp_statementDoorNode
          this.isSubStatement = _tmp_isSubStatement
        }
      }
    }
  }

  override suspend fun findByUidWithActivityAsync(statementIdHi: Long, statementIdLo: Long):
      StatementAndActivity? = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT StatementEntity.*, ActivityEntity.*
    |          FROM StatementEntity
    |               LEFT JOIN ActivityEntity
    |                         ON ActivityEntity.actUid = StatementEntity.statementObjectUid1
    |         WHERE StatementEntity.statementIdHi = ?
    |           AND StatementEntity.statementIdLo = ?
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,statementIdHi)
    _stmt.setLong(2,statementIdLo)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapNextRow(null) {
        var _tmp_StatementEntity_nullCount = 0
        val _tmp_statementIdHi = _result.getLong("statementIdHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementIdLo = _result.getLong("statementIdLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementActorPersonUid = _result.getLong("statementActorPersonUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementVerbUid = _result.getLong("statementVerbUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectType = _result.getInt("statementObjectType")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectUid1 = _result.getLong("statementObjectUid1")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementObjectUid2 = _result.getLong("statementObjectUid2")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementActorUid = _result.getLong("statementActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_authorityActorUid = _result.getLong("authorityActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_teamUid = _result.getLong("teamUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultCompletion = _result.getBooleanNullable("resultCompletion")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultSuccess = _result.getBooleanNullable("resultSuccess")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreScaled = _result.getFloatNullable("resultScoreScaled")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreRaw = _result.getFloatNullable("resultScoreRaw")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreMin = _result.getFloatNullable("resultScoreMin")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultScoreMax = _result.getFloatNullable("resultScoreMax")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultDuration = _result.getLongNullable("resultDuration")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_resultResponse = _result.getString("resultResponse")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_timestamp = _result.getLong("timestamp")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_stored = _result.getLong("stored")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextRegistrationHi = _result.getLong("contextRegistrationHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextRegistrationLo = _result.getLong("contextRegistrationLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextPlatform = _result.getString("contextPlatform")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextStatementRefIdHi = _result.getLong("contextStatementRefIdHi")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextStatementRefIdLo = _result.getLong("contextStatementRefIdLo")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_contextInstructorActorUid = _result.getLong("contextInstructorActorUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementLct = _result.getLong("statementLct")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_extensionProgress = _result.getIntNullable("extensionProgress")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_completionOrProgress = _result.getBoolean("completionOrProgress")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementContentEntryUid = _result.getLong("statementContentEntryUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementLearnerGroupUid = _result.getLong("statementLearnerGroupUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementClazzUid = _result.getLong("statementClazzUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementCbUid = _result.getLong("statementCbUid")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_statementDoorNode = _result.getLong("statementDoorNode")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_isSubStatement = _result.getBoolean("isSubStatement")
        if(_result.wasNull()) _tmp_StatementEntity_nullCount++
        val _tmp_StatementEntity_isAllNull = _tmp_StatementEntity_nullCount == 35
        var _tmp_ActivityEntity_nullCount = 0
        val _tmp_actUid = _result.getLong("actUid")
        if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
        val _tmp_actIdIri = _result.getString("actIdIri")
        if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
        val _tmp_actType = _result.getString("actType")
        if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
        val _tmp_actMoreInfo = _result.getString("actMoreInfo")
        if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
        val _tmp_actInteractionType = _result.getInt("actInteractionType")
        if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
        val _tmp_actCorrectResponsePatterns = _result.getString("actCorrectResponsePatterns")
        if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
        val _tmp_actLct = _result.getLong("actLct")
        if(_result.wasNull()) _tmp_ActivityEntity_nullCount++
        val _tmp_ActivityEntity_isAllNull = _tmp_ActivityEntity_nullCount == 7
        StatementAndActivity().apply {
          if(!_tmp_StatementEntity_isAllNull) {
            this.statementEntity = StatementEntity().apply {
              this.statementIdHi = _tmp_statementIdHi
              this.statementIdLo = _tmp_statementIdLo
              this.statementActorPersonUid = _tmp_statementActorPersonUid
              this.statementVerbUid = _tmp_statementVerbUid
              this.statementObjectType = _tmp_statementObjectType
              this.statementObjectUid1 = _tmp_statementObjectUid1
              this.statementObjectUid2 = _tmp_statementObjectUid2
              this.statementActorUid = _tmp_statementActorUid
              this.authorityActorUid = _tmp_authorityActorUid
              this.teamUid = _tmp_teamUid
              this.resultCompletion = _tmp_resultCompletion
              this.resultSuccess = _tmp_resultSuccess
              this.resultScoreScaled = _tmp_resultScoreScaled
              this.resultScoreRaw = _tmp_resultScoreRaw
              this.resultScoreMin = _tmp_resultScoreMin
              this.resultScoreMax = _tmp_resultScoreMax
              this.resultDuration = _tmp_resultDuration
              this.resultResponse = _tmp_resultResponse
              this.timestamp = _tmp_timestamp
              this.stored = _tmp_stored
              this.contextRegistrationHi = _tmp_contextRegistrationHi
              this.contextRegistrationLo = _tmp_contextRegistrationLo
              this.contextPlatform = _tmp_contextPlatform
              this.contextStatementRefIdHi = _tmp_contextStatementRefIdHi
              this.contextStatementRefIdLo = _tmp_contextStatementRefIdLo
              this.contextInstructorActorUid = _tmp_contextInstructorActorUid
              this.statementLct = _tmp_statementLct
              this.extensionProgress = _tmp_extensionProgress
              this.completionOrProgress = _tmp_completionOrProgress
              this.statementContentEntryUid = _tmp_statementContentEntryUid
              this.statementLearnerGroupUid = _tmp_statementLearnerGroupUid
              this.statementClazzUid = _tmp_statementClazzUid
              this.statementCbUid = _tmp_statementCbUid
              this.statementDoorNode = _tmp_statementDoorNode
              this.isSubStatement = _tmp_isSubStatement
            }
          }
          if(!_tmp_ActivityEntity_isAllNull) {
            this.activityEntity = ActivityEntity().apply {
              this.actUid = _tmp_actUid
              this.actIdIri = _tmp_actIdIri
              this.actType = _tmp_actType
              this.actMoreInfo = _tmp_actMoreInfo
              this.actInteractionType = _tmp_actInteractionType
              this.actCorrectResponsePatterns = _tmp_actCorrectResponsePatterns
              this.actLct = _tmp_actLct
            }
          }
        }
      }
    }
  }
}
