Partial SQL insert in haskelldb - sql

I just started a new project and wanted to use HaskellDB in the beginning. I created a database with 2 columns:
create table sensor (
service text,
name text
);
..found out how to do the basic HaskellDB machinery (ohhh..the documentation) and wanted to do an insert. However, I wanted to do a partial insert (there are supposed to be more columns), something like:
insert into sensor (service) values ('myservice');
Translated into HaskellDB:
transaction db $ insert db SE.sensor (SE.service <<- (Just $ senService sensor))
But...that simply doesn't work. What also does not work is if I specify the column names in different order, which is not exactly conenient as well. Is there a way to do a partial insert in haskelldb?
The error codes I get are - when I just inserted a different column (the 'name') as the first one:
Couldn't match expected type `SEI.Service'
against inferred type `SEI.Name'
Expected type: SEI.Intsensor
Inferred type: Database.HaskellDB.HDBRec.RecCons
SEI.Name (Expr String) er
When using functional dependencies to combine
Database.HaskellDB.Query.InsertRec
(Database.HaskellDB.HDBRec.RecCons f (e a) r)
(Database.HaskellDB.HDBRec.RecCons f (Expr a) er),
etc..
And when I do the 'service' as the first - and only - field, I get:
Couldn't match expected type `Database.HaskellDB.HDBRec.RecCons
SEI.Name
(Expr String)
(Database.HaskellDB.HDBRec.RecCons
SEI.Time
(Expr Int)
(Database.HaskellDB.HDBRec.RecCons
SEI.Intval (Expr Int) Database.HaskellDB.HDBRec.RecNil))'
against inferred type `Database.HaskellDB.HDBRec.RecNil'
(I have a couple of other columns in the table)
This looks really like 'by design', unfortunately :(

You're right, that does look intentional. The HaskellDB.Query docs show that insert has a type of:
insert :: (ToPrimExprs r, ShowRecRow r, InsertRec r er) => Database -> Table er -> Record r -> IO ()
In particular, the relation InsertRec r er must hold. That's defined elsewhere by the recursive type program:
InsertRec RecNil RecNil
(InsertExpr e, InsertRec r er) => InsertRec (RecCons f (e a) r) (RecCons f (Expr a) er)
The first line is the base case. The second line is an inductive case. It really does want to walk every element of er, the table. There's no short-circuit, and no support for re-ordering. But in my own tests, I have seen this work, using _default:
insQ db = insert db test_tbl1 (c1 <<- (Just 5) # c2 << _default)
So if you want a partial insert, you can always say:
insC1 db x = insert db test_tbl1 (c1 <<- (Just x) # c2 << _default)
insC2 db x = insert db test_tbl2 (c1 << _default # c2 <<- (Just x))
I realize this isn't everything you're looking for. It looks like InsertRec can be re-written in the style of HList, to permit more generalization. That would be an excellent contribution.

Related

SQL Array aggregation in Haskell + Squeal

I'm using an SQL library called Squeal in Haskell.
What's the correct way to aggregate multiple text rows into one array in Squeal library?
Say I got a very simple Schema with just one table containing a column 'keyword' (of PG text type) + associated types:
import Squeal.PostgreSQL
import qualified GHC.Generics as GHC
import qualified Generics.SOP as SOP
type Constraints = '["pk_keywords" ::: 'PrimaryKey '["id"]]
type Columns
= '["id" ::: 'Def :=> 'NotNull 'PGint8, "keyword" ::: 'NoDef :=> 'NotNull 'PGtext]
type Table = 'Table (Constraints :=> KColumns)
type Schema = '["keywords" ::: Table]
type Schemas = '["public" ::: Schema]
newtype Keywords = Keywords {unKeywords :: [Text]} deriving (GHC.Generic)
instance SOP.Generic Keywords
instance SOP.HasDatatypeInfo Keywords
type instance PG Keywords = 'PGvararray ( 'NotNull 'PGtext)
This is the part I need help with:
I'm trying an aggregation query like this:
keywords :: Query_ Schemas () Keywords
keywords =
select_ ((arrayAgg (All #keyword)) `as` #fromOnly) (from (table #keywords))
However, I keep getting an error:
* Couldn't match type 'NotNull (PG [Text])
with 'Null ('PGvararray ty0)
arising from a use of `as'
From what I understand, arrayAgg can produce NULL so I need to provide a default of empty array [] somehow with fromNull from here:
https://hackage.haskell.org/package/squeal-postgresql-0.5.1.0/docs/Squeal-PostgreSQL-Expression-Null.html#v:fromNull
But I don't quite know how to provide that.
What about the value type mismatch (PG [Text] vs 'PGvararray ty0)? How to solve that?
For the record, the library's author provided a solution as follows:
keywords :: Query_ Schemas () (Only (VarArray [Text]))
keywords = select_
(fromNull (array [] & inferredtype) (arrayAgg (All #keyword)) `as` #fromOnly)
(from (table #keywords) & groupBy Nil)
The key factors here are:
Provide a default empty array with fromNull (array [] & inferredtype) .... This way we can avoid using Maybe in the return type
Provide grouping with groupBy Nil
Choose either Distinct or All rows in arrayAgg
Finally, the return type should be VarArray x

Force FsCheck to generate NonEmptyString for discriminating union fields of type string

I'm trying to achieve the following behaviour with FsCheck: I'd like to create a generator that will generate a instance of MyUnion type, with every string field being non-null/empty.
type MyNestedUnion =
| X of string
| Y of int * string
type MyUnion =
| A of int * int * string * string
| B of MyNestedUnion
My 'real' type is much larger/deeper than the MyUnion, and FsCheck is able to generate a instance without any problem, but the string fields of the union cases are sometimes empty. (For example it might generate B (Y (123, "")))
Perhaps there's some obvious way of combining FsCheck's NonEmptyString and its support for generating arbitrary union types that I'm missing?
Any tips/pointers in the right direction greatly appreciated.
Thanks!
This goes against the grain of property based testing (in that you explicitly prevent valid test cases from being generated), but you could wire up the non-empty string generator to be used for all strings:
type Alt =
static member NonEmptyString () : Arbitrary<string> =
Arb.Default.NonEmptyString()
|> Arb.convert
(fun (nes : NonEmptyString) -> nes.Get)
NonEmptyString.NonEmptyString
Arb.register<Alt>()
let g = Arb.generate<MyUnion>
Gen.sample 1 10 g
Note that you'd need to re-register the default generator after the test since the mappings are global.
A more by-the-book solution would be to use the default derived generator and then filter values that contain invalid strings (i.e. use ==>), but you might find it not feasible for particularly deep nested types.

Coq - Passing parameters to a record

I'm having trouble in comparing elements of sets belonging to two distinct
instances of the same record type. Consider the following record.
Record ToyRec := {
X:Set;
Labels:Set;
r:X->Labels
}
Say that two objects T1 and T2 of type ToyRec form a good pair if
for every element in T1.(X) there exists an element in T2.(X) with the
same label.
Definition GoodPair(T1 T2:ToyRec):Prop :=
forall x1:T1.(X), exists x2:T2.(X), T1.(r) x1 = T2.(r) x2.
The problem is that I get an error saying that T1.(r) x1 is of type X1.(Labels),
and T2.(r) x2 is of type X2.(Labels).
I understand the problem, and I imagine it could be solved if I could somehow
declare the set Labels outside the record, and then pass it as a parameter.
Is there a way to do this in Coq? Or what would be the most elegant way of
defining the records I want and the property GoodPair?
The closest thing I got from your code his the following:
Record ToyRec {Labels : Set} := {
X:Set;
r:X->Labels
}.
Definition GoodPair {Labels:Set} (T1 T2 : #ToyRec Labels) : Prop :=
forall x1: X T1, exists x2: X T2, r T1 x1 = r T2 x2.
By having Labels as a dependency for ToyRec you can be sure that both records are using the same type.
PS: I used {Labels : Set} instead of (Labels : Set) to specify that this argument is implicit and should be inferred whenever possible.

Long schema name of hadoop pig

I have a complex job.
After several steps, now the schema come to below:
K: {C::group::sig: int,C::group::sn: chararray,long,DG::sn: chararray,DG::lat: float,DG::lng: float,DG::country: chararray,DG::region: int}
I can store and load, then re-assign the schema name for each item such as (sig:int, sn:chararray....)..
is there any other to do it in memory without load and store?
At any time, you can rename a field when you GENERATE it.
DESCRIBE K;
K: {C::group::sig: int,C::group::sn: chararray,long,DG::sn: chararray,DG::lat: float,DG::lng: float,DG::country: chararray,DG::region: int}
K2 =
FOREACH K
GENERATE
sig AS sig,
C::group::sn AS sn,
$2,
DG::sn AS sn2,
lat AS lat,
lng AS lng,
country AS country,
region AS region;
DESCRIBE K2;
K2: {sig: int,sn: chararray,long,sn2: chararray,lat: float,lng: float,country: chararray,region: int}
Also note that if the name is unambiguous (e.g., sig), you do not need to use the full name when working with the field. If it is ambiguous (e.g., C::group::sn and DG::sn), you do need to use the full name.

Currying and compiler design

This is a homework question:
Explain the transformations the type
of a routine undergoes in partial
parameterization.
So far I understand currying. But I cannot find any resources on how a function like this is implemented by the compiler in memory. Could I be pointed in the right direction, maybe keywords to search for or links to resources or possibly an explanation here of how the compiler generates the type and symbol table among other things thats related to the question.
Thanks.
Currying is the conversion of n argument functions into n unary functions:
Example, if you have a ternary function f :: t1 x t2 x t3 -> t you can represent this function as
f1 :: t1 -> (t2 -> (t3 -> t))
In other words, f1 is a function which takes an argument of type t1 and returns a function of type f2.
f2 :: t2 -> (t3 -> t)
f2 is a function which takes an argument of type t2 and returns a function of type f3.
f3 :: t3 -> t
f3 is a function which takes an argument of type t3 and returns type t.
Example, if f(a,b,c) = a+b*c then:
f3(C) == c1+c2*C where c1 and c2 are constant.
f2(B) == f3(C) where c1 is constant and c2 is replaced with B.
f1(A) == f2(B) where c1 is replaced with A.
In functional languages, functions are first class citizens so its common to have them as return type.
Currying is like fixing a parameter of the function. What you really need to modify is the prototype of the function called.. if you have for example retn_type function(param1, param2) and you currying it on first parameter you set it to a fixed value and you obtain a new function retn_type(param2) that can be called and passed in a different way from the original one.
Actually you can obtain it in a compiler in many ways or hacks but the core of everything to its simplicity is just to redefine a new version that is linked to first one. So when you call retn_type(param2) you execute the same code of first function assuming that parameter1 is specified by curryfication.