Skip to content

Commit

Permalink
Remove parameter table join from SQL queries [DPP-705] (#11562)
Browse files Browse the repository at this point in the history
* Add wiring of ledger-end to necessary places
* change SQL queries to use ledger-end-cache instead of parameter table join
* Fixes tests/test suite DB providers

changelog_begin
changelog_end
  • Loading branch information
nmarton-da authored Nov 4, 2021
1 parent af7f7f3 commit 9ef2eaf
Show file tree
Hide file tree
Showing 15 changed files with 116 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ import com.daml.platform.store.cache.LedgerEndCache
trait CommonStorageBackendFactory extends StorageBackendFactory {

override def createPackageStorageBackend(ledgerEndCache: LedgerEndCache): PackageStorageBackend =
PackageStorageBackendTemplate
new PackageStorageBackendTemplate(ledgerEndCache)

override val createParameterStorageBackend: ParameterStorageBackend =
ParameterStorageBackendTemplate

override def createConfigurationStorageBackend(
ledgerEndCache: LedgerEndCache
): ConfigurationStorageBackend =
ConfigurationStorageBackendTemplate
new ConfigurationStorageBackendTemplate(ledgerEndCache)

override val createIntegrityStorageBackend: IntegrityStorageBackend =
IntegrityStorageBackendTemplate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import com.daml.platform.store.Conversions.offset
import com.daml.platform.store.SimpleSqlAsVectorOf.SimpleSqlAsVectorOf
import com.daml.platform.store.appendonlydao.JdbcLedgerDao.{acceptType, rejectType}
import com.daml.platform.store.backend.ConfigurationStorageBackend
import com.daml.platform.store.cache.LedgerEndCache
import com.daml.platform.store.entries.ConfigurationEntry

private[backend] object ConfigurationStorageBackendTemplate extends ConfigurationStorageBackend {
private[backend] class ConfigurationStorageBackendTemplate(ledgerEndCache: LedgerEndCache)
extends ConfigurationStorageBackend {

private val SQL_GET_CONFIGURATION_ENTRIES = SQL(
"""select
Expand All @@ -26,12 +28,10 @@ private[backend] object ConfigurationStorageBackendTemplate extends Configuratio
| configuration_entries.configuration,
| configuration_entries.rejection_reason
| from
| configuration_entries,
| parameters
| configuration_entries
| where
| ({startExclusive} is null or ledger_offset>{startExclusive}) and
| ledger_offset <= {endInclusive} and
| parameters.ledger_end >= ledger_offset
| ledger_offset <= {endInclusive}
| order by ledger_offset asc
| offset {queryOffset} rows
| fetch next {pageSize} rows only
Expand All @@ -47,11 +47,10 @@ private[backend] object ConfigurationStorageBackendTemplate extends Configuratio
| configuration_entries.configuration,
| configuration_entries.rejection_reason
| from
| configuration_entries,
| parameters
| configuration_entries
| where
| configuration_entries.typ = '$acceptType' and
| parameters.ledger_end >= ledger_offset
| {ledger_end_offset} >= ledger_offset
| order by ledger_offset desc
| fetch next 1 row only""".stripMargin
)
Expand Down Expand Up @@ -88,7 +87,7 @@ private[backend] object ConfigurationStorageBackendTemplate extends Configuratio

def ledgerConfiguration(connection: Connection): Option[(Offset, Configuration)] =
SQL_GET_LATEST_CONFIGURATION_ENTRY
.on()
.on("ledger_end_offset" -> ledgerEndCache()._1.toHexString.toString)
.asVectorOf(configurationEntryParser)(connection)
.collectFirst { case (offset, ConfigurationEntry.Accepted(_, configuration)) =>
offset -> configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.daml.platform.store.backend.common

import java.sql.Connection

import anorm.SqlParser.{byteArray, int, long, str}
import anorm.{ResultSetParser, Row, RowParser, SimpleSql, SqlParser, ~}
import com.daml.lf.data.Ref
Expand All @@ -19,6 +20,7 @@ import com.daml.platform.store.SimpleSqlAsVectorOf.SimpleSqlAsVectorOf
import com.daml.platform.store.appendonlydao.events.{ContractId, Key}
import com.daml.platform.store.backend.common.ComposableQuery.{CompositeSql, SqlStringInterpolation}
import com.daml.platform.store.backend.ContractStorageBackend
import com.daml.platform.store.cache.LedgerEndCache
import com.daml.platform.store.interfaces.LedgerDaoContractsReader.{
KeyAssigned,
KeyState,
Expand All @@ -27,7 +29,10 @@ import com.daml.platform.store.interfaces.LedgerDaoContractsReader.{

import scala.util.{Failure, Success, Try}

class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends ContractStorageBackend {
class ContractStorageBackendTemplate(
queryStrategy: QueryStrategy,
ledgerEndCache: LedgerEndCache,
) extends ContractStorageBackend {

override def contractKeyGlobally(key: Key)(connection: Connection): Option[ContractId] =
contractKey(
Expand All @@ -36,7 +41,7 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
)(
readers = None,
key = key,
validAt = None,
validAt = ledgerEndCache()._2,
)(connection)

private def emptyContractIds: Throwable =
Expand All @@ -49,31 +54,34 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
s"The following contracts have not been found: ${missingContractIds.map(_.coid).mkString(", ")}"
)

protected def maximumLedgerTimeSqlLiteral(id: ContractId): SimpleSql[Row] = {
protected def maximumLedgerTimeSqlLiteral(
id: ContractId,
lastEventSequentialId: Long,
): SimpleSql[Row] = {
import com.daml.platform.store.Conversions.ContractIdToStatement
SQL"""
WITH archival_event AS (
SELECT participant_events.*
FROM participant_events, parameters
FROM participant_events
WHERE contract_id = $id
AND event_kind = 20 -- consuming exercise
AND event_sequential_id <= parameters.ledger_end_sequential_id
AND event_sequential_id <= $lastEventSequentialId
FETCH NEXT 1 ROW ONLY
),
create_event AS (
SELECT ledger_effective_time
FROM participant_events, parameters
FROM participant_events
WHERE contract_id = $id
AND event_kind = 10 -- create
AND event_sequential_id <= parameters.ledger_end_sequential_id
AND event_sequential_id <= $lastEventSequentialId
FETCH NEXT 1 ROW ONLY -- limit here to guide planner wrt expected number of results
),
divulged_contract AS (
SELECT ledger_effective_time
FROM participant_events, parameters
FROM participant_events
WHERE contract_id = $id
AND event_kind = 0 -- divulgence
AND event_sequential_id <= parameters.ledger_end_sequential_id
AND event_sequential_id <= $lastEventSequentialId
ORDER BY event_sequential_id
-- prudent engineering: make results more stable by preferring earlier divulgence events
-- Results might still change due to pruning.
Expand All @@ -95,11 +103,12 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
override def maximumLedgerTime(
ids: Set[ContractId]
)(connection: Connection): Try[Option[Timestamp]] = {
val lastEventSequentialId = ledgerEndCache()._2
if (ids.isEmpty) {
Failure(emptyContractIds)
} else {
def lookup(id: ContractId): Option[Option[Timestamp]] =
maximumLedgerTimeSqlLiteral(id).as(
maximumLedgerTimeSqlLiteral(id, lastEventSequentialId).as(
timestampFromMicros("ledger_effective_time").?.singleOpt
)(
connection
Expand Down Expand Up @@ -132,7 +141,7 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
)(
readers = None,
key = key,
validAt = Some(validAt),
validAt = validAt,
)(connection).getOrElse(KeyUnassigned)

private val fullDetailsContractRowParser: RowParser[ContractStorageBackend.RawContractState] =
Expand Down Expand Up @@ -239,32 +248,33 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
resultColumns: List[String],
coalescedColumns: String,
): SimpleSql[Row] = {
val lastEventSequentialId = ledgerEndCache()._2
import com.daml.platform.store.Conversions.ContractIdToStatement
SQL""" WITH archival_event AS (
SELECT participant_events.*
FROM participant_events, parameters
FROM participant_events
WHERE contract_id = $contractId
AND event_kind = 20 -- consuming exercise
AND event_sequential_id <= parameters.ledger_end_sequential_id
AND event_sequential_id <= $lastEventSequentialId
AND $treeEventWitnessesClause -- only use visible archivals
FETCH NEXT 1 ROW ONLY
),
create_event AS (
SELECT contract_id, #${resultColumns.mkString(", ")}
FROM participant_events, parameters
FROM participant_events
WHERE contract_id = $contractId
AND event_kind = 10 -- create
AND event_sequential_id <= parameters.ledger_end_sequential_id
AND event_sequential_id <= $lastEventSequentialId
AND $treeEventWitnessesClause
FETCH NEXT 1 ROW ONLY -- limit here to guide planner wrt expected number of results
),
-- no visibility check, as it is used to backfill missing template_id and create_arguments for divulged contracts
create_event_unrestricted AS (
SELECT contract_id, #${resultColumns.mkString(", ")}
FROM participant_events, parameters
FROM participant_events
WHERE contract_id = $contractId
AND event_kind = 10 -- create
AND event_sequential_id <= parameters.ledger_end_sequential_id
AND event_sequential_id <= $lastEventSequentialId
FETCH NEXT 1 ROW ONLY -- limit here to guide planner wrt expected number of results
),
divulged_contract AS (
Expand All @@ -275,11 +285,10 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
-- therefore only communicates the change in visibility to the IndexDB, but
-- does not include a full divulgence event.
#$coalescedColumns
FROM participant_events divulgence_events LEFT OUTER JOIN create_event_unrestricted ON (divulgence_events.contract_id = create_event_unrestricted.contract_id),
parameters
FROM participant_events divulgence_events LEFT OUTER JOIN create_event_unrestricted ON (divulgence_events.contract_id = create_event_unrestricted.contract_id)
WHERE divulgence_events.contract_id = $contractId -- restrict to aid query planner
AND divulgence_events.event_kind = 0 -- divulgence
AND divulgence_events.event_sequential_id <= parameters.ledger_end_sequential_id
AND divulgence_events.event_sequential_id <= $lastEventSequentialId
AND $treeEventWitnessesClause
ORDER BY divulgence_events.event_sequential_id
-- prudent engineering: make results more stable by preferring earlier divulgence events
Expand Down Expand Up @@ -355,7 +364,7 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
)(
readers = Some(readers),
key = key,
validAt = None,
validAt = ledgerEndCache()._2,
)(connection)

private def contractKey[T](
Expand All @@ -364,7 +373,7 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
)(
readers: Option[Set[Ref.Party]],
key: Key,
validAt: Option[Long],
validAt: Long,
)(
connection: Connection
): Option[T] = {
Expand Down Expand Up @@ -393,25 +402,16 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
_,
)
)
val validAtClause = validAt match {
case Some(validAt) =>
cSQL"AND event_sequential_id <= $validAt"

case None =>
cSQL""
}
def ifNoValidAt(s: String): String = if (validAt.isEmpty) s else ""

import com.daml.platform.store.Conversions.HashToStatement
SQL"""
WITH last_contract_key_create AS (
SELECT participant_events.*
FROM participant_events#${ifNoValidAt(", parameters")}
FROM participant_events
WHERE event_kind = 10 -- create
AND create_key_hash = ${key.hash}
#${ifNoValidAt("AND event_sequential_id <= parameters.ledger_end_sequential_id")}
-- do NOT check visibility here, as otherwise we do not abort the scan early
$validAtClause
AND event_sequential_id <= $validAt
ORDER BY event_sequential_id DESC
FETCH NEXT 1 ROW ONLY
)
Expand All @@ -420,12 +420,11 @@ class ContractStorageBackendTemplate(queryStrategy: QueryStrategy) extends Contr
WHERE $lastContractKeyFlatEventWitnessesClause -- check visibility only here
NOT EXISTS -- check no archival visible
(SELECT 1
FROM participant_events#${ifNoValidAt(", parameters")}
FROM participant_events
WHERE event_kind = 20 AND -- consuming exercise
#${ifNoValidAt("event_sequential_id <= parameters.ledger_end_sequential_id AND")}
$participantEventsFlatEventWitnessesClause
contract_id = last_contract_key_create.contract_id
$validAtClause
AND event_sequential_id <= $validAt
)"""
.as(resultParser.singleOpt)(connection)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.daml.platform.store.backend.common

import java.sql.Connection

import anorm.SqlParser.{array, bool, byteArray, int, long, str}
import anorm.{Row, RowParser, SimpleSql, ~}
import com.daml.ledger.offset.Offset
Expand All @@ -23,12 +24,14 @@ import com.daml.platform.store.backend.EventStorageBackend
import com.daml.platform.store.backend.EventStorageBackend.{FilterParams, RangeParams}
import com.daml.platform.store.backend.EventStorageBackend.RawTransactionEvent
import com.daml.platform.store.backend.common.ComposableQuery.{CompositeSql, SqlStringInterpolation}
import com.daml.platform.store.cache.LedgerEndCache

import scala.collection.compat.immutable.ArraySeq

abstract class EventStorageBackendTemplate(
eventStrategy: EventStrategy,
queryStrategy: QueryStrategy,
ledgerEndCache: LedgerEndCache,
// TODO Refactoring: This method is needed in pruneEvents, but belongs to [[ParameterStorageBackend]].
// Remove with the break-out of pruneEvents.
participantAllDivulgedContractsPrunedUpToInclusive: Connection => Option[Offset],
Expand Down Expand Up @@ -255,7 +258,7 @@ abstract class EventStorageBackendTemplate(

private def events[T](
columnPrefix: String,
joinClause: String,
joinClause: CompositeSql,
additionalAndClause: CompositeSql,
rowParser: RowParser[T],
selectColumns: String,
Expand All @@ -273,7 +276,7 @@ abstract class EventStorageBackendTemplate(
case when ${eventStrategy
.submittersArePartiesClause("submitters", parties)} then command_id else '' end as command_id
FROM
participant_events #$columnPrefix #$joinClause
participant_events #$columnPrefix $joinClause
WHERE
$additionalAndClause
${eventStrategy.witnessesWhereClause(witnessesColumn, filterParams)}
Expand All @@ -291,7 +294,7 @@ abstract class EventStorageBackendTemplate(
import com.daml.platform.store.Conversions.OffsetToStatement
events(
columnPrefix = "active_cs",
joinClause = "",
joinClause = cSQL"",
additionalAndClause = cSQL"""
event_sequential_id > ${rangeParams.startExclusive} AND
event_sequential_id <= ${rangeParams.endInclusive} AND
Expand Down Expand Up @@ -320,7 +323,7 @@ abstract class EventStorageBackendTemplate(
)(connection: Connection): Vector[EventsTable.Entry[Raw.FlatEvent]] = {
events(
columnPrefix = "",
joinClause = "",
joinClause = cSQL"",
additionalAndClause = cSQL"""
event_sequential_id > ${rangeParams.startExclusive} AND
event_sequential_id <= ${rangeParams.endInclusive} AND""",
Expand All @@ -341,9 +344,9 @@ abstract class EventStorageBackendTemplate(
import com.daml.platform.store.Conversions.ledgerStringToStatement
events(
columnPrefix = "",
joinClause = """JOIN parameters ON
| (participant_pruned_up_to_inclusive is null or event_offset > participant_pruned_up_to_inclusive)
| AND event_offset <= ledger_end""".stripMargin,
joinClause = cSQL"""JOIN parameters ON
(participant_pruned_up_to_inclusive is null or event_offset > participant_pruned_up_to_inclusive)
AND event_offset <= ${ledgerEndCache()._1.toHexString.toString}""",
additionalAndClause = cSQL"""
transaction_id = $transactionId AND
event_kind != 0 AND -- we do not want to fetch divulgence events""",
Expand All @@ -363,7 +366,7 @@ abstract class EventStorageBackendTemplate(
)(connection: Connection): Vector[EventsTable.Entry[Raw.TreeEvent]] = {
events(
columnPrefix = "",
joinClause = "",
joinClause = cSQL"",
additionalAndClause = cSQL"""
event_sequential_id > ${rangeParams.startExclusive} AND
event_sequential_id <= ${rangeParams.endInclusive} AND
Expand All @@ -386,9 +389,9 @@ abstract class EventStorageBackendTemplate(
import com.daml.platform.store.Conversions.ledgerStringToStatement
events(
columnPrefix = "",
joinClause = """JOIN parameters ON
| (participant_pruned_up_to_inclusive is null or event_offset > participant_pruned_up_to_inclusive)
| AND event_offset <= ledger_end""".stripMargin,
joinClause = cSQL"""JOIN parameters ON
(participant_pruned_up_to_inclusive is null or event_offset > participant_pruned_up_to_inclusive)
AND event_offset <= ${ledgerEndCache()._1.toHexString.toString}""",
additionalAndClause = cSQL"""
transaction_id = $transactionId AND
event_kind != 0 AND -- we do not want to fetch divulgence events""",
Expand Down
Loading

0 comments on commit 9ef2eaf

Please sign in to comment.