How to retrieve JSON jsonb value with postgresql-simple? - postgresql

I have a column (jsonExample) in the postgresql database with type jsonb.
selectCALogs :: IO [(Int, Object)]
selectCALogs = do
con <- connection
query_ con "select \"clusterId\", \"jsonExample\" from cluster"
This gives an error of:
• No instance for (Database.PostgreSQL.Simple.FromField.FromField
(unordered-containers-0.2.10.0:Data.HashMap.Base.HashMap
Text Value))
arising from a use of ‘query_’
• In a stmt of a 'do' block:
query_ con "select \"clusterId\", \"clusterCALogs\"
from cluster"
In the expression:
do con <- connection
query_ con "select \"clusterId\", \"clusterCALogs\"from cluster"
In an equation for ‘selectCALogs’:
selectCALogs
= do con <- connection
query_ con "select \"clusterId\",
\"clusterCALogs\" from cluster"
|
80 | query_ con "select \"clusterId\", \"clusterCALogs\"
from cluster"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
How can I have it return a JSON object - using aeson or something else?

Looking at the FromField instances here (http://hackage.haskell.org/package/postgresql-simple-0.6.2/docs/Database-PostgreSQL-Simple-FromField.html#t:FromField) I realized it should be a Value and not a Object.
Hence:
selectCALogs :: IO [(Int, Value)]
selectCALogs = do
con <- connection
query_ con "select \"clusterId\", \"jsonExample\" from cluster"

Related

Passing list of values to SELECT PostgreSQL query in Haskell

I'm studying PostgreSQL with Haskell with this lib: https://hackage.haskell.org/package/postgresql-simple-0.4.10.0/docs/Database-PostgreSQL-Simple.html#v:query
While I could select an user like this:
(query_ conn "SELECT * FROM users WHERE NAME == john" :: IO [Only Int]) >>= mapM_ print
using query_:
query_ :: FromRow r => Connection -> Query -> IO [r]
I think I should use query:
query :: (ToRow q, FromRow r) => Connection -> Query -> q -> IO [r]
to pass a list of values. However, how do I pass this list?
For example, for INSERT, I was able to do this:
(execute conn "INSERT INTO users (NAME, PASSWORD) VALUES (?,?)") (["john", "123456"]::[String]) >>= print
but what is the equivalent for SELECT?
I'm not sure I understand your question, since you ask about lists and I don't see how they enter into the picture. But the parameterized version of your select query is this:
query conn "SELECT * FROM users where NAME == ?" (Only ("john" :: String))

How to insert bytea value using postgresql-simple in Haskell

I have a table defined as
CREATE TABLE users (id SERIAL PRIMARY KEY, val BYTEA);
Then I want to serialize my data structure with binary and store in the table, and then retrieve and deserialize back.
{-# LANGUAGE OverloadedStrings, DeriveAnyClass #-}
import Control.Monad (forM_)
import Data.Binary (encode, decode, Binary)
import Database.PostgreSQL.Simple
import GHC.Generics (Generic)
data User = { name :: Text, email :: Text } deriving (Show, Generic, Binary)
main = do
conn <- connect --...
let encoded = encode User {name = "me", email = "me#home.net" }
execute conn "INSERT INTO users(val) values(?)" $ Only encoded
rs <- query_ conn "SELECT id, val FROM users"
forM_ rs $ \(id,val) ->
putStrLn $ (show (id :: Int)) ++ ": " ++ show (decode val :: User)
But I get error Data.Binary.Get.runGet at position 0: not enough bytes.
Query
SELECT * FROM users;
gives
id | val
----+-----
1 | \x
I can't figure out how to map ByteStrings to 'BYTEA`s. According to the docs everything should be OK. What am I doing wrong?
Fixed by replacing the line
execute conn "INSERT INTO users(val) values(?)" $ Only encoded
with
execute conn "INSERT INTO users(val) values(?)" $ Only $ Binary encoded
It's because toField(ByteString) yields Escape whereas toField(Binary ByteString) yields EscapeByteA

How to pull data by inner joining two DB2 table using pyspark?

I'm using following query to pull data from DB2
SELECT A.Emp_ID,B1.Manager_Name,B1.Manager_Phone,B1.Manager_mail
FROM Employee A
INNER JOIN Manager_DETAIL B1
ON (B1.EMP_ID = A.EMP_ID
OR B1.Manager_mail = A.SuperVisor_mail
AND B1.Join_year = '2017' AND B1.QTR = 'Q1'
AND B1.Dept_Name
IN ('support')
How do I do same thing using pyspark?
I tried with this code
tab_A= spark.read.jdbc("My Connection String","Employee",
properties={"user": "my user id",
"password": "my passwore",
'driver' : 'com.ibm.db2.jcc.DB2Driver'})
tab_A.registerTempTable('data_table')
# query to get columns necessary to create indexes
sql = "SELECT * FROM data_table"
A = spark.sql(sql)
tab_B= spark.read.jdbc("My Connection String","Manager_DETAIL",
properties={"user": "my user id",
"password": "my passwore",
'driver' : 'com.ibm.db2.jcc.DB2Driver'})
tab_B.registerTempTable('data_table1')
# query to get columns necessary to create indexes
sql = "SELECT * FROM data_table1"
B1 = spark.sql(sql)
C=spark.sql("SELECT A.Emp_ID,B1.Manager_Name,B1.Manager_Phone,B1.Manager_mail
FROM A
INNER JOIN B1
ON (B1.EMP_ID == A.EMP_ID) |\
(B1.Manager_mail == A.SuperVisor_mail) \
& (B1.Join_year == '2017' & B1.QTR == 'Q1') \
& B1.Dept_Name IN ('support')")
But I'm getting invalid syntax error

Haskell: get table count(*) with postgresql.simple (with Connection Pool)

Please,.. how can I get count(*) from one table? I'm trying to connect some fragments of code,..but so far no success.
This is what I have:
fetchSimple :: FromRow r => Pool Connection -> Query -> IO [r]
fetchSimple pool sql = withResource pool retrieve
where retrieve conn = query_ conn sql
getUsersCount :: Pool Connection -> IO (Int)
getUsersCount pool = do
res <- fetchSimple pool "SELECT count(*) FROM article" :: IO [Int]
let f = head res
return f
this gives me following error:
No instance for (FromRow Int) arising from a use of ‘fetchSimple’
In a stmt of a 'do' block:
res <- fetchSimple pool "SELECT count(*) FROM article" :: IO [Int]
In the expression:
do { res <- fetchSimple pool "SELECT count(*) FROM article" ::
IO [Int];
let f = head res;
return f }
In an equation for ‘getUsersCount’:
getUsersCount pool
= do { res <- fetchSimple pool "SELECT count(*) FROM article" ::
IO [Int];
let f = ...;
return f }
If you only want to extract a single value, you don't do so directly. You wrap it in an Only.
So try the annotation :: IO [Only Int]

postgresql-simple query error

EDIT: I now have a better idea of what is going wrong. When I perform that query in plain old psql, I get the following result:
lwm#verbos
=# SELECT * FROM gerund LIMIT1;
infinitive │ gerund │ gerund_english
────────────┼─────────────┼────────────────
abandonar │ abandonando │ abandoning
So, I am getting back 3 strings? However, I say that I am getting back IO [Only String]. I am sure it is my type signature here that is messing things up ...
I am trying to make a simple query using the postgresql-simple library with Haskell. My code is pasted below along with the error I am seeing. Anyone got any ideas?
My database is called verbos and within it, I have a table called gerund. I am able to run a query_ that contains: conn "SELECT 2 + 2" and that works fine. I can also connect to my database with the default data as specified with the default information (password = 'postgres' : psql -h localhost -p 5432 -U postgres (from the docs[1])
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Monad
import Control.Applicative
import Database.PostgreSQL.Simple
main = do
conn <- connect defaultConnectInfo {
connectPassword = "postgres",
connectDatabase = "verbos"
}
mapM_ print =<< (query_ conn "SELECT * FROM gerund LIMIT 1" :: IO [Only String])
Gives me the following error:
ConversionFailed {errSQLType = "3 values: [(Basic {typoid = Oid 1043,
typcategory = 'S', typdelim = ',', typname = \"varchar\"},Just
\"abandonar\"),(Basic {typoid = Oid 1043, typcategory = 'S', typdelim
= ',', typname = \"varchar\"},Just \"abandonando\"),(Basic {typoid = Oid 1043, typcategory = 'S', typdelim = ',', typname =
\"varchar\"},Just \"abandoning\")]", errSQLTableOid = Nothing,
errSQLField = "", errHaskellType = "1 slots in target type",
errMessage = "mismatch between number of columns to convert and number
in target type"}
OK, Thanks to #AlpMestanogullari, #muistooshort, I got an answer here. My final code is:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Applicative
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.FromRow
data Gerund = Gerund {
f :: String,
s :: String,
t :: String
} deriving (Show)
instance FromRow Gerund where
fromRow = Gerund <$> field <*> field <*> field
main = do
conn <- connect defaultConnectInfo {
connectPassword = "postgres",
connectDatabase = "verbos"
}
mapM_ print =<< (query_ conn q :: IO [Gerund])
where q = "SELECT * FROM gerund LIMIT 1"
Notes:
Knowing that my result contained 3 result columns, I needed to define a type that had 'space' for the results (f, s and t in the Gerund type)
I followed the docs[1] for FromRow closely to get my type and instance defined.
You need to import import Database.PostgreSQL.Simple.FromRow to access things like field.