Error when calling a function using route - postgresql

I've wrote this function to insert an "account" in the database:
(defn create-account [accountnumber]
(if (= nil (find-by-number accountnumber))
(jdbc/insert! db-spec :accounts {:accountnumber accountnumber})
nil
))
This tests passes, so the function it's working:
(testing "create and find-by-number account"
(account/create-account 10)
(is (= 10 ((account/find-by-number 10) :accountnumber)))
)
But when I try to use this route:
(defroutes app-routes
(GET "/:account" [account] (account/create-account account))
(route/not-found "Not Found"))
(def app
(-> app-routes
rmp/wrap-params
wrap-json-response
wrap-json-body))
I got this error:
org.postgresql.util.PSQLException
ERROR: column "accountnumber" is of type integer but expression is of
type character varying Hint: You will need to rewrite or cast the
expression.
Verifying types, I can see that when I run the test, accountnumber type is java.lang.Long and when it comes from routes, it's type is java.lang.String, I've tried to convert it but got no success.

This is because the route is returning a param. Params are strings.
If you change your route to be something like this:
(defroutes app-routes
(GET "/:account" [account] (account/create-account (Integer/parseInt account)))
(route/not-found "Not Found"))
it should work.

Related

Pre-compile textual replacement macro with arguments

I am trying to create some kind of a dut_error wrapper. Something that will take some arguments and construct them in a specific way to a dut_error.
I can't use a method to replace the calls to dut_error because to my understanding after check that ... then ... else can only come a dut_error (or dut_errorf). And indeed if I try to do something like:
my_dut_error(arg1: string, arg2: string) is {
dut_error("first argument is ", arg, " and second argument is ", arg2);
};
check that FALSE else my_dut_error("check1", "check2");
I get an error:
*** Error: Unrecognized exp
[Unrecognized expression 'FALSE else my_dut_error("check1", "check2")']
at line x in main.e
check that FALSE else my_dut_error("check1", "check2");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
So I thought about defining a macro to simply do a textual replace from my wrapper to an actual dut_error:
define <my_dut_error'exp> "my_dut_error(<arg1'name>, <arg2'name>)" as {
dut_error("first argument is ", <arg1'name>, " and second argument is ", <arg2'name>)
};
But got the same error.
Then I read about the preprocessor directive #define so tried:
#define my_dut_error(arg1, arg2) dut_error("first argument is ", arg, " and second argument is ", arg2)
But that just gave a syntax error.
How can I define a pre-compiled textual replacement macro that takes arguments, similar to C?
The reason I want to do that is to achieve some sort of an "interface" to the dut_error so all errors have a consistent structure. This way, different people writing different errors will only pass the arguments necessary by that interface and internally an appropriate message will be created.
not sure i understood what you want to do in the wrapper, but perhaps you can achieve what you want by using the dut_error_struct.
it has set of api, which you can use as hooks (do something when the error is caught) and to query about the specific error.
for example:
extend dut_error_struct {
pre_error() is also {
if source_method_name() == "post_generate" and
source_struct() is a BLUE packet {
out("\nProblem in generation? ", source_location());
// do something for error during generation
};
write() is first {
if get_mesage() ~ "AHB Error..." {
ahb_monitor::increase_errors();
};
};
};
dut_error accepts one parameter, one string. but you can decide of a "separator", that will define two parts to the message.
e.g. - instruct people to write "XXX" in the message, before "first arg" and "second arg".
check that legal else dut_error("ONE thing", "XXX", "another thing");
check that x < 7 else dut_error("failure ", "XXX", "of x not 7 but is ", x);
extend dut_error_struct {
write() is first {
var message_parts := str_split(get_message(), "XXX");
if message_parts.size() == 2 {
out ("First part of message is ", message_parts[0],
"\nand second part of message is ", message_parts[1]
);
};
};
I could get pretty close to what I want using the dut_errorf method combined with a preprocessor directive defining the format string:
#define DUT_FORMAT "first argument is %s and second argument is %s"
check that FALSE else dut_errorf(DUT_FORMAT, "check1", "check2");
but I would still prefer a way that doesn't require this DUT_FORMAT directive and instead uses dut_error_struct or something similar.

How to do a case insensitive match for command line arguments in scala?

I'm working on a command line tool written in Scala which is executed as:
sbt "run --customerAccount 1234567"
Now, I wish to make this flexible to accept "--CUSTOMERACCOUNT" or --cUsToMerAccount or --customerACCOUNT ...you get the drift
Here's what the code looks like:
lazy val OptionsParser: OptionParser[Args] = new scopt.OptionParser[Args]("scopt") {
head(
"XML Generator",
"Creates XML for testing"
)
help("help").text(s"Prints this usage message. $envUsage")
opt[String]('c', "customerAccount")
.text("Required: Please provide customer account number as -c 12334 or --customerAccount 12334")
.required()
.action { (cust, args) =>
assert(cust.nonEmpty, "cust is REQUIRED!!")
args.copy(cust = cust)
}
}
I assume the opt[String]('c', "customerAccount") does the pattern matching from the command line and will match with "customerAccount" - how do I get this to match with "--CUSTOMERACCOUNT" or --cUsToMerAccount or --customerACCOUNT? What exactly does the args.copy (cust = cust) do?
I apologize if the questions seem too basic. I'm incredibly new to Scala, have worked in Java and Python earlier so sometimes I find the syntax a little hard to understand as well.
You'd normally be parsing the args with code like:
OptionsParser.parse(args, Args())
So if you want case-insensitivity, probably the easiest way is to canonicalize the case of args with something like
val canonicalized = args.map(_.toLowerCase)
OptionsParser.parse(canonicalized, Args())
Or, if you for instance wanted to only canonicalize args starting with -- and before a bare --:
val canonicalized =
args.foldLeft(false -> List.empty[String]) { (state, arg) =>
val (afterDashes, result) = state
if (afterDashes) true -> (arg :: result) // pass through unchanged
else {
if (arg == "==") true -> (arg :: result) // move to afterDash state & pass through
else {
if (arg.startsWith("--")) false -> (arg.toLowerCase :: result)
else false -> (arg :: result) // pass through unchanged
}
}
}
._2 // Extract the result
.reverse // Reverse it back into the original order (if building up a sequence, your first choice should be to build a list in reversed order and reverse at the end)
OptionsParser.parse(canonicalized, Args())
Re the second question, since Args is (almost certainly) a case class, it has a copy method which constructs a new object with (most likely, depending on usage) different values for its fields. So
args.copy(cust = cust)
creates a new Args object, where:
the value of the cust field in that object is the value of the cust variable in that block (this is basically a somewhat clever hack that works with named method arguments)
every other field's value is taken from args

Evaluating variables in Racket response/xexpr

I'm trying to make a simple bookmarking web-app in Racket.
It's meant to receive a url as a CGI argument, and right now, I'm just trying to confirm I received it by reflecting it back.
(define (start request)
(response/xexpr
(let* ([bindings (request-bindings request)]
[url (if (exists-binding? 'url bindings)
(extract-binding/single 'url bindings)
"NO URL")])
`(html
(head (title "TITLE"))
(body (h2 "TITLE")
(p "URL = " url))
))))
However, instead of seeing what I expect to see .. which is a page that contains
URL = http://google.com
I'm seeing
URL = &url;
Which suggests that url is being quoted literally in the xexpr (treated as an entity), rather than being evaluated as a variable.
So what am I doing wrong? How do I get url evaluated?
You need to use quasiquote and unquote to inject values into a quoted experession, more often seen as their reader abbreviation equivalents, ` and ,, respectively. When you use unquote/, inside of quasiquote/`, it will evaluate the expression and insert it into the surrounding quotation:
> (define url "http://google.com")
> `(p "URL = " ,url)
(p "URL = " "http://google.com")
You should put , in front of url in your template to unquote it.
For a more detailed explanation of quotation and quasiquotation, see Appendix A of this answer.
Use ,url :
`(html
(head (title "TITLE"))
(body (h2 "TITLE")
(p "URL = " ,url))
))))
Look for unquote in the documentation: http://docs.racket-lang.org/reference/quasiquote.html?q=unquote#%28form.%28%28quote.~23~25kernel%29._unquote%29%29

Select from H2 adds "clob:" to texts in clojure

I am using a h2 database with clojure. I made a table and put some data in like this
(j/create-table :locations
[:id "bigint primary key auto_increment"]
[:title "varchar (255)"]
[:part "clob"])
(j/insert-records :locations
{:title "Steven Gerrard: I'm not the new Beckham" :part "He might not have the Becks appeal -- but Steven Gerrard says he's ready to light up Hollywood in his own way..."}))
)
)
And then I selected the data
(defn newest []
(database/mysql-db)
(let [results (j/with-connection db-spec
(j/with-query-results res
["select id, title, part from locations"]
(doall res)))]
results))
And I used the data on a clostache page
<div class="container">
<sections>
{{#newest}}
<p style="padding-bottom: 15px;">{{title}}<p>
<p style="padding-bottom: 15px;">{{part}}<p>
{{/newest}}
</sections>
</div>
On the page i get
Steven Gerrard: I'm not the new Beckham
clob0: 'He might not have the Becks appeal -- but Steven Gerrard says he''s ready to light up Hollywood in his own way...'
How can I remove the clob0: string that is attached to the text I have in the database? This happens even if I use text instead of clob for the part column in my database.
The 'clob0:' prefix is not actually attached to your data in database.
The reason you get this is because ResultSet returns instances of class java.sql.Clob for column "part" (for both CLOB and TEXT data types, they are actually synonyms).
It's not proper way to convert Clob to String by using toString() method, implementation is free to return any human-readable form. Correct way may be found in other answers.
You might have noticed that new lines get lost by the above... something like this adds them back in...
(defn clob-to-string [clob]
"Turn an Clob into a String, with new new lines"
(with-open [rdr (java.io.BufferedReader. (.getCharacterStream clob))]
(let [lseq (line-seq rdr)
butlast-line (butlast lseq)
butlast-line-mapped (map (fn [l] (str l "\n")) butlast-line)
last-line (last lseq)
all-lines-with-newline (concat butlast-line-mapped last-line)
]
(apply str all-lines-with-newline)
)))
I removed the clob: with:
(defn clob-to-string [row]
(assoc row :text (with-open [rdr (java.io.BufferedReader. (.getCharacterStream (:text row)))]
(apply str (line-seq rdr)))))
(defn newest []
(database/mysql-db)
(j/query db-spec
["select id, title, text from news"]
:row-fn clob-to-string
))

Haskell Snap: mongodb field type error

I get an error which I can't resolve.
The snap application compiles without a problem and everything seems to be ok.
But when I render the relevant page in a browser I get this error:
A web handler threw an exception. Details:
expected ("code" :: Integer) in [ _id: 50b56f19208c2e9a09dccc2b, id: 1.0, code: "hdg435", name: "froggy"]
The code value is just a rendom string I picked for testing. I am not sure why an integer is expected?
These are the relevant parts of an example snap application.
getData :: IO [Document]
getData = do
pipe <- runIOE $ connect $ host "127.0.0.1"
let run act = access pipe master "test" act
result <- run (find (select [] "pcs") >>= rest)
close pipe
return $ either (const []) id result
mkSplice :: Document -> Splice AppHandler
mkSplice d = runChildrenWithText [dtp "id" d
,dtp "code" d
,dtp "name" d
]
dtp :: Text -> Document -> (Text,Text)
dtp tag d = (tag, T.pack $ show $ at tag d)
recSplice :: Splice AppHandler
recSplice = mapSplices mkSplice =<< liftIO getData
table :: Handler App App ()
table = heistLocal (bindSplice "rec" recSplice) $ render "table"
The relevant Heist template part of table.tpl is here:
<table>
<tbody>
<rec>
<tr><td><id/></td><td><code/></td><td><name/></td></tr>
</rec>
</tbody>
</table>
Please let me know what other parts of code need to be posted.
When I compile your dtp function I get:
import Data.Bson
import Data.Text (Text)
import qualified Data.Text as T
dtp :: Text -> Document -> (Text,Text)
dtp tag d = (tag, T.pack $ show $ at tag d)
Ambiguous type variable `a0' in the constraints:
(Show a0)
[...]
which makes perfect sense. It seems like in your case it's defaulting to Integer when you really want String. You can try adding a signature or better yet, just:
dtp tag d = (tag, at tag d)
If you want this to work for other types, you'll have to work harder.
UPDATE
Here's a GHCi session that illustrates the problem and how GHCi seems to default the Show instance to Integer:
Prelude Data.Bson> show $ at "hello" ["hello" =: "world"]
"*** Exception: expected ("hello" :: Integer) in [ hello: "world"]