packages feed

moonlight-core-0.1.0.0: src-term/Moonlight/Core/Term/Database/Index.hs

{-# LANGUAGE BangPatterns #-}

module Moonlight.Core.Term.Database.Index where

import Data.IntMap.Strict (IntMap)
import Data.IntMap.Strict qualified as IntMap
import Data.IntSet (IntSet)
import Data.IntSet qualified as IntSet
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Primitive.PrimArray (PrimArray)
import Data.Primitive.PrimArray qualified as PrimArray
import Data.Primitive.SmallArray qualified as SmallArray
import Data.Traversable (mapAccumL)
import Moonlight.Core.Term.Database.Types
import Prelude

derivedResultIndex :: OperatorTable f -> ResultIndex
derivedResultIndex =
  resultIx
{-# INLINE derivedResultIndex #-}

derivedChildColumnValueIndex :: OperatorTable f -> ChildColumnValueIndex
derivedChildColumnValueIndex =
  childColumnIx
{-# INLINE derivedChildColumnValueIndex #-}

derivedExactIndex :: OperatorTable f -> ExactIndex
derivedExactIndex =
  exactIx
{-# INLINE derivedExactIndex #-}

derivedChildUserIndex :: OperatorTable f -> ChildUserIndex
derivedChildUserIndex =
  childUserIx
{-# INLINE derivedChildUserIndex #-}

emptyExactIndex :: Int -> ExactIndex
emptyExactIndex =
  emptyChildTupleIndex

emptyExactResultIndex :: Int -> ExactResultIndex
emptyExactResultIndex =
  emptyChildTupleIndex

emptyChildTupleIndex :: Int -> ChildTupleIndex
emptyChildTupleIndex arity =
  case arity of
    0 -> NullaryChildTupleIndex IntSet.empty
    1 -> UnaryChildTupleIndex IntMap.empty
    2 -> BinaryChildTupleIndex IntMap.empty
    _ -> NaryChildTupleIndex Map.empty

emptyResultIndex :: ResultIndex
emptyResultIndex =
  IntMap.empty

emptyChildColumnValueIndex :: Int -> ChildColumnValueIndex
emptyChildColumnValueIndex arity =
  case arity of
    0 -> NullaryChildColumnValueIndex
    1 -> UnaryChildColumnValueIndex IntMap.empty
    2 -> BinaryChildColumnValueIndex IntMap.empty IntMap.empty
    _ -> NaryChildColumnValueIndex (SmallArray.smallArrayFromList (replicate arity IntMap.empty))
{-# INLINE emptyChildColumnValueIndex #-}

emptyChildUserIndex :: ChildUserIndex
emptyChildUserIndex =
  IntMap.empty

lookupExactIndex :: [Int] -> ExactIndex -> RowIdSet
lookupExactIndex children =
  RowIdSet . lookupChildTupleProbe children
{-# INLINE lookupExactIndex #-}

lookupExactIndexArray :: PrimArray Int -> ExactIndex -> RowIdSet
lookupExactIndexArray children =
  RowIdSet . lookupChildTupleIndex children
{-# INLINE lookupExactIndexArray #-}

lookupExactResultIndex :: PrimArray Int -> ExactResultIndex -> IntSet
lookupExactResultIndex =
  lookupChildTupleIndex
{-# INLINE lookupExactResultIndex #-}

lookupChildTupleProbe :: [Int] -> ChildTupleIndex -> IntSet
lookupChildTupleProbe children childTupleIndex =
  case childTupleIndex of
    NullaryChildTupleIndex keys ->
      case children of
        [] -> keys
        _nonNullaryChildren -> IntSet.empty
    UnaryChildTupleIndex byChild ->
      case children of
        [child] -> IntMap.findWithDefault IntSet.empty child byChild
        _nonUnaryChildren -> IntSet.empty
    BinaryChildTupleIndex byLeftChild ->
      case children of
        [leftChild, rightChild] ->
          maybe IntSet.empty (IntMap.findWithDefault IntSet.empty rightChild) (IntMap.lookup leftChild byLeftChild)
        _nonBinaryChildren -> IntSet.empty
    NaryChildTupleIndex byChildren ->
      Map.findWithDefault IntSet.empty (ProbeChildTupleKey children) byChildren
{-# INLINE lookupChildTupleProbe #-}

lookupChildTupleIndex :: PrimArray Int -> ChildTupleIndex -> IntSet
lookupChildTupleIndex children childTupleIndex =
  case childTupleIndex of
    NullaryChildTupleIndex keys ->
      if PrimArray.sizeofPrimArray children == 0
        then keys
        else IntSet.empty
    UnaryChildTupleIndex byChild ->
      if PrimArray.sizeofPrimArray children == 1
        then IntMap.findWithDefault IntSet.empty (PrimArray.indexPrimArray children 0) byChild
        else IntSet.empty
    BinaryChildTupleIndex byLeftChild ->
      if PrimArray.sizeofPrimArray children == 2
        then
          maybe
            IntSet.empty
            (IntMap.findWithDefault IntSet.empty (PrimArray.indexPrimArray children 1))
            (IntMap.lookup (PrimArray.indexPrimArray children 0) byLeftChild)
        else IntSet.empty
    NaryChildTupleIndex byChildren ->
      Map.findWithDefault IntSet.empty (StoredChildTupleKey children) byChildren
{-# INLINE lookupChildTupleIndex #-}

lookupResultIndex :: Int -> ResultIndex -> RowIdSet
lookupResultIndex resultKey =
  RowIdSet . IntMap.findWithDefault IntSet.empty resultKey
{-# INLINE lookupResultIndex #-}

intMapDependentsOfMany :: [Int] -> IntMap IntSet -> IntSet
intMapDependentsOfMany keys indexValue =
  foldMap (\key -> IntMap.findWithDefault IntSet.empty key indexValue) keys
{-# INLINE intMapDependentsOfMany #-}

insertExactIndex :: Int -> PrimArray Int -> ExactIndex -> ExactIndex
insertExactIndex =
  insertChildTupleIndex
{-# INLINE insertExactIndex #-}

insertExactResultIndex :: Int -> PrimArray Int -> ExactResultIndex -> ExactResultIndex
insertExactResultIndex =
  insertChildTupleIndex
{-# INLINE insertExactResultIndex #-}

insertChildTupleIndex :: Int -> PrimArray Int -> ChildTupleIndex -> ChildTupleIndex
insertChildTupleIndex dependent children childTupleIndex =
  case childTupleIndex of
    NullaryChildTupleIndex keys ->
      if PrimArray.sizeofPrimArray children == 0
        then NullaryChildTupleIndex (IntSet.insert dependent keys)
        else childTupleIndex
    UnaryChildTupleIndex byChild ->
      if PrimArray.sizeofPrimArray children == 1
        then UnaryChildTupleIndex (insertIntSetAtKey (PrimArray.indexPrimArray children 0) dependent byChild)
        else childTupleIndex
    BinaryChildTupleIndex byLeftChild ->
      if PrimArray.sizeofPrimArray children == 2
        then
          BinaryChildTupleIndex $
            IntMap.insertWith
              (IntMap.unionWith IntSet.union)
              (PrimArray.indexPrimArray children 0)
              (IntMap.singleton (PrimArray.indexPrimArray children 1) (IntSet.singleton dependent))
              byLeftChild
        else childTupleIndex
    NaryChildTupleIndex byChildren ->
      NaryChildTupleIndex $
        Map.insertWith
          IntSet.union
          (StoredChildTupleKey children)
          (IntSet.singleton dependent)
          byChildren
{-# INLINE insertChildTupleIndex #-}

insertResultIndex :: Int -> Int -> ResultIndex -> ResultIndex
insertResultIndex rowKey resultKey =
  insertIntSetAtKey resultKey rowKey
{-# INLINE insertResultIndex #-}

insertChildUserIndex :: Int -> Int -> ChildUserIndex -> ChildUserIndex
insertChildUserIndex rowKey childKey =
  insertIntSetAtKey childKey rowKey
{-# INLINE insertChildUserIndex #-}

deleteExactIndex :: Int -> PrimArray Int -> ExactIndex -> ExactIndex
deleteExactIndex =
  deleteChildTupleIndex
{-# INLINE deleteExactIndex #-}

deleteExactResultIndex :: Int -> PrimArray Int -> ExactResultIndex -> ExactResultIndex
deleteExactResultIndex =
  deleteChildTupleIndex
{-# INLINE deleteExactResultIndex #-}

deleteResultIndex :: Int -> Int -> ResultIndex -> ResultIndex
deleteResultIndex rowKey resultKey =
  removeIntSetAtIntKey resultKey rowKey
{-# INLINE deleteResultIndex #-}

deleteChildUserIndex :: Int -> Int -> ChildUserIndex -> ChildUserIndex
deleteChildUserIndex rowKey childKey =
  removeIntSetAtIntKey childKey rowKey
{-# INLINE deleteChildUserIndex #-}

deleteChildTupleIndex :: Int -> PrimArray Int -> ChildTupleIndex -> ChildTupleIndex
deleteChildTupleIndex dependent children childTupleIndex =
  case childTupleIndex of
    NullaryChildTupleIndex keys ->
      if PrimArray.sizeofPrimArray children == 0
        then NullaryChildTupleIndex (IntSet.delete dependent keys)
        else childTupleIndex
    UnaryChildTupleIndex byChild ->
      if PrimArray.sizeofPrimArray children == 1
        then UnaryChildTupleIndex (removeIntSetAtIntKey (PrimArray.indexPrimArray children 0) dependent byChild)
        else childTupleIndex
    BinaryChildTupleIndex byLeftChild ->
      if PrimArray.sizeofPrimArray children == 2
        then
          BinaryChildTupleIndex $
            IntMap.update
              (nonEmptyIntMap . removeIntSetAtIntKey (PrimArray.indexPrimArray children 1) dependent)
              (PrimArray.indexPrimArray children 0)
              byLeftChild
        else childTupleIndex
    NaryChildTupleIndex byChildren ->
      NaryChildTupleIndex (removeIntSetAtMapKey (StoredChildTupleKey children) dependent byChildren)
{-# INLINE deleteChildTupleIndex #-}

insertIntSetAtKey :: Int -> Int -> IntMap IntSet -> IntMap IntSet
insertIntSetAtKey key dependent =
  IntMap.insertWith IntSet.union key (IntSet.singleton dependent)
{-# INLINE insertIntSetAtKey #-}

removeIntSetAtIntKey :: Int -> Int -> IntMap IntSet -> IntMap IntSet
removeIntSetAtIntKey key dependent =
  IntMap.update (nonEmptyIntSet . IntSet.delete dependent) key
{-# INLINE removeIntSetAtIntKey #-}

removeIntSetAtMapKey :: Ord key => key -> Int -> Map key IntSet -> Map key IntSet
removeIntSetAtMapKey key dependent =
  Map.update (nonEmptyIntSet . IntSet.delete dependent) key
{-# INLINE removeIntSetAtMapKey #-}

nonEmptyIntSet :: IntSet -> Maybe IntSet
nonEmptyIntSet values
  | IntSet.null values = Nothing
  | otherwise = Just values
{-# INLINE nonEmptyIntSet #-}

nonEmptyIntMap :: IntMap value -> Maybe (IntMap value)
nonEmptyIntMap values
  | IntMap.null values = Nothing
  | otherwise = Just values
{-# INLINE nonEmptyIntMap #-}

insertChildColumnValueIndex :: Int -> PrimArray Int -> ChildColumnValueIndex -> ChildColumnValueIndex
insertChildColumnValueIndex =
  alterChildColumnValueIndex insertIntSetAtKey
{-# INLINE insertChildColumnValueIndex #-}

deleteChildColumnValueIndex :: Int -> PrimArray Int -> ChildColumnValueIndex -> ChildColumnValueIndex
deleteChildColumnValueIndex =
  alterChildColumnValueIndex removeIntSetAtIntKey
{-# INLINE deleteChildColumnValueIndex #-}

alterChildColumnValueIndex ::
  (Int -> Int -> IntMap IntSet -> IntMap IntSet) ->
  Int ->
  PrimArray Int ->
  ChildColumnValueIndex ->
  ChildColumnValueIndex
alterChildColumnValueIndex alterValueRows rowKey children childColumnIndexes =
  case childColumnIndexes of
    NullaryChildColumnValueIndex ->
      childColumnIndexes
    UnaryChildColumnValueIndex values ->
      if PrimArray.sizeofPrimArray children == 1
        then UnaryChildColumnValueIndex (alterValueRows (PrimArray.indexPrimArray children 0) rowKey values)
        else childColumnIndexes
    BinaryChildColumnValueIndex leftValues rightValues ->
      if PrimArray.sizeofPrimArray children == 2
        then
          BinaryChildColumnValueIndex
            (alterValueRows (PrimArray.indexPrimArray children 0) rowKey leftValues)
            (alterValueRows (PrimArray.indexPrimArray children 1) rowKey rightValues)
        else childColumnIndexes
    NaryChildColumnValueIndex values ->
      if PrimArray.sizeofPrimArray children == SmallArray.sizeofSmallArray values
        then NaryChildColumnValueIndex (snd (mapAccumL alterColumnAt 0 values))
        else childColumnIndexes
  where
    alterColumnAt !childIndex childValueRows =
      ( childIndex + 1,
        alterValueRows
          (PrimArray.indexPrimArray children childIndex)
          rowKey
          childValueRows
      )
{-# INLINE alterChildColumnValueIndex #-}