@@ -8,7 +8,7 @@ Stability: experimental
8Squeal expressions are the atoms used to build statements.
8Squeal expressions are the atoms used to build statements.
11−{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
11+{-# OPTIONS_GHC -fno-warn-redundant-constraints -fno-warn-unticked-promoted-constructors #-}
12{-# LANGUAGE
12{-# LANGUAGE
13 AllowAmbiguousTypes
13 AllowAmbiguousTypes
14 , ConstraintKinds
14 , ConstraintKinds
@@ -50,6 +50,7 @@ module Squeal.PostgreSQL.Expression
50 , unsafeBinaryOp
50 , unsafeBinaryOp
51 , unsafeUnaryOp
51 , unsafeUnaryOp
52 , unsafeFunction
52 , unsafeFunction
53+ , unsafeVariadicFunction
@@ -90,6 +91,7 @@ module Squeal.PostgreSQL.Expression
90 , PGarrayOf
91 , PGarrayOf
91 , PGjsonKey
92 , PGjsonKey
@@ -108,6 +110,10 @@ module Squeal.PostgreSQL.Expression
108 , toJsonb
110 , toJsonb
109 , arrayToJson
111 , arrayToJson
110 , rowToJson
112 , rowToJson
111 , jsonObjectKeys
117 , jsonObjectKeys
112 , jsonbObjectKeys
118 , jsonbObjectKeys
113 -- ** Aggregation
119 -- ** Aggregation
@@ -506,12 +512,13 @@ unsafeFunction fun x = UnsafeExpression $
506 fun <> parenthesized (renderExpression x)
512 fun <> parenthesized (renderExpression x)
508unsafeVariadicFunction
514unsafeVariadicFunction
509− :: ByteString
516+ => ByteString
510 -- ^ function
517 -- ^ function
511− -> [Expression schema relations grouping params xty]
518+ -> NP (Expression schema relations grouping params) elems
512− -> Expression schema relations grouping params (yty)
519+ -> Expression schema relations grouping params ret
513unsafeVariadicFunction fun x = UnsafeExpression $
520unsafeVariadicFunction fun x = UnsafeExpression $
514− fun <> parenthesized (commaSeparated (map renderExpression x))
521+ fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderExpression) x)))
516instance PGNum ty
523instance PGNum ty
517 => Num (Expression schema relations grouping params (nullity ty)) where
524 => Num (Expression schema relations grouping params (nullity ty)) where
@@ -902,132 +909,119 @@ like
902like = unsafeBinaryOp "LIKE"
909like = unsafeBinaryOp "LIKE"
904{-----------------------------------------
911{-----------------------------------------
905−json and jsonb operators
912+ -- json and jsonb support
906−see https://www.postgresql.org/docs/10/static/functions-json.html
914+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
915+comments lifted directly from this page.
917+Table 9.44: json and jsonb operators
907-----------------------------------------}
918-----------------------------------------}
909type PGjsonKey key = key `In` '[ 'PGint2, 'PGint4, 'PGtext ]
920type PGjsonKey key = key `In` '[ 'PGint2, 'PGint4, 'PGtext ]
911type PGjson_ json = json `In` '[ 'PGjson, 'PGjsonb ]
922type PGjson_ json = json `In` '[ 'PGjson, 'PGjsonb ]
913−type Placeholder k
924+type Placeholder k = 'Text "(_::" :<>: 'ShowType k :<>: 'Text ")"
916− ':<>: 'ShowType k ':<>:
919−type ErrArrayOf arr ty = arr ':<>: 'Text " " ':<>: ty
925+type ErrArrayOf arr ty = arr :<>: 'Text " " :<>: ty
920−type ErrPGfixarrayOf t = ErrArrayOf ('ShowType 'PGfixarray ':<>: 'Text " " ':<>: Placeholder Nat) t
926+type ErrPGfixarrayOf t = ErrArrayOf ('ShowType 'PGfixarray :<>: 'Text " " :<>: Placeholder Nat) t
921type ErrPGvararrayOf t = ErrArrayOf ('ShowType 'PGvararray) t
927type ErrPGvararrayOf t = ErrArrayOf ('ShowType 'PGvararray) t
923−type family PGarray arr :: Constraint where
929+type family PGarray name arr :: Constraint where
924− PGarray ('PGvararray x) = ()
930+ PGarray name ('PGvararray x) = ()
925− PGarray ('PGfixarray n x) = ()
931+ PGarray name ('PGfixarray n x) = ()
926− PGarray val = TypeError
932+ PGarray name val = TypeError
927− ('Text "Unsatisfied PGarrayOf constraint. Expected either: "
933+ ('Text name :<>: 'Text ": Unsatisfied PGarrayOf constraint. Expected either: "
928− ':$$: 'Text " • " ':<>: ErrPGvararrayOf (Placeholder PGType)
934+ :$$: 'Text " • " :<>: ErrPGvararrayOf (Placeholder PGType)
929− ':$$: 'Text " • " ':<>: ErrPGfixarrayOf (Placeholder PGType)
935+ :$$: 'Text " • " :<>: ErrPGfixarrayOf (Placeholder PGType)
930− ':$$: 'Text "But got: " ':<>: 'ShowType val)
936+ :$$: 'Text "But got: " :<>: 'ShowType val)
932−type family PGarrayOf arr ty :: Constraint where
938+type family PGarrayOf name arr ty :: Constraint where
933− PGarrayOf ('PGvararray x) ty = x ~ ty
939+ PGarrayOf name ('PGvararray x) ty = x ~ ty
934− PGarrayOf ('PGfixarray n x) ty = x ~ ty
940+ PGarrayOf name ('PGfixarray n x) ty = x ~ ty
935− PGarrayOf val ty = TypeError
941+ PGarrayOf name val ty = TypeError
936− ('Text "Unsatisfied PGarrayOf constraint. Expected either: "
942+ ( 'Text name :<>: 'Text "Unsatisfied PGarrayOf constraint. Expected either: "
937− ':$$: 'Text " • " ':<>: ErrPGvararrayOf ('ShowType ty)
943+ :$$: 'Text " • " :<>: ErrPGvararrayOf ( 'ShowType ty )
938− ':$$: 'Text " • " ':<>: ErrPGfixarrayOf ('ShowType ty)
944+ :$$: 'Text " • " :<>: ErrPGfixarrayOf ( 'ShowType ty )
939− ':$$: 'Text "But got: " ':<>: 'ShowType val)
945+ :$$: 'Text "But got: " :<>: 'ShowType val)
941−type IsPGtextArray arr = PGarrayOf arr 'PGtext
947+type IsPGtextArray name arr = PGarrayOf name arr 'PGtext
943-- | Get JSON value (object field or array element) at a key.
949-- | Get JSON value (object field or array element) at a key.
945 :: (PGjson_ json, PGjsonKey key)
951 :: (PGjson_ json, PGjsonKey key)
946− => Expression schema relations grouping params (jnull json)
952+ => Expression schema relations grouping params (nullity json)
947− -> Expression schema relations grouping params (knull key)
953+ -> Expression schema relations grouping params (nullity key)
948 -> Expression schema relations grouping params ('Null json)
954 -> Expression schema relations grouping params ('Null json)
949(.->) = unsafeBinaryOp "->"
955(.->) = unsafeBinaryOp "->"
951-- | Get JSON value (object field or array element) at a key, as text.
957-- | Get JSON value (object field or array element) at a key, as text.
953 :: (PGjson_ json, PGjsonKey key)
959 :: (PGjson_ json, PGjsonKey key)
954− => Expression schema relations grouping params (jnull json)
960+ => Expression schema relations grouping params (nullity json)
955− -> Expression schema relations grouping params (knull key)
961+ -> Expression schema relations grouping params (nullity key)
956 -> Expression schema relations grouping params ('Null 'PGtext)
962 -> Expression schema relations grouping params ('Null 'PGtext)
957(.->>) = unsafeBinaryOp "->>"
963(.->>) = unsafeBinaryOp "->>"
959-- | Get JSON value at a specified path.
965-- | Get JSON value at a specified path.
961− :: (PGjson_ json, IsPGtextArray path)
967+ :: (PGjson_ json, IsPGtextArray "(.#>)" path)
962− => Expression schema relations grouping params (jnull json)
968+ => Expression schema relations grouping params (nullity json)
963− -> Expression schema relations grouping params (knull path)
969+ -> Expression schema relations grouping params (nullity path)
964 -> Expression schema relations grouping params ('Null json)
970 -> Expression schema relations grouping params ('Null json)
965(.#>) = unsafeBinaryOp "#>"
971(.#>) = unsafeBinaryOp "#>"
967-- | Get JSON value at a specified path as text.
973-- | Get JSON value at a specified path as text.
969− :: (PGjson_ json, IsPGtextArray path)
975+ :: (PGjson_ json, IsPGtextArray "(.#>>)" path)
970− => Expression schema relations grouping params (jnull json)
976+ => Expression schema relations grouping params (nullity json)
971− -> Expression schema relations grouping params (knull path)
977+ -> Expression schema relations grouping params (nullity path)
972 -> Expression schema relations grouping params ('Null 'PGtext)
978 -> Expression schema relations grouping params ('Null 'PGtext)
973(.#>>) = unsafeBinaryOp "#>>"
979(.#>>) = unsafeBinaryOp "#>>"
975-- Additional jsonb operators
981-- Additional jsonb operators
977−-- | Or operator for nulls; if either argument is null, then the result is null.
978−type family Null2 a b where
979− Null2 'Null a = 'Null
980− Null2 a 'Null = 'Null
981− Null2 'NotNull 'NotNull = 'NotNull
984−type family NullOfN xs where
985− NullOfN ('Null ty:xs) = 'Null
986− NullOfN (x:xs) = NullOfN xs
987− NullOfN '[] = 'NotNull
989-- | Does the left JSON value contain the right JSON path/value entries at the
983-- | Does the left JSON value contain the right JSON path/value entries at the
990-- top level?
984-- top level?
992− :: Expression schema relations grouping params (null0 'PGjsonb)
986+ :: Expression schema relations grouping params (nullity 'PGjsonb)
993− -> Expression schema relations grouping params (null1 'PGjsonb)
987+ -> Expression schema relations grouping params (nullity 'PGjsonb)
994− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
988+ -> Expression schema relations grouping params ('NotNull 'PGbool)
995(.@>) = unsafeBinaryOp "@>"
989(.@>) = unsafeBinaryOp "@>"
997-- | Are the left JSON path/value entries contained at the top level within the
991-- | Are the left JSON path/value entries contained at the top level within the
998-- right JSON value?
992-- right JSON value?
1000− :: Expression schema relations grouping params (null0 'PGjsonb)
994+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1001− -> Expression schema relations grouping params (null1 'PGjsonb)
995+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1002− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
996+ -> Expression schema relations grouping params ('NotNull 'PGbool)
1003(.<@) = unsafeBinaryOp "<@"
997(.<@) = unsafeBinaryOp "<@"
1005-- | Does the string exist as a top-level key within the JSON value?
999-- | Does the string exist as a top-level key within the JSON value?
1007− :: Expression schema relations grouping params (null0 'PGjsonb)
1001+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1008− -> Expression schema relations grouping params (null1 'PGtext)
1002+ -> Expression schema relations grouping params (nullity 'PGtext)
1009− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
1003+ -> Expression schema relations grouping params ('NotNull 'PGbool)
1010(.?) = unsafeBinaryOp "?"
1004(.?) = unsafeBinaryOp "?"
1012-- | Do any of these array strings exist as top-level keys?
1006-- | Do any of these array strings exist as top-level keys?
1014− :: Expression schema relations grouping params (null0 'PGjsonb)
1008+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1015− -> Expression schema relations grouping params (null1 ('PGvararray 'PGtext))
1009+ -> Expression schema relations grouping params (nullity ('PGvararray 'PGtext))
1016− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
1010+ -> Expression schema relations grouping params ('NotNull 'PGbool)
1017(.?|) = unsafeBinaryOp "?|"
1011(.?|) = unsafeBinaryOp "?|"
1019-- | Do all of these array strings exist as top-level keys?
1013-- | Do all of these array strings exist as top-level keys?
1021− :: Expression schema relations grouping params (null0 'PGjsonb)
1015+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1022− -> Expression schema relations grouping params (null1 ('PGvararray 'PGtext))
1016+ -> Expression schema relations grouping params (nullity ('PGvararray 'PGtext))
1023− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
1017+ -> Expression schema relations grouping params ('NotNull 'PGbool)
1024(.?&) = unsafeBinaryOp "?&"
1018(.?&) = unsafeBinaryOp "?&"
1026−-- | Concatenate two jsonb values into a new jsonb value
1020+-- | Concatenate two jsonb values into a new jsonb value.
1028− :: Expression schema relations grouping params (null0 'PGjsonb)
1022+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1029− -> Expression schema relations grouping params (null1 'PGjsonb)
1023+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1030− -> Expression schema relations grouping params (Null2 null0 null1 'PGjsonb)
1024+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1031(.||.) = unsafeBinaryOp "||"
1025(.||.) = unsafeBinaryOp "||"
1033-- | Delete a key or keys from a JSON object, or remove an array element.
1027-- | Delete a key or keys from a JSON object, or remove an array element.
@@ -1044,41 +1038,163 @@ type family NullOfN xs where
1044-- count from the end). Throws an error if top level container is not an array.
1038-- count from the end). Throws an error if top level container is not an array.
1046 :: (key `In` '[ 'PGtext, 'PGvararray 'PGtext, 'PGint4, 'PGint2 ]) -- hlint error without parens here
1040 :: (key `In` '[ 'PGtext, 'PGvararray 'PGtext, 'PGint4, 'PGint2 ]) -- hlint error without parens here
1047− => Expression schema relations grouping params (null0 'PGjsonb)
1041+ => Expression schema relations grouping params (nullity 'PGjsonb)
1048− -> Expression schema relations grouping params (null1 key)
1042+ -> Expression schema relations grouping params (nullity key)
1049− -> Expression schema relations grouping params (Null2 null0 null1 'PGjsonb)
1043+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1050(.-.) = unsafeBinaryOp "-"
1044(.-.) = unsafeBinaryOp "-"
1052-- | Delete the field or element with specified path (for JSON arrays, negative
1046-- | Delete the field or element with specified path (for JSON arrays, negative
1053-- integers count from the end)
1047-- integers count from the end)
1055− :: IsPGtextArray arrayty
1049+ :: IsPGtextArray "(#-.)" arrayty
1056− => Expression schema relations grouping params (null0 'PGjsonb)
1050+ => Expression schema relations grouping params (nullity 'PGjsonb)
1057− -> Expression schema relations grouping params (null1 arrayty)
1051+ -> Expression schema relations grouping params (nullity arrayty)
1058− -> Expression schema relations grouping params (Null2 null0 null1 'PGjsonb)
1052+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1059(#-.) = unsafeBinaryOp "#-"
1053(#-.) = unsafeBinaryOp "#-"
1055+{-----------------------------------------
1056+Table 9.45: JSON creation functions
1057+-----------------------------------------}
1059+-- | Returns the value as json. Arrays and composites are converted
1060+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1061+-- type to json, the cast function will be used to perform the conversion;
1062+-- otherwise, a scalar value is produced. For any scalar type other than a
1063+-- number, a Boolean, or a null value, the text representation will be used, in
1064+-- such a fashion that it is a valid json value.
1062 :: Expression schema relations grouping params (nullity ty)
1066 :: Expression schema relations grouping params (nullity ty)
1063 -> Expression schema relations grouping params (nullity 'PGjson)
1067 -> Expression schema relations grouping params (nullity 'PGjson)
1064toJson = unsafeFunction "to_json"
1068toJson = unsafeFunction "to_json"
1070+-- | Returns the value as jsonb. Arrays and composites are converted
1071+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1072+-- type to json, the cast function will be used to perform the conversion;
1073+-- otherwise, a scalar value is produced. For any scalar type other than a
1074+-- number, a Boolean, or a null value, the text representation will be used, in
1075+-- such a fashion that it is a valid jsonb value.
1067 :: Expression schema relations grouping params (nullity ty)
1077 :: Expression schema relations grouping params (nullity ty)
1068 -> Expression schema relations grouping params (nullity 'PGjsonb)
1078 -> Expression schema relations grouping params (nullity 'PGjsonb)
1069toJsonb = unsafeUnaryOp "to_jsonb"
1079toJsonb = unsafeUnaryOp "to_jsonb"
1081+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1082+-- becomes a JSON array of arrays. Line feeds will be added between dimension-1
1083+-- elements if pretty_bool is true.
1071arrayToJson
1084arrayToJson
1072− :: PGarray arr
1085+ :: PGarray "arrayToJson" arr
1073 => Expression schema relations grouping params (nullity arr)
1086 => Expression schema relations grouping params (nullity arr)
1074 -> Expression schema relations grouping params (nullity 'PGjson)
1087 -> Expression schema relations grouping params (nullity 'PGjson)
1075arrayToJson = unsafeFunction "array_to_json"
1088arrayToJson = unsafeFunction "array_to_json"
1090+-- | Returns the row as a JSON object. Line feeds will be added between level-1
1091+-- elements if pretty_bool is true.
1077rowToJson
1092rowToJson
1078 :: Expression schema relations grouping params (nullity ('PGcomposite ty))
1093 :: Expression schema relations grouping params (nullity ('PGcomposite ty))
1079 -> Expression schema relations grouping params (nullity 'PGjson)
1094 -> Expression schema relations grouping params (nullity 'PGjson)
1080rowToJson = unsafeFunction "row_to_json"
1095rowToJson = unsafeFunction "row_to_json"
1097+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1101+ => NP (Expression schema relations grouping params) elems
1102+ -> Expression schema relations grouping params (nullity 'PGjson)
1103+jsonBuildArray = unsafeVariadicFunction "json_build_array"
1105+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1106+-- variadic argument list.
1109+ => NP (Expression schema relations grouping params) elems
1110+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1111+jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1113+type family PGobjectpairs name x :: Constraint where
1114+ PGobjectpairs name ('NotNull 'PGtext : nullity arg : xs) = PGobjectpairs name xs
1115+ PGobjectpairs name '[] = ()
1116+ PGobjectpairs name (x:xs) = TypeError
1117+ ( 'Text name :<>: 'Text ": Incorrect argument list:"
1118+ :$$: 'Text "Expected alternating list of keys and values."
1119+ :$$: 'Text "But got " :<>: 'ShowType (x:xs))
1121+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1122+-- argument list. The elements of the argument list must alternate between text
1125+ :: (PGobjectpairs "jsonBuildObject" elems, SListI elems)
1126+ => NP (Expression schema relations grouping params) elems
1127+ -> Expression schema relations grouping params (nullity 'PGjson)
1128+jsonBuildObject = unsafeVariadicFunction "json_build_object"
1130+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1131+-- variadic argument list. The elements of the argument list must alternate
1132+-- between text and values.
1134+ :: (PGobjectpairs "jsonbBuildObject" elems, SListI elems)
1135+ => NP (Expression schema relations grouping params) elems
1136+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1137+jsonbBuildObject = unsafeVariadicFunction "jsonb_build_object"
1139+-- | Builds a JSON object out of a text array. The array must have either
1140+-- exactly one dimension with an even number of members, in which case they are
1141+-- taken as alternating key/value pairs, or two dimensions such that each inner
1142+-- array has exactly two elements, which are taken as a key/value pair.
1144+ :: PGarrayOf "jsonObject" arr 'PGtext
1145+ => Expression schema relations grouping params (nullity arr)
1146+ -> Expression schema relations grouping params (nullity 'PGjson)
1147+jsonObject = unsafeFunction "json_object"
1149+-- | Builds a binary JSON object out of a text array. The array must have either
1150+-- exactly one dimension with an even number of members, in which case they are
1151+-- taken as alternating key/value pairs, or two dimensions such that each inner
1152+-- array has exactly two elements, which are taken as a key/value pair.
1154+ :: PGarrayOf "jsonbObject" arr 'PGtext
1155+ => Expression schema relations grouping params (nullity arr)
1156+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1157+jsonbObject = unsafeFunction "jsonb_object"
1159+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1160+-- keys and one for values, that are zipped pairwise to create a JSON object.
1162+ :: ( PGarrayOf "jsonZipObject" keysArray 'PGtext
1163+ , PGarrayOf "jsonZipObject" valuesArray 'PGtext)
1164+ => Expression schema relations grouping params (nullity keysArray)
1165+ -> Expression schema relations grouping params (nullity valuesArray)
1166+ -> Expression schema relations grouping params (nullity 'PGjson)
1167+jsonZipObject ks vs =
1168+ unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1170+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1171+-- keys and one for values, that are zipped pairwise to create a binary JSON
1174+ :: ( PGarrayOf "jsonbZipObject" keysArray 'PGtext
1175+ , PGarrayOf "jsonbZipObject" valuesArray 'PGtext)
1176+ => Expression schema relations grouping params (nullity keysArray)
1177+ -> Expression schema relations grouping params (nullity valuesArray)
1178+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1179+jsonbZipObject ks vs =
1180+ unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1182+{-----------------------------------------
1183+Table 9.46: JSON processing functions
1184+-----------------------------------------}
1186+-- | Returns the number of elements in the outermost JSON array.
1188+ :: Expression schema relations grouping params (nullity 'PGjson)
1189+ -> Expression schema relations grouping params (nullity 'PGint4)
1190+jsonArrayLength = unsafeFunction "json_array_length"
1192+-- | Returns the number of elements in the outermost binary JSON array.
1194+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1195+ -> Expression schema relations grouping params (nullity 'PGint4)
1196+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1082jsonObjectKeys
1198jsonObjectKeys
1083 :: Expression schema relations grouping params (nullity 'PGjson)
1199 :: Expression schema relations grouping params (nullity 'PGjson)
1084 -> Expression schema relations grouping params (nullity 'PGtext)
1200 -> Expression schema relations grouping params (nullity 'PGtext)
@@ -1089,10 +1205,6 @@ jsonbObjectKeys
1089 -> Expression schema relations grouping params (nullity 'PGtext)
1205 -> Expression schema relations grouping params (nullity 'PGtext)
1090jsonbObjectKeys = unsafeFunction "jsonb_object_keys"
1206jsonbObjectKeys = unsafeFunction "jsonb_object_keys"
1092−-- TODO: jsonBuildArray, jsonbBuildArray, jsonObject, jsonbObject
1093−-- probably something like
1094−-- :: NP (Expression s r g p) xs -> Expression s r g p ('NotNull 'PGjson[b])
1096{-----------------------------------------
1208{-----------------------------------------
1097aggregation
1209aggregation
1098-----------------------------------------}
1210-----------------------------------------}