Skip to content

Commit 2107456

Browse files
committed
Allow custom database indexes via environment variables
Closes #206.
1 parent c12f942 commit 2107456

3 files changed

Lines changed: 67 additions & 27 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
- New slot-range index usage for wildcard (*) match queries (see [#194](https://github.com/CardanoSolutions/kupo/issues/194)).
88

9+
- Custom indexes can now be added via environment variable, prefixed with `KUPO_INDEX_`. They behave as standard indexes with regards to `--defer-db-indexes` and are only installed if not already present. Indexes are named after the environment variable (after the dropping the prefix). So for example, to add an index for unspent inputs by payment credential, you can now provide:
10+
11+
```console
12+
KUPO_INDEX_inputsByPaymentCredentialUnspent="inputs(payment_credential COLLATE NOCASE) WHERE spent_at IS NULL" kupo ...
13+
```
14+
915
#### Changed
1016

1117
- Bumped internal dependencies to cardano-node==11.0.1.

docs/api/nightly.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,25 @@ info:
273273
$ man kupo
274274
```
275275
276+
# Custom database indexes
277+
278+
Kupo supports custom database indexes, provided by environment variable.
279+
Hence, any environment variable prefixed with `KUPO_INDEX_` will be parsed
280+
and interpreted as a custom database index, managed with the pre-defined
281+
indexes.
282+
283+
For example, you can add a custom index `inputsByPaymentCredentialUnspent`
284+
for matching unspent inputs by payment cred by setting the following
285+
environment variable:
286+
287+
```env
288+
KUPO_INDEX_inputsByPaymentCredentialUnspent="inputs(payment_credential COLLATE NOCASE) WHERE spent_at IS NULL"
289+
```
290+
291+
Use this carefully, as too many indexes may greatly impact the database sync performances and also other queries.
292+
293+
Existing indexes and the overall database internal schema is [available here](https://github.com/CardanoSolutions/kupo/tree/master/db#overview).
294+
276295
# Patterns
277296
278297
## Overview

src/Kupo/App/Database/SQLite.hs

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ import Kupo.Control.MonadLog
181181
( TraceProgress (..)
182182
, nullTracer
183183
)
184+
import System.Environment
185+
( getEnvironment
186+
)
184187
import Text.URI
185188
( URI
186189
)
@@ -1161,33 +1164,45 @@ installIndexes
11611164
-> Connection
11621165
-> DeferIndexesInstallation
11631166
-> IO ()
1164-
installIndexes tr conn = \case
1165-
SkipNonEssentialIndexes -> do
1166-
dropIndexIfExists (contramap DatabaseConnection tr) conn "inputsByAddress" False
1167-
dropIndexIfExists (contramap DatabaseConnection tr) conn "inputsByDatumHash" False
1168-
dropIndexIfExists (contramap DatabaseConnection tr) conn "inputsByPaymentCredential" False
1169-
dropIndexIfExists (contramap DatabaseConnection tr) conn "inputsByCreatedAt" False
1170-
dropIndexIfExists (contramap DatabaseConnection tr) conn "inputsBySpentAt" False
1171-
dropIndexIfExists (contramap DatabaseConnection tr) conn "policiesByPolicyId" False
1172-
InstallIndexesIfNotExist -> do
1173-
installIndex tr conn
1174-
"inputsByAddress"
1175-
"inputs(address COLLATE NOCASE)"
1176-
installIndex tr conn
1177-
"inputsByDatumHash"
1178-
"inputs(datum_hash)"
1179-
installIndex tr conn
1180-
"inputsByPaymentCredential"
1181-
"inputs(payment_credential COLLATE NOCASE)"
1182-
installIndex tr conn
1183-
"inputsByCreatedAt"
1184-
"inputs(created_at)"
1185-
installIndex tr conn
1186-
"inputsBySpentAt"
1187-
"inputs(spent_at)"
1188-
installIndex tr conn
1189-
"policiesByPolicyId"
1190-
"policies(policy_id)"
1167+
installIndexes tr conn indexBehavior = do
1168+
customIndexes <- parseCustomIndexes <$> getEnvironment
1169+
1170+
case indexBehavior of
1171+
SkipNonEssentialIndexes -> do
1172+
dropIndex "inputsByAddress"
1173+
dropIndex "inputsByDatumHash"
1174+
dropIndex "inputsByPaymentCredential"
1175+
dropIndex "inputsByCreatedAt"
1176+
dropIndex "inputsBySpentAt"
1177+
dropIndex "policiesByPolicyId"
1178+
forM_ customIndexes (\(name, _definition) -> dropIndex name)
1179+
where
1180+
dropIndex name = dropIndexIfExists (contramap DatabaseConnection tr) conn name False
1181+
InstallIndexesIfNotExist -> do
1182+
installIndex tr conn
1183+
"inputsByAddress"
1184+
"inputs(address COLLATE NOCASE)"
1185+
installIndex tr conn
1186+
"inputsByDatumHash"
1187+
"inputs(datum_hash)"
1188+
installIndex tr conn
1189+
"inputsByPaymentCredential"
1190+
"inputs(payment_credential COLLATE NOCASE)"
1191+
installIndex tr conn
1192+
"inputsByCreatedAt"
1193+
"inputs(created_at)"
1194+
installIndex tr conn
1195+
"inputsBySpentAt"
1196+
"inputs(spent_at)"
1197+
installIndex tr conn
1198+
"policiesByPolicyId"
1199+
"policies(policy_id)"
1200+
forM_ customIndexes (uncurry (installIndex tr conn))
1201+
where
1202+
parseCustomIndexes = mapMaybe $ \(key, value) ->
1203+
case T.stripPrefix "KUPO_INDEX_" (toText key) of
1204+
Nothing -> Nothing
1205+
Just name -> Just (name, toText value)
11911206

11921207
-- Create the given index with some extra logging around it.
11931208
installIndex :: Tracer IO TraceDatabase -> Connection -> Text -> Text -> IO ()

0 commit comments

Comments
 (0)