Haskell SQLite3 query all - sqlite

Would like to determine the size of a table (length) to avoid a user entering an incremental ID that already exists (Note: left all Haskell books to get my feet wet). Got a table with id, task, date_in, date_out and need to count the number id's. Using this function:
checkUniqueID = do
conn <- open "taglist.db"
len <- query conn "SELECT * FROM task;" (Only xxx) :: IO [id]
let showLength = length $ len
print showLength
close conn
return ()
However: omitting the 'Only' will result in ghci mentioning too few arguments, but I really cannot figure out what to put at xxx. Too bad all Haskell doc is so fragmented, since it is such a cool language.
Thanks guys!

I am not terribly familiar with these libraries. I check the docs
of Database.PostgreSQL.Simple
and found out that, if you don't have arguments to your query, you can use query_ and omit the argument tuple. The examples at the very beginning of the docs are quite helpful.
That being said, your approach looks wrong. You are pulling the whole table from the DB only to count the entries. This is a waste: you should instead use something like select count(*) from .. so that you query for the length only.
This might work: (again, I've never used that library)
[Only len] <- query_ conn "select count(*) from task" :: IO [Only Int]

Related

Julia Querying from SQLite

Following this tutorial https://www.youtube.com/watch?app=desktop&v=qUrtLJcehE0, I created a database called Movies. Within the database a table called movies was created and next an entry was also added,
using SQLite
db = SQLite.DB("Movies")
SQLite.execute(db,"CREATE TABLE IF NOT EXISTS movies(movie_id REAL,movie_name TEXT, location TEXT)")
SQLite.execute(db,"INSERT INTO movies (movie_id,movie_name,location) VALUES(1,'Avengers','USA')")
However now when I try to Query the entry as follows,
SQLite.Query(db, "SELECT * from movies")
I get the this error, Error: MethodError: no method matching SQLite.Query.(::SQLite.DB,::String).
Any Ideas what I am doing wrong?
I don't know SQL, but I think you want to use SQLite.execute again not SQLite.Query. SQLite.Query is a struct not a function, and it doesn't have any documentation. I don't think you are meant to call it externally. Further documentation is here.
Method error means you are calling something with the wrong arguments. The SQLite.Query struct expects all of the following arguments:
struct Query
stmt::Stmt
status::Base.RefValue{Cint}
names::Vector{Symbol}
types::Vector{Type}
lookup::Dict{Symbol, Int}
end
The SQLite.execute function expects arguments in one of these forms:
SQLite.execute(db::SQLite.DB, sql, [params])
SQLite.execute(stmt::SQLite.Stmt, [params])
By convention in Julia, functions are all lowercase and types are capitalized.
To load a table using SQLite package,
using SQLite
using DataFrames
# Make a connection
db = SQLite.DB("Movies")
# To find out all tables available in schema
tbls = SQLite.tables(db)
# To load a specific table (movies table from Movies.db)
q = "SELECT * FROM movies"
data = SQLite.DBInterface.execute(db,q)
# To get as a dataframe
df = DataFrames.DataFrame(data)

F# collection type for mixed types

This question is coming from someone who is working on making the transition from R to F#. I fully acknowledge my approach here may be wrong so I am looking for the F# way of doing this. I have a situation where I want iterate through a set of XML files, parse them, and extract several values to identify which ones need further processing. My natural inclination is to Map over the array of XML data, exampleData in this case, parse each using the RawDataProvider type provider, and finally create a Map object for each file containing the parsed XML, the Status value from the XML, and the ItemId value.
Turns out that the Map type in F# is not like a List in R. Lists in R are essentially hashmaps which can support having mixed types. It appears that the Map type in F# does not support storing mixed types. I have found this to be incredibly useful in my R work and am looking for what the right F# collection is for this.
Or, am I thinking about this all wrong? This is a very natural way for me to process data in R so I would expect there would be a way to do it in F# as well. The assumption is that I am going to do further analysis and add additional elements of data to these collections.
Update:
This seems like such a simple use case that there must be an idiomatic way of doing this in F# without having to define a Record type for each step of the analysis. I have updated my example to further illustrate what I am trying to do. I want to return an Array of the Map objects that I have analyzed:
type RawDataProvider = XmlProvider<"""<product Status="Good" ItemId="123" />""">
let exampleData = [| """<product Status="Good" ItemId="123" />"""; """<product Status="Bad" ItemId="456" />"""; """<product Status="Good" ItemId="789" />"""|]
let dataResult =
exampleData
|> Array.map(fun fileData -> RawDataProvider.Parse(fileData))
|> Array.map(fun xml -> Map.empty.Add("xml", xml).Add("Status", xml.Status).Add("ItemId", xml.ItemId))
|> Array.map(fun elem -> elem.["calc1Value"] = calc1 elem["itemId"])
|> Array.map(fun elem -> elem.["calc2"] = calc2 elem.["ItemId"] elem.["calc1Value"])
This is what I would consider almost idiomatic here - I'm keeping the same shape as in your example so you can match the two:
let dataResult =
exampleData
|> Array.map(fun fileData -> RawDataProvider.Parse(fileData))
|> Array.map(fun xml -> xml, calc1 xml.ItemId)
|> Array.map(fun (xml, calcedValue1) -> xml, calcedValue1, calc2 xml.ItemId calcedValue1)
What XmlProvider really gives you is not simply xml parsing, but the fact that it generates a strongly typed representation of the xml. This is better than putting the data in a map, in that it gives you stronger guarantees about whether your program is doing the right thing. For instance it wouldn't let you mix up itemId and ItemId as it happened in your code snippet ;)
For the values you calculate in the following steps, you could use tuples instead of a record. In general, records are preferred to tuples as they lead to more readable code, but combining related values of different types into ad-hoc aggregates is really the scenario where using tuples shines.
Now, I said almost idiomatic - I would break up parsing and processing parsed xmls into separate functions, and calculate both calc1 and calc2 results in a single function instead of composing two Array.maps like this:
let dataResult =
parsedData
|> Array.map(fun xml ->
let calced1 = calc1 xml.ItemId
xml, calced1, calc2 xml.ItemId calced1)
If you're coming from R background, you might want to check out Deedle for an alternative approach. It gives you a workflow similar to R in F#.

PostScript forall on dictionaries

According to the PLRM it doesn't matter in which order you execute a forall on a dict:
(p. 597) forall pushes a key and a value on the operand stack and executes proc for each key-value pair in the dictionary
...
(p. 597) The order in which forall enumerates the entries in the dictionary is arbitrary. New entries put in the dictionary during the execution of proc may or may not be included in the enumeration. Existing entries removed from the dictionary by proc will not be encountered later in the enumeration.
Now I was executing some code:
/d 5 dict def
d /abc 123 put
d { } forall
My output (operand stack) is:
--------top-
/abc
123
-----bottom-
The output of ghostscript and PLRM (operand stack) is:
--------top-
123
/abc
-----bottom-
Does it really not matter in what order you process the key-value pairs of the dict?
on the stack, do you first need to push the value and then the key, or do you need to push the key first? (as the PLRM only talks about "a key and a value", but doesnt tell you anything about the order).
Thanks in advance
It would probably help if you quoted the page number qhen you quote sections from the PLRM, its hard to see where you are getting this from.
When executing forall the order in which forall enumerates the dictionary pairs is arbitrary, you have no influence over it. However forall always pushes the key and then the value. Even if this is implied in the text you (didn't quite) quote, you can see from the example in the forall operator that this is hte case.
when you say 'my output' do you mean you are writing your own PostScript interpreter ? If so then your output is incorrect, when pushing a key/value pair the key is pushed first.

How to define variables in a PL/R (plr) function as parameters for a query inside

I've written a function that queries x,y,z values for creating sections with R.
Now, I want to do that with PL/R, instead of using RStudio.
CREATE OR REPLACE FUNCTION section_graph() RETURNS text AS
'
require(RPostgreSQL)
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, host="localhost", user="postgres", password="...", dbname="...", port="5432")
rs <- dbSendQuery(con, "SELECT x,y,z FROM (SELECT (section(1,3)).*) AS foo")
section1 <- fetch(rs, 2000)
dbClearResult(rs)
dbDisconnect(con)
pdf("/tmp/myplot.pdf", width=18, height=9)
plot(section1$y, section1$z, type="l", lwd=1.5, lty=3)
dev.off()
print("done")
'
LANGUAGE 'plr';
Within the dbSendQuery command there is the query SELECT x,y,z FROM (SELECT (section(1,3)).*) AS foo. The paramter 1 represents an ID, the second one is the accuracy of the section (3m).
Now, I want to use my function above like a common PostgreSQL function (e.g. with language 'sql'). That means, a want to define parameters within the function like this:
SELECT x,y,z FROM (SELECT (section($1,$2)).*) AS foo
$1 $2 are the parameters for my function section_graph.
Is this possible with the language 'plr'? I didn't found something helpful.
Obviously there are problems with the double quotes of the query within the function.
Did you try looking at the pl/r documentation? Took me about ten seconds. The parameters are either called arg1 to argN:
CREATE OR REPLACE FUNCTION r_max (integer, integer) RETURNS integer AS '
if (arg1 > arg2)
return(arg1)
else
return(arg2)
' LANGUAGE 'plr' STRICT;
or, PG 8 and above, you can name them:
CREATE OR REPLACE FUNCTION sd(vals float8[]) RETURNS float AS '
sd(vals)
' LANGUAGE 'plr' STRICT;
http://www.joeconway.com/plr/doc/plr-funcs.html
Something else in your code gives me the fear though. Remember, this R code is being called by the Postgres server while executing queries, and you are connecting to, presumably the same Postgres server and executing another query. This looks like a dozen shades of wrong.
The right way to access the DB in PL/R is via the routines outlined in the 'Normal Support' section:
http://www.joeconway.com/plr/doc/plr-spi-rsupport-funcs-normal.html
There are some 'compatibility support' functions that are like the RPostgreSQL package functions:
http://www.joeconway.com/plr/doc/plr-spi-rsupport-funcs-compat.html
but if you require(RPostgreSQL) in your PL/R code you'll probably mask them and your database will disappear up a black hole. Use the 'normal support' routines in PL/R functions.

Haskell function to get part of date as string

I have a beginner question about dates and String in Haskell.
I need to get part of date (year, month or day) as String in Haskell. I found out, that if I write the following two lines in GHCi
Prelude> now <- getCurrentTime
Prelude> let mon = formatTime defaultTimeLocale "%B" now
then mon is of type String. However, I am unable to put this in a function. I tried for instance the following:
getCurrMonth = do
now <- getCurrentTime
putStrLn (formatTime defaultTimeLocale "%B" now)
But this returns type IO () and I need String (also not IO String, only String).
I understand that do statement creates a monad, which I don't want, but I have been unable to find any other solution for getting date in Haskell.
So, is there any way to write a function like this?
Thanks in advance for any help!
If you want to return a String representing the current time, it will have to be in the IO monad, as the value of the current time is always changing!
What you can do is to return a String in the IO monad:
> getCurrMonth :: IO String
> getCurrMonth = do
> now <- getCurrentTime
> return (formatTime defaultTimeLocale "%B" now)
then, from your top level (e.g. in main), you can pass the String around:
> main = do
> s <- getCurrMonth
> ... do something with s ...
If you really want a pure function of that sort, then you need to pass in the time explicitly as a parameter.
import System.Locale (defaultTimeLocale)
import System.Time (formatCalendarTime, toUTCTime, getClockTime, ClockTime)
main = do now <- getClockTime
putStrLn $ getMonthString now
getMonthString :: ClockTime -> String
getMonthString = formatCalendarTime defaultTimeLocale "%B" . toUTCTime
Notice how getMonthString can be pure since the IO action getClockTime is performed elsewhere.
I used the old-time functions, because I was testing it out on codepad, which apparently doesn't have the newer time package. :( I'm new to the old time functions so this might be off a couple hours since it uses toUTCTime.
As Don said, there's no way to avoid using monads in this situation. Remember that Haskell is a pure functional language, and therefore a function must always return the same output given a particular input. Haskell.org provides a great explanation and introduction here that is certainly worth looking at. You'd also probably benefit from monad introduction like this one or a Haskell I/O tutorial like this one. Of course there are tons more resources online you can find. Monads can initially be daunting, but they're really not as difficult as they seem at first.
Oh, and I strongly advise against using unsafePerformIO. There's a very good reason it has the word "unsafe" in the name, and it was definitely not created for situations like this. Using it will only lead to bad habits and problems down the line.
Good luck learning Haskell!
You can't get just a String, it has to be IO String. This is because getCurrMonth is not a pure function, it returns different values at different times, so it has to be in IO.

Resources