on dev help sign in
fix all tests

and add specialized manipulations

commitbcfd6e350a7af7d9adbe6ecba56bbaed8e1469cf authorEitan Chatav <eitan.chatav@gmail.com> dateFri 23 Feb 2018, 12:44 (9 years ago) parent1d68991
6 files changed+337−187
squeal-postgresql/src/Squeal/PostgreSQL/Definition.hs+25−37 squeal-postgresql/src/Squeal/PostgreSQL/Expression.hs+134−25 squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+117−53 squeal-postgresql/src/Squeal/PostgreSQL/PQ.hs+2−1 squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+54−71 squeal-postgresql/src/Squeal/PostgreSQL/Untitled-1+5
squeal-postgresql/src/Squeal/PostgreSQL/Definition.hs+25−37
@@ -357,7 +357,7 @@ ALTER statements
357357
358358-- | `alterTable` changes the definition of a table from the schema.
359359alterTable
360− :: (KnownSymbol tab, (tab ::: table0) `In` schema)
360+ :: Has tab schema table0
361361 => Alias tab -- ^ table to alter
362362 -> AlterTable schema table0 table1 -- ^ alteration to perform
363363 -> Definition schema (Alter tab schema table1)
@@ -424,10 +424,10 @@ newtype AlterTable
424424-- >>> :{
425425-- let
426426-- definition :: Definition
427−-- '["tab" ::: '["col1" ::: 'Required ('Null 'PGint4)]]
428−-- '["tab" :::
429−-- '[ "col1" ::: 'Required ('Null 'PGint4)
430−-- , "col2" ::: 'Optional ('Null 'PGtext) ]]
427+-- '["tab" ::: '[] :=> '["col1" ::: 'NoDef :=> 'Null 'PGint4]]
428+-- '["tab" ::: '[] :=>
429+-- '[ "col1" ::: 'NoDef :=> 'Null 'PGint4
430+-- , "col2" ::: 'Def :=> 'Null 'PGtext ]]
431431-- definition = alterTable #tab
432432-- (addColumnDefault #col2 (text & default_ "foo"))
433433-- in renderDefinition definition
@@ -447,10 +447,10 @@ addColumnDefault column ty = UnsafeAlterTable $
447447-- >>> :{
448448-- let
449449-- definition :: Definition
450−-- '["tab" ::: '["col1" ::: 'Required ('Null 'PGint4)]]
451−-- '["tab" :::
452−-- '[ "col1" ::: 'Required ('Null 'PGint4)
453−-- , "col2" ::: 'Required ('Null 'PGtext) ]]
450+-- '["tab" ::: '[] :=> '["col1" ::: 'NoDef :=> 'Null 'PGint4]]
451+-- '["tab" ::: '[] :=>
452+-- '[ "col1" ::: 'NoDef :=> 'Null 'PGint4
453+-- , "col2" ::: 'NoDef :=> 'Null 'PGtext ]]
454454-- definition = alterTable #tab (addColumnNull #col2 text)
455455-- in renderDefinition definition
456456-- :}
@@ -471,10 +471,10 @@ addColumnNull column ty = UnsafeAlterTable $
471471-- >>> :{
472472-- let
473473-- definition :: Definition
474−-- '["tab" :::
475−-- '[ "col1" ::: 'Required ('Null 'PGint4)
476−-- , "col2" ::: 'Required ('Null 'PGtext) ]]
477−-- '["tab" ::: '["col1" ::: 'Required ('Null 'PGint4)]]
474+-- '["tab" ::: '[] :=>
475+-- '[ "col1" ::: 'NoDef :=> 'Null 'PGint4
476+-- , "col2" ::: 'NoDef :=> 'Null 'PGtext ]]
477+-- '["tab" ::: '[] :=> '["col1" ::: 'NoDef :=> 'Null 'PGint4]]
478478-- definition = alterTable #tab (dropColumn #col2)
479479-- in renderDefinition definition
480480-- :}
@@ -488,18 +488,6 @@ dropColumn column = UnsafeAlterTable $
488488
489489-- | Like `dropColumn` but authorizes dropping everything that depends
490490-- on the column.
491−--
492−-- >>> :{
493−-- let
494−-- definition :: Definition
495−-- '["tab" :::
496−-- '[ "col1" ::: 'Required ('Null 'PGint4)
497−-- , "col2" ::: 'Required ('Null 'PGtext) ]]
498−-- '["tab" ::: '["col1" ::: 'Required ('Null 'PGint4)]]
499−-- definition = alterTable #tab (dropColumnCascade #col2)
500−-- in renderDefinition definition
501−-- :}
502−-- "ALTER TABLE tab DROP COLUMN col2 CASCADE;"
503491-- dropColumnCascade
504492-- :: KnownSymbol column
505493-- => Alias column -- ^ column to remove
@@ -512,8 +500,8 @@ dropColumn column = UnsafeAlterTable $
512500-- >>> :{
513501-- let
514502-- definition :: Definition
515−-- '["tab" ::: '["foo" ::: 'Required ('Null 'PGint4)]]
516−-- '["tab" ::: '["bar" ::: 'Required ('Null 'PGint4)]]
503+-- '["tab" ::: '[] :=> '["foo" ::: 'NoDef :=> 'Null 'PGint4]]
504+-- '["tab" ::: '[] :=> '["bar" ::: 'NoDef :=> 'Null 'PGint4]]
517505-- definition = alterTable #tab (renameColumn #foo #bar)
518506-- in renderDefinition definition
519507-- :}
@@ -548,8 +536,8 @@ newtype AlterColumn (ty0 :: ColumnType) (ty1 :: ColumnType) =
548536-- >>> :{
549537-- let
550538-- definition :: Definition
551−-- '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]]
552−-- '["tab" ::: '["col" ::: 'Optional ('Null 'PGint4)]]
539+-- '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
540+-- '["tab" ::: '[] :=> '["col" ::: 'Def :=> 'Null 'PGint4]]
553541-- definition = alterTable #tab (alterColumn #col (setDefault 5))
554542-- in renderDefinition definition
555543-- :}
@@ -565,8 +553,8 @@ setDefault expression = UnsafeAlterColumn $
565553-- >>> :{
566554-- let
567555-- definition :: Definition
568−-- '["tab" ::: '["col" ::: 'Optional ('Null 'PGint4)]]
569−-- '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]]
556+-- '["tab" ::: '[] :=> '["col" ::: 'Def :=> 'Null 'PGint4]]
557+-- '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
570558-- definition = alterTable #tab (alterColumn #col dropDefault)
571559-- in renderDefinition definition
572560-- :}
@@ -581,8 +569,8 @@ dropDefault = UnsafeAlterColumn $ "DROP DEFAULT"
581569-- >>> :{
582570-- let
583571-- definition :: Definition
584−-- '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]]
585−-- '["tab" ::: '["col" ::: 'Required ('NotNull 'PGint4)]]
572+-- '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
573+-- '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4]]
586574-- definition = alterTable #tab (alterColumn #col setNotNull)
587575-- in renderDefinition definition
588576-- :}
@@ -595,8 +583,8 @@ setNotNull = UnsafeAlterColumn $ "SET NOT NULL"
595583-- >>> :{
596584-- let
597585-- definition :: Definition
598−-- '["tab" ::: '["col" ::: 'Required ('NotNull 'PGint4)]]
599−-- '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]]
586+-- '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4]]
587+-- '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
600588-- definition = alterTable #tab (alterColumn #col dropNotNull)
601589-- in renderDefinition definition
602590-- :}
@@ -611,8 +599,8 @@ dropNotNull = UnsafeAlterColumn $ "DROP NOT NULL"
611599-- >>> :{
612600-- let
613601-- definition :: Definition
614−-- '["tab" ::: '["col" ::: 'Required ('NotNull 'PGint4)]]
615−-- '["tab" ::: '["col" ::: 'Required ('NotNull 'PGnumeric)]]
602+-- '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4]]
603+-- '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGnumeric]]
616604-- definition =
617605-- alterTable #tab (alterColumn #col (alterType (numeric & notNull)))
618606-- in renderDefinition definition
squeal-postgresql/src/Squeal/PostgreSQL/Expression.hs+134−25
@@ -452,7 +452,12 @@ instance (PGNum ty, PGFloating ty) => Floating
452452 acosh x = log (x + sqrt (x*x - 1))
453453 atanh x = log ((1 + x) / (1 - x)) / 2
454454
455−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGfloat4)) $ atan2_ pi 2
455+-- | :{
456+-- let
457+-- expression :: Expression tables grouping params (nullity 'PGfloat4)
458+-- expression = atan2_ pi 2
459+-- in renderExpression expression
460+-- :}
456461-- "atan2(pi(), 2)"
457462atan2_
458463 :: PGFloating float
@@ -480,8 +485,12 @@ cast ty x = UnsafeExpression $ parenthesized $
480485 renderExpression x <+> "::" <+> renderTypeExpression ty
481486
482487-- | integer division, truncates the result
483−--
484−-- >>> renderExpression @_ @_ @_ @(_(_ 'PGint2)) $ 5 `quot_` 2
488+-- :{
489+-- let
490+-- expression :: Expression tables grouping params (nullity 'PGint2)
491+-- expression = 5 `quot_` 2
492+-- in renderExpression expression
493+-- :}
485494-- "(5 / 2)"
486495quot_
487496 :: PGIntegral int
@@ -494,7 +503,12 @@ quot_ = unsafeBinaryOp "/"
494503
495504-- | remainder upon integer division
496505--
497−-- >>> renderExpression @_ @_ @_ @(_ (_ 'PGint2)) $ 5 `rem_` 2
506+-- :{
507+-- let
508+-- expression :: Expression tables grouping params (nullity 'PGint2)
509+-- expression = 5 `rem_` 2
510+-- in renderExpression expression
511+-- :}
498512-- "(5 % 2)"
499513rem_
500514 :: PGIntegral int
@@ -505,7 +519,12 @@ rem_
505519 -> Expression tables grouping params (nullity int)
506520rem_ = unsafeBinaryOp "%"
507521
508−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGfloat4)) $ trunc pi
522+-- | :{
523+-- let
524+-- expression :: Expression tables grouping params (nullity 'PGfloat4)
525+-- expression = trunc pi
526+-- in renderExpression expression
527+-- :}
509528-- "trunc(pi())"
510529trunc
511530 :: PGFloating frac
@@ -514,7 +533,12 @@ trunc
514533 -> Expression tables grouping params (nullity frac)
515534trunc = unsafeFunction "trunc"
516535
517−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGfloat4)) $ round_ pi
536+-- | :{
537+-- let
538+-- expression :: Expression tables grouping params (nullity 'PGfloat4)
539+-- expression = round_ pi
540+-- in renderExpression expression
541+-- :}
518542-- "round(pi())"
519543round_
520544 :: PGFloating frac
@@ -523,7 +547,12 @@ round_
523547 -> Expression tables grouping params (nullity frac)
524548round_ = unsafeFunction "round"
525549
526−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGfloat4)) $ ceiling_ pi
550+-- | :{
551+-- let
552+-- expression :: Expression tables grouping params (nullity 'PGfloat4)
553+-- expression = ceiling_ pi
554+-- in renderExpression expression
555+-- :}
527556-- "ceiling(pi())"
528557ceiling_
529558 :: PGFloating frac
@@ -572,7 +601,12 @@ not_ = unsafeUnaryOp "NOT"
572601 -> Condition tables grouping params
573602(.||) = unsafeBinaryOp "OR"
574603
575−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGint2)) $ caseWhenThenElse [(true, 1), (false, 2)] 3
604+-- | :{
605+-- let
606+-- expression :: Expression tables grouping params (nullity 'PGint2)
607+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
608+-- in renderExpression expression
609+-- :}
576610-- "CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END"
577611caseWhenThenElse
578612 :: [ ( Condition tables grouping params
@@ -593,7 +627,12 @@ caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
593627 , " END"
594628 ]
595629
596−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGint2)) $ ifThenElse true 1 0
630+-- | :{
631+-- let
632+-- expression :: Expression tables grouping params (nullity 'PGint2)
633+-- expression = ifThenElse true 1 0
634+-- in renderExpression expression
635+-- :}
597636-- "CASE WHEN TRUE THEN 1 ELSE 0 END"
598637ifThenElse
599638 :: Condition tables grouping params
@@ -775,7 +814,12 @@ unsafeAggregateDistinct
775814unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
776815 [fun, "(DISTINCT ", renderExpression x, ")"]
777816
778−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGnumeric)]] $ sum_ #col
817+-- | :{
818+-- let
819+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGnumeric]] grouping params (nullity 'PGnumeric)
820+-- expression = sum_ #col
821+-- in renderExpression expression
822+-- :}
779823-- "sum(col)"
780824sum_
781825 :: PGNum ty
@@ -784,7 +828,12 @@ sum_
784828 -> Expression tables ('Grouped bys) params (nullity ty)
785829sum_ = unsafeAggregate "sum"
786830
787−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGnumeric)]] $ sumDistinct #col
831+-- | :{
832+-- let
833+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGnumeric]] grouping params (nullity 'PGnumeric)
834+-- expression = sumDistinct #col
835+-- in renderExpression expression
836+-- :}
788837-- "sum(DISTINCT col)"
789838sumDistinct
790839 :: PGNum ty
@@ -810,7 +859,12 @@ instance PGAvg 'PGfloat4 'PGfloat8
810859instance PGAvg 'PGfloat8 'PGfloat8
811860instance PGAvg 'PGinterval 'PGinterval
812861
813−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGint4)]] $ bitAnd #col
862+-- | :{
863+-- let
864+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGint4]] grouping params (nullity 'PGint4)
865+-- expression = bitAnd #col
866+-- in renderExpression expression
867+-- :}
814868-- "bit_and(col)"
815869bitAnd
816870 :: PGIntegral int
@@ -819,7 +873,12 @@ bitAnd
819873 -> Expression tables ('Grouped bys) params (nullity int)
820874bitAnd = unsafeAggregate "bit_and"
821875
822−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGint4)]] $ bitOr #col
876+-- | :{
877+-- let
878+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGint4]] grouping params (nullity 'PGint4)
879+-- expression = bitOr #col
880+-- in renderExpression expression
881+-- :}
823882-- "bit_or(col)"
824883bitOr
825884 :: PGIntegral int
@@ -828,7 +887,12 @@ bitOr
828887 -> Expression tables ('Grouped bys) params (nullity int)
829888bitOr = unsafeAggregate "bit_or"
830889
831−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGint4)]] $ bitAndDistinct #col
890+-- | :{
891+-- let
892+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGint4]] grouping params (nullity 'PGint4)
893+-- expression = bitAndDistinct #col
894+-- in renderExpression expression
895+-- :}
832896-- "bit_and(DISTINCT col)"
833897bitAndDistinct
834898 :: PGIntegral int
@@ -837,7 +901,12 @@ bitAndDistinct
837901 -> Expression tables ('Grouped bys) params (nullity int)
838902bitAndDistinct = unsafeAggregateDistinct "bit_and"
839903
840−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGint4)]] $ bitOrDistinct #col
904+-- | :{
905+-- let
906+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGint4]] grouping params (nullity 'PGint4)
907+-- expression = bitOrDistinct #col
908+-- in renderExpression expression
909+-- :}
841910-- "bit_or(DISTINCT col)"
842911bitOrDistinct
843912 :: PGIntegral int
@@ -846,7 +915,12 @@ bitOrDistinct
846915 -> Expression tables ('Grouped bys) params (nullity int)
847916bitOrDistinct = unsafeAggregateDistinct "bit_or"
848917
849−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ boolAnd #col
918+-- | :{
919+-- let
920+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGbool]] grouping params (nullity 'PGbool)
921+-- expression = boolAnd #col
922+-- in renderExpression expression
923+-- :}
850924-- "bool_and(col)"
851925boolAnd
852926 :: Expression tables 'Ungrouped params (nullity 'PGbool)
@@ -854,7 +928,12 @@ boolAnd
854928 -> Expression tables ('Grouped bys) params (nullity 'PGbool)
855929boolAnd = unsafeAggregate "bool_and"
856930
857−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ boolOr #col
931+-- | :{
932+-- let
933+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGbool]] grouping params (nullity 'PGbool)
934+-- expression = boolOr #col
935+-- in renderExpression expression
936+-- :}
858937-- "bool_or(col)"
859938boolOr
860939 :: Expression tables 'Ungrouped params (nullity 'PGbool)
@@ -862,7 +941,12 @@ boolOr
862941 -> Expression tables ('Grouped bys) params (nullity 'PGbool)
863942boolOr = unsafeAggregate "bool_or"
864943
865−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ boolAndDistinct #col
944+-- | :{
945+-- let
946+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGbool]] grouping params (nullity 'PGbool)
947+-- expression = boolAndDistinct #col
948+-- in renderExpression expression
949+-- :}
866950-- "bool_and(DISTINCT col)"
867951boolAndDistinct
868952 :: Expression tables 'Ungrouped params (nullity 'PGbool)
@@ -870,7 +954,12 @@ boolAndDistinct
870954 -> Expression tables ('Grouped bys) params (nullity 'PGbool)
871955boolAndDistinct = unsafeAggregateDistinct "bool_and"
872956
873−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ boolOrDistinct #col
957+-- | :{
958+-- let
959+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGbool]] grouping params (nullity 'PGbool)
960+-- expression = boolOrDistinct #col
961+-- in renderExpression expression
962+-- :}
874963-- "bool_or(DISTINCT col)"
875964boolOrDistinct
876965 :: Expression tables 'Ungrouped params (nullity 'PGbool)
@@ -886,25 +975,40 @@ countStar
886975 :: Expression tables ('Grouped bys) params ('NotNull 'PGint8)
887976countStar = UnsafeExpression $ "count(*)"
888977
889−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Optional _]] $ count #col
978+-- | :{
979+-- let
980+-- expression :: Expression [tab ::: ["col" ::: nullity ty]] grouping params (nullity 'PGbool)
981+-- expression = count #col
982+-- in renderExpression expression
983+-- :}
890984-- "count(col)"
891985count
892− :: Expression tables 'Ungrouped params (ty)
986+ :: Expression tables 'Ungrouped params ty
893987 -- ^ what to count
894988 -> Expression tables ('Grouped bys) params ('NotNull 'PGint8)
895989count = unsafeAggregate "count"
896990
897−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required _]] $ countDistinct #col
991+-- | :{
992+-- let
993+-- expression :: Expression [tab ::: ["col" ::: nullity ty]] grouping params (nullity 'PGbool)
994+-- expression = countDistinct #col
995+-- in renderExpression expression
996+-- :}
898997-- "count(DISTINCT col)"
899998countDistinct
900− :: Expression tables 'Ungrouped params (ty)
999+ :: Expression tables 'Ungrouped params ty
9011000 -- ^ what to count
9021001 -> Expression tables ('Grouped bys) params ('NotNull 'PGint8)
9031002countDistinct = unsafeAggregateDistinct "count"
9041003
9051004-- | synonym for `boolAnd`
9061005--
907−-- >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ every #col
1006+-- :{
1007+-- let
1008+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGbool]] grouping params (nullity 'PGbool)
1009+-- expression = every #col
1010+-- in renderExpression expression
1011+-- :}
9081012-- "every(col)"
9091013every
9101014 :: Expression tables 'Ungrouped params (nullity 'PGbool)
@@ -914,7 +1018,12 @@ every = unsafeAggregate "every"
9141018
9151019-- | synonym for `boolAndDistinct`
9161020--
917−-- >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ everyDistinct #col
1021+-- :{
1022+-- let
1023+-- expression :: Expression [tab ::: ["col" ::: nullity 'PGbool]] grouping params (nullity 'PGbool)
1024+-- expression = everyDistinct #col
1025+-- in renderExpression expression
1026+-- :}
9181027-- "every(DISTINCT col)"
9191028everyDistinct
9201029 :: Expression tables 'Ungrouped params (nullity 'PGbool)
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+117−53
@@ -30,14 +30,20 @@ module Squeal.PostgreSQL.Manipulation
3030 , queryStatement
3131 -- * Insert
3232 , insertRows
33+ , insertRow
34+ , insertRows_
35+ , insertRow_
3336 , insertQuery
37+ , insertQuery_
3438 , ReturningClause (ReturningStar, Returning)
3539 , renderReturningClause
3640 , ConflictClause (OnConflictDoRaise, OnConflictDoNothing, OnConflictDoUpdate)
3741 , renderConflictClause
3842 -- * Update
3943 , update
44+ , update_
4045 , deleteFrom
46+ , deleteFrom_
4147 , ColumnValue (..)
4248 ) where
4349
@@ -86,30 +92,27 @@ simple insert:
8692>>> :{
8793let
8894 manipulation :: Manipulation
89− '[ "tab" :::
90− '[ "col1" ::: 'Required ('NotNull 'PGint4)
91− , "col2" ::: 'Required ('NotNull 'PGint4) ]] '[] '[]
95+ '[ "tab" ::: '[] :=>
96+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
97+ , "col2" ::: 'Def :=> 'NotNull 'PGint4 ]] '[] '[]
9298 manipulation =
93− insertInto #tab (ColumnValues (2 `As` #col1 :* 4 `As` #col2 :* Nil) [])
94− OnConflictDoRaise (Returning Nil)
99+ insertRow_ #tab (Set 2 `As` #col1 :* Default `As` #col2 :* Nil)
95100in renderManipulation manipulation
96101:}
97−"INSERT INTO tab (col1, col2) VALUES (2, 4);"
102+"INSERT INTO tab (col1, col2) VALUES (2, DEFAULT);"
98103
99104parameterized insert:
100105
101106>>> :{
102107let
103108 manipulation :: Manipulation
104− '[ "tab" :::
105− '[ "col1" ::: 'Required ('NotNull 'PGint4)
106− , "col2" ::: 'Required ('NotNull 'PGint4) ]]
107− '[ 'Required ('NotNull 'PGint4)
108− , 'Required ('NotNull 'PGint4) ] '[]
109+ '[ "tab" ::: '[] :=>
110+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
111+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4 ]]
112+ '[ 'NotNull 'PGint4, 'NotNull 'PGint4 ] '[]
109113 manipulation =
110− insertInto #tab
111− (ColumnValues (param @1 `As` #col1 :* param @2 `As` #col2 :* Nil) [])
112− OnConflictDoRaise (Returning Nil)
114+ insertRow_ #tab
115+ (Set (param @1) `As` #col1 :* Set (param @2) `As` #col2 :* Nil)
113116in renderManipulation manipulation
114117:}
115118"INSERT INTO tab (col1, col2) VALUES (($1 :: int4), ($2 :: int4));"
@@ -119,36 +122,34 @@ returning insert:
119122>>> :{
120123let
121124 manipulation :: Manipulation
122− '[ "tab" :::
123− '[ "col1" ::: 'Required ('NotNull 'PGint4)
124− , "col2" ::: 'Required ('NotNull 'PGint4) ]] '[]
125− '["fromOnly" ::: 'Required ('NotNull 'PGint4)]
125+ '[ "tab" ::: '[] :=>
126+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
127+ , "col2" ::: 'Def :=> 'NotNull 'PGint4 ]] '[]
128+ '["fromOnly" ::: 'NotNull 'PGint4]
126129 manipulation =
127− insertInto #tab (ColumnValues (2 `As` #col1 :* 4 `As` #col2 :* Nil) [])
130+ insertRow #tab (Set 2 `As` #col1 :* Default `As` #col2 :* Nil)
128131 OnConflictDoRaise (Returning (#col1 `As` #fromOnly :* Nil))
129132in renderManipulation manipulation
130133:}
131−"INSERT INTO tab (col1, col2) VALUES (2, 4) RETURNING col1 AS fromOnly;"
134+"INSERT INTO tab (col1, col2) VALUES (2, DEFAULT) RETURNING col1 AS fromOnly;"
132135
133136query insert:
134137
135138>>> :{
136139let
137140 manipulation :: Manipulation
138− '[ "tab" :::
139− '[ "col1" ::: 'Required ('NotNull 'PGint4)
140− , "col2" ::: 'Required ('NotNull 'PGint4)
141+ '[ "tab" ::: '[] :=>
142+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
143+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4
141144 ]
142− , "other_tab" :::
143− '[ "col1" ::: 'Required ('NotNull 'PGint4)
144− , "col2" ::: 'Required ('NotNull 'PGint4)
145+ , "other_tab" ::: '[] :=>
146+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
147+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4
145148 ]
146149 ] '[] '[]
147150 manipulation =
148− insertInto #tab
149− ( ColumnValuesQuery $
150− selectStar (from (Table (#other_tab `As` #t))) )
151− OnConflictDoRaise (Returning Nil)
151+ insertQuery_ #tab
152+ (selectStar (from (Table (#other_tab `As` #t))))
152153in renderManipulation manipulation
153154:}
154155"INSERT INTO tab SELECT * FROM other_tab AS t;"
@@ -158,18 +159,17 @@ upsert:
158159>>> :{
159160let
160161 manipulation :: Manipulation
161− '[ "tab" :::
162− '[ "col1" ::: 'Required ('NotNull 'PGint4)
163− , "col2" ::: 'Required ('NotNull 'PGint4) ]]
164− '[] '[ "sum" ::: 'Required ('NotNull 'PGint4)]
162+ '[ "tab" ::: '[] :=>
163+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
164+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4 ]]
165+ '[] '[ "sum" ::: 'NotNull 'PGint4]
165166 manipulation =
166− insertInto #tab
167− (ColumnValues
168− (2 `As` #col1 :* 4 `As` #col2 :* Nil)
169− [6 `As` #col1 :* 8 `As` #col2 :* Nil])
167+ insertRows #tab
168+ (Set 2 `As` #col1 :* Set 4 `As` #col2 :* Nil)
169+ [Set 6 `As` #col1 :* Set 8 `As` #col2 :* Nil]
170170 (OnConflictDoUpdate
171171 (Set 2 `As` #col1 :* Same `As` #col2 :* Nil)
172− (Just (#col1 .== #col2)))
172+ [#col1 .== #col2])
173173 (Returning $ (#col1 + #col2) `As` #sum :* Nil)
174174in renderManipulation manipulation
175175:}
@@ -204,6 +204,39 @@ insertRows tab row rows conflict returning = UnsafeManipulation $
204204 Default -> "DEFAULT"
205205 Set expression -> renderExpression expression
206206
207+insertRow
208+ :: ( SOP.SListI columns
209+ , SOP.SListI results
210+ , Has tab schema table
211+ , columns ~ TableToColumns table )
212+ => Alias tab -- ^ table to insert into
213+ -> NP (Aliased (ColumnValue '[] params)) columns
214+ -> ConflictClause columns params
215+ -- ^ what to do in case of constraint conflict
216+ -> ReturningClause columns params results -- ^ results to return
217+ -> Manipulation schema params results
218+insertRow tab row = insertRows tab row []
219+
220+insertRows_
221+ :: ( SOP.SListI columns
222+ , Has tab schema table
223+ , columns ~ TableToColumns table )
224+ => Alias tab -- ^ table to insert into
225+ -> NP (Aliased (ColumnValue '[] params)) columns
226+ -> [NP (Aliased (ColumnValue '[] params)) columns]
227+ -> Manipulation schema params '[]
228+insertRows_ tab row rows =
229+ insertRows tab row rows OnConflictDoRaise (Returning Nil)
230+
231+insertRow_
232+ :: ( SOP.SListI columns
233+ , Has tab schema table
234+ , columns ~ TableToColumns table )
235+ => Alias tab -- ^ table to insert into
236+ -> NP (Aliased (ColumnValue '[] params)) columns
237+ -> Manipulation schema params '[]
238+insertRow_ tab row = insertRow tab row OnConflictDoRaise (Returning Nil)
239+
207240insertQuery
208241 :: ( SOP.SListI columns
209242 , SOP.SListI results
@@ -221,6 +254,16 @@ insertQuery tab query conflict returning = UnsafeManipulation $
221254 <> renderConflictClause conflict
222255 <> renderReturningClause returning
223256
257+insertQuery_
258+ :: ( SOP.SListI columns
259+ , Has tab schema table
260+ , columns ~ TableToColumns table )
261+ => Alias tab -- ^ table to insert into
262+ -> Query schema params (ColumnsToRelation columns)
263+ -> Manipulation schema params '[]
264+insertQuery_ tab query =
265+ insertQuery tab query OnConflictDoRaise (Returning Nil)
266+
224267data ColumnValue
225268 (columns :: RelationType)
226269 (params :: [NullityType])
@@ -248,11 +291,11 @@ data ReturningClause
248291 (results :: RelationType)
249292 where
250293 ReturningStar
251− :: ReturningClause columns params (ColumnsToRelation columns)
294+ :: results ~ ColumnsToRelation columns
295+ => ReturningClause columns params results
252296 Returning
253− :: NP
254− (Aliased (Expression '[table ::: (ColumnsToRelation columns)] 'Ungrouped params))
255− results
297+ :: rel ~ ColumnsToRelation columns
298+ => NP (Aliased (Expression '[table ::: rel] 'Ungrouped params)) results
256299 -> ReturningClause columns params results
257300
258301-- | Render a `ReturningClause`.
@@ -314,12 +357,12 @@ UPDATE statements
314357-- >>> :{
315358-- let
316359-- manipulation :: Manipulation
317−-- '[ "tab" :::
318−-- '[ "col1" ::: 'Required ('NotNull 'PGint4)
319−-- , "col2" ::: 'Required ('NotNull 'PGint4) ]] '[] '[]
360+-- '[ "tab" ::: '[] :=>
361+-- '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
362+-- , "col2" ::: 'NoDef :=> 'NotNull 'PGint4 ]] '[] '[]
320363-- manipulation =
321−-- update #tab (Set 2 `As` #col1 :* Same `As` #col2 :* Nil)
322−-- (#col1 ./= #col2) (Returning Nil)
364+-- update_ #tab (Set 2 `As` #col1 :* Same `As` #col2 :* Nil)
365+-- (#col1 ./= #col2)
323366-- in renderManipulation manipulation
324367-- :}
325368-- "UPDATE tab SET col1 = 2 WHERE (col1 <> col2);"
@@ -353,6 +396,18 @@ update table columns wh returning = UnsafeManipulation $
353396 Set expression `As` column -> Just $
354397 renderAlias column <+> "=" <+> renderExpression expression
355398
399+update_
400+ :: ( SOP.SListI columns
401+ , Has tab schema table
402+ , columns ~ TableToColumns table )
403+ => Alias tab -- ^ table to update
404+ -> NP (Aliased (ColumnValue (ColumnsToRelation columns) params)) columns
405+ -- ^ modified values to replace old values
406+ -> Condition '[tab ::: ColumnsToRelation columns] 'Ungrouped params
407+ -- ^ condition under which to perform update on a row
408+ -> Manipulation schema params '[]
409+update_ table columns wh = update table columns wh (Returning Nil)
410+
356411{-----------------------------------------
357412DELETE statements
358413-----------------------------------------}
@@ -362,11 +417,11 @@ DELETE statements
362417-- >>> :{
363418-- let
364419-- manipulation :: Manipulation
365−-- '[ "tab" :::
366−-- '[ "col1" ::: 'Required ('NotNull 'PGint4)
367−-- , "col2" ::: 'Required ('NotNull 'PGint4) ]] '[]
368−-- '[ "col1" ::: 'Required ('NotNull 'PGint4)
369−-- , "col2" ::: 'Required ('NotNull 'PGint4) ]
420+-- '[ "tab" ::: '[] :=>
421+-- '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
422+-- , "col2" ::: 'NoDef :=> 'NotNull 'PGint4 ]] '[]
423+-- '[ "col1" ::: 'NotNull 'PGint4
424+-- , "col2" ::: 'NotNull 'PGint4 ]
370425-- manipulation = deleteFrom #tab (#col1 .== #col2) ReturningStar
371426-- in renderManipulation manipulation
372427-- :}
@@ -384,3 +439,12 @@ deleteFrom table wh returning = UnsafeManipulation $
384439 "DELETE FROM" <+> renderAlias table
385440 <+> "WHERE" <+> renderExpression wh
386441 <> renderReturningClause returning
442+
443+deleteFrom_
444+ :: ( Has tab schema table
445+ , columns ~ TableToColumns table )
446+ => Alias tab -- ^ table to delete from
447+ -> Condition '[tab ::: ColumnsToRelation columns] 'Ungrouped params
448+ -- ^ condition under which to delete a row
449+ -> Manipulation schema params '[]
450+deleteFrom_ tab wh = deleteFrom tab wh (Returning Nil)
squeal-postgresql/src/Squeal/PostgreSQL/PQ.hs+2−1
@@ -119,8 +119,9 @@ backslashes within the value must be escaped with a backslash, i.e., ' and \.
119119To specify the schema you wish to connect with, use type application.
120120
121121>>> :set -XDataKinds
122+>>> :set -XPolyKinds
122123>>> :set -XTypeOperators
123−>>> type Schema = '["tab" ::: Unconstraint :=> '["col" ::: 'NoDef :=> 'Null 'PGint2]]
124+>>> type Schema = '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint2]]
124125>>> :set -XTypeApplications
125126>>> :set -XOverloadedStrings
126127>>> conn <- connectdb @Schema "host=localhost port=5432 dbname=exampledb"
squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+54−71
@@ -77,7 +77,6 @@ import Data.Word
7777import Generics.SOP hiding (from)
7878import GHC.TypeLits
7979
80−import qualified Data.ByteString as ByteString
8180import qualified GHC.Generics as GHC
8281
8382import Squeal.PostgreSQL.Expression
@@ -94,8 +93,10 @@ simple query:
9493
9594>>> :{
9695let
97− query :: Query '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]] '[]
98− '["col" ::: 'Required ('Null 'PGint4)]
96+ query :: Query
97+ '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
98+ '[]
99+ '["col" ::: 'Null 'PGint4]
99100 query = selectStar (from (Table (#tab `As` #t)))
100101in renderQuery query
101102:}
@@ -106,12 +107,12 @@ restricted query:
106107>>> :{
107108let
108109 query :: Query
109− '[ "tab" :::
110− '[ "col1" ::: 'Required ('NotNull 'PGint4)
111− , "col2" ::: 'Required ('NotNull 'PGint4) ]]
110+ '[ "tab" ::: '[] :=>
111+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
112+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4 ]]
112113 '[]
113− '[ "sum" ::: 'Required ('NotNull 'PGint4)
114− , "col1" ::: 'Required ('NotNull 'PGint4) ]
114+ '[ "sum" ::: 'NotNull 'PGint4
115+ , "col1" ::: 'NotNull 'PGint4 ]
115116 query =
116117 select
117118 ((#col1 + #col2) `As` #sum :* #col1 `As` #col1 :* Nil)
@@ -126,8 +127,10 @@ subquery:
126127
127128>>> :{
128129let
129− query :: Query '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]] '[]
130− '["col" ::: 'Required ('Null 'PGint4)]
130+ query :: Query
131+ '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
132+ '[]
133+ '["col" ::: 'Null 'PGint4]
131134 query =
132135 selectStar
133136 (from (Subquery (selectStar (from (Table (#tab `As` #t))) `As` #sub)))
@@ -139,8 +142,10 @@ limits and offsets:
139142
140143>>> :{
141144let
142− query :: Query '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]] '[]
143− '["col" ::: 'Required ('Null 'PGint4)]
145+ query :: Query
146+ '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
147+ '[]
148+ '["col" ::: 'Null 'PGint4]
144149 query = selectStar
145150 (from (Table (#tab `As` #t)) & limit 100 & offset 2 & limit 50 & offset 2)
146151in renderQuery query
@@ -151,9 +156,10 @@ parameterized query:
151156
152157>>> :{
153158let
154− query :: Query '["tab" ::: '["col" ::: 'Required ('NotNull 'PGfloat8)]]
155− '[ 'Required ('NotNull 'PGfloat8)]
156− '["col" ::: 'Required ('NotNull 'PGfloat8)]
159+ query :: Query
160+ '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGfloat8]]
161+ '[ 'NotNull 'PGfloat8]
162+ '["col" ::: 'NotNull 'PGfloat8]
157163 query = selectStar
158164 (from (Table (#tab `As` #t)) & where_ (#col .> param @1))
159165in renderQuery query
@@ -165,12 +171,12 @@ aggregation query:
165171>>> :{
166172let
167173 query :: Query
168− '[ "tab" :::
169− '[ "col1" ::: 'Required ('NotNull 'PGint4)
170− , "col2" ::: 'Required ('NotNull 'PGint4) ]]
174+ '[ "tab" ::: '[] :=>
175+ '[ "col1" ::: 'NoDef :=> 'NotNull 'PGint4
176+ , "col2" ::: 'NoDef :=> 'NotNull 'PGint4 ]]
171177 '[]
172− '[ "sum" ::: 'Required ('NotNull 'PGint4)
173− , "col1" ::: 'Required ('NotNull 'PGint4) ]
178+ '[ "sum" ::: 'NotNull 'PGint4
179+ , "col1" ::: 'NotNull 'PGint4 ]
174180 query =
175181 select (sum_ #col2 `As` #sum :* #col1 `As` #col1 :* Nil)
176182 ( from (Table (#tab `As` #table1))
@@ -184,8 +190,10 @@ sorted query:
184190
185191>>> :{
186192let
187− query :: Query '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]] '[]
188− '["col" ::: 'Required ('Null 'PGint4)]
193+ query :: Query
194+ '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
195+ '[]
196+ '["col" ::: 'Null 'PGint4]
189197 query = selectStar
190198 (from (Table (#tab `As` #t)) & orderBy [#col & AscNullsFirst])
191199in renderQuery query
@@ -199,24 +207,29 @@ joins:
199207let
200208 query :: Query
201209 '[ "orders" :::
202− '[ "id" ::: 'Required ('NotNull 'PGint4)
203− , "price" ::: 'Required ('NotNull 'PGfloat4)
204− , "customer_id" ::: 'Required ('NotNull 'PGint4)
205− , "shipper_id" ::: 'Required ('NotNull 'PGint4)
210+ '["pk" ::: PrimaryKey '["id"]
211+ ,"fk_customer" ::: ForeignKey '["customer_id"] "customers" '["id"]
212+ ,"fk_shipper" ::: ForeignKey '["shipper_id"] "shippers" '["id"]] :=>
213+ '[ "id" ::: 'NoDef :=> 'NotNull 'PGint4
214+ , "price" ::: 'NoDef :=> 'NotNull 'PGfloat4
215+ , "customer_id" ::: 'NoDef :=> 'NotNull 'PGint4
216+ , "shipper_id" ::: 'NoDef :=> 'NotNull 'PGint4
206217 ]
207218 , "customers" :::
208− '[ "id" ::: 'Required ('NotNull 'PGint4)
209− , "name" ::: 'Required ('NotNull 'PGtext)
219+ '["pk" ::: PrimaryKey '["id"]] :=>
220+ '[ "id" ::: 'NoDef :=> 'NotNull 'PGint4
221+ , "name" ::: 'NoDef :=> 'NotNull 'PGtext
210222 ]
211223 , "shippers" :::
212− '[ "id" ::: 'Required ('NotNull 'PGint4)
213− , "name" ::: 'Required ('NotNull 'PGtext)
224+ '["pk" ::: PrimaryKey '["id"]] :=>
225+ '[ "id" ::: 'NoDef :=> 'NotNull 'PGint4
226+ , "name" ::: 'NoDef :=> 'NotNull 'PGtext
214227 ]
215228 ]
216229 '[]
217− '[ "order_price" ::: 'Required ('NotNull 'PGfloat4)
218− , "customer_name" ::: 'Required ('NotNull 'PGtext)
219− , "shipper_name" ::: 'Required ('NotNull 'PGtext)
230+ '[ "order_price" ::: 'NotNull 'PGfloat4
231+ , "customer_name" ::: 'NotNull 'PGtext
232+ , "shipper_name" ::: 'NotNull 'PGtext
220233 ]
221234 query = select
222235 ( #o ! #price `As` #order_price :*
@@ -235,8 +248,10 @@ self-join:
235248
236249>>> :{
237250let
238− query :: Query '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]] '[]
239− '["col" ::: 'Required ('Null 'PGint4)]
251+ query :: Query
252+ '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
253+ '[]
254+ '["col" ::: 'Null 'PGint4]
240255 query = selectDotStar #t1
241256 (from (Table (#tab `As` #t1) & CrossJoin (Table (#tab `As` #t2))))
242257in renderQuery query
@@ -247,8 +262,10 @@ set operations:
247262
248263>>> :{
249264let
250− query :: Query '["tab" ::: '["col" ::: 'Required ('Null 'PGint4)]] '[]
251− '["col" ::: 'Required ('Null 'PGint4)]
265+ query :: Query
266+ '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'Null 'PGint4]]
267+ '[]
268+ '["col" ::: 'Null 'PGint4]
252269 query =
253270 selectStar (from (Table (#tab `As` #t)))
254271 `unionAll`
@@ -619,9 +636,6 @@ data FromClause schema params tables where
619636 Subquery
620637 :: Aliased (Query schema params) table
621638 -> FromClause schema params '[table]
622− JoinRef
623− :: JoinRef schema tables
624− -> FromClause schema params tables
625639 CrossJoin
626640 :: FromClause schema params right
627641 -> FromClause schema params left
@@ -652,7 +666,6 @@ data FromClause schema params tables where
652666renderFromClause :: FromClause schema params tables -> ByteString
653667renderFromClause = \case
654668 Table table -> renderAliasedAs renderTable table
655− JoinRef joinRef -> renderJoinRef joinRef
656669 Subquery selection -> renderAliasedAs (parenthesized . renderQuery) selection
657670 CrossJoin right left ->
658671 renderFromClause left <+> "CROSS JOIN" <+> renderFromClause right
@@ -665,36 +678,6 @@ renderFromClause = \case
665678 renderFromClause left <+> op <+> renderFromClause right
666679 <+> "ON" <+> renderExpression on
667680
668−newtype JoinRef (schema :: TablesType) (relations :: RelationsType)
669− = UnsafeJoinRef { renderJoinRef :: ByteString }
670− deriving (GHC.Generic,Show,Eq,Ord,NFData)
671−
672−utilizing
673− :: ( Has left schema (constraints :=> lcols)
674− , ColumnsToRelation lcols ~ lrel
675− , Has right (TablesToRelations schema) rrel
676− , Has ref constraints ('ForeignKey lnames right rnames)
677− , All KnownSymbol lnames
678− , All KnownSymbol rnames
679− )
680− => (Alias right, NP Alias rnames)
681− -> Alias ref
682− -> (Alias left, NP Alias lnames)
683− -> JoinRef schema '[left ::: lrel,right ::: rrel]
684−utilizing (rtab,rcols) _ref (ltab,lcols) = UnsafeJoinRef $
685− lname <+> "JOIN" <+> rname <+> "ON" <+> refEq
686− where
687− lname = renderAlias ltab
688− rname = renderAlias rtab
689− eq1 lcol rcol = lname <> "." <> lcol <> " = " <> rname <> "." <> rcol
690− renderAliases :: All KnownSymbol names => NP Alias names -> [ByteString]
691− renderAliases = \case
692− Nil -> []
693− alias :* aliases -> renderAlias alias : renderAliases aliases
694− refEq = ByteString.intercalate " AND " $ zipWith eq1
695− (renderAliases lcols)
696− (renderAliases rcols)
697−
698681{-----------------------------------------
699682Grouping
700683-----------------------------------------}
squeal-postgresql/src/Squeal/PostgreSQL/Untitled-1new file+5
@@ -0,0 +1,5 @@
1+:{
2+type Schema0 = '["tab" ::: '[] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4]]
3+type Schema1 = '["tab" ::: '["positive" ::: 'Check ] :=> '["col" ::: 'NoDef :=> 'NotNull 'PGint4]]
4+let x = 'x'
5+:}