on dev help sign in
move json stuff
commit880eb7f24adde2f5e781a2b0c1910b75aadd9219 authorEitan Chatav <eitan@Eitans-MacBook-Pro.local> dateFri 12 Apr 2019, 14:46 (8 years ago) parentcc7dadc
2 files changed+176−174
squeal-postgresql/src/Squeal/PostgreSQL/Expression/Json.hs+176 squeal-postgresql/src/Squeal/PostgreSQL/Query.hs−174
squeal-postgresql/src/Squeal/PostgreSQL/Expression/Json.hs+176
@@ -2,6 +2,8 @@
22 DataKinds
33 , FlexibleContexts
44 , FlexibleInstances
5+ , GADTs
6+ , OverloadedLabels
57 , OverloadedStrings
68 , PolyKinds
79 , TypeOperators
@@ -47,14 +49,40 @@ module Squeal.PostgreSQL.Expression.Json
4749 , jsonbSet
4850 , jsonbInsert
4951 , jsonbPretty
52+ -- * Json and Jsonb set returning functions
53+ , jsonEach
54+ , jsonbEach
55+ , jsonEachText
56+ , jsonbEachText
57+ , jsonObjectKeys
58+ , jsonbObjectKeys
59+ , jsonPopulateRecord
60+ , jsonbPopulateRecord
61+ , jsonPopulateRecordSet
62+ , jsonbPopulateRecordSet
63+ , jsonToRecord
64+ , jsonbToRecord
65+ , jsonToRecordSet
66+ , jsonbToRecordSet
5067 ) where
5168
69+import Data.ByteString (ByteString)
70+import GHC.TypeLits
71+
72+import Squeal.PostgreSQL.Alias
5273import Squeal.PostgreSQL.Expression
74+import Squeal.PostgreSQL.Expression.SetOf
75+import Squeal.PostgreSQL.Expression.Type
5376import Squeal.PostgreSQL.List
77+import Squeal.PostgreSQL.Query
78+import Squeal.PostgreSQL.Render
5479import Squeal.PostgreSQL.Schema
5580
5681import qualified Generics.SOP as SOP
5782
83+-- $setup
84+-- >>> import Squeal.PostgreSQL
85+
5886{-----------------------------------------
5987 -- json and jsonb support
6088
@@ -346,3 +374,151 @@ jsonbInsert tgt path val insertAfter = case insertAfter of
346374-- | Returns its argument as indented JSON text.
347375jsonbPretty :: null 'PGjsonb :--> null 'PGtext
348376jsonbPretty = unsafeFunction "jsonb_pretty"
377+
378+
379+-- | Expands the outermost JSON object into a set of key/value pairs.
380+-- >>> import Data.Aeson
381+-- >>> printSQL (select Star (from (jsonEach (literal (Json (object ["a" .= "foo", "b" .= "bar"]))))))
382+-- SELECT * FROM json_each(('{"a":"foo","b":"bar"}' :: json))
383+jsonEach
384+ :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
385+ -> FromClause outer commons schemas params
386+ '["json_each" ::: '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGjson]]
387+jsonEach = unsafeSetOfFunction "json_each"
388+
389+-- | Expands the outermost binary JSON object into a set of key/value pairs.
390+-- >>> import Data.Aeson
391+-- >>> printSQL (select Star (from (jsonbEach (literal (Jsonb (object ["a" .= "foo", "b" .= "bar"]))))))
392+-- SELECT * FROM jsonb_each(('{"a":"foo","b":"bar"}' :: jsonb))
393+jsonbEach
394+ :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
395+ -> FromClause outer commons schemas params
396+ '["jsonb_each" ::: '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGjson]]
397+jsonbEach = unsafeSetOfFunction "jsonb_each"
398+
399+-- | Expands the outermost JSON object into a set of key/value pairs.-- | Expands the outermost binary JSON object into a set of key/value pairs.
400+-- >>> import Data.Aeson
401+-- >>> printSQL (select Star (from (jsonEachText (literal (Json (object ["a" .= "foo", "b" .= "bar"]))))))
402+-- SELECT * FROM json_each_text(('{"a":"foo","b":"bar"}' :: json))
403+jsonEachText
404+ :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
405+ -> FromClause outer commons schemas params
406+ '["json_each" ::: '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGtext]]
407+jsonEachText = unsafeSetOfFunction "json_each_text"
408+
409+-- | Expands the outermost binary JSON object into a set of key/value pairs.
410+-- >>> import Data.Aeson
411+-- >>> printSQL (select Star (from (jsonbEachText (literal (Jsonb (object ["a" .= "foo", "b" .= "bar"]))))))
412+-- SELECT * FROM jsonb_each_text(('{"a":"foo","b":"bar"}' :: jsonb))
413+jsonbEachText
414+ :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
415+ -> FromClause outer commons schemas params
416+ '["jsonb_each" ::: '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGtext]]
417+jsonbEachText = unsafeSetOfFunction "jsonb_each_text"
418+
419+-- | Returns set of keys in the outermost JSON object.
420+-- >>> import Data.Aeson
421+-- >>> printSQL (jsonObjectKeys (literal (Json (object ["a" .= "foo", "b" .= "bar"]))))
422+-- json_object_keys(('{"a":"foo","b":"bar"}' :: json))
423+jsonObjectKeys
424+ :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
425+ -> FromClause outer commons schemas params
426+ '["json_object_keys" ::: '["json_object_keys" ::: 'NotNull 'PGtext]]
427+jsonObjectKeys = unsafeSetOfFunction "json_object_keys"
428+
429+-- | Returns set of keys in the outermost JSON object.
430+-- >>> import Data.Aeson
431+-- >>> printSQL (jsonbObjectKeys (literal (Jsonb (object ["a" .= "foo", "b" .= "bar"]))))
432+-- jsonb_object_keys(('{"a":"foo","b":"bar"}' :: jsonb))
433+jsonbObjectKeys
434+ :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
435+ -> FromClause outer commons schemas params
436+ '["jsonb_object_keys" ::: '["jsonb_object_keys" ::: 'NotNull 'PGtext]]
437+jsonbObjectKeys = unsafeSetOfFunction "jsonb_object_keys"
438+
439+unsafePopulateFunction
440+ :: KnownSymbol fun
441+ => Alias fun
442+ -> TypeExpression schemas (nullity ('PGcomposite row))
443+ -> Expression outer commons 'Ungrouped schemas params '[] ty
444+ -> FromClause outer commons schemas params '[fun ::: row]
445+unsafePopulateFunction fun ty expr = UnsafeFromClause $ renderSQL fun
446+ <> parenthesized ("null::" <> renderSQL ty <> ", " <> renderSQL expr)
447+
448+-- | Expands the JSON expression to a row whose columns match the record
449+-- type defined by the given table.
450+jsonPopulateRecord
451+ :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
452+ -> Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
453+ -> FromClause outer commons schemas params '["json_populate_record" ::: row]
454+jsonPopulateRecord = unsafePopulateFunction #json_populate_record
455+
456+-- | Expands the binary JSON expression to a row whose columns match the record
457+-- type defined by the given table.
458+jsonbPopulateRecord
459+ :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
460+ -> Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
461+ -> FromClause outer commons schemas params '["jsonb_populate_record" ::: row]
462+jsonbPopulateRecord = unsafePopulateFunction #jsonb_populate_record
463+
464+-- | Expands the outermost array of objects in the given JSON expression to a
465+-- set of rows whose columns match the record type defined by the given table.
466+jsonPopulateRecordSet
467+ :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
468+ -> Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json array
469+ -> FromClause outer commons schemas params '["json_populate_record_set" ::: row]
470+jsonPopulateRecordSet = unsafePopulateFunction #json_populate_record_set
471+
472+-- | Expands the outermost array of objects in the given binary JSON expression
473+-- to a set of rows whose columns match the record type defined by the given
474+-- table.
475+jsonbPopulateRecordSet
476+ :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
477+ -> Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb array
478+ -> FromClause outer commons schemas params '["jsonb_populate_record_set" ::: row]
479+jsonbPopulateRecordSet = unsafePopulateFunction #jsonb_populate_record_set
480+
481+unsafeRecordFunction
482+ :: (SOP.SListI record, json `In` PGJsonType)
483+ => ByteString
484+ -> Expression outer commons 'Ungrouped schemas params '[] (nullity json)
485+ -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
486+ -> FromClause outer commons schemas params '[tab ::: record]
487+unsafeRecordFunction fun expr (types `As` tab) = UnsafeFromClause $
488+ fun <> parenthesized (renderSQL expr) <+> "AS" <+> renderSQL tab
489+ <> parenthesized (renderCommaSeparated renderTy types)
490+ where
491+ renderTy :: Aliased (TypeExpression schemas) ty -> ByteString
492+ renderTy (ty `As` alias) = renderSQL alias <+> renderSQL ty
493+
494+-- | Builds an arbitrary record from a JSON object.
495+jsonToRecord
496+ :: SOP.SListI record
497+ => Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
498+ -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
499+ -> FromClause outer commons schemas params '[tab ::: record]
500+jsonToRecord = unsafeRecordFunction "json_to_record"
501+
502+-- | Builds an arbitrary record from a binary JSON object.
503+jsonbToRecord
504+ :: SOP.SListI record
505+ => Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
506+ -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
507+ -> FromClause outer commons schemas params '[tab ::: record]
508+jsonbToRecord = unsafeRecordFunction "jsonb_to_record"
509+
510+-- | Builds an arbitrary set of records from a JSON array of objects.
511+jsonToRecordSet
512+ :: SOP.SListI record
513+ => Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json array
514+ -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
515+ -> FromClause outer commons schemas params '[tab ::: record]
516+jsonToRecordSet = unsafeRecordFunction "json_to_record_set"
517+
518+-- | Builds an arbitrary set of records from a binary JSON array of objects.
519+jsonbToRecordSet
520+ :: SOP.SListI record
521+ => Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb array
522+ -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
523+ -> FromClause outer commons schemas params '[tab ::: record]
524+jsonbToRecordSet = unsafeRecordFunction "jsonb_to_record_set"
squeal-postgresql/src/Squeal/PostgreSQL/Query.hs−174
@@ -53,21 +53,6 @@ module Squeal.PostgreSQL.Query
5353 -- ** With
5454 , With (..)
5555 , CommonTableExpression (..)
56− -- ** Json
57− , jsonEach
58− , jsonbEach
59− , jsonEachText
60− , jsonbEachText
61− , jsonObjectKeys
62− , jsonbObjectKeys
63− , jsonPopulateRecord
64− , jsonbPopulateRecord
65− , jsonPopulateRecordSet
66− , jsonbPopulateRecordSet
67− , jsonToRecord
68− , jsonbToRecord
69− , jsonToRecordSet
70− , jsonbToRecordSet
7156 -- * Table Expressions
7257 , TableExpression (..)
7358 , from
@@ -107,7 +92,6 @@ import Squeal.PostgreSQL.Alias
10792import Squeal.PostgreSQL.Expression
10893import Squeal.PostgreSQL.Expression.Logic
10994import Squeal.PostgreSQL.Expression.Sort
110−import Squeal.PostgreSQL.Expression.Type
11195import Squeal.PostgreSQL.Expression.Window
11296import Squeal.PostgreSQL.List
11397import Squeal.PostgreSQL.PG
@@ -713,164 +697,6 @@ offset
713697 -> TableExpression outer commons grp schemas params from
714698offset off rels = rels {offsetClause = off : offsetClause rels}
715699
716−{-----------------------------------------
717−JSON stuff
718−-----------------------------------------}
719−
720−unsafeSetOfFunction
721− :: ByteString
722− -> Expression outer commons 'Ungrouped schemas params '[] ty
723− -> FromClause outer commons schemas params from
724−unsafeSetOfFunction fun expr = UnsafeFromClause $
725− fun <> "(" <> renderSQL expr <> ")"
726−
727−-- | Expands the outermost JSON object into a set of key/value pairs.
728−-- >>> import Data.Aeson
729−-- >>> printSQL (select Star (from (jsonEach (literal (Json (object ["a" .= "foo", "b" .= "bar"]))))))
730−-- SELECT * FROM json_each(('{"a":"foo","b":"bar"}' :: json))
731−jsonEach
732− :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
733− -> FromClause outer commons schemas params
734− '["json_each" ::: '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGjson]]
735−jsonEach = unsafeSetOfFunction "json_each"
736−
737−-- | Expands the outermost binary JSON object into a set of key/value pairs.
738−-- >>> import Data.Aeson
739−-- >>> printSQL (select Star (from (jsonbEach (literal (Jsonb (object ["a" .= "foo", "b" .= "bar"]))))))
740−-- SELECT * FROM jsonb_each(('{"a":"foo","b":"bar"}' :: jsonb))
741−jsonbEach
742− :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
743− -> FromClause outer commons schemas params
744− '["jsonb_each" ::: '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGjson]]
745−jsonbEach = unsafeSetOfFunction "jsonb_each"
746−
747−-- | Expands the outermost JSON object into a set of key/value pairs.-- | Expands the outermost binary JSON object into a set of key/value pairs.
748−-- >>> import Data.Aeson
749−-- >>> printSQL (select Star (from (jsonEachText (literal (Json (object ["a" .= "foo", "b" .= "bar"]))))))
750−-- SELECT * FROM json_each_text(('{"a":"foo","b":"bar"}' :: json))
751−jsonEachText
752− :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
753− -> FromClause outer commons schemas params
754− '["json_each" ::: '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGtext]]
755−jsonEachText = unsafeSetOfFunction "json_each_text"
756−
757−-- | Expands the outermost binary JSON object into a set of key/value pairs.
758−-- >>> import Data.Aeson
759−-- >>> printSQL (select Star (from (jsonbEachText (literal (Jsonb (object ["a" .= "foo", "b" .= "bar"]))))))
760−-- SELECT * FROM jsonb_each_text(('{"a":"foo","b":"bar"}' :: jsonb))
761−jsonbEachText
762− :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
763− -> FromClause outer commons schemas params
764− '["jsonb_each" ::: '["key" ::: 'NotNull 'PGtext, "value" ::: 'NotNull 'PGtext]]
765−jsonbEachText = unsafeSetOfFunction "jsonb_each_text"
766−
767−-- | Returns set of keys in the outermost JSON object.
768−-- >>> import Data.Aeson
769−-- >>> printSQL (jsonObjectKeys (literal (Json (object ["a" .= "foo", "b" .= "bar"]))))
770−-- json_object_keys(('{"a":"foo","b":"bar"}' :: json))
771−jsonObjectKeys
772− :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
773− -> FromClause outer commons schemas params
774− '["json_object_keys" ::: '["json_object_keys" ::: 'NotNull 'PGtext]]
775−jsonObjectKeys = unsafeSetOfFunction "json_object_keys"
776−
777−-- | Returns set of keys in the outermost JSON object.
778−-- >>> import Data.Aeson
779−-- >>> printSQL (jsonbObjectKeys (literal (Jsonb (object ["a" .= "foo", "b" .= "bar"]))))
780−-- jsonb_object_keys(('{"a":"foo","b":"bar"}' :: jsonb))
781−jsonbObjectKeys
782− :: Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
783− -> FromClause outer commons schemas params
784− '["jsonb_object_keys" ::: '["jsonb_object_keys" ::: 'NotNull 'PGtext]]
785−jsonbObjectKeys = unsafeSetOfFunction "jsonb_object_keys"
786−
787−unsafePopulateFunction
788− :: KnownSymbol fun
789− => Alias fun
790− -> TypeExpression schemas (nullity ('PGcomposite row))
791− -> Expression outer commons 'Ungrouped schemas params '[] ty
792− -> FromClause outer commons schemas params '[fun ::: row]
793−unsafePopulateFunction fun ty expr = UnsafeFromClause $ renderSQL fun
794− <> parenthesized ("null::" <> renderSQL ty <> ", " <> renderSQL expr)
795−
796−-- | Expands the JSON expression to a row whose columns match the record
797−-- type defined by the given table.
798−jsonPopulateRecord
799− :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
800− -> Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
801− -> FromClause outer commons schemas params '["json_populate_record" ::: row]
802−jsonPopulateRecord = unsafePopulateFunction #json_populate_record
803−
804−-- | Expands the binary JSON expression to a row whose columns match the record
805−-- type defined by the given table.
806−jsonbPopulateRecord
807− :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
808− -> Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
809− -> FromClause outer commons schemas params '["jsonb_populate_record" ::: row]
810−jsonbPopulateRecord = unsafePopulateFunction #jsonb_populate_record
811−
812−-- | Expands the outermost array of objects in the given JSON expression to a
813−-- set of rows whose columns match the record type defined by the given table.
814−jsonPopulateRecordSet
815− :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
816− -> Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json array
817− -> FromClause outer commons schemas params '["json_populate_record_set" ::: row]
818−jsonPopulateRecordSet = unsafePopulateFunction #json_populate_record_set
819−
820−-- | Expands the outermost array of objects in the given binary JSON expression
821−-- to a set of rows whose columns match the record type defined by the given
822−-- table.
823−jsonbPopulateRecordSet
824− :: TypeExpression schemas (nullity ('PGcomposite row)) -- ^ row type
825− -> Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb array
826− -> FromClause outer commons schemas params '["jsonb_populate_record_set" ::: row]
827−jsonbPopulateRecordSet = unsafePopulateFunction #jsonb_populate_record_set
828−
829−unsafeRecordFunction
830− :: (SListI record, json `In` PGJsonType)
831− => ByteString
832− -> Expression outer commons 'Ungrouped schemas params '[] (nullity json)
833− -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
834− -> FromClause outer commons schemas params '[tab ::: record]
835−unsafeRecordFunction fun expr (types `As` tab) = UnsafeFromClause $
836− fun <> parenthesized (renderSQL expr) <+> "AS" <+> renderSQL tab
837− <> parenthesized (renderCommaSeparated renderTy types)
838− where
839− renderTy :: Aliased (TypeExpression schemas) ty -> ByteString
840− renderTy (ty `As` alias) = renderSQL alias <+> renderSQL ty
841−
842−-- | Builds an arbitrary record from a JSON object.
843−jsonToRecord
844− :: SListI record
845− => Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json object
846− -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
847− -> FromClause outer commons schemas params '[tab ::: record]
848−jsonToRecord = unsafeRecordFunction "json_to_record"
849−
850−-- | Builds an arbitrary record from a binary JSON object.
851−jsonbToRecord
852− :: SListI record
853− => Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb object
854− -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
855− -> FromClause outer commons schemas params '[tab ::: record]
856−jsonbToRecord = unsafeRecordFunction "jsonb_to_record"
857−
858−-- | Builds an arbitrary set of records from a JSON array of objects.
859−jsonToRecordSet
860− :: SListI record
861− => Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjson) -- ^ json array
862− -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
863− -> FromClause outer commons schemas params '[tab ::: record]
864−jsonToRecordSet = unsafeRecordFunction "json_to_record_set"
865−
866−-- | Builds an arbitrary set of records from a binary JSON array of objects.
867−jsonbToRecordSet
868− :: SListI record
869− => Expression outer commons 'Ungrouped schemas params '[] (nullity 'PGjsonb) -- ^ jsonb array
870− -> Aliased (NP (Aliased (TypeExpression schemas))) (tab ::: record)
871− -> FromClause outer commons schemas params '[tab ::: record]
872−jsonbToRecordSet = unsafeRecordFunction "jsonb_to_record_set"
873−
874700{-----------------------------------------
875701FROM clauses
876702-----------------------------------------}