If you are an SAP Employee, please follow us on Jam.
OCaml is an industrial strength programming language supporting functional, imperative and object-oriented styles.
Sounds nice, right? OCaml is the next step of the Caml programming language.
Having learning other functional programming languages like Haskell and Erlang, OCaml was the next obvious choice for me…so I decided to start learning it…not an easy task for sure…but really fun and enlighten.
So…no example or demonstration would be complete if we didn’t hook it up with SAP HANA, right? So…let’s go and do it -;)
First, we need to create a Calculation View and call it “FLIGHTS_BY_CARRIER”. It will be composed of two tables, SCARR and SFLIGHT.
First, we need to create a Join object and link the table by MANDT and CARRID. From here select the following fields as output MANDT, CARRID, CARRNAME, PRICE and CURRENCY.
Then create an Aggregation object selecting the fields CARRNAME, PRICE (As Aggregated Column) and CURRENCY. Filter the CURRENCY field by ‘USD’.
Then create a Projection object and select only PRICE and CARRNAME.
On the Semantics object make sure to select “CROSS CLIENT” as the Default Client.
Now, switch to the SAP HANA Development View and create a new repository. Call it “Flights”.
Create a new “XS Engine” project and call it “Flights” as well. Link it to the “Flights” repository.
Create an empty “.xsapp” file.
Create a file called “.xsaccess” with the following code.
.xsaccess |
---|
{ "exposed" : true, "authentication" : [ { "method" : "Basic" } ] } |
Finally create a file called “flights.xsodata” with the following code
flights.xsodata |
---|
service { "Blag/FLIGHTS_BY_CARRIER.calculationview" as "FLIGHTS" keys generate local "Id"; } |
Activate your project and launch it on your browser, you should see something like this…
The SAP HANA part is done…so we can move into the OCaml part…
For first timers, OPAM (the package manager for OCaml can be tricky and sometimes frustrating), so let’s make your lives easier by following this single easy steps…on a terminal session type this…
- opam init
- eval `opam config env`
- opam switch 4.01.0
- eval `opam config env`
- opam install core utop core_extended async uri yojson cohttp lwt ezjsonm
It will take a while but by installing all the required packages in a single command, prevents errors from happening.
To code for OCaml I use one of the most awesome editors I have ever found…Geany. It comes almost pre-configured to handle a lot of programming languages, but just to make sure, here’s how I configure it to work with OCaml.
First, create a file and save it as OCaml_HANA.ml
Then, click on the “Choose more build actions” button
The little half arrow on the right of the brown brick looking button. This will open the following screen
On Compile put the following
corebuild -pkg yojson,cohttp.async,cohttp.lwt,lwt,ezjsonm "%e.native"
And on Execute put
“./%e.native”
With that, we should be more than ready to start coding :smile: Copy and paste the following code…
OCaml_HANA.ml |
---|
open Core.Std open Yojson.Basic.Util open Ezjsonm let get_definition_from_json json = let json = Ezjsonm.from_string(json) in let json = Ezjsonm.(find json ["d";"results"]) in let json = Ezjsonm.to_string(json) in let json = Yojson.Basic.from_string(json) in let json = Yojson.Basic.Util.to_list json in let carrname = Yojson.Basic.Util.filter_member "CARRNAME" json in let carrname = Yojson.Basic.Util.filter_string carrname in let price = Yojson.Basic.Util.filter_member "PRICE" json in let price = Yojson.Basic.Util.filter_string price in printf "Reading SAP HANA from OCaml\n\n"; for i = 0 to List.length(carrname) - 1 do printf "%s: %s\n" (List.nth_exn carrname i) (List.nth_exn price i) done let fetch uri = let cred = Cohttp.Auth.string_of_credential(`Basic("SYSTEM", "YourPassword")) in let headers = Cohttp.Header.init() in let headers = Cohttp.Header.add headers "Authorization" cred in let open Lwt in Cohttp_lwt_unix.Client.get ~headers:headers uri >>= fun (_,body) -> Cohttp_lwt_body.to_string_list body >>= fun strings -> return(get_definition_from_json (String.concat strings)) let () = let hana_uri = Uri.of_string "http://YourServer:8000/Flights/flights.xsodata/FLIGHTS?$format=json" in Lwt_main.run (fetch hana_uri) |
Save your file, press the “Compile the current file” button. The first on the previous images which shows a triangle with an arrow and a ball (all in nice 3D) and then press the “Run or view the current file” button. Last one on the previous image which shows two engines.
You will notice that it comes pretty fast…
Now…something funny about my code…and that might be because of two simple reasons…
- I’m still learning OCaml
- The documentation for external packages is almost non-existent (Actually, I need to browse the GitHub source codes in order to achieve most of the code)
So…the funny thing is that I’m using two different JSON libraries to actually read the ODATA generated by SAP HANA…by using only one I couldn’t manage to get the information that I needed…so using both and extracting pieces from here and there I actually got what I wanted…not so fun when you are doing it…but in the end there a big reward on finally being able to compile it and get the desired output -;)