All Downloads are FREE. Search and download functionalities are using the official Maven repository.

quasar.physical.mongodb.planner.elideQuasarSigil.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014–2017 SlamData Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package quasar.physical.mongodb.planner

import slamdata.Predef.{Map => _, _}
import quasar.contrib.pathy.AFile
import quasar.fs.{FileSystemError, MonadFsErr}
import quasar.physical.mongodb.{sigil, Collection}
import quasar.qscript._

import matryoshka._
import matryoshka.implicits._
import org.bson.{BsonDocument, BsonValue}
import scalaz._, Scalaz._

/** A QScript transformation that, given a function to retrieve a document
  * from a collection, inserts projections around any `ShiftedRead`s of
  * collections having documents wrapped in the Quasar sigil, eliding them
  * from the query.
  */
object elideQuasarSigil {
  import FileSystemError.pathErr
  import MapFuncsCore._

  def apply[T[_[_]]: CorecursiveT, F[_]: Functor, M[_]: Monad: MonadFsErr]
      (anyDoc: Collection => OptionT[M, BsonDocument])
      (implicit
        SR: Const[ShiftedRead[AFile], ?] :<: F,
        QC: QScriptCore[T, ?] :<: F)
      : F[T[F]] => M[F[T[F]]] = {

    case sr @ SR(Const(ShiftedRead(f, IdOnly))) =>
      sr.point[M]

    case sr @ SR(Const(ShiftedRead(f, idStatus))) =>
      (collection[M](f).liftM[OptionT] >>= anyDoc).run
        .map(_.flatMap(getValue[T]).fold(sr) { fm =>
          QC(Map(sr.embed, elideSigil[T](idStatus, fm)))
        })

    case other => other.point[M]
  }

  ////

  private def collection[M[_]: Monad: MonadFsErr](f: AFile): M[Collection] =
    Collection.fromFile(f).fold(
      e => MonadFsErr[M].raiseError(pathErr(e)),
      _.point[M])

  private def elideSigil[T[_[_]]: CorecursiveT](idStatus: IdStatus, prj: FreeMap[T]): FreeMap[T] =
    idStatus match {
      case IdOnly    => HoleF
      case ExcludeId => prj
      case IncludeId =>
        MapFuncCore.StaticArray(List(
          Free.roll(MFC(ProjectIndex(HoleF, IntLit(0)))),
          prj >> Free.roll(MFC(ProjectIndex(HoleF, IntLit(1))))))
    }

  private def getValue[T[_[_]]: CorecursiveT](doc: BsonDocument): Option[FreeMap[T]] =
    if (sigil.Sigil[BsonValue].mapReduceQuasarSigilExists(doc))
      Some(sigil.projectMapReduceQuasarValue[T])
    else if (sigil.Sigil[BsonValue].quasarSigilExists(doc))
      Some(sigil.projectQuasarValue[T])
    else
      None
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy