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.xapi.StatementEntityAndRelated
import com.ustadmobile.lib.db.entities.Person
import com.ustadmobile.lib.db.entities.StatementEntityAndDisplayDetails
import com.ustadmobile.lib.db.entities.StatementReportData
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 kotlin.Boolean
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 =
        "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(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

    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_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 == 24
            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.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_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.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 (    (CAST(? AS BIGINT) = 0 AND CAST(? AS BIGINT) = 0) 
    |                 OR (statementIdHi = CAST(? AS BIGINT) AND statementIdLo = CAST(? AS BIGINT)))
    |                  
    |    
    """.trimMargin(),
    postgreSql = """
    |
    |        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 = CAST(? AS BIGINT) 
    |           AND statementIdLo = CAST(? AS BIGINT)       
    |    
    """.trimMargin(),
    postgreSql = """
    |
    |        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 = CAST(? AS BIGINT)
    |           AND StatementEntity.statementContentEntryUid = CAST(? AS BIGINT)
    |           AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |           AND (CAST(? AS BIGINT) = 0 OR StatementEntity.statementCbUid = CAST(? AS BIGINT))
    |    
    |        AND (    (CAST(StatementEntity.resultCompletion AS INTEGER) = 1)
    |              OR (StatementEntity.extensionProgress IS NOT NULL))
    |        
    |        
    |    
    |    
    """.trimMargin(),
    postgreSql = """
    |
    |        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 = CAST(? AS BIGINT)
    |         AND StatementEntity.statementContentEntryUid IN (
    |             SELECT ContentEntryParentChildJoin.cepcjChildContentEntryUid
    |               FROM ContentEntryParentChildJoin
    |              WHERE ContentEntryParentChildJoin.cepcjParentContentEntryUid = CAST(? AS BIGINT))
    |         AND CAST(StatementEntity.completionOrProgress AS INTEGER) = 1
    |         AND (    (CAST(StatementEntity.resultCompletion AS INTEGER) = 1)
    |              OR (StatementEntity.extensionProgress IS NOT NULL))     
    |    
    |    
    """.trimMargin(),
    postgreSql = """
    |
    |        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 CAST(? AS BIGINT) 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 = CAST(? AS BIGINT)
    |                   AND ClazzEnrolment.clazzEnrolmentPersonUid = CAST(? AS BIGINT)
    |                   AND ClazzEnrolment.clazzEnrolmentRole = 1000))
    |    )
    |                AND StatementEntity.statementActorUid IN (
    |                    SELECT ActorUidsForPersonUid.actorUid
    |                      FROM ActorUidsForPersonUid)
    |                AND StatementEntity.statementClazzUid = CAST(? AS BIGINT)
    |                AND (    (CAST(StatementEntity.resultCompletion AS INTEGER) = 1)
    |                      OR (StatementEntity.extensionProgress IS NOT NULL))
    |    
    |    
    """.trimMargin(),
    postgreSql = """
    |
    |        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 = CAST(? AS BIGINT) 
    |                               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 = CAST(? AS BIGINT) 
    |                               AND ClazzEnrolment.clazzEnrolmentActive 
    |                               AND ClazzEnrolment.clazzEnrolmentRole = ? 
    |                               AND (? != 1 
    |                                     OR (CAST(? AS BIGINT) 
    |                                          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 = CAST(? AS BIGINT)), 0) = CAST(? AS BIGINT))
    |              /* 
    |              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 = CAST(? AS BIGINT)
    |                                       AND _ClazzEnrolment_AccountPersonInner.clazzEnrolmentActive
    |                                  ORDER BY _ClazzEnrolment_AccountPersonInner.clazzEnrolmentDateLeft DESC   
    |                                     LIMIT 1), 0))
    |    
    |                         WHERE CoursePermission.cpClazzUid = CAST(? AS BIGINT)
    |                           AND (CoursePermission.cpToPersonUid = CAST(? AS BIGINT) 
    |                                OR CoursePermission.cpToEnrolmentRole = ClazzEnrolment_ForAccountPerson.clazzEnrolmentRole)
    |                           AND (CoursePermission.cpPermissionsFlag & 
    |         128
    |                                
    |        ) > 0)
    |              OR EXISTS(SELECT SystemPermission.spUid
    |                          FROM SystemPermission
    |                         WHERE SystemPermission.spToPersonUid = CAST(? AS BIGINT)
    |                           AND (SystemPermission.spPermissionsFlag & 
    |     128
    |                                
    |        ) > 0)
    |               )
    |    )
    |                            OR Person.personUid = CAST(? AS BIGINT)
    |                           )  
    |                       /* 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 = CAST(? AS BIGINT)
    |           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(),
    postgreSql = """
    |
    |        -- 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 = CAST(? AS BIGINT)
    |           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,
    postgreSql = """
    |
    |        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(),
    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 CAST(? AS BIGINT) = CAST(? AS BIGINT)
    |           AND CAST(? AS BIGINT) = CAST(? AS BIGINT)
    |    
    """.trimMargin(),
    hasListParams = true,
    postgreSql = """
    |
    |        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(),
    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 = CAST(? AS BIGINT)
    |                    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 CAST(? AS BIGINT) = CAST(? AS BIGINT) 
    |    
    """.trimMargin(),
    hasListParams = true,
    postgreSql = """
    |
    |        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(),
    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 = CAST(? AS BIGINT)
      |                    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 CAST(? AS BIGINT) = CAST(? AS BIGINT) 
      |    
      """.trimMargin(),
      hasListParams = true,
      postgreSql = """
      |
      |        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(),
      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 = CAST(? AS BIGINT)
    |                AND StatementEntity.statementObjectUid1 = CAST(? AS BIGINT)
    |                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 = CAST(? AS BIGINT)
    |                      AND StatementEntity_Inner.statementObjectUid1 = CAST(? AS BIGINT)
    |                      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 CAST(? AS BIGINT) IN 
    |               (SELECT ActorEntity.actorPersonUid
    |                  FROM ActorEntity
    |                 WHERE ActorEntity.actorUid = CAST(? AS BIGINT))          
    |                     
    |    
    """.trimMargin(),
    postgreSql = """
    |
    |        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
        }
      }
    }
  }
}
