public inbox for [email protected]help / color / mirror / Atom feed
[PATCH v15 2/7] Add pg_depend.refobjversion. 19+ messages / 6 participants [nested] [flat]
* [PATCH v15 2/7] Add pg_depend.refobjversion. @ 2019-05-28 18:16 Thomas Munro <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Thomas Munro @ 2019-05-28 18:16 UTC (permalink / raw) Provide a place for the version of referenced database objects to be recorded. Later commits will be able to use this to record dependencies on collation versions for indexes and perhaps more things later. Author: Thomas Munro Reviewed-by: Julien Rouhaud and Peter Eisentraut Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- doc/src/sgml/catalogs.sgml | 13 +++++++ src/backend/catalog/dependency.c | 11 +++--- src/backend/catalog/pg_depend.c | 28 ++++++++++++--- src/bin/initdb/initdb.c | 44 +++++++++++------------ src/include/catalog/dependency.h | 6 ++++ src/include/catalog/pg_depend.h | 3 ++ src/test/regress/expected/misc_sanity.out | 7 ++-- 7 files changed, 79 insertions(+), 33 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index c2d33c76e0..ad44c44530 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -2950,6 +2950,15 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </entry> </row> + <row> + <entry><structfield>refobjversion</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry> + An optional version for the referenced object; see text + </entry> + </row> + </tbody> </tgroup> </table> @@ -3116,6 +3125,10 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l must be satisfied. </para> + <para> + The only current use of <structfield>refobjversion</structfield> is to + record dependencies between indexes and collation versions. + </para> </sect1> diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index ffd52c1153..660033b9c1 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1603,7 +1603,8 @@ recordDependencyOnExpr(const ObjectAddress *depender, /* And record 'em */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -1690,7 +1691,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the self-dependencies with the appropriate direction */ if (!reverse_self) recordMultipleDependencies(depender, - self_addrs->refs, self_addrs->numrefs, + self_addrs->refs, NULL, + self_addrs->numrefs, self_behavior); else { @@ -1710,7 +1712,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the external dependencies */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -2682,7 +2685,7 @@ record_object_address_dependencies(const ObjectAddress *depender, { eliminate_duplicate_dependencies(referenced); recordMultipleDependencies(depender, - referenced->refs, referenced->numrefs, + referenced->refs, NULL, referenced->numrefs, behavior); } diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index 596dafe19c..b7beb2884e 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -44,7 +44,22 @@ recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior) { - recordMultipleDependencies(depender, referenced, 1, behavior); + recordMultipleDependencies(depender, referenced, NULL, 1, behavior); +} + +/* + * As recordDependencyOn(), but also capture a version string so that changes + * in the referenced object can be detected. The meaning of the version + * string depends on the referenced object. Currently it is used for + * detecting changes in collation versions. + */ +void +recordDependencyOnVersion(const ObjectAddress *depender, + const ObjectAddress *referenced, + const NameData *version, + DependencyType behavior) +{ + recordMultipleDependencies(depender, referenced, version, 1, behavior); } /* @@ -54,6 +69,7 @@ recordDependencyOn(const ObjectAddress *depender, void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const NameData *version, int nreferenced, DependencyType behavior) { @@ -79,8 +95,6 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Don't open indexes unless we need to make an update */ indstate = NULL; - memset(nulls, false, sizeof(nulls)); - for (i = 0; i < nreferenced; i++, referenced++) { /* @@ -94,6 +108,9 @@ recordMultipleDependencies(const ObjectAddress *depender, * Record the Dependency. Note we don't bother to check for * duplicate dependencies; there's no harm in them. */ + memset(nulls, false, sizeof(nulls)); + memset(values, 0, sizeof(values)); + values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); @@ -101,9 +118,12 @@ recordMultipleDependencies(const ObjectAddress *depender, values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); + if (version) + values[Anum_pg_depend_refobjversion - 1] = CStringGetTextDatum(version); + else + nulls[Anum_pg_depend_refobjversion - 1] = true; values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - tup = heap_form_tuple(dependDesc->rd_att, values, nulls); /* fetch index info only when we know we need it */ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a6577486ce..b7e01a4678 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1560,55 +1560,55 @@ setup_depend(FILE *cmdfd) "DELETE FROM pg_shdepend;\n\n", "VACUUM pg_shdepend;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_class;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_proc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_type;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_cast;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_constraint;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_conversion;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_attrdef;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_language;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_operator;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opclass;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opfamily;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_am;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amop;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amproc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_rewrite;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_trigger;\n\n", /* * restriction here to avoid pinning the public namespace */ - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_namespace " " WHERE nspname LIKE 'pg%';\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_parser;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_dict;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_template;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_config;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_collation;\n\n", "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' " " FROM pg_authid;\n\n", diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index ab5e92bdc6..7d9fc866b9 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -182,8 +182,14 @@ extern void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior); +extern void recordDependencyOnVersion(const ObjectAddress *depender, + const ObjectAddress *referenced, + const NameData *version, + DependencyType behavior); + extern void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const NameData *version, int nreferenced, DependencyType behavior); diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h index ccf0a98330..9f2e10d428 100644 --- a/src/include/catalog/pg_depend.h +++ b/src/include/catalog/pg_depend.h @@ -61,6 +61,9 @@ CATALOG(pg_depend,2608,DependRelationId) * field. See DependencyType in catalog/dependency.h. */ char deptype; /* see codes in dependency.h */ +#ifdef CATALOG_VARLEN + text refobjversion; /* version tracking, NULL if not used or unknown */ +#endif } FormData_pg_depend; /* ---------------- diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index 8538173ff8..41efb4a2c8 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -18,8 +18,8 @@ WHERE refclassid = 0 OR refobjid = 0 OR deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR (deptype != 'p' AND (classid = 0 OR objid = 0)) OR (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0)); - classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype ----------+-------+----------+------------+----------+-------------+--------- + classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion +---------+-------+----------+------------+----------+-------------+---------+--------------- (0 rows) -- **************** pg_shdepend **************** @@ -103,9 +103,10 @@ ORDER BY 1, 2; pg_class | relacl | aclitem[] pg_class | reloptions | text[] pg_class | relpartbound | pg_node_tree + pg_depend | refobjversion | text pg_index | indexprs | pg_node_tree pg_index | indpred | pg_node_tree pg_largeobject | data | bytea pg_largeobject_metadata | lomacl | aclitem[] -(11 rows) +(12 rows) -- 2.20.1 --bp/iNruPH9dso1Pn Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v15-0003-Implement-type-regcollation.patch" ^ permalink raw reply [nested|flat] 19+ messages in thread
* [PATCH v18 2/6] Add pg_depend.refobjversion. @ 2019-05-28 18:16 Thomas Munro <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Thomas Munro @ 2019-05-28 18:16 UTC (permalink / raw) Provide a place for the version of referenced database objects to be recorded. Later commits will be able to use this to record dependencies on collation versions for indexes and perhaps more things later. Author: Thomas Munro Reviewed-by: Julien Rouhaud, Peter Eisentraut and Michael Paquier Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- doc/src/sgml/catalogs.sgml | 12 ++++++- src/backend/catalog/dependency.c | 14 +++++--- src/backend/catalog/pg_depend.c | 14 +++++--- src/bin/initdb/initdb.c | 44 +++++++++++------------ src/include/catalog/dependency.h | 1 + src/include/catalog/pg_depend.h | 4 +++ src/include/catalog/toasting.h | 1 + src/test/regress/expected/misc_sanity.out | 4 +-- 8 files changed, 61 insertions(+), 33 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index dbfb525069..b2a125de78 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -2950,6 +2950,17 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </entry> </row> + <row> + <entry><structfield>refobjversion</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry> + An optional version for the referenced object. The only current use of + <structfield>refobjversion</structfield> is to record dependencies + between indexes and collation versions. + </entry> + </row> + </tbody> </tgroup> </table> @@ -3115,7 +3126,6 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l dependencies' restrictions about which objects must be dropped together must be satisfied. </para> - </sect1> diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index ffd52c1153..281f5b7c28 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1603,7 +1603,9 @@ recordDependencyOnExpr(const ObjectAddress *depender, /* And record 'em */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, + context.addrs->numrefs, + NULL, behavior); free_object_addresses(context.addrs); @@ -1690,7 +1692,9 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the self-dependencies with the appropriate direction */ if (!reverse_self) recordMultipleDependencies(depender, - self_addrs->refs, self_addrs->numrefs, + self_addrs->refs, + self_addrs->numrefs, + NULL, self_behavior); else { @@ -1710,7 +1714,9 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the external dependencies */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, + context.addrs->numrefs, + NULL, behavior); free_object_addresses(context.addrs); @@ -2682,7 +2688,7 @@ record_object_address_dependencies(const ObjectAddress *depender, { eliminate_duplicate_dependencies(referenced); recordMultipleDependencies(depender, - referenced->refs, referenced->numrefs, + referenced->refs, referenced->numrefs, NULL, behavior); } diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index 596dafe19c..84a0b99311 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -24,6 +24,7 @@ #include "catalog/pg_extension.h" #include "commands/extension.h" #include "miscadmin.h" +#include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/rel.h" @@ -44,7 +45,7 @@ recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior) { - recordMultipleDependencies(depender, referenced, 1, behavior); + recordMultipleDependencies(depender, referenced, 1, NULL, behavior); } /* @@ -55,6 +56,7 @@ void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, + const char *version, DependencyType behavior) { Relation dependDesc; @@ -79,8 +81,6 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Don't open indexes unless we need to make an update */ indstate = NULL; - memset(nulls, false, sizeof(nulls)); - for (i = 0; i < nreferenced; i++, referenced++) { /* @@ -94,6 +94,9 @@ recordMultipleDependencies(const ObjectAddress *depender, * Record the Dependency. Note we don't bother to check for * duplicate dependencies; there's no harm in them. */ + memset(nulls, false, sizeof(nulls)); + memset(values, 0, sizeof(values)); + values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); @@ -101,9 +104,12 @@ recordMultipleDependencies(const ObjectAddress *depender, values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); + if (version) + values[Anum_pg_depend_refobjversion - 1] = CStringGetTextDatum(version); + else + nulls[Anum_pg_depend_refobjversion - 1] = true; values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - tup = heap_form_tuple(dependDesc->rd_att, values, nulls); /* fetch index info only when we know we need it */ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a6577486ce..b7e01a4678 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1560,55 +1560,55 @@ setup_depend(FILE *cmdfd) "DELETE FROM pg_shdepend;\n\n", "VACUUM pg_shdepend;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_class;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_proc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_type;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_cast;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_constraint;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_conversion;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_attrdef;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_language;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_operator;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opclass;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opfamily;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_am;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amop;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amproc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_rewrite;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_trigger;\n\n", /* * restriction here to avoid pinning the public namespace */ - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_namespace " " WHERE nspname LIKE 'pg%';\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_parser;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_dict;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_template;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_config;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_collation;\n\n", "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' " " FROM pg_authid;\n\n", diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index ab5e92bdc6..62e86a19b6 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -185,6 +185,7 @@ extern void recordDependencyOn(const ObjectAddress *depender, extern void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, + const char *version, DependencyType behavior); extern void recordDependencyOnCurrentExtension(const ObjectAddress *object, diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h index ccf0a98330..7489022795 100644 --- a/src/include/catalog/pg_depend.h +++ b/src/include/catalog/pg_depend.h @@ -61,6 +61,10 @@ CATALOG(pg_depend,2608,DependRelationId) * field. See DependencyType in catalog/dependency.h. */ char deptype; /* see codes in dependency.h */ +#ifdef CATALOG_VARLEN + text refobjversion; /* version tracking, NULL if not used or + * unknown */ +#endif } FormData_pg_depend; /* ---------------- diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h index 8f131893dc..e320d82203 100644 --- a/src/include/catalog/toasting.h +++ b/src/include/catalog/toasting.h @@ -53,6 +53,7 @@ DECLARE_TOAST(pg_aggregate, 4159, 4160); DECLARE_TOAST(pg_attrdef, 2830, 2831); DECLARE_TOAST(pg_constraint, 2832, 2833); DECLARE_TOAST(pg_default_acl, 4143, 4144); +DECLARE_TOAST(pg_depend, 8888, 8889); DECLARE_TOAST(pg_description, 2834, 2835); DECLARE_TOAST(pg_event_trigger, 4145, 4146); DECLARE_TOAST(pg_extension, 4147, 4148); diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index 8538173ff8..d40afeef78 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -18,8 +18,8 @@ WHERE refclassid = 0 OR refobjid = 0 OR deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR (deptype != 'p' AND (classid = 0 OR objid = 0)) OR (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0)); - classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype ----------+-------+----------+------------+----------+-------------+--------- + classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion +---------+-------+----------+------------+----------+-------------+---------+--------------- (0 rows) -- **************** pg_shdepend **************** -- 2.20.1 --vtzGhvizbBRQ85DL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v18-0003-Track-collation-versions-for-indexes.patch" ^ permalink raw reply [nested|flat] 19+ messages in thread
* [PATCH v17 2/7] Add pg_depend.refobjversion. @ 2019-05-28 18:16 Thomas Munro <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Thomas Munro @ 2019-05-28 18:16 UTC (permalink / raw) Provide a place for the version of referenced database objects to be recorded. Later commits will be able to use this to record dependencies on collation versions for indexes and perhaps more things later. Author: Thomas Munro Reviewed-by: Julien Rouhaud, Peter Eisentraut and Michael Paquier Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- doc/src/sgml/catalogs.sgml | 12 ++++++- src/backend/catalog/dependency.c | 14 +++++--- src/backend/catalog/pg_depend.c | 14 +++++--- src/bin/initdb/initdb.c | 44 +++++++++++------------ src/include/catalog/dependency.h | 1 + src/include/catalog/pg_depend.h | 4 +++ src/include/catalog/toasting.h | 1 + src/test/regress/expected/misc_sanity.out | 4 +-- 8 files changed, 61 insertions(+), 33 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index c2d33c76e0..4dacebf8c9 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -2950,6 +2950,17 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </entry> </row> + <row> + <entry><structfield>refobjversion</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry> + An optional version for the referenced object. The only current use of + <structfield>refobjversion</structfield> is to record dependencies + between indexes and collation versions. + </entry> + </row> + </tbody> </tgroup> </table> @@ -3115,7 +3126,6 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l dependencies' restrictions about which objects must be dropped together must be satisfied. </para> - </sect1> diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index ffd52c1153..281f5b7c28 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1603,7 +1603,9 @@ recordDependencyOnExpr(const ObjectAddress *depender, /* And record 'em */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, + context.addrs->numrefs, + NULL, behavior); free_object_addresses(context.addrs); @@ -1690,7 +1692,9 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the self-dependencies with the appropriate direction */ if (!reverse_self) recordMultipleDependencies(depender, - self_addrs->refs, self_addrs->numrefs, + self_addrs->refs, + self_addrs->numrefs, + NULL, self_behavior); else { @@ -1710,7 +1714,9 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the external dependencies */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, + context.addrs->numrefs, + NULL, behavior); free_object_addresses(context.addrs); @@ -2682,7 +2688,7 @@ record_object_address_dependencies(const ObjectAddress *depender, { eliminate_duplicate_dependencies(referenced); recordMultipleDependencies(depender, - referenced->refs, referenced->numrefs, + referenced->refs, referenced->numrefs, NULL, behavior); } diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index 596dafe19c..84a0b99311 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -24,6 +24,7 @@ #include "catalog/pg_extension.h" #include "commands/extension.h" #include "miscadmin.h" +#include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/rel.h" @@ -44,7 +45,7 @@ recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior) { - recordMultipleDependencies(depender, referenced, 1, behavior); + recordMultipleDependencies(depender, referenced, 1, NULL, behavior); } /* @@ -55,6 +56,7 @@ void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, + const char *version, DependencyType behavior) { Relation dependDesc; @@ -79,8 +81,6 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Don't open indexes unless we need to make an update */ indstate = NULL; - memset(nulls, false, sizeof(nulls)); - for (i = 0; i < nreferenced; i++, referenced++) { /* @@ -94,6 +94,9 @@ recordMultipleDependencies(const ObjectAddress *depender, * Record the Dependency. Note we don't bother to check for * duplicate dependencies; there's no harm in them. */ + memset(nulls, false, sizeof(nulls)); + memset(values, 0, sizeof(values)); + values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); @@ -101,9 +104,12 @@ recordMultipleDependencies(const ObjectAddress *depender, values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); + if (version) + values[Anum_pg_depend_refobjversion - 1] = CStringGetTextDatum(version); + else + nulls[Anum_pg_depend_refobjversion - 1] = true; values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - tup = heap_form_tuple(dependDesc->rd_att, values, nulls); /* fetch index info only when we know we need it */ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a6577486ce..b7e01a4678 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1560,55 +1560,55 @@ setup_depend(FILE *cmdfd) "DELETE FROM pg_shdepend;\n\n", "VACUUM pg_shdepend;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_class;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_proc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_type;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_cast;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_constraint;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_conversion;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_attrdef;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_language;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_operator;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opclass;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opfamily;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_am;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amop;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amproc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_rewrite;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_trigger;\n\n", /* * restriction here to avoid pinning the public namespace */ - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_namespace " " WHERE nspname LIKE 'pg%';\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_parser;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_dict;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_template;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_config;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_collation;\n\n", "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' " " FROM pg_authid;\n\n", diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index ab5e92bdc6..62e86a19b6 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -185,6 +185,7 @@ extern void recordDependencyOn(const ObjectAddress *depender, extern void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, + const char *version, DependencyType behavior); extern void recordDependencyOnCurrentExtension(const ObjectAddress *object, diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h index ccf0a98330..7489022795 100644 --- a/src/include/catalog/pg_depend.h +++ b/src/include/catalog/pg_depend.h @@ -61,6 +61,10 @@ CATALOG(pg_depend,2608,DependRelationId) * field. See DependencyType in catalog/dependency.h. */ char deptype; /* see codes in dependency.h */ +#ifdef CATALOG_VARLEN + text refobjversion; /* version tracking, NULL if not used or + * unknown */ +#endif } FormData_pg_depend; /* ---------------- diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h index 8f131893dc..e320d82203 100644 --- a/src/include/catalog/toasting.h +++ b/src/include/catalog/toasting.h @@ -53,6 +53,7 @@ DECLARE_TOAST(pg_aggregate, 4159, 4160); DECLARE_TOAST(pg_attrdef, 2830, 2831); DECLARE_TOAST(pg_constraint, 2832, 2833); DECLARE_TOAST(pg_default_acl, 4143, 4144); +DECLARE_TOAST(pg_depend, 8888, 8889); DECLARE_TOAST(pg_description, 2834, 2835); DECLARE_TOAST(pg_event_trigger, 4145, 4146); DECLARE_TOAST(pg_extension, 4147, 4148); diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index 8538173ff8..d40afeef78 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -18,8 +18,8 @@ WHERE refclassid = 0 OR refobjid = 0 OR deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR (deptype != 'p' AND (classid = 0 OR objid = 0)) OR (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0)); - classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype ----------+-------+----------+------------+----------+-------------+--------- + classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion +---------+-------+----------+------------+----------+-------------+---------+--------------- (0 rows) -- **************** pg_shdepend **************** -- 2.20.1 --FCuugMFkClbJLl1L Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v17-0003-Implement-type-regcollation.patch" ^ permalink raw reply [nested|flat] 19+ messages in thread
* [PATCH v16 2/7] Add pg_depend.refobjversion. @ 2019-05-28 18:16 Thomas Munro <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Thomas Munro @ 2019-05-28 18:16 UTC (permalink / raw) Provide a place for the version of referenced database objects to be recorded. Later commits will be able to use this to record dependencies on collation versions for indexes and perhaps more things later. Author: Thomas Munro Reviewed-by: Julien Rouhaud, Peter Eisentraut and Michael Paquier Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- doc/src/sgml/catalogs.sgml | 12 ++++++- src/backend/catalog/dependency.c | 11 +++--- src/backend/catalog/pg_depend.c | 14 +++++--- src/bin/initdb/initdb.c | 44 +++++++++++------------ src/include/catalog/dependency.h | 1 + src/include/catalog/pg_depend.h | 3 ++ src/include/catalog/toasting.h | 1 + src/test/regress/expected/misc_sanity.out | 4 +-- 8 files changed, 57 insertions(+), 33 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index c2d33c76e0..4dacebf8c9 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -2950,6 +2950,17 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </entry> </row> + <row> + <entry><structfield>refobjversion</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry> + An optional version for the referenced object. The only current use of + <structfield>refobjversion</structfield> is to record dependencies + between indexes and collation versions. + </entry> + </row> + </tbody> </tgroup> </table> @@ -3115,7 +3126,6 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l dependencies' restrictions about which objects must be dropped together must be satisfied. </para> - </sect1> diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index ffd52c1153..660033b9c1 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1603,7 +1603,8 @@ recordDependencyOnExpr(const ObjectAddress *depender, /* And record 'em */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -1690,7 +1691,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the self-dependencies with the appropriate direction */ if (!reverse_self) recordMultipleDependencies(depender, - self_addrs->refs, self_addrs->numrefs, + self_addrs->refs, NULL, + self_addrs->numrefs, self_behavior); else { @@ -1710,7 +1712,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the external dependencies */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -2682,7 +2685,7 @@ record_object_address_dependencies(const ObjectAddress *depender, { eliminate_duplicate_dependencies(referenced); recordMultipleDependencies(depender, - referenced->refs, referenced->numrefs, + referenced->refs, NULL, referenced->numrefs, behavior); } diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index 596dafe19c..312d4d3d90 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -24,6 +24,7 @@ #include "catalog/pg_extension.h" #include "commands/extension.h" #include "miscadmin.h" +#include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/rel.h" @@ -44,7 +45,7 @@ recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior) { - recordMultipleDependencies(depender, referenced, 1, behavior); + recordMultipleDependencies(depender, referenced, NULL, 1, behavior); } /* @@ -54,6 +55,7 @@ recordDependencyOn(const ObjectAddress *depender, void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const char *version, int nreferenced, DependencyType behavior) { @@ -79,8 +81,6 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Don't open indexes unless we need to make an update */ indstate = NULL; - memset(nulls, false, sizeof(nulls)); - for (i = 0; i < nreferenced; i++, referenced++) { /* @@ -94,6 +94,9 @@ recordMultipleDependencies(const ObjectAddress *depender, * Record the Dependency. Note we don't bother to check for * duplicate dependencies; there's no harm in them. */ + memset(nulls, false, sizeof(nulls)); + memset(values, 0, sizeof(values)); + values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); @@ -101,9 +104,12 @@ recordMultipleDependencies(const ObjectAddress *depender, values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); + if (version) + values[Anum_pg_depend_refobjversion - 1] = CStringGetTextDatum(version); + else + nulls[Anum_pg_depend_refobjversion - 1] = true; values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - tup = heap_form_tuple(dependDesc->rd_att, values, nulls); /* fetch index info only when we know we need it */ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a6577486ce..b7e01a4678 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1560,55 +1560,55 @@ setup_depend(FILE *cmdfd) "DELETE FROM pg_shdepend;\n\n", "VACUUM pg_shdepend;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_class;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_proc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_type;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_cast;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_constraint;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_conversion;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_attrdef;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_language;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_operator;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opclass;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opfamily;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_am;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amop;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amproc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_rewrite;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_trigger;\n\n", /* * restriction here to avoid pinning the public namespace */ - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_namespace " " WHERE nspname LIKE 'pg%';\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_parser;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_dict;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_template;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_config;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_collation;\n\n", "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' " " FROM pg_authid;\n\n", diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index ab5e92bdc6..473342dad2 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -184,6 +184,7 @@ extern void recordDependencyOn(const ObjectAddress *depender, extern void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const char *version, int nreferenced, DependencyType behavior); diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h index ccf0a98330..9f2e10d428 100644 --- a/src/include/catalog/pg_depend.h +++ b/src/include/catalog/pg_depend.h @@ -61,6 +61,9 @@ CATALOG(pg_depend,2608,DependRelationId) * field. See DependencyType in catalog/dependency.h. */ char deptype; /* see codes in dependency.h */ +#ifdef CATALOG_VARLEN + text refobjversion; /* version tracking, NULL if not used or unknown */ +#endif } FormData_pg_depend; /* ---------------- diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h index 8f131893dc..e320d82203 100644 --- a/src/include/catalog/toasting.h +++ b/src/include/catalog/toasting.h @@ -53,6 +53,7 @@ DECLARE_TOAST(pg_aggregate, 4159, 4160); DECLARE_TOAST(pg_attrdef, 2830, 2831); DECLARE_TOAST(pg_constraint, 2832, 2833); DECLARE_TOAST(pg_default_acl, 4143, 4144); +DECLARE_TOAST(pg_depend, 8888, 8889); DECLARE_TOAST(pg_description, 2834, 2835); DECLARE_TOAST(pg_event_trigger, 4145, 4146); DECLARE_TOAST(pg_extension, 4147, 4148); diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index 8538173ff8..d40afeef78 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -18,8 +18,8 @@ WHERE refclassid = 0 OR refobjid = 0 OR deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR (deptype != 'p' AND (classid = 0 OR objid = 0)) OR (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0)); - classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype ----------+-------+----------+------------+----------+-------------+--------- + classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion +---------+-------+----------+------------+----------+-------------+---------+--------------- (0 rows) -- **************** pg_shdepend **************** -- 2.20.1 --fUYQa+Pmc3FrFX/N Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v16-0003-Implement-type-regcollation.patch" ^ permalink raw reply [nested|flat] 19+ messages in thread
* [PATCH v16 2/7] Add pg_depend.refobjversion. @ 2019-05-28 18:16 Thomas Munro <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Thomas Munro @ 2019-05-28 18:16 UTC (permalink / raw) Provide a place for the version of referenced database objects to be recorded. Later commits will be able to use this to record dependencies on collation versions for indexes and perhaps more things later. Author: Thomas Munro Reviewed-by: Julien Rouhaud, Peter Eisentraut and Michael Paquier Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- doc/src/sgml/catalogs.sgml | 12 ++++++- src/backend/catalog/dependency.c | 11 +++--- src/backend/catalog/pg_depend.c | 28 ++++++++++++--- src/bin/initdb/initdb.c | 44 +++++++++++------------ src/include/catalog/dependency.h | 6 ++++ src/include/catalog/pg_depend.h | 3 ++ src/include/catalog/toasting.h | 1 + src/test/regress/expected/misc_sanity.out | 4 +-- 8 files changed, 76 insertions(+), 33 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index c2d33c76e0..4dacebf8c9 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -2950,6 +2950,17 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </entry> </row> + <row> + <entry><structfield>refobjversion</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry> + An optional version for the referenced object. The only current use of + <structfield>refobjversion</structfield> is to record dependencies + between indexes and collation versions. + </entry> + </row> + </tbody> </tgroup> </table> @@ -3115,7 +3126,6 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l dependencies' restrictions about which objects must be dropped together must be satisfied. </para> - </sect1> diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index ffd52c1153..660033b9c1 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1603,7 +1603,8 @@ recordDependencyOnExpr(const ObjectAddress *depender, /* And record 'em */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -1690,7 +1691,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the self-dependencies with the appropriate direction */ if (!reverse_self) recordMultipleDependencies(depender, - self_addrs->refs, self_addrs->numrefs, + self_addrs->refs, NULL, + self_addrs->numrefs, self_behavior); else { @@ -1710,7 +1712,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the external dependencies */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -2682,7 +2685,7 @@ record_object_address_dependencies(const ObjectAddress *depender, { eliminate_duplicate_dependencies(referenced); recordMultipleDependencies(depender, - referenced->refs, referenced->numrefs, + referenced->refs, NULL, referenced->numrefs, behavior); } diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index 596dafe19c..b7beb2884e 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -44,7 +44,22 @@ recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior) { - recordMultipleDependencies(depender, referenced, 1, behavior); + recordMultipleDependencies(depender, referenced, NULL, 1, behavior); +} + +/* + * As recordDependencyOn(), but also capture a version string so that changes + * in the referenced object can be detected. The meaning of the version + * string depends on the referenced object. Currently it is used for + * detecting changes in collation versions. + */ +void +recordDependencyOnVersion(const ObjectAddress *depender, + const ObjectAddress *referenced, + const NameData *version, + DependencyType behavior) +{ + recordMultipleDependencies(depender, referenced, version, 1, behavior); } /* @@ -54,6 +69,7 @@ recordDependencyOn(const ObjectAddress *depender, void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const NameData *version, int nreferenced, DependencyType behavior) { @@ -79,8 +95,6 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Don't open indexes unless we need to make an update */ indstate = NULL; - memset(nulls, false, sizeof(nulls)); - for (i = 0; i < nreferenced; i++, referenced++) { /* @@ -94,6 +108,9 @@ recordMultipleDependencies(const ObjectAddress *depender, * Record the Dependency. Note we don't bother to check for * duplicate dependencies; there's no harm in them. */ + memset(nulls, false, sizeof(nulls)); + memset(values, 0, sizeof(values)); + values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); @@ -101,9 +118,12 @@ recordMultipleDependencies(const ObjectAddress *depender, values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); + if (version) + values[Anum_pg_depend_refobjversion - 1] = CStringGetTextDatum(version); + else + nulls[Anum_pg_depend_refobjversion - 1] = true; values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - tup = heap_form_tuple(dependDesc->rd_att, values, nulls); /* fetch index info only when we know we need it */ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a6577486ce..b7e01a4678 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1560,55 +1560,55 @@ setup_depend(FILE *cmdfd) "DELETE FROM pg_shdepend;\n\n", "VACUUM pg_shdepend;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_class;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_proc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_type;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_cast;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_constraint;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_conversion;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_attrdef;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_language;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_operator;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opclass;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opfamily;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_am;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amop;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amproc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_rewrite;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_trigger;\n\n", /* * restriction here to avoid pinning the public namespace */ - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_namespace " " WHERE nspname LIKE 'pg%';\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_parser;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_dict;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_template;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_config;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_collation;\n\n", "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' " " FROM pg_authid;\n\n", diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index ab5e92bdc6..7d9fc866b9 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -182,8 +182,14 @@ extern void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior); +extern void recordDependencyOnVersion(const ObjectAddress *depender, + const ObjectAddress *referenced, + const NameData *version, + DependencyType behavior); + extern void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const NameData *version, int nreferenced, DependencyType behavior); diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h index ccf0a98330..9f2e10d428 100644 --- a/src/include/catalog/pg_depend.h +++ b/src/include/catalog/pg_depend.h @@ -61,6 +61,9 @@ CATALOG(pg_depend,2608,DependRelationId) * field. See DependencyType in catalog/dependency.h. */ char deptype; /* see codes in dependency.h */ +#ifdef CATALOG_VARLEN + text refobjversion; /* version tracking, NULL if not used or unknown */ +#endif } FormData_pg_depend; /* ---------------- diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h index 8f131893dc..e320d82203 100644 --- a/src/include/catalog/toasting.h +++ b/src/include/catalog/toasting.h @@ -53,6 +53,7 @@ DECLARE_TOAST(pg_aggregate, 4159, 4160); DECLARE_TOAST(pg_attrdef, 2830, 2831); DECLARE_TOAST(pg_constraint, 2832, 2833); DECLARE_TOAST(pg_default_acl, 4143, 4144); +DECLARE_TOAST(pg_depend, 8888, 8889); DECLARE_TOAST(pg_description, 2834, 2835); DECLARE_TOAST(pg_event_trigger, 4145, 4146); DECLARE_TOAST(pg_extension, 4147, 4148); diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index 8538173ff8..d40afeef78 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -18,8 +18,8 @@ WHERE refclassid = 0 OR refobjid = 0 OR deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR (deptype != 'p' AND (classid = 0 OR objid = 0)) OR (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0)); - classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype ----------+-------+----------+------------+----------+-------------+--------- + classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion +---------+-------+----------+------------+----------+-------------+---------+--------------- (0 rows) -- **************** pg_shdepend **************** -- 2.20.1 --sdtB3X0nJg68CQEu Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v16-0003-Implement-type-regcollation.patch" ^ permalink raw reply [nested|flat] 19+ messages in thread
* [PATCH 2/6] Add pg_depend.refobjversion. @ 2019-05-28 18:16 Thomas Munro <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Thomas Munro @ 2019-05-28 18:16 UTC (permalink / raw) Provide a place for the version of referenced database objects to be recorded. Later commits will be able to use this to record dependencies on collation versions, for indexes, check constraints and so forth. Author: Thomas Munro Reviewed-by: Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- src/backend/catalog/dependency.c | 11 +++--- src/backend/catalog/pg_depend.c | 28 ++++++++++++--- src/bin/initdb/initdb.c | 44 +++++++++++------------ src/include/catalog/dependency.h | 6 ++++ src/include/catalog/pg_depend.h | 3 ++ src/test/regress/expected/misc_sanity.out | 7 ++-- 6 files changed, 66 insertions(+), 33 deletions(-) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index c4a4df25b8..78c31baa34 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1602,7 +1602,8 @@ recordDependencyOnExpr(const ObjectAddress *depender, /* And record 'em */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -1689,7 +1690,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the self-dependencies with the appropriate direction */ if (!reverse_self) recordMultipleDependencies(depender, - self_addrs->refs, self_addrs->numrefs, + self_addrs->refs, NULL, + self_addrs->numrefs, self_behavior); else { @@ -1709,7 +1711,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the external dependencies */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -2681,7 +2684,7 @@ record_object_address_dependencies(const ObjectAddress *depender, { eliminate_duplicate_dependencies(referenced); recordMultipleDependencies(depender, - referenced->refs, referenced->numrefs, + referenced->refs, NULL, referenced->numrefs, behavior); } diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index f9af245eec..7fdbdf0ae8 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -44,7 +44,22 @@ recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior) { - recordMultipleDependencies(depender, referenced, 1, behavior); + recordMultipleDependencies(depender, referenced, NULL, 1, behavior); +} + +/* + * As recordDependencyOn(), but also capture a version string so that changes + * in the referenced object can be detected. The meaning of the version + * string depends on the referenced object. Currently it is used for + * detecting changes in collation versions. + */ +void +recordDependencyOnVersion(const ObjectAddress *depender, + const ObjectAddress *referenced, + const NameData *version, + DependencyType behavior) +{ + recordMultipleDependencies(depender, referenced, version, 1, behavior); } /* @@ -54,6 +69,7 @@ recordDependencyOn(const ObjectAddress *depender, void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const NameData *version, int nreferenced, DependencyType behavior) { @@ -79,8 +95,6 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Don't open indexes unless we need to make an update */ indstate = NULL; - memset(nulls, false, sizeof(nulls)); - for (i = 0; i < nreferenced; i++, referenced++) { /* @@ -94,6 +108,9 @@ recordMultipleDependencies(const ObjectAddress *depender, * Record the Dependency. Note we don't bother to check for * duplicate dependencies; there's no harm in them. */ + memset(nulls, false, sizeof(nulls)); + memset(values, 0, sizeof(values)); + values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); @@ -101,9 +118,12 @@ recordMultipleDependencies(const ObjectAddress *depender, values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); + if (version) + values[Anum_pg_depend_refobjversion - 1] = CStringGetTextDatum(version); + else + nulls[Anum_pg_depend_refobjversion - 1] = true; values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - tup = heap_form_tuple(dependDesc->rd_att, values, nulls); /* fetch index info only when we know we need it */ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a6577486ce..b7e01a4678 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1560,55 +1560,55 @@ setup_depend(FILE *cmdfd) "DELETE FROM pg_shdepend;\n\n", "VACUUM pg_shdepend;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_class;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_proc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_type;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_cast;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_constraint;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_conversion;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_attrdef;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_language;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_operator;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opclass;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opfamily;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_am;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amop;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amproc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_rewrite;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_trigger;\n\n", /* * restriction here to avoid pinning the public namespace */ - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_namespace " " WHERE nspname LIKE 'pg%';\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_parser;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_dict;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_template;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_config;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_collation;\n\n", "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' " " FROM pg_authid;\n\n", diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index 0cd6fcf027..77cf0612ed 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -182,8 +182,14 @@ extern void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior); +extern void recordDependencyOnVersion(const ObjectAddress *depender, + const ObjectAddress *referenced, + const NameData *version, + DependencyType behavior); + extern void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const NameData *version, int nreferenced, DependencyType behavior); diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h index ccf0a98330..9f2e10d428 100644 --- a/src/include/catalog/pg_depend.h +++ b/src/include/catalog/pg_depend.h @@ -61,6 +61,9 @@ CATALOG(pg_depend,2608,DependRelationId) * field. See DependencyType in catalog/dependency.h. */ char deptype; /* see codes in dependency.h */ +#ifdef CATALOG_VARLEN + text refobjversion; /* version tracking, NULL if not used or unknown */ +#endif } FormData_pg_depend; /* ---------------- diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index 8538173ff8..41efb4a2c8 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -18,8 +18,8 @@ WHERE refclassid = 0 OR refobjid = 0 OR deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR (deptype != 'p' AND (classid = 0 OR objid = 0)) OR (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0)); - classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype ----------+-------+----------+------------+----------+-------------+--------- + classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion +---------+-------+----------+------------+----------+-------------+---------+--------------- (0 rows) -- **************** pg_shdepend **************** @@ -103,9 +103,10 @@ ORDER BY 1, 2; pg_class | relacl | aclitem[] pg_class | reloptions | text[] pg_class | relpartbound | pg_node_tree + pg_depend | refobjversion | text pg_index | indexprs | pg_node_tree pg_index | indpred | pg_node_tree pg_largeobject | data | bytea pg_largeobject_metadata | lomacl | aclitem[] -(11 rows) +(12 rows) -- 2.20.1 --mP3DRpeJDSE+ciuQ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0003-Implement-type-regcollation-v12.patch" ^ permalink raw reply [nested|flat] 19+ messages in thread
* [PATCH v14 2/7] Add pg_depend.refobjversion. @ 2019-05-28 18:16 Thomas Munro <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Thomas Munro @ 2019-05-28 18:16 UTC (permalink / raw) Provide a place for the version of referenced database objects to be recorded. Later commits will be able to use this to record dependencies on collation versions for indexes and perhaps more things later. Author: Thomas Munro Reviewed-by: Julien Rouhaud and Peter Eisentraut Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- doc/src/sgml/catalogs.sgml | 13 +++++++ src/backend/catalog/dependency.c | 11 +++--- src/backend/catalog/pg_depend.c | 28 ++++++++++++--- src/bin/initdb/initdb.c | 44 +++++++++++------------ src/include/catalog/dependency.h | 6 ++++ src/include/catalog/pg_depend.h | 3 ++ src/test/regress/expected/misc_sanity.out | 7 ++-- 7 files changed, 79 insertions(+), 33 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index c2d33c76e0..ad44c44530 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -2950,6 +2950,15 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </entry> </row> + <row> + <entry><structfield>refobjversion</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry> + An optional version for the referenced object; see text + </entry> + </row> + </tbody> </tgroup> </table> @@ -3116,6 +3125,10 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l must be satisfied. </para> + <para> + The only current use of <structfield>refobjversion</structfield> is to + record dependencies between indexes and collation versions. + </para> </sect1> diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index ffd52c1153..660033b9c1 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1603,7 +1603,8 @@ recordDependencyOnExpr(const ObjectAddress *depender, /* And record 'em */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -1690,7 +1691,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the self-dependencies with the appropriate direction */ if (!reverse_self) recordMultipleDependencies(depender, - self_addrs->refs, self_addrs->numrefs, + self_addrs->refs, NULL, + self_addrs->numrefs, self_behavior); else { @@ -1710,7 +1712,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender, /* Record the external dependencies */ recordMultipleDependencies(depender, - context.addrs->refs, context.addrs->numrefs, + context.addrs->refs, NULL, + context.addrs->numrefs, behavior); free_object_addresses(context.addrs); @@ -2682,7 +2685,7 @@ record_object_address_dependencies(const ObjectAddress *depender, { eliminate_duplicate_dependencies(referenced); recordMultipleDependencies(depender, - referenced->refs, referenced->numrefs, + referenced->refs, NULL, referenced->numrefs, behavior); } diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index f9af245eec..7fdbdf0ae8 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -44,7 +44,22 @@ recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior) { - recordMultipleDependencies(depender, referenced, 1, behavior); + recordMultipleDependencies(depender, referenced, NULL, 1, behavior); +} + +/* + * As recordDependencyOn(), but also capture a version string so that changes + * in the referenced object can be detected. The meaning of the version + * string depends on the referenced object. Currently it is used for + * detecting changes in collation versions. + */ +void +recordDependencyOnVersion(const ObjectAddress *depender, + const ObjectAddress *referenced, + const NameData *version, + DependencyType behavior) +{ + recordMultipleDependencies(depender, referenced, version, 1, behavior); } /* @@ -54,6 +69,7 @@ recordDependencyOn(const ObjectAddress *depender, void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const NameData *version, int nreferenced, DependencyType behavior) { @@ -79,8 +95,6 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Don't open indexes unless we need to make an update */ indstate = NULL; - memset(nulls, false, sizeof(nulls)); - for (i = 0; i < nreferenced; i++, referenced++) { /* @@ -94,6 +108,9 @@ recordMultipleDependencies(const ObjectAddress *depender, * Record the Dependency. Note we don't bother to check for * duplicate dependencies; there's no harm in them. */ + memset(nulls, false, sizeof(nulls)); + memset(values, 0, sizeof(values)); + values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); @@ -101,9 +118,12 @@ recordMultipleDependencies(const ObjectAddress *depender, values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); + if (version) + values[Anum_pg_depend_refobjversion - 1] = CStringGetTextDatum(version); + else + nulls[Anum_pg_depend_refobjversion - 1] = true; values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - tup = heap_form_tuple(dependDesc->rd_att, values, nulls); /* fetch index info only when we know we need it */ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a6577486ce..b7e01a4678 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1560,55 +1560,55 @@ setup_depend(FILE *cmdfd) "DELETE FROM pg_shdepend;\n\n", "VACUUM pg_shdepend;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_class;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_proc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_type;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_cast;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_constraint;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_conversion;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_attrdef;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_language;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_operator;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opclass;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_opfamily;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_am;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amop;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_amproc;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_rewrite;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_trigger;\n\n", /* * restriction here to avoid pinning the public namespace */ - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_namespace " " WHERE nspname LIKE 'pg%';\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_parser;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_dict;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_template;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_ts_config;\n\n", - "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' " + "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p',NULL" " FROM pg_collation;\n\n", "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' " " FROM pg_authid;\n\n", diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index 0cd6fcf027..77cf0612ed 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -182,8 +182,14 @@ extern void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior); +extern void recordDependencyOnVersion(const ObjectAddress *depender, + const ObjectAddress *referenced, + const NameData *version, + DependencyType behavior); + extern void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, + const NameData *version, int nreferenced, DependencyType behavior); diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h index ccf0a98330..9f2e10d428 100644 --- a/src/include/catalog/pg_depend.h +++ b/src/include/catalog/pg_depend.h @@ -61,6 +61,9 @@ CATALOG(pg_depend,2608,DependRelationId) * field. See DependencyType in catalog/dependency.h. */ char deptype; /* see codes in dependency.h */ +#ifdef CATALOG_VARLEN + text refobjversion; /* version tracking, NULL if not used or unknown */ +#endif } FormData_pg_depend; /* ---------------- diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index 8538173ff8..41efb4a2c8 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -18,8 +18,8 @@ WHERE refclassid = 0 OR refobjid = 0 OR deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR (deptype != 'p' AND (classid = 0 OR objid = 0)) OR (deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0)); - classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype ----------+-------+----------+------------+----------+-------------+--------- + classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype | refobjversion +---------+-------+----------+------------+----------+-------------+---------+--------------- (0 rows) -- **************** pg_shdepend **************** @@ -103,9 +103,10 @@ ORDER BY 1, 2; pg_class | relacl | aclitem[] pg_class | reloptions | text[] pg_class | relpartbound | pg_node_tree + pg_depend | refobjversion | text pg_index | indexprs | pg_node_tree pg_index | indpred | pg_node_tree pg_largeobject | data | bytea pg_largeobject_metadata | lomacl | aclitem[] -(11 rows) +(12 rows) -- 2.20.1 --wRRV7LY7NUeQGEoC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v14-0003-Implement-type-regcollation.patch" ^ permalink raw reply [nested|flat] 19+ messages in thread
* [PATCH v2 07/11] Cleanup summary of role powers. @ 2023-09-25 21:39 Karl O. Pinc <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Karl O. Pinc @ 2023-09-25 21:39 UTC (permalink / raw) Make sentences shorter. Explain privileges v.s. permissions. This commit assumes that there is a distinction in the PostgreSQL vocabulary between role privileges and permissions. Privileges being a specific Postgres term for powers granted to roles via GRANT. Permissions being abilities to perform specific operations that comes with privileges, but also with role attributes like CREATEDB. So permissions are a broader category than privileges, in terms of where they come from. As well as being a narrower category in another sense, in that some privileges, like object ownership, carry with them a swath of individual permissions/abilities, like USAGE. It seems a useful distinction to make, in terms of thinking about how object access works. Essential in fact, since both privileges (e.g. ownership) and role attributes (e.g. SUPERUSER) give roles abilities, aka permissions (e.g. SELECT). Without the distinction you can't describe role inheritance (attributes don't, privileges do) or discuss the source of particular access rights. If access rights, aka permissions, aka "abilities to do things", are the same as privileges how come some privileges convey multiple abilities, abilities that have their own names; how can you get an ability via a role attribute but not have the privilege? It seems most clear to, conceptually at least, have a separate set of permissions (abilities) that come via privileges granted to roles and role attributes assigned to roles. So, I'm not sure my choice of vocabulary is perfect. One might use "rights" or some other word rather than "permissions". But I think that there should be a clear distinction between the 3 concepts of granted privileges, role attributes, and permissions to perform specific operations. I also would argue that it is not necessary to scour the existing documentation and patch to obtain perfect consistency in vocabulary usage. The existing wording seems acceptable in practice and I don't see anyone who's read what's already there to be confused by the changes presented here. --- doc/src/sgml/user-manag.sgml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index 27c1f3d703..492325e8a2 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -7,11 +7,14 @@ <productname>PostgreSQL</productname> manages database access permissions using the concept of <firstterm>roles</firstterm>. A role can be thought of as either a database user, or a group of database users, depending on how - the role is set up. Roles can own database objects (for example, tables - and functions) and can assign privileges on those objects to other roles to - control who has access to which objects. Furthermore, it is possible - to grant <firstterm>membership</firstterm> in a role to another role, thus - allowing the member role to use privileges assigned to another role. + the role is set up. + Roles can own database objects (for example, tables and functions). + They can assign privileges on the owned objects, and thus the permissions + the privileges carry, to other roles. + Roles therefore control who has what access to which objects. + It is possible to grant <firstterm>membership</firstterm> in a role to + another role, thus allowing the member role to use the privileges assigned + to another role. </para> <para> -- 2.30.2 --MP_/RgO6TscyR9fMvkEm1k5N=yu Content-Type: text/x-patch Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=v2-0008-Explain-the-difference-between-role-attributes-an.patch ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2024-09-17 20:53 Florents Tselai <[email protected]> 0 siblings, 1 reply; 19+ messages in thread From: Florents Tselai @ 2024-09-17 20:53 UTC (permalink / raw) To: Andrew Dunstan <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> On Tue, Sep 17, 2024 at 5:11 PM Andrew Dunstan <[email protected]> wrote: > > On 2024-09-17 Tu 5:26 AM, Florents Tselai wrote: > > Currently: > > > jsonb_strip_nulls ( jsonb ) → jsonb > > Deletes all object fields that have null values from the given JSON value, > recursively. Null values that are not object fields are untouched. > > > > Null values that are not object fields are untouched. > > > Can we revisit this and make it work with arrays, too? > > Tbh, at first sight that looked like the expected behavior for me. > > That is strip nulls from arrays as well. > > > This has been available since 9.5 and iiuc predates lots of the jsonb > array work. > > > I don't think that's a great idea. Removing an object field which has a > null value shouldn't have any effect on the surrounding data, nor really > any on other operations (If you try to get the value of the missing field > it should give you back null). But removing a null array member isn't like > that at all - unless it's the trailing member of the array it will renumber > all the succeeding array members. > > And I don't think we should be changing the behaviour of a function, that > people might have been relying on for the better part of a decade. > > > > In practice, though, whenever jsonb_build_array is used (especially with > jsonpath), > > a few nulls do appear in the resulting array most of the times, > > Currently, there’s no expressive way to remove this. > > > We could also have jsonb_array_strip_nulls(jsonb) as well > > > We could, if we're going to do anything at all in this area. Another > possibility would be to provide a second optional parameter for > json{b}_strip_nulls. That's probably a better way to go. > Here's a patch that adds that argument (only for jsonb; no json implementation yet) That's how I imagined & implemented it, but there may be non-obvious pitfalls in the semantics. as-is version select jsonb_strip_nulls('[1,2,null,3,4]'); jsonb_strip_nulls -------------------- [1, 2, null, 3, 4] (1 row) select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}'); jsonb_strip_nulls -------------------------------------------- {"a": 1, "c": [2, null, 3], "d": {"e": 4}} (1 row) with the additional boolean flag added select jsonb_strip_nulls('[1,2,null,3,4]', *true*); jsonb_strip_nulls ------------------- [1, 2, 3, 4] (1 row) select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', *true*); jsonb_strip_nulls -------------------------------------- {"a": 1, "c": [2, 3], "d": {"e": 4}} (1 row) GH PR view: https://github.com/Florents-Tselai/postgres/pull/6/files > cheers > > > andrew > > > -- > Andrew Dunstan > EDB: https://www.enterprisedb.com > > Attachments: [application/octet-stream] v1-0002-Add-docs-for-strip_in_arrays-argument.patch (2.1K, ../../CA+v5N43=48Ddg=Ub313bX3g2qu9VRHzfTP3TAGN10WF6XNX_2w@mail.gmail.com/3-v1-0002-Add-docs-for-strip_in_arrays-argument.patch) download | inline diff: From a29ac77c075523cf1e885a4b5ade6249b82ec82a Mon Sep 17 00:00:00 2001 From: Florents Tselai <[email protected]> Date: Tue, 17 Sep 2024 23:38:01 +0300 Subject: [PATCH v1 2/2] Add docs for strip_in_arrays argument --- doc/src/sgml/func.sgml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 84eb3a45ee..5840d833d3 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17119,25 +17119,31 @@ ERROR: value too long for type character(2) <indexterm> <primary>json_strip_nulls</primary> </indexterm> - <function>json_strip_nulls</function> ( <type>json</type> ) + <function>json_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type>, <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) <returnvalue>json</returnvalue> </para> <para role="func_signature"> <indexterm> <primary>jsonb_strip_nulls</primary> </indexterm> - <function>jsonb_strip_nulls</function> ( <type>jsonb</type> ) + <function>jsonb_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type>, <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) <returnvalue>jsonb</returnvalue> </para> <para> Deletes all object fields that have null values from the given JSON value, recursively. Null values that are not object fields are untouched. + If <parameter>strip_in_arrays</parameter> is true (default is false), null array elements are also stripped. </para> <para> <literal>json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]')</literal> <returnvalue>[{"f1":1},2,null,3]</returnvalue> - </para></entry> + </para> + <para> + <literal>jsonb_strip_nulls('[1,2,null,3,4]', true);</literal> + <returnvalue>[1,2,3,4]</returnvalue> + </para> + </entry> </row> <row> -- 2.39.3 (Apple Git-146) [application/octet-stream] v1-0001-jsonb_strip_nulls-jsonb-bool-wip.patch (5.8K, ../../CA+v5N43=48Ddg=Ub313bX3g2qu9VRHzfTP3TAGN10WF6XNX_2w@mail.gmail.com/4-v1-0001-jsonb_strip_nulls-jsonb-bool-wip.patch) download | inline diff: From 86e8883459fa3e4f64c1c16a31b49d123aac472f Mon Sep 17 00:00:00 2001 From: Florents Tselai <[email protected]> Date: Tue, 17 Sep 2024 22:05:58 +0300 Subject: [PATCH v1 1/2] jsonb_strip_nulls(jsonb, bool) wip Implementation and passing tests for jsonb_strip_nulls(jsonb, bool) no docs yet. --- src/backend/catalog/system_functions.sql | 7 ++++ src/backend/utils/adt/jsonfuncs.c | 11 +++++- src/include/catalog/pg_proc.dat | 2 +- src/test/regress/expected/jsonb.out | 50 ++++++++++++++++++++++++ src/test/regress/sql/jsonb.sql | 18 +++++++++ 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index 623b9539b1..2e9fcc9e02 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -610,6 +610,13 @@ LANGUAGE INTERNAL STRICT STABLE PARALLEL SAFE AS 'jsonb_path_query_first_tz'; +CREATE OR REPLACE FUNCTION + jsonb_strip_nulls(target jsonb, strip_in_arrays boolean DEFAULT false) +RETURNS jsonb +LANGUAGE INTERNAL +STRICT STABLE PARALLEL SAFE +AS 'jsonb_strip_nulls'; + -- default normalization form is NFC, per SQL standard CREATE OR REPLACE FUNCTION "normalize"(text, text DEFAULT 'NFC') diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 62a17a2667..7d6b4ebfaa 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -4520,12 +4520,13 @@ json_strip_nulls(PG_FUNCTION_ARGS) } /* - * SQL function jsonb_strip_nulls(jsonb) -> jsonb + * SQL function jsonb_strip_nulls(jsonb, bool) -> jsonb */ Datum jsonb_strip_nulls(PG_FUNCTION_ARGS) { Jsonb *jb = PG_GETARG_JSONB_P(0); + bool strip_in_arrays = false; JsonbIterator *it; JsonbParseState *parseState = NULL; JsonbValue *res = NULL; @@ -4534,6 +4535,9 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS) JsonbIteratorToken type; bool last_was_key = false; + if (PG_NARGS() == 2) + strip_in_arrays = PG_GETARG_BOOL(1); + if (JB_ROOT_IS_SCALAR(jb)) PG_RETURN_POINTER(jb); @@ -4564,6 +4568,11 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS) (void) pushJsonbValue(&parseState, WJB_KEY, &k); } + /* if strip_in_arrays is set, also skip null array elements */ + if (strip_in_arrays) + if (type == WJB_ELEM && v.type == jbvNull) + continue; + if (type == WJB_VALUE || type == WJB_ELEM) res = pushJsonbValue(&parseState, type, &v); else diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 2513c36fcb..03ad446c76 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -10114,7 +10114,7 @@ prorettype => 'jsonb', proargtypes => '', prosrc => 'jsonb_build_object_noargs' }, { oid => '3262', descr => 'remove object fields with null values from jsonb', - proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb', + proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb bool', prosrc => 'jsonb_strip_nulls' }, { oid => '3478', diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 7d163a156e..e55ed196e8 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -4153,6 +4153,56 @@ select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); {"a": {}, "d": {}} (1 row) +-- jsonb_strip_nulls (strip_in_arrays=true) +select jsonb_strip_nulls(null, true); + jsonb_strip_nulls +------------------- + +(1 row) + +select jsonb_strip_nulls('1', true); + jsonb_strip_nulls +------------------- + 1 +(1 row) + +select jsonb_strip_nulls('"a string"', true); + jsonb_strip_nulls +------------------- + "a string" +(1 row) + +select jsonb_strip_nulls('null', true); + jsonb_strip_nulls +------------------- + null +(1 row) + +select jsonb_strip_nulls('[1,2,null,3,4]', true); + jsonb_strip_nulls +------------------- + [1, 2, 3, 4] +(1 row) + +select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + jsonb_strip_nulls +-------------------------------------- + {"a": 1, "c": [2, 3], "d": {"e": 4}} +(1 row) + +select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + jsonb_strip_nulls +-------------------------- + [1, {"a": 1, "c": 2}, 3] +(1 row) + +-- an empty object is not null and should not be stripped +select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); + jsonb_strip_nulls +-------------------- + {"a": {}, "d": {}} +(1 row) + select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}'); jsonb_pretty ---------------------------- diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index 5f0190d5a2..a6eee0da3c 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -1102,6 +1102,24 @@ select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]'); -- an empty object is not null and should not be stripped select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); +-- jsonb_strip_nulls (strip_in_arrays=true) + +select jsonb_strip_nulls(null, true); + +select jsonb_strip_nulls('1', true); + +select jsonb_strip_nulls('"a string"', true); + +select jsonb_strip_nulls('null', true); + +select jsonb_strip_nulls('[1,2,null,3,4]', true); + +select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + +select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + +-- an empty object is not null and should not be stripped +select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}'); select jsonb_pretty('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]'); -- 2.39.3 (Apple Git-146) ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-01-08 16:45 Andrew Dunstan <[email protected]> parent: Florents Tselai <[email protected]> 0 siblings, 1 reply; 19+ messages in thread From: Andrew Dunstan @ 2025-01-08 16:45 UTC (permalink / raw) To: Florents Tselai <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> On 2024-09-17 Tu 4:53 PM, Florents Tselai wrote: > > We could, if we're going to do anything at all in this area. > Another possibility would be to provide a second optional > parameter for json{b}_strip_nulls. That's probably a better way to go. > > Here's a patch that adds that argument (only for jsonb; no json > implementation yet) > > I think it looks sane. We're not stripping a top level null, which is one thing I looked out for. I think we need a json implementation as well, though. cheers andrew -- Andrew Dunstan EDB:https://www.enterprisedb.com ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-01-18 09:51 Florents Tselai <[email protected]> parent: Andrew Dunstan <[email protected]> 0 siblings, 1 reply; 19+ messages in thread From: Florents Tselai @ 2025-01-18 09:51 UTC (permalink / raw) To: Andrew Dunstan <[email protected]>; +Cc: pgsql-hackers <[email protected]> > On 8 Jan 2025, at 6:45 PM, Andrew Dunstan <[email protected]> wrote: > > > > On 2024-09-17 Tu 4:53 PM, Florents Tselai wrote: >> >>> We could, if we're going to do anything at all in this area. Another possibility would be to provide a second optional parameter for json{b}_strip_nulls. That's probably a better way to go. >>> >> Here's a patch that adds that argument (only for jsonb; no json implementation yet) >> >> > > I think it looks sane. We're not stripping a top level null, which is one thing I looked out for. > > I think we need a json implementation as well, though. > > > Thanks for having a Look, Andrew; if there aren’t any other objections, I’ll come back with a json implementation too. > cheers > > > > andrew > > > > -- > Andrew Dunstan > EDB: https://www.enterprisedb.com <https://www.enterprisedb.com/; ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-02-19 21:23 Florents Tselai <[email protected]> parent: Florents Tselai <[email protected]> 0 siblings, 1 reply; 19+ messages in thread From: Florents Tselai @ 2025-02-19 21:23 UTC (permalink / raw) To: Andrew Dunstan <[email protected]>; +Cc: pgsql-hackers <[email protected]> > On 18 Jan 2025, at 11:51 AM, Florents Tselai <[email protected]> wrote: > > > >> On 8 Jan 2025, at 6:45 PM, Andrew Dunstan <[email protected]> wrote: >> >> >> >> On 2024-09-17 Tu 4:53 PM, Florents Tselai wrote: >>> >>>> We could, if we're going to do anything at all in this area. Another possibility would be to provide a second optional parameter for json{b}_strip_nulls. That's probably a better way to go. >>>> >>> Here's a patch that adds that argument (only for jsonb; no json implementation yet) >>> >>> >> >> I think it looks sane. We're not stripping a top level null, which is one thing I looked out for. >> >> I think we need a json implementation as well, though. >> >> >> > Thanks for having a Look, Andrew; > if there aren’t any other objections, I’ll come back with a json implementation too. Attached is a v2 patch with the missing json implementation. jsonb one remains the same.  >> >> cheers >> >> >> >> andrew >> >> >> >> -- >> Andrew Dunstan >> EDB: https://www.enterprisedb.com <https://www.enterprisedb.com/; Attachments: [application/octet-stream] v2-0001-jsonb_strip_nulls-jsonb-bool-wip.patch (5.8K, ../../[email protected]/3-v2-0001-jsonb_strip_nulls-jsonb-bool-wip.patch) download | inline diff: From cd7a43911daeae9af09a5163c95a2c4c3268f497 Mon Sep 17 00:00:00 2001 From: Florents Tselai <[email protected]> Date: Tue, 17 Sep 2024 22:05:58 +0300 Subject: [PATCH v2 1/3] jsonb_strip_nulls(jsonb, bool) wip Implementation and passing tests for jsonb_strip_nulls(jsonb, bool) no docs yet. --- src/backend/catalog/system_functions.sql | 7 ++++ src/backend/utils/adt/jsonfuncs.c | 11 +++++- src/include/catalog/pg_proc.dat | 2 +- src/test/regress/expected/jsonb.out | 50 ++++++++++++++++++++++++ src/test/regress/sql/jsonb.sql | 18 +++++++++ 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index 591157b1d1b..54bf061036f 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -607,6 +607,13 @@ LANGUAGE INTERNAL STRICT STABLE PARALLEL SAFE AS 'jsonb_path_query_first_tz'; +CREATE OR REPLACE FUNCTION + jsonb_strip_nulls(target jsonb, strip_in_arrays boolean DEFAULT false) +RETURNS jsonb +LANGUAGE INTERNAL +STRICT STABLE PARALLEL SAFE +AS 'jsonb_strip_nulls'; + -- default normalization form is NFC, per SQL standard CREATE OR REPLACE FUNCTION "normalize"(text, text DEFAULT 'NFC') diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index c2e90f1a3bf..cc74fa55a11 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -4520,12 +4520,13 @@ json_strip_nulls(PG_FUNCTION_ARGS) } /* - * SQL function jsonb_strip_nulls(jsonb) -> jsonb + * SQL function jsonb_strip_nulls(jsonb, bool) -> jsonb */ Datum jsonb_strip_nulls(PG_FUNCTION_ARGS) { Jsonb *jb = PG_GETARG_JSONB_P(0); + bool strip_in_arrays = false; JsonbIterator *it; JsonbParseState *parseState = NULL; JsonbValue *res = NULL; @@ -4534,6 +4535,9 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS) JsonbIteratorToken type; bool last_was_key = false; + if (PG_NARGS() == 2) + strip_in_arrays = PG_GETARG_BOOL(1); + if (JB_ROOT_IS_SCALAR(jb)) PG_RETURN_POINTER(jb); @@ -4564,6 +4568,11 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS) (void) pushJsonbValue(&parseState, WJB_KEY, &k); } + /* if strip_in_arrays is set, also skip null array elements */ + if (strip_in_arrays) + if (type == WJB_ELEM && v.type == jbvNull) + continue; + if (type == WJB_VALUE || type == WJB_ELEM) res = pushJsonbValue(&parseState, type, &v); else diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index b37e8a6f882..0a812d6a23b 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -10174,7 +10174,7 @@ prorettype => 'jsonb', proargtypes => '', prosrc => 'jsonb_build_object_noargs' }, { oid => '3262', descr => 'remove object fields with null values from jsonb', - proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb', + proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb bool', prosrc => 'jsonb_strip_nulls' }, { oid => '3478', diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 7d163a156e3..e55ed196e84 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -4153,6 +4153,56 @@ select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); {"a": {}, "d": {}} (1 row) +-- jsonb_strip_nulls (strip_in_arrays=true) +select jsonb_strip_nulls(null, true); + jsonb_strip_nulls +------------------- + +(1 row) + +select jsonb_strip_nulls('1', true); + jsonb_strip_nulls +------------------- + 1 +(1 row) + +select jsonb_strip_nulls('"a string"', true); + jsonb_strip_nulls +------------------- + "a string" +(1 row) + +select jsonb_strip_nulls('null', true); + jsonb_strip_nulls +------------------- + null +(1 row) + +select jsonb_strip_nulls('[1,2,null,3,4]', true); + jsonb_strip_nulls +------------------- + [1, 2, 3, 4] +(1 row) + +select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + jsonb_strip_nulls +-------------------------------------- + {"a": 1, "c": [2, 3], "d": {"e": 4}} +(1 row) + +select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + jsonb_strip_nulls +-------------------------- + [1, {"a": 1, "c": 2}, 3] +(1 row) + +-- an empty object is not null and should not be stripped +select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); + jsonb_strip_nulls +-------------------- + {"a": {}, "d": {}} +(1 row) + select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}'); jsonb_pretty ---------------------------- diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index 5f0190d5a2b..a6eee0da3cb 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -1102,6 +1102,24 @@ select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]'); -- an empty object is not null and should not be stripped select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); +-- jsonb_strip_nulls (strip_in_arrays=true) + +select jsonb_strip_nulls(null, true); + +select jsonb_strip_nulls('1', true); + +select jsonb_strip_nulls('"a string"', true); + +select jsonb_strip_nulls('null', true); + +select jsonb_strip_nulls('[1,2,null,3,4]', true); + +select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + +select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + +-- an empty object is not null and should not be stripped +select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}'); select jsonb_pretty('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]'); -- 2.48.1 [application/octet-stream] v2-0002-Add-docs-for-strip_in_arrays-argument.patch (2.1K, ../../[email protected]/5-v2-0002-Add-docs-for-strip_in_arrays-argument.patch) download | inline diff: From 9672e714371e7fdf12b0c58fe0b355e2a8d1ebd2 Mon Sep 17 00:00:00 2001 From: Florents Tselai <[email protected]> Date: Tue, 17 Sep 2024 23:38:01 +0300 Subject: [PATCH v2 2/3] Add docs for strip_in_arrays argument --- doc/src/sgml/func.sgml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 47370e581ae..129103323c5 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17179,25 +17179,31 @@ ERROR: value too long for type character(2) <indexterm> <primary>json_strip_nulls</primary> </indexterm> - <function>json_strip_nulls</function> ( <type>json</type> ) + <function>json_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type>, <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) <returnvalue>json</returnvalue> </para> <para role="func_signature"> <indexterm> <primary>jsonb_strip_nulls</primary> </indexterm> - <function>jsonb_strip_nulls</function> ( <type>jsonb</type> ) + <function>jsonb_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type>, <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) <returnvalue>jsonb</returnvalue> </para> <para> Deletes all object fields that have null values from the given JSON value, recursively. Null values that are not object fields are untouched. + If <parameter>strip_in_arrays</parameter> is true (default is false), null array elements are also stripped. </para> <para> <literal>json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]')</literal> <returnvalue>[{"f1":1},2,null,3]</returnvalue> - </para></entry> + </para> + <para> + <literal>jsonb_strip_nulls('[1,2,null,3,4]', true);</literal> + <returnvalue>[1,2,3,4]</returnvalue> + </para> + </entry> </row> <row> -- 2.48.1 [application/octet-stream] v2-0003-Add-implementation-for-json_strip_nulls-json-bool.patch (6.0K, ../../[email protected]/7-v2-0003-Add-implementation-for-json_strip_nulls-json-bool.patch) download | inline diff: From 42664c0db2032b491b1e9926748d367c421540d0 Mon Sep 17 00:00:00 2001 From: Florents Tselai <[email protected]> Date: Wed, 19 Feb 2025 23:12:58 +0200 Subject: [PATCH v2 3/3] Add implementation for json_strip_nulls(json,bool) --- src/backend/catalog/system_functions.sql | 7 ++++ src/backend/utils/adt/jsonfuncs.c | 16 +++++++- src/include/catalog/pg_proc.dat | 2 +- src/test/regress/expected/json.out | 50 ++++++++++++++++++++++++ src/test/regress/sql/json.sql | 19 +++++++++ 5 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index 54bf061036f..60306e09f0f 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -614,6 +614,13 @@ LANGUAGE INTERNAL STRICT STABLE PARALLEL SAFE AS 'jsonb_strip_nulls'; +CREATE OR REPLACE FUNCTION + json_strip_nulls(target json, strip_in_arrays boolean DEFAULT false) +RETURNS json +LANGUAGE INTERNAL +STRICT STABLE PARALLEL SAFE +AS 'json_strip_nulls'; + -- default normalization form is NFC, per SQL standard CREATE OR REPLACE FUNCTION "normalize"(text, text DEFAULT 'NFC') diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index cc74fa55a11..9f43b58dba5 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -286,6 +286,7 @@ typedef struct StripnullState JsonLexContext *lex; StringInfo strval; bool skip_next_null; + bool strip_in_arrays; } StripnullState; /* structure for generalized json/jsonb value passing */ @@ -4460,8 +4461,19 @@ sn_array_element_start(void *state, bool isnull) { StripnullState *_state = (StripnullState *) state; - if (_state->strval->data[_state->strval->len - 1] != '[') + /* If strip_in_arrays is enabled and this is a null, mark it for skipping */ + if (isnull && _state->strip_in_arrays) + { + _state->skip_next_null = true; + return JSON_SUCCESS; + } + + /* Only add a comma if this is not the first valid element */ + if (_state->strval->len > 0 && + _state->strval->data[_state->strval->len - 1] != '[') + { appendStringInfoCharMacro(_state->strval, ','); + } return JSON_SUCCESS; } @@ -4493,6 +4505,7 @@ Datum json_strip_nulls(PG_FUNCTION_ARGS) { text *json = PG_GETARG_TEXT_PP(0); + bool strip_in_arrays = PG_NARGS() == 2 ? PG_GETARG_BOOL(1) : false; StripnullState *state; JsonLexContext lex; JsonSemAction *sem; @@ -4503,6 +4516,7 @@ json_strip_nulls(PG_FUNCTION_ARGS) state->lex = makeJsonLexContext(&lex, json, true); state->strval = makeStringInfo(); state->skip_next_null = false; + state->strip_in_arrays = strip_in_arrays; sem->semstate = state; sem->object_start = sn_object_start; diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 0a812d6a23b..d0ebb4b8541 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -9238,7 +9238,7 @@ proname => 'to_json', provolatile => 's', prorettype => 'json', proargtypes => 'anyelement', prosrc => 'to_json' }, { oid => '3261', descr => 'remove object fields with null values from json', - proname => 'json_strip_nulls', prorettype => 'json', proargtypes => 'json', + proname => 'json_strip_nulls', prorettype => 'json', proargtypes => 'json bool', prosrc => 'json_strip_nulls' }, { oid => '3947', diff --git a/src/test/regress/expected/json.out b/src/test/regress/expected/json.out index 96c40911cb9..04b478cb468 100644 --- a/src/test/regress/expected/json.out +++ b/src/test/regress/expected/json.out @@ -2504,6 +2504,56 @@ select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); {"a":{},"d":{}} (1 row) +-- json_strip_nulls (strip_in_arrays=true) +select json_strip_nulls(null, true); + json_strip_nulls +------------------ + +(1 row) + +select json_strip_nulls('1', true); + json_strip_nulls +------------------ + 1 +(1 row) + +select json_strip_nulls('"a string"', true); + json_strip_nulls +------------------ + "a string" +(1 row) + +select json_strip_nulls('null', true); + json_strip_nulls +------------------ + null +(1 row) + +select json_strip_nulls('[1,2,null,3,4]', true); + json_strip_nulls +------------------ + [1,2,3,4] +(1 row) + +select json_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + json_strip_nulls +------------------------------- + {"a":1,"c":[2,3],"d":{"e":4}} +(1 row) + +select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + json_strip_nulls +--------------------- + [1,{"a":1,"c":2},3] +(1 row) + +-- an empty object is not null and should not be stripped +select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); + json_strip_nulls +------------------ + {"a":{},"d":{}} +(1 row) + -- json to tsvector select to_tsvector('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::json); to_tsvector diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql index 8251f4f4006..e9800b21ffe 100644 --- a/src/test/regress/sql/json.sql +++ b/src/test/regress/sql/json.sql @@ -814,6 +814,25 @@ select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]'); -- an empty object is not null and should not be stripped select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); +-- json_strip_nulls (strip_in_arrays=true) + +select json_strip_nulls(null, true); + +select json_strip_nulls('1', true); + +select json_strip_nulls('"a string"', true); + +select json_strip_nulls('null', true); + +select json_strip_nulls('[1,2,null,3,4]', true); + +select json_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + +select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + +-- an empty object is not null and should not be stripped +select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); + -- json to tsvector select to_tsvector('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::json); -- 2.48.1 ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-02-19 22:18 Andrew Dunstan <[email protected]> parent: Florents Tselai <[email protected]> 0 siblings, 1 reply; 19+ messages in thread From: Andrew Dunstan @ 2025-02-19 22:18 UTC (permalink / raw) To: Florents Tselai <[email protected]>; +Cc: pgsql-hackers <[email protected]> On 2025-02-19 We 4:23 PM, Florents Tselai wrote: > > >> On 18 Jan 2025, at 11:51 AM, Florents Tselai >> <[email protected]> wrote: >> >> >> >>> On 8 Jan 2025, at 6:45 PM, Andrew Dunstan <[email protected]> wrote: >>> >>> >>> On 2024-09-17 Tu 4:53 PM, Florents Tselai wrote: >>>> >>>> We could, if we're going to do anything at all in this area. >>>> Another possibility would be to provide a second optional >>>> parameter for json{b}_strip_nulls. That's probably a better way >>>> to go. >>>> >>>> Here's a patch that adds that argument (only for jsonb; no json >>>> implementation yet) >>>> >>>> >>> >>> I think it looks sane. We're not stripping a top level null, which >>> is one thing I looked out for. >>> >>> I think we need a json implementation as well, though. >>> >>> >> Thanks for having a Look, Andrew; >> if there aren’t any other objections, I’ll come back with a json >> implementation too. > > Attached is a v2 patch with the missing json implementation. > jsonb one remains the same. Please add this to the next Commitfest at https://commitfest.postgresql.org/52/ cheers andrew > > > -- Andrew Dunstan EDB:https://www.enterprisedb.com ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-02-28 17:57 Florents Tselai <[email protected]> parent: Andrew Dunstan <[email protected]> 0 siblings, 1 reply; 19+ messages in thread From: Florents Tselai @ 2025-02-28 17:57 UTC (permalink / raw) To: Andrew Dunstan <[email protected]>; +Cc: pgsql-hackers <[email protected]> > On 20 Feb 2025, at 12:18 AM, Andrew Dunstan <[email protected]> wrote: > > > > On 2025-02-19 We 4:23 PM, Florents Tselai wrote: >> >> >>> On 18 Jan 2025, at 11:51 AM, Florents Tselai <[email protected]> <mailto:[email protected]> wrote: >>> >>> >>> >>>> On 8 Jan 2025, at 6:45 PM, Andrew Dunstan <[email protected]> <mailto:[email protected]> wrote: >>>> >>>> >>>> >>>> On 2024-09-17 Tu 4:53 PM, Florents Tselai wrote: >>>>> >>>>>> We could, if we're going to do anything at all in this area. Another possibility would be to provide a second optional parameter for json{b}_strip_nulls. That's probably a better way to go. >>>>>> >>>>> Here's a patch that adds that argument (only for jsonb; no json implementation yet) >>>>> >>>>> >>>> >>>> I think it looks sane. We're not stripping a top level null, which is one thing I looked out for. >>>> >>>> I think we need a json implementation as well, though. >>>> >>>> >>>> >>> Thanks for having a Look, Andrew; >>> if there aren’t any other objections, I’ll come back with a json implementation too. >> >> Attached is a v2 patch with the missing json implementation. >> jsonb one remains the same. > > > Please add this to the next Commitfest at https://commitfest.postgresql.org/52/ > Added ; thanks https://commitfest.postgresql.org/patch/5260/ > > cheers > > > > andrew > > > >> >> >> > -- > Andrew Dunstan > EDB: https://www.enterprisedb.com <https://www.enterprisedb.com/; ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-03-06 00:10 Ian Lawrence Barwick <[email protected]> parent: Florents Tselai <[email protected]> 0 siblings, 2 replies; 19+ messages in thread From: Ian Lawrence Barwick @ 2025-03-06 00:10 UTC (permalink / raw) To: Florents Tselai <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers <[email protected]> Hi 2025年3月1日(土) 2:58 Florents Tselai <[email protected]>: > Please add this to the next Commitfest at https://commitfest.postgresql.org/52/ > > > Added ; thanks > https://commitfest.postgresql.org/patch/5260/ I see this was committed, but there's a small formatting error in the docs (extra comma in the parameter list); patch attached. Regards Ian Barwick Attachments: [text/x-patch] json_strip_nulls-doc-fix.patch (1.3K, ../../CAB8KJ=gYd5g0tcDc7oQecLkfQ0jBPBmE+QnyYQGk8MBDDXndEw@mail.gmail.com/2-json_strip_nulls-doc-fix.patch) download | inline diff: diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index f97f0ce570a..e5a3c3427ec 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17345,14 +17345,14 @@ ERROR: value too long for type character(2) <indexterm> <primary>json_strip_nulls</primary> </indexterm> - <function>json_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type>, <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) + <function>json_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type> <optional>, <parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) <returnvalue>json</returnvalue> </para> <para role="func_signature"> <indexterm> <primary>jsonb_strip_nulls</primary> </indexterm> - <function>jsonb_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type>, <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) + <function>jsonb_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type> <optional>, <parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) <returnvalue>jsonb</returnvalue> </para> <para> ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-03-06 06:30 Florents Tselai <[email protected]> parent: Ian Lawrence Barwick <[email protected]> 1 sibling, 0 replies; 19+ messages in thread From: Florents Tselai @ 2025-03-06 06:30 UTC (permalink / raw) To: Ian Lawrence Barwick <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers <[email protected]> > On 6 Mar 2025, at 2:10 AM, Ian Lawrence Barwick <[email protected]> wrote: > > Hi > > 2025年3月1日(土) 2:58 Florents Tselai <[email protected]>: >> Please add this to the next Commitfest at https://commitfest.postgresql.org/52/ >> >> >> Added ; thanks >> https://commitfest.postgresql.org/patch/5260/ > > I see this was committed, but there's a small formatting error in the docs > (extra comma in the parameter list); patch attached. > > Regards > > Ian Barwick > <json_strip_nulls-doc-fix.patch> You’re corrrect. ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-03-06 13:51 Andrew Dunstan <[email protected]> parent: Ian Lawrence Barwick <[email protected]> 1 sibling, 1 reply; 19+ messages in thread From: Andrew Dunstan @ 2025-03-06 13:51 UTC (permalink / raw) To: Ian Lawrence Barwick <[email protected]>; Florents Tselai <[email protected]>; +Cc: pgsql-hackers <[email protected]> On 2025-03-05 We 7:10 PM, Ian Lawrence Barwick wrote: > Hi > > 2025年3月1日(土) 2:58 Florents Tselai <[email protected]>: >> Please add this to the next Commitfest at https://commitfest.postgresql.org/52/ >> >> >> Added ; thanks >> https://commitfest.postgresql.org/patch/5260/ > I see this was committed, but there's a small formatting error in the docs > (extra comma in the parameter list); patch attached. > Thanks, pushed. cheers andrew -- Andrew Dunstan EDB: https://www.enterprisedb.com ^ permalink raw reply [nested|flat] 19+ messages in thread
* RE: jsonb_strip_nulls with arrays? @ 2025-03-06 14:17 Shinoda, Noriyoshi (SXD Japan FSI) <[email protected]> parent: Andrew Dunstan <[email protected]> 0 siblings, 1 reply; 19+ messages in thread From: Shinoda, Noriyoshi (SXD Japan FSI) @ 2025-03-06 14:17 UTC (permalink / raw) To: Andrew Dunstan <[email protected]>; Ian Lawrence Barwick <[email protected]>; Florents Tselai <[email protected]>; +Cc: pgsql-hackers <[email protected]> Hi, Thanks for developing the good feature. I've attached a small patch for the documentation of the json_strip_nulls function. The data type of the 'target' parameter is different between the implementation and the documentation. The implementation is json_stripe_nulls (target JSON, ...), but the current documentation says json_stripe_nulls(target JSONB, ...). Regards, Noriyoshi Shinoda -----Original Message----- From: Andrew Dunstan <[email protected]> Sent: Thursday, March 6, 2025 10:51 PM To: Ian Lawrence Barwick <[email protected]>; Florents Tselai <[email protected]> Cc: pgsql-hackers <[email protected]> Subject: Re: jsonb_strip_nulls with arrays? On 2025-03-05 We 7:10 PM, Ian Lawrence Barwick wrote: > Hi > > 2025年3月1日(土) 2:58 Florents Tselai <[email protected]>: >> Please add this to the next Commitfest at >> https://urldefense.com/v3/__https://commitfest.postgresql.org/52/__;! >> !NpxR!moyYqgSNJn8nLYGjlKKZDuERAzIwnFY8Ge_C5MHDuoPRpTJI9Ee0gsyF4IeybO- >> t--xu2idPkLF240-sxqpR$ >> >> >> Added ; thanks >> >> https://urldefense.com/v3/__https://commitfest.postgresql.org/patch/5 >> 260/__;!!NpxR!moyYqgSNJn8nLYGjlKKZDuERAzIwnFY8Ge_C5MHDuoPRpTJI9Ee0gsy >> F4IeybO-t--xu2idPkLF24zKVAj03$ > I see this was committed, but there's a small formatting error in the > docs (extra comma in the parameter list); patch attached. > Thanks, pushed. cheers andrew -- Andrew Dunstan EDB: https://urldefense.com/v3/__https://www.enterprisedb.com__;!!NpxR!moyYqgSNJn8nLYGjlKKZDuERAzIwnFY8Ge... Attachments: [application/octet-stream] json_strip_nulls_doc_v1.diff (774B, ../../DM4PR84MB17343BC3605930E0D98FE185EECA2@DM4PR84MB1734.NAMPRD84.PROD.OUTLOOK.COM/2-json_strip_nulls_doc_v1.diff) download | inline diff: diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 53565075ca7..4d6061a8458 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17345,7 +17345,7 @@ ERROR: value too long for type character(2) <indexterm> <primary>json_strip_nulls</primary> </indexterm> - <function>json_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type> <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) + <function>json_strip_nulls</function> ( <parameter>target</parameter> <type>json</type> <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> ) <returnvalue>json</returnvalue> </para> <para role="func_signature"> ^ permalink raw reply [nested|flat] 19+ messages in thread
* Re: jsonb_strip_nulls with arrays? @ 2025-03-06 15:57 Andrew Dunstan <[email protected]> parent: Shinoda, Noriyoshi (SXD Japan FSI) <[email protected]> 0 siblings, 0 replies; 19+ messages in thread From: Andrew Dunstan @ 2025-03-06 15:57 UTC (permalink / raw) To: Shinoda, Noriyoshi (SXD Japan FSI) <[email protected]>; Ian Lawrence Barwick <[email protected]>; Florents Tselai <[email protected]>; +Cc: pgsql-hackers <[email protected]> On 2025-03-06 Th 9:17 AM, Shinoda, Noriyoshi (SXD Japan FSI) wrote: > Hi, > Thanks for developing the good feature. > I've attached a small patch for the documentation of the json_strip_nulls function. The data type of the 'target' parameter is different between the implementation and the documentation. The implementation is json_stripe_nulls (target JSON, ...), but the current documentation says json_stripe_nulls(target JSONB, ...). > Argh! My glasses must have been fogged up yesterday. pushed, thanks cheers andrew -- Andrew Dunstan EDB: https://www.enterprisedb.com ^ permalink raw reply [nested|flat] 19+ messages in thread
end of thread, other threads:[~2025-03-06 15:57 UTC | newest] Thread overview: 19+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2019-05-28 18:16 [PATCH 2/6] Add pg_depend.refobjversion. Thomas Munro <[email protected]> 2019-05-28 18:16 [PATCH v15 2/7] Add pg_depend.refobjversion. Thomas Munro <[email protected]> 2019-05-28 18:16 [PATCH v17 2/7] Add pg_depend.refobjversion. Thomas Munro <[email protected]> 2019-05-28 18:16 [PATCH v16 2/7] Add pg_depend.refobjversion. Thomas Munro <[email protected]> 2019-05-28 18:16 [PATCH v14 2/7] Add pg_depend.refobjversion. Thomas Munro <[email protected]> 2019-05-28 18:16 [PATCH v18 2/6] Add pg_depend.refobjversion. Thomas Munro <[email protected]> 2019-05-28 18:16 [PATCH v16 2/7] Add pg_depend.refobjversion. Thomas Munro <[email protected]> 2023-09-25 21:39 [PATCH v2 07/11] Cleanup summary of role powers. Karl O. Pinc <[email protected]> 2024-09-17 20:53 Re: jsonb_strip_nulls with arrays? Florents Tselai <[email protected]> 2025-01-08 16:45 ` Re: jsonb_strip_nulls with arrays? Andrew Dunstan <[email protected]> 2025-01-18 09:51 ` Re: jsonb_strip_nulls with arrays? Florents Tselai <[email protected]> 2025-02-19 21:23 ` Re: jsonb_strip_nulls with arrays? Florents Tselai <[email protected]> 2025-02-19 22:18 ` Re: jsonb_strip_nulls with arrays? Andrew Dunstan <[email protected]> 2025-02-28 17:57 ` Re: jsonb_strip_nulls with arrays? Florents Tselai <[email protected]> 2025-03-06 00:10 ` Re: jsonb_strip_nulls with arrays? Ian Lawrence Barwick <[email protected]> 2025-03-06 06:30 ` Re: jsonb_strip_nulls with arrays? Florents Tselai <[email protected]> 2025-03-06 13:51 ` Re: jsonb_strip_nulls with arrays? Andrew Dunstan <[email protected]> 2025-03-06 14:17 ` RE: jsonb_strip_nulls with arrays? Shinoda, Noriyoshi (SXD Japan FSI) <[email protected]> 2025-03-06 15:57 ` Re: jsonb_strip_nulls with arrays? Andrew Dunstan <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox