How should I use MayErr[IntegrityConstraintViolation,Int] in Scala and Anorm? - scala

I use Anorm to do database queries. When I do an executeUpdate(), how should I do proper error handling? it has return type MayErr[IntegrityConstraintViolation,Int], is this a Set or a Map?
There is an example, but I don't understand how I should handle the return value:
val result = SQL("delete from City where id = 99").executeUpdate().fold(
e => "Oops, there was an error" ,
c => c + " rows were updated!"
)
How do I check if the query failed? (using result), and how do I get the numer of affected rows if the query was successful?
At the moment I use this code:
SQL(
"""
INSERT INTO users (firstname, lastname) VALUES ({firstname}, {lastname})
"""
).on("firstname" -> user.firstName, "lastname" -> user.lastName)
.executeUpdate().fold(
e => "Oops, therw was an error",
c => c + " rows were updated!"
)
But I don't know how my error-handling code should look like. Is there any example on how to use the return value of type MayErr[IntegrityConstraintViolation,Int]?

It looks like MayErr is wrapping Either. So it's neither a Map nor a Set, but rather an object that can contain one of two differently typed objects.
Take a look at this question, and you'll see some ways of processing an Either object, which in this case contains either an IntegrityConstraintViolation or an Int. Referring to http://scala.playframework.org/.../Scala$MayErr.html, it looks like you can grab an Either object by referring to the value member e. There seems to be an implicit conversion available too, so you can just treat a MayErr[IntegrityConstraintViolation,Int] as an Either[IntegrityConstraintViolation,Int] without further ceremony.

You could obviously do a
val updateResult = ....executeUpdate()
val success = updateResult.fold(e => false, c => true)
It looks like you can also call
val success = updateResult.isRight
More generally, you can access the wrapped Either with
updateResult.e match {
case Left(error) => ... do something with error ...
case Right(updateCount) => ...do something with updateCount...
}
Maybe someone more familiar with Play would explain why scala.Either is wrapped in MayErr?

Related

How do I convert a List[Option[(A, List[B])]] to the Option[(A,List[B])]? (Basically retrieve Option[X] from List[Option[X]])

I have a List of “rules” tuples as follows:
val rules = List[(A, List[B])], where A and B are two separate case-classes
For the purposes of my use-case, I need to convert this to an Option[(A, List[B])]. The A case class contains a property id which is of type Option[String], based on which the tuple is returned.
I have written a function def findRule(entryId: Option[String]), from which I intend to return the tuple (A, List[B]) whose A.id = entryId as an Option. So far, I have written the following snippet of code:
def findRule(entryId: Option[String]) = {
for {
ruleId <- rules.flatMap(_._1.id) // ruleId is a String
id <- entryId // entryId is an Option[String]
} yield {
rules.find(_ => ruleId.equalsIgnoreCase(id)) // returns List[Option[(A, List[B])]
}
}
This snippet returns a List[Option[(A, List[B])] but I can’t figure out how to retrieve just the Option from it. Using .head() isn’t an option, since the rules list may be empty. Please help as I am new to Scala.
Example (the real examples are too large to post here, so please consider this representative example):
val rules = [(A = {id=1, ….}, B = [{B1}, {B2}, {B3}, …]), (A={id=2, ….}, B = [{B10}, {B11}, {B12}, …]), …. ] (B is not really important here, I need to find the tuple based on the id element of case-class A)
Now, suppose entryId = Some(1)
After the findRule() function, this would currently look like:
[Some((A = {id=1, …}, B = [{B1}, {B2}, {B3}, …]))]
I want to return:

Some((A = {id=1, …}, B = [{B1}, {B2}, {B3}, …])) , ie, the Option within the List returned (currently) from findRule()
From your question, it sounds like you're trying to pick a single item from your list based on some conditional, which means you'll probably want to start with rules.find. The problem then becomes how to express the predicate function that you pass to find.
From my read of your question, the conditional is
The id on the A part of the tuple needs to match the entryId that was passed in elsewhere
def findRule(entryId: Option[String]) =
rules.find { case (a, listOfB) => entryId.contains(a.id) }
The case expression is just nice syntax for dealing with the tuple. I could have also done
rules.find { tup => entryId.contains(tup._1.id) }
The contains method on Option roughly does "if I'm a Some, see if my value equals the argument; if I'm a None, just return false and ignore the argument". It works as a comparison between the Option[String] you have for entryId and the plain String you have for A's id.
Your first attempt didn't work because rules.flatMap got you a List, and using that after the <- in the for-comprehension means another flatMap, which keeps things as a List.
A variant that I personally prefer is
def findRule(entryId: Option[String]): Option[(A, List[B])] = {
entryId.flatMap { id =>
rules.find { case (a, _) => a.id == id }
}
}
In the case where entryId is None, it just immediately returns None. If you start with rules.find, then it will iterate through all of the rules and check each one even when entryId is None. It's unlikely to make any observable performance difference if the list of rules is small, but I also find it more intuitive to understand.

Scala / Neo4J - Removing/ deleting a relationship path between nodes and returning true or false as result

I'm attempting to remove a relationship between two specific nodes by their ID. I've tried the following:
def deleteRelationship(nodeAID: String, nodeBID: String)(implicit neoFormat: NeoFormat[Node]) : Future[Boolean] = {
val txn = storeAPI.NeoTransaction()
val deleteQuery =
s"""
| MATCH relationship = (a: $NODE_A {id: "$NodeAID"})-[r]-(b: $NODE_B {id: "$NodeBID"})
| DELETE r
""".stripMargin
txn.querySingle(deleteQuery).flatMap {
result =>
txn.commit().map (_ => true)
}.recoverWith {
case e: Exception =>
logger.error(s"Error during deleteRelationship", e)
txn.rollback().map{_ => false}
}
}
I am trying to delete the relationship between the two specific nodes. When I try to run it, the method returns false. I suspect that it has something to do with the query rather than the scala method, but I have included it anyway.
Any suggestions would be very helpful.
txn.querySingle(deleteQuery) does expect a result. In the original method, a result wasn't being returned as designed. However, because of this, it was skipping the block with the txn.commit().map(_ => true) and therefore never returning true.
Adding RETURN r to the end of my query provides txn.querySingle(deleteQuery) with a result and therefore reaches the txn.commit().map(_ => true).
I'm sure there is a better way to not rely on a result for a DELETE query, but this solves my issue for now.
Please feel free to add any better suggestions. I'll select the best answer if suggestions are provided.

Error while finding lines starting with H or I using Scala

I am trying to learn Spark and Scala. I am working on a scenario to identify the lines that start with H or I. Below is my code
def startWithHorI(s:String):String=
{
if(s.startsWith("I")
return s
if(s.startsWith("H")
return s
}
val fileRDD=sc.textFile("wordcountsample.txt")
val checkRDD=fileRDD.map(startWithHorI)
checkRDD.collect
It is throwing an error while creating the function Found:Unit Required:Boolean.
From research I understood that it is not able to recognize the return as Unit means void. Could someone help me.
There are a few things wrong with your def, we will start there:
It is throwing the error because according to the code posted, your syntax is incomplete and the def is defined improperly:
def startWithHorI(s:String): String=
{
if(s.startsWith("I")) // missing extra paren char in original post
s // do not need return statement
if(s.startsWith("H")) // missing extra paren char in original post
s // do not need return statement
}
This will still return an error because we are expecting a String when the compiler sees that it's returning an Any. We cannot do this if we do not have an else case (what will be returned when s does not start with H or I?) - the compiler will see this as an Any return type. The correction for this would be to have an else condition that ultimately returns a String.
def startWithHorI(s: String): String = {
if(s.startsWith("I")) s else "no I"
if(s.startsWith("H")) s else "no H"
}
If you don't want to return anything, then an Option is worth looking at for a return type.
Finally we can achieve what you are doing via filter - no need to map with a def:
val fileRDD = sc.textFile("wordcountsample.txt")
val checkRDD = fileRDD.filter(s => s.startsWith("H") || s.startsWith("I"))
checkRDD.collect
While passing any function to rdd.map(fn) make sure that fn covers all possible scenarios.
If you want to completely avoid strings which does not start with either H or I then use flatMap and return Option[String] from your function.
Example:
def startWithHorI(s:String): Option[String]=
{
if(s.startsWith("I") || s.startsWith("H")) Some(s)
else None
}
Then,
sc.textFile("wordcountsample.txt").flatMap(startWithHorI)
This will remove all rows not starting with H or I.
In general, to minimize run-time errors try to create total functions which handles all possible values of the arguments.
Something like below would work for you?
val fileRDD=sc.textFile("wordcountsample.txt")
fileRDD.collect
Array[String] = Array("Hello ", Hello World, Instragram, Good Morning)
val filterRDD=fileRDD.filter( x=> (x(0) == 'H'||x(0) == 'I'))
filterRDD.collect()
Array[String] = Array("Hello ", Hello World, Instragram)

Dynamic OR filtering - Slick

Ok, I've got a method with multiple optional arguments like this
def(username: Option[String], petname: Option[String], favouritefood: Option[String])
and i want to write a dynamic query that will be capable of fetching the data of defined arguments in a way of this
select * from table where un like username or pn like pn or ff like ff;
so depending of which arguments are defined to add them to query with OR operator?
Something like this should work. I had to use a similiar fragment in my own code and it is also close to what cvogt proposes in above comment (I think).
val username = Option("")
val petname = Option("")
val ff:Option[String] = None
val default = LiteralColumn(1) === LiteralColumn(1)
yourTable.filter { it =>
List(
username.map(it.username === _),
petname.map(it.petname === _),
ff.map(it.ff === _)
).collect({case Some(it) => it}).reduceLeftOption(_ || _).getOrElse(default)
}
The thoefer is nice for simple use cases but has some limits. Like if all your options are None's the list is empty and you can't reduce an empty list :)
If you need something more composable, based on predicate, conjunctions and disjunctions (a bit like Hibernate/JPA Criteria API), you can check my answer in Slick: create query conjunctions/disjunctions dynamically

scala: how to handle validations in a functional way

I'm developing a method that is supposed to persist an object, if it passes a list of conditions.
If any (or many) condition fail (or any other kind of error appears), a list with the errors should be returned, if everything goes well, a saved entity should be returned.
I was thinking about something like this (it's pseudocode, of course):
request.body.asJson.map { json =>
json.asOpt[Wine].map { wine =>
wine.save.map { wine =>
Ok(toJson(wine.update).toString)
}.getOrElse { errors => BadRequest(toJson(errors))}
}.getOrElse { BadRequest(toJson(Error("Invalid Wine entity")))}
}.getOrElse { BadRequest(toJson(Error("Expecting JSON data")))}
That is, I'd like to treat it like an Option[T], that if any validation fails, instead of returning None it gives me the list of errors...
The idea is to return an array of JSON errors...
So the question would be, is this the right way to handle these kind of situation? And what would be the way to accomplish it in Scala?
--
Oops, just posted the question and discovered Either
http://www.scala-lang.org/api/current/scala/Either.html
Anyway, I'd like to know what you think about the chosen approach, and if there's any other better alternative to handle it.
Using scalaz you have Validation[E, A], which is like Either[E, A] but has the property that if E is a semigroup (meaning things that can be concatenated, like lists) than multiple validated results can be combined in a way that keeps all the errors that occured.
Using Scala 2.10-M6 and Scalaz 7.0.0-M2 for example, where Scalaz has a custom Either[L, R] named \/[L, R] which is right-biased by default:
import scalaz._, Scalaz._
implicit class EitherPimp[E, A](val e: E \/ A) extends AnyVal {
def vnel: ValidationNEL[E, A] = e.validation.toValidationNEL
}
def parseInt(userInput: String): Throwable \/ Int = ???
def fetchTemperature: Throwable \/ Int = ???
def fetchTweets(count: Int): Throwable \/ List[String] = ???
val res = (fetchTemperature.vnel |#| fetchTweets(5).vnel) { case (temp, tweets) =>
s"In $temp degrees people tweet ${tweets.size}"
}
Here result is a Validation[NonEmptyList[Throwable], String], either containing all the errors occured (temp sensor error and/or twitter error or none) or the successful message. You can then switch back to \/ for convenience.
Note: The difference between Either and Validation is mainly that with Validation you can accumulate errors, but cannot flatMap to lose the accumulated errors, while with Either you can't (easily) accumulate but can flatMap (or in a for-comprehension) and possibly lose all but the first error message.
About error hierarchies
I think this might be of interest for you. Regardless of using scalaz/Either/\//Validation, I experienced that getting started was easy but going forward needs some additional work. The problem is, how do you collect errors from multiple erring functions in a meaningful way? Sure, you can just use Throwable or List[String] everywhere and have an easy time, but doesn't sound too much usable or interpretable. Imagine getting a list of errors like "child age missing" :: "IO error reading file" :: "division by zero".
So my choice is to create error hierarchies (using ADT-s), just like as one would wrap checked exceptions of Java into hierarchies. For example:
object errors {
object gamestart {
sealed trait Error
case class ResourceError(e: errors.resource.Error) extends Error
case class WordSourceError(e: errors.wordsource.Error) extends Error
}
object resource {
case class Error(e: GdxRuntimeException)
}
object wordsource {
case class Error(e: /*Ugly*/ Any)
}
}
Then when using result of erring functions with different error types, I join them under a relevant parent error type.
for {
wordSource <-
errors.gamestart.WordSourceError <-:
errors.wordsource.Error <-:
wordSourceCreator.doCreateWordSource(mtRandom).catchLeft.unsafePerformIO.toEither
resources <-
errors.gamestart.ResourceError <-:
GameViewResources(layout)
} yield ...
Here f <-: e maps the function f on the left of e: \/ since \/ is a Bifunctor. For se: scala.Either you might have se.left.map(f).
This may be further improved by providing shapeless HListIsos to be able to draw nice error trees.
Revisions
Updated: (e: \/).vnel lifts the failure side into a NonEmptyList so if we have a failure we have at least one error (was: or none).
If you have Option values, and you want to turn them into success/failure values, you can turn an Option into an Either using the toLeft or toRight method.
Usually a Right represents success, so use o.toRight("error message") to turn Some(value) into Right(value) and None into Left("error message").
Unfortunately Scala doesn't recognise this right-bias by default, so you have to jump through a hoop (by calling the .right method) in order to neatly compose your Eithers in a for-comprehension.
def requestBodyAsJson: Option[String] = Some("""{"foo":"bar"}""")
def jsonToWine(json: String): Option[Wine] = sys.error("TODO")
val wineOrError: Either[String, Wine] = for {
body <- requestBodyAsJson.toRight("Expecting JSON Data").right
wine <- jsonToWine(body).toRight("Invalid Wine entity").right
} yield wine
If you need an empty value, instead of using Either[A,Option[B]] you can use lift Box, which can have three values:
Full (there is a valid result)
Empty (no result, but no error either)
Failure (an error happened)
Box are more flexible than Either thanks to a rich API. Of course, although they were created for Lift, you can use them in any other framework.
well, this is my attemp using Either
def save() = CORSAction { request =>
request.body.asJson.map { json =>
json.asOpt[Wine].map { wine =>
wine.save.fold(
errors => JsonBadRequest(errors),
wine => Ok(toJson(wine).toString)
)
}.getOrElse (JsonBadRequest("Invalid Wine entity"))
}.getOrElse (JsonBadRequest("Expecting JSON data"))
}
And wine.save is like the following:
def save(wine: Wine): Either[List[Error],Wine] = {
val errors = validate(wine)
if (errors.length > 0) {
Left(errors)
} else {
DB.withConnection { implicit connection =>
val newId = SQL("""
insert into wine (
name, year, grapes, country, region, description, picture
) values (
{name}, {year}, {grapes}, {country}, {region}, {description}, {picture}
)"""
).on(
'name -> wine.name, 'year -> wine.year, 'grapes -> wine.grapes,
'country -> wine.country, 'region -> wine.region, 'description -> wine.description,
'picture -> wine.picture
).executeInsert()
val newWine = for {
id <- newId;
wine <- findById(id)
} yield wine
newWine.map { wine =>
Right(wine)
}.getOrElse {
Left(List(ValidationError("Could not create wine")))
}
}
}
}
Validate checks several preconditions. I still have to add a try/catch to catch any db error
I'm still looking for a way to improve the whole thing, it feels much to verbose to my taste...