Coder Social home page Coder Social logo

reactivemongo / reactivemongo-bson Goto Github PK

View Code? Open in Web Editor NEW
8.0 8.0 11.0 1020 KB

:leaves: BSON library for ReactiveMongo

Home Page: http://reactivemongo.org/releases/0.1x/documentation/tutorial/bison.html

License: Apache License 2.0

Shell 0.46% Scala 99.51% Java 0.03%
bson mongodb reactivemongo scala

reactivemongo-bson's Introduction

ReactiveMongo

ReactiveMongo is a scala driver that provides fully non-blocking and asynchronous I/O operations.

Usage

First add the dependencies in your build.sbt.

libraryDependencies ++= Seq(
  "org.reactivemongo" %% "reactivemongo" % "VERSION"
)

Maven Javadocs

See the documentation

Build manually

To benefit from the latest improvements and fixes, you may want to compile ReactiveMongo from source. You will need a Git client and SBT.

From the shell, first checkout the source:

$ git clone [email protected]:ReactiveMongo/ReactiveMongo.git

Then go to the ReactiveMongo directory and launch the SBT build console:

$ cd ReactiveMongo
$ sbt
> +publishLocal

Running tests:

In order to execute the unit and integration tests, SBT can be used as follows.

sbt testOnly

The test environement must be able to handle the maximum number of incoming connection for the MongoDB instance. This must be checked, and eventually updated, using ulimit -n.

CircleCI Test coverage

Reproduce CI build:

To reproduce a CI build, see the Docker tools.

Learn More

See also the samples

reactivemongo-bson's People

Contributors

avdv avatar cchantep avatar gatorcse avatar jtjeferreira avatar ornicar avatar scala-steward avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

reactivemongo-bson's Issues

Release `reactivemongo-bson-compat` and other packages to 1.0.0

Hi guys,

I see that you released reactivemongo package to 1.0.0 but the latest version of reactivemongo-bson-compat is still 0.20.13. Unfortunately, this cause some classpath issues.

I would like to ask if you plan to support reactivemongo-bson-compat also with the future versions or it's by design - 0.20.13 the latest version?

Thanks in advance.

Macro generated `BSONWriter` and `BSONReader` fails to compile when writer/reader for `Option` is in scope

ReactiveMongo Version (0.10.5, 0.11.6 / etc)

ReactiveMongo 1.0.10

Scala version

2.13.8, 2.11.7

Operating System (Ubuntu 15.10 / MacOS 10.10 / Windows 10)

Ubuntu 21.04

JDK (Oracle 1.8.0_72, OpenJDK 1.8.x, Azul Zing)

openjdk version "11.0.10" 2021-01-19 LTS

Expected Behavior

  1. I define a custom reader/writer for Option.
  2. The defined reader and writer are resolved and properly used when deriving for a case class using the provided macros.

Actual Behavior

Given a case class like this:

final case class Person(name: String, age: Option[Int])

When a a custom Option reader or writer is in scope when calling Macros.writer or Macros.reader (and their other flavors Macros.readerOpts etc.) the generated code fails to type check.

Analyzing the output of Macros.writerOpts[Person, MacroOptions.Verbose] for the age field:

// Writer
Person.unapply(macroVal) match {
  ...

    tuple$macro$1._2.foreach(((age$macro$9: Int) => (Person.this.optionAsNullWriter[Int](reactivemongo.api.bson.`package`.BSONIntegerHandler).writeTry(age$macro$9): _root_.scala.util.Try[_root_.reactivemongo.api.bson.BSONValue]) match {
      case _root_.scala.util.Success((bson$macro$8 @ _)) => {
        ok$macro$2.$plus$eq(_root_.reactivemongo.api.bson.BSONElement(macroCfg$macro$6.fieldNaming("age"), bson$macro$8));
        ()
      }
      case _root_.scala.util.Failure((cause$macro$4 @ _)) => {
        err$macro$3.$plus$eq(_root_.reactivemongo.api.bson.exceptions.HandlerException("age", cause$macro$4));
        ()
      }
    }));

...
}

We can see that the macro calls foreach on the age field (which is of type Option[Int]) and then tries to apply the resolved BSONWriter[Option[Int]] inside foreach (where it is of type Int) hence the type mismatch; found : Int required: Option[Int] compilation failure.

I think I managed to pinpoint the issue to this call for writer where the macro actually takes notice of a BSONWriter for Option but it is not acted upon (the call is forwarded to the same case as the one without explicit BSONWriter for `Option).

Following up with the output for Macros.readerOpts[Person, MacroOptions.Verbose] for the age field:

// Reader
{
...

  macroDoc.getAsUnflattenedTry(macroCfg$macro$6.fieldNaming("age"))(Person.this.optionAsNullReader[Int](reactivemongo.api.bson.`package`.BSONIntegerHandler)) match {
    case _root_.scala.util.Success((read$macro$7 @ _)) => {
      age$macro$3.take(read$macro$7);
      ()
    }
    case _root_.scala.util.Failure((cause$macro$4 @ _)) => err$macro$1.$plus$eq(_root_.reactivemongo.api.bson.exceptions.HandlerException("age", cause$macro$4))
  };

...
  }
}

Here we can see the macro calls getAsUnflattenedTry which has a result type Try[Option[T]], please note it calls it on a Option[Int] which results in the type Try[Option[Option[Int]] hence the second type error type mismatch; found : Option[Option[Int] required: Option[Int]. I think the line responsible for this is located here.

Reproducible Test Case

package repro

import reactivemongo.api.bson.Macros
import scala.util.Success
import reactivemongo.api.bson._

final case class Person(name: String, age: Option[Int])

object Person {
  implicit def optionAsNullWriter[A](implicit writer: BSONWriter[A]): BSONWriter[Option[A]] =
    BSONWriter.from(_.map(writer.writeTry).getOrElse(Success(BSONNull)))

  implicit def optionAsNullReader[A](implicit reader: BSONReader[A]): BSONReader[Option[A]] =
    BSONReader.from {
      case BSONNull => Success(None)
      case value => reader.readTry(value).map(Some.apply)
    }

  implicit val writer: BSONDocumentWriter[Person] = Macros.writer[Person] // type mismatch; found : Int required: Option[Int]
  implicit val reader: BSONDocumentReader[Person] = Macros.reader[Person] // type mismatch; found : Option[Option[Int] required: Option[Int]
}

Macros.handler compile error for case class with type parameter and Option

ReactiveMongo Version (0.10.5, 0.11.6 / etc)

0.19.3

Operating System

MacOS 10.14.6

JDK (Oracle 1.8.0_72, OpenJDK 1.8.x, Azul Zing)

/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home

Expected Behavior

Macros.handler should generate handler for case class with type parameter S and field with type Option[S] like this: case class Aaa[S](aaa: Int, bbb: String, ccc: Option[S])

Actual Behavior

implicit val aaaHandler = Macros.handler[Aaa[String]] does not compile (the same compile error for both reactivemongo.bson._ and reactivemongo.api.bson._)

Reproducible Test Case

package com.example

import reactivemongo.bson._

//noinspection TypeAnnotation
object BSONTesting extends App {

  case class Ccc(aaa: Int, bbb: String)
  case class Aaa[S](aaa: Int, bbb: String, ccc: Option[S])
  implicit val cccHandler = Macros.handler[Ccc]
  // Does not compile:
  // Error:(18, 43) type mismatch;
  // found   : S
  // required: com.example.BSONTesting.Ccc
  // Note: implicit value aaaHandler is not applicable here because it comes after the application point and it lacks an explicit result type
  //  implicit val aaaHandler = Macros.handler[Aaa[Ccc]]
  implicit val aaaHandler = Macros.handler[Aaa[Ccc]]
  def foobar()(implicit h: BSONDocumentHandler[Aaa[Ccc]]): Unit = println("*** FOO-BAR")
  foobar()

}

//noinspection TypeAnnotation
object BSONTesting1 extends App {
  case class Aaa[S](aaa: Int, bbb: String, ccc: Option[S])
  // Does not compile:
  // Error:(27, 43) type mismatch;
  // found   : S
  // required: String
  // Note: implicit value aaaHandler is not applicable here because it comes after the application point and it lacks an explicit result type
  //  implicit val aaaHandler = Macros.handler[Aaa[String]]
  implicit val aaaHandler = Macros.handler[Aaa[String]]
  def foobar()(implicit h: BSONDocumentHandler[Aaa[String]]): Unit = println("*** FOO-BAR")
  foobar()

}


//noinspection TypeAnnotation
object BSONTesting2 extends App {
  // Compiled and output: *** FOO-BAR-2
  case class Ccc(aaa: Int, bbb: String)
  case class Aaa[S](aaa: Int, bbb: String, ccc: S)
  implicit val cccHandler = Macros.handler[Ccc]
  implicit val aaaHandler = Macros.handler[Aaa[Ccc]]
  def foobar()(implicit h: BSONDocumentHandler[Aaa[Ccc]]): Unit = println("*** FOO-BAR-2")
  foobar()
}

//noinspection TypeAnnotation
object BSONTesting3 extends App {
  // Compiled and output: *** FOO-BAR-3
  case class Ccc(aaa: Int, bbb: String)
  case class Aaa(aaa: Int, bbb: String, ccc: Option[Ccc])
  implicit val cccHandler = Macros.handler[Ccc]
  implicit val aaaHandler = Macros.handler[Aaa]
  def foobar()(implicit h: BSONDocumentHandler[Aaa]): Unit = println("*** FOO-BAR-3")
  foobar()
}


BSONDocument `isEmpty` gives false for empty document

Expected Behavior

Please describe the expected behavior of the issue, starting from the first action.

  1. BSONDocument from an optional element producer, BSONDocument("foo" -> None)
  2. .isEmpty on such document should give true
  3. .elements should give empty sequence

Actual Behavior

  1. .isEmpty gives false
  2. .elements gives empty sequence

For the given document constructor, ElementProducer could be the empty version.

    def apply(elms: ElementProducer*): BSONDocument

Then isEmpty computation based on elms.isEmpty yields wrong result

Support Scala 3 Enumeration

https://dotty.epfl.ch/docs/reference/enums/enums.html

enum Color:
  case Red, Green, Blue

summon[scala.deriving.Mirror.SumOf[Color]]
val res1: 
  (
    deriving.Mirror.Sum{
      MirroredType = Color; MirroredMonoType = Color; MirroredElemTypes <: Tuple
    }
   & 
    scala.deriving.Mirror.Sum{
      MirroredMonoType = Color; MirroredType = Color; MirroredLabel = "Color"
    }
  ){
    MirroredElemTypes = (Color.Red.type, Color.Green.type, Color.Blue.type); 
      MirroredElemLabels = ("Red", "Green", "Blue")
  } = anon$1@246ff730

BSONObjectID.parse is messing up the time

ReactiveMongo Version 0.19.1

MongDB - 4.0.9 Docker

Operating System - Ubuntu 16.04

ksisu@ksisu-Aspire-VN7-592G:~$ uname -a
Linux ksisu-Aspire-VN7-592G 4.15.0-65-generic ReactiveMongo/ReactiveMongo#74~16.04.1-Ubuntu SMP Wed Sep 18 09:51:44 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

JDK - OpenJDK 1.8.0_222

ksisu@ksisu-Aspire-VN7-592G:~$ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1ubuntu1~16.04.1-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)

Description

I think reactivemongo.api.bson.BSONObjectID#parse is messing up the time.

I tested two different way:

1.

val time  = 1000000000000L
val originalId = BSONObjectID.fromTime(time)
originalId.time shouldEqual time
// OK
val parsedId = BSONObjectID.parse(originalId.stringify).get
parsedId.time shouldEqual time
// NOK - 989907456000 did not equal 1000000000000

2.

I have an id: 5dde527a817738a072bef284. I get the time with an online tool: 2019-11-27T10:39:54.000Z

val expectedTime = LocalDateTime.parse("2019-11-27T10:39:54.000Z", DateTimeFormatter.ISO_DATE_TIME).toEpochSecond(ZoneOffset.UTC)
val id = BSONObjectID.parse("5dde527a817738a072bef284").get
id.timeSecond shouldEqual expectedTime
// NOK - 1560302202 did not equal 1574851194

[msb-compat] Handler from org.bson types to `Map[K, V]` uses view

Hi.

I am using the official mongo scala driver with RM's macros and reader/writer support. I wrote a Codec[BSONValue] myself to parse org.bson types to RM's types but since I discovered the msb-compat module, thought that I could use this one instead.

Seemed straight forward; I ran into some problems, however.

First thing is that decoding BsonValue -> BSONValue -> MyCaseClass seems to be successful, but when trying to use a property of the class of type Map[String, M], I see an exception:

$ val codec: Codec[X] = BSONHandler[X]
$ val model = codec.decode(...) // OK, as long as you don't print it
...
$ println(model) // ->
// reactivemongo.api.bson.exceptions.HandlerException: Fails to handle default: BSONString != BSONDocument
// Caused by: reactivemongo.api.bson.exceptions.TypeDoesNotMatchException: BSONString != BSONDocument

That is caused by using the mapValues method from Utils, which calls Map.mapValues which just creates a view, and does not yet convert the values.

mapValues(doc.fields) { v =>
valueReader.readTry(v).get
}

I would expect the decode to fail right away if it can't parse the input.

Macros fails when case class has 23 values

ReactiveMongo Version 1.0.3

MongoDB version 3.6

Actual Behavior

Compilation of

    case class TestCaseClass(
      string1: String,
      string2: String,
      string3: String,
      string4: String,
      string5: String,
      string6: String,
      string7: String,
      string8: String,
      string9: String,
      string10: String,
      string11: String,
      string12: String,
      string13: String,
      string14: String,
      string15: String,
      string16: String,
      string17: String,
      string18: String,
      string19: String,
      string20: String,
      string21: String,
      string22: String,
      string23: String
    )

    implicit val handler = Macros.handler[TestCaseClass]

Fails with message

No matching apply/unapply found: com.test.TestCaseClass
[error]     implicit val hander = Macros.handler[TestCaseClass]

Expected Behavior

Handler should be created.

Is there any workaround for this? (other than changing case class)

Check Macros with sealed family

Case members of trait not at the same level:

sealed trait Foo

object Foo {
  case object Bar extends Foo
  case object Lorem extends Foo
}

import reactivemongo.api.bson._

val h = Macros.handlerOpts[Foo, MacroOptions.Verbose]

h.writeTry(Foo.Bar).foreach { v =>
  println(BSONValue pretty v)
}

Error

Whereas:

sealed trait Foo
case object Bar extends Foo
case object Lorem extends Foo

import reactivemongo.bson.Macros

val h = Macros.handlerOpts[Foo, Macros.Options.AllImplementations]

h.write(Bar)
h.write(Lorem)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.