diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/executor/nodeAgg.c | 2 | ||||
-rw-r--r-- | src/backend/executor/nodeWindowAgg.c | 19 | ||||
-rw-r--r-- | src/backend/optimizer/path/pathkeys.c | 213 | ||||
-rw-r--r-- | src/backend/utils/adt/pg_locale.c | 21 | ||||
-rw-r--r-- | src/backend/utils/adt/pg_locale_builtin.c | 7 | ||||
-rw-r--r-- | src/backend/utils/adt/pg_locale_icu.c | 7 | ||||
-rw-r--r-- | src/backend/utils/adt/pg_locale_libc.c | 23 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 8 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump_sort.c | 3 | ||||
-rw-r--r-- | src/include/lib/simplehash.h | 4 | ||||
-rw-r--r-- | src/include/nodes/memnodes.h | 2 | ||||
-rw-r--r-- | src/include/utils/pg_locale.h | 3 | ||||
-rw-r--r-- | src/test/regress/expected/constraints.out | 4 | ||||
-rw-r--r-- | src/test/regress/sql/constraints.sql | 5 |
14 files changed, 178 insertions, 143 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index a4f3d30f307..64643c3943a 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -2911,7 +2911,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) perhash = &aggstate->perhash[aggstate->current_set]; - ResetTupleHashIterator(hashtable, &perhash->hashiter); + ResetTupleHashIterator(perhash->hashtable, &perhash->hashiter); continue; } diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 47e00be7b49..aa145d4e1a9 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -3270,8 +3270,9 @@ window_gettupleslot(WindowObject winobj, int64 pos, TupleTableSlot *slot) return true; } -/* - * get tuple and evaluate in partition +/* gettuple_eval_partition + * get tuple in a patition and evaluate the window function's argument + * expression on it. */ static Datum gettuple_eval_partition(WindowObject winobj, int argno, @@ -3790,9 +3791,15 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno, continue; /* keep on moving forward or backward */ else /* need to check NULL or not */ { - /* get tuple and evaluate in partition */ - datum = gettuple_eval_partition(winobj, argno, - abs_pos, isnull, &myisout); + /* + * NOT NULL info does not exist yet. Get tuple and evaluate func + * arg in partition. We ignore the return value from + * gettuple_eval_partition because we are just interested in + * whether we are inside or outside of partition, NULL or NOT + * NULL. + */ + (void) gettuple_eval_partition(winobj, argno, + abs_pos, isnull, &myisout); if (myisout) /* out of partition? */ break; if (!*isnull) @@ -3802,7 +3809,7 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno, } } while (notnull_offset < notnull_relpos); - /* get tuple and evaluate in partition */ + /* get tuple and evaluate func arg in partition */ datum = gettuple_eval_partition(winobj, argno, abs_pos, isnull, &myisout); if (!myisout && set_mark) diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index 879dcb4608e..139fa1f875a 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -2147,174 +2147,126 @@ right_merge_direction(PlannerInfo *root, PathKey *pathkey) } /* - * pathkeys_useful_for_ordering - * Count the number of pathkeys that are useful for meeting the - * query's requested output ordering. - * - * Because we the have the possibility of incremental sort, a prefix list of - * keys is potentially useful for improving the performance of the requested - * ordering. Thus we return 0, if no valuable keys are found, or the number - * of leading keys shared by the list and the requested ordering. + * count_common_leading_pathkeys_ordered + * Returns the number of leading pathkeys which both lists have in common */ static int -pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys) +count_common_leading_pathkeys_ordered(List *keys1, List *keys2) { - int n_common_pathkeys; + int ncommon; - (void) pathkeys_count_contained_in(root->sort_pathkeys, pathkeys, - &n_common_pathkeys); + (void) pathkeys_count_contained_in(keys1, keys2, &ncommon); - return n_common_pathkeys; + return ncommon; } /* - * pathkeys_useful_for_windowing - * Count the number of pathkeys that are useful for meeting the - * query's desired sort order for window function evaluation. + * count_common_leading_pathkeys_unordered + * Returns the number of leading PathKeys in 'keys2' which exist in + * 'keys1'. */ static int -pathkeys_useful_for_windowing(PlannerInfo *root, List *pathkeys) +count_common_leading_pathkeys_unordered(List *keys1, List *keys2) { - int n_common_pathkeys; + int ncommon = 0; - (void) pathkeys_count_contained_in(root->window_pathkeys, - pathkeys, - &n_common_pathkeys); - - return n_common_pathkeys; -} - -/* - * pathkeys_useful_for_grouping - * Count the number of pathkeys that are useful for grouping (instead of - * explicit sort) - * - * Group pathkeys could be reordered to benefit from the ordering. The - * ordering may not be "complete" and may require incremental sort, but that's - * fine. So we simply count prefix pathkeys with a matching group key, and - * stop once we find the first pathkey without a match. - * - * So e.g. with pathkeys (a,b,c) and group keys (a,b,e) this determines (a,b) - * pathkeys are useful for grouping, and we might do incremental sort to get - * path ordered by (a,b,e). - * - * This logic is necessary to retain paths with ordering not matching grouping - * keys directly, without the reordering. - * - * Returns the length of pathkey prefix with matching group keys. - */ -static int -pathkeys_useful_for_grouping(PlannerInfo *root, List *pathkeys) -{ - ListCell *key; - int n = 0; - - /* no special ordering requested for grouping */ - if (root->group_pathkeys == NIL) + /* No point in searching keys2 when keys1 is empty */ + if (keys1 == NIL) return 0; - /* walk the pathkeys and search for matching group key */ - foreach(key, pathkeys) + /* walk keys2 and search for matching PathKeys in keys1 */ + foreach_node(PathKey, pathkey, keys2) { - PathKey *pathkey = (PathKey *) lfirst(key); - - /* no matching group key, we're done */ - if (!list_member_ptr(root->group_pathkeys, pathkey)) + /* + * return the number of matches so far as soon as keys1 doesn't + * contain the given keys2 key. + */ + if (!list_member_ptr(keys1, pathkey)) break; - n++; + ncommon++; } - return n; + return ncommon; } /* - * pathkeys_useful_for_distinct - * Count the number of pathkeys that are useful for DISTINCT or DISTINCT - * ON clause. - * - * DISTINCT keys could be reordered to benefit from the given pathkey list. As - * with pathkeys_useful_for_grouping, we return the number of leading keys in - * the list that are shared by the distinctClause pathkeys. + * truncate_useless_pathkeys + * Shorten the given PathKey List to just the useful PathKeys. If all + * PathKeys are useful, return the input List, otherwise return a new + * List containing only the useful PathKeys. */ -static int -pathkeys_useful_for_distinct(PlannerInfo *root, List *pathkeys) +List * +truncate_useless_pathkeys(PlannerInfo *root, + RelOptInfo *rel, + List *pathkeys) { - int n_common_pathkeys; + int nuseful; + int nuseful2; + int ntotal = list_length(pathkeys); /* - * distinct_pathkeys may have become empty if all of the pathkeys were - * determined to be redundant. Return 0 in this case. + * Here we determine how many items in 'pathkeys' might be useful for + * various Path sort ordering requirements the planner has. Operations + * such as ORDER BY require a Path's pathkeys to match the PathKeys of the + * ORDER BY in the same order, however operations such as GROUP BY and + * DISTINCT are less critical as a Unique or GroupAggregate only need to + * care that all PathKeys exist in their subpath, and don't need to care + * if they're in the same order as the clause in the query. */ - if (root->distinct_pathkeys == NIL) - return 0; + nuseful = count_common_leading_pathkeys_ordered(root->sort_pathkeys, + pathkeys); - /* walk the pathkeys and search for matching DISTINCT key */ - n_common_pathkeys = 0; - foreach_node(PathKey, pathkey, pathkeys) - { - /* no matching DISTINCT key, we're done */ - if (!list_member_ptr(root->distinct_pathkeys, pathkey)) - break; + /* Short-circuit at any point we discover *all* pathkeys are useful */ + if (nuseful == ntotal) + return pathkeys; - n_common_pathkeys++; - } + nuseful2 = count_common_leading_pathkeys_ordered(root->window_pathkeys, + pathkeys); + if (nuseful2 == ntotal) + return pathkeys; - return n_common_pathkeys; -} + nuseful = Max(nuseful, nuseful2); + nuseful2 = count_common_leading_pathkeys_ordered(root->setop_pathkeys, + pathkeys); + if (nuseful2 == ntotal) + return pathkeys; -/* - * pathkeys_useful_for_setop - * Count the number of leading common pathkeys root's 'setop_pathkeys' in - * 'pathkeys'. - */ -static int -pathkeys_useful_for_setop(PlannerInfo *root, List *pathkeys) -{ - int n_common_pathkeys; + nuseful = Max(nuseful, nuseful2); - (void) pathkeys_count_contained_in(root->setop_pathkeys, pathkeys, - &n_common_pathkeys); + /* + * Check if these pathkeys are useful for GROUP BY or DISTINCT. The order + * of the pathkeys does not matter here as Unique and GroupAggregate for + * these operations can take advantage of Paths presorted by any of the + * GROUP BY/DISTINCT pathkeys. + */ + nuseful2 = count_common_leading_pathkeys_unordered(root->group_pathkeys, + pathkeys); + if (nuseful2 == ntotal) + return pathkeys; - return n_common_pathkeys; -} + nuseful = Max(nuseful, nuseful2); + nuseful2 = count_common_leading_pathkeys_unordered(root->distinct_pathkeys, + pathkeys); -/* - * truncate_useless_pathkeys - * Shorten the given pathkey list to just the useful pathkeys. - */ -List * -truncate_useless_pathkeys(PlannerInfo *root, - RelOptInfo *rel, - List *pathkeys) -{ - int nuseful; - int nuseful2; + if (nuseful2 == ntotal) + return pathkeys; - nuseful = pathkeys_useful_for_merging(root, rel, pathkeys); - nuseful2 = pathkeys_useful_for_ordering(root, pathkeys); - if (nuseful2 > nuseful) - nuseful = nuseful2; - nuseful2 = pathkeys_useful_for_windowing(root, pathkeys); - if (nuseful2 > nuseful) - nuseful = nuseful2; - nuseful2 = pathkeys_useful_for_grouping(root, pathkeys); - if (nuseful2 > nuseful) - nuseful = nuseful2; - nuseful2 = pathkeys_useful_for_distinct(root, pathkeys); - if (nuseful2 > nuseful) - nuseful = nuseful2; - nuseful2 = pathkeys_useful_for_setop(root, pathkeys); - if (nuseful2 > nuseful) - nuseful = nuseful2; + nuseful = Max(nuseful, nuseful2); + + /* + * Finally, check how many PathKeys might be useful for Merge Joins. This + * is a bit more expensive, so do it last and only if we've not figured + * out that all the pathkeys are useful already. + */ + nuseful2 = pathkeys_useful_for_merging(root, rel, pathkeys); + nuseful = Max(nuseful, nuseful2); /* * Note: not safe to modify input list destructively, but we can avoid * copying the list if we're not actually going to change it */ - if (nuseful == 0) - return NIL; - else if (nuseful == list_length(pathkeys)) + if (nuseful == ntotal) return pathkeys; else return list_copy_head(pathkeys, nuseful); @@ -2340,9 +2292,8 @@ has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel) { if (rel->joininfo != NIL || rel->has_eclass_joins) return true; /* might be able to use pathkeys for merging */ - if (root->group_pathkeys != NIL) - return true; /* might be able to use pathkeys for grouping */ if (root->query_pathkeys != NIL) - return true; /* might be able to use them for ordering */ + return true; /* the upper planner might need them */ + return false; /* definitely useless */ } diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index 50b25445f7a..00d1e031472 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -1163,6 +1163,15 @@ init_database_collation(void) } /* + * Get database default locale. + */ +pg_locale_t +pg_database_locale(void) +{ + return pg_newlocale_from_collation(DEFAULT_COLLATION_OID); +} + +/* * Create a pg_locale_t from a collation OID. Results are cached for the * lifetime of the backend. Thus, do not free the result with freelocale(). * @@ -1493,6 +1502,18 @@ pg_iswspace(pg_wchar wc, pg_locale_t locale) return locale->ctype->wc_isspace(wc, locale); } +bool +pg_iswxdigit(pg_wchar wc, pg_locale_t locale) +{ + if (locale->ctype == NULL) + return (wc <= (pg_wchar) 127 && + ((pg_char_properties[wc] & PG_ISDIGIT) || + ((wc >= 'A' && wc <= 'F') || + (wc >= 'a' && wc <= 'f')))); + else + return locale->ctype->wc_isxdigit(wc, locale); +} + pg_wchar pg_towupper(pg_wchar wc, pg_locale_t locale) { diff --git a/src/backend/utils/adt/pg_locale_builtin.c b/src/backend/utils/adt/pg_locale_builtin.c index 526ab3c6711..3dc611b50e1 100644 --- a/src/backend/utils/adt/pg_locale_builtin.c +++ b/src/backend/utils/adt/pg_locale_builtin.c @@ -164,6 +164,12 @@ wc_isspace_builtin(pg_wchar wc, pg_locale_t locale) } static bool +wc_isxdigit_builtin(pg_wchar wc, pg_locale_t locale) +{ + return pg_u_isxdigit(wc, !locale->builtin.casemap_full); +} + +static bool char_is_cased_builtin(char ch, pg_locale_t locale) { return IS_HIGHBIT_SET(ch) || @@ -196,6 +202,7 @@ static const struct ctype_methods ctype_methods_builtin = { .wc_isprint = wc_isprint_builtin, .wc_ispunct = wc_ispunct_builtin, .wc_isspace = wc_isspace_builtin, + .wc_isxdigit = wc_isxdigit_builtin, .char_is_cased = char_is_cased_builtin, .wc_tolower = wc_tolower_builtin, .wc_toupper = wc_toupper_builtin, diff --git a/src/backend/utils/adt/pg_locale_icu.c b/src/backend/utils/adt/pg_locale_icu.c index 9f0b4eead73..05bad202669 100644 --- a/src/backend/utils/adt/pg_locale_icu.c +++ b/src/backend/utils/adt/pg_locale_icu.c @@ -212,6 +212,12 @@ wc_isspace_icu(pg_wchar wc, pg_locale_t locale) return u_isspace(wc); } +static bool +wc_isxdigit_icu(pg_wchar wc, pg_locale_t locale) +{ + return u_isxdigit(wc); +} + static const struct ctype_methods ctype_methods_icu = { .strlower = strlower_icu, .strtitle = strtitle_icu, @@ -226,6 +232,7 @@ static const struct ctype_methods ctype_methods_icu = { .wc_isprint = wc_isprint_icu, .wc_ispunct = wc_ispunct_icu, .wc_isspace = wc_isspace_icu, + .wc_isxdigit = wc_isxdigit_icu, .char_is_cased = char_is_cased_icu, .wc_toupper = toupper_icu, .wc_tolower = tolower_icu, diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c index f56b5dbdd37..34865ccf00e 100644 --- a/src/backend/utils/adt/pg_locale_libc.c +++ b/src/backend/utils/adt/pg_locale_libc.c @@ -173,6 +173,16 @@ wc_isspace_libc_sb(pg_wchar wc, pg_locale_t locale) } static bool +wc_isxdigit_libc_sb(pg_wchar wc, pg_locale_t locale) +{ +#ifndef WIN32 + return isxdigit_l((unsigned char) wc, locale->lt); +#else + return _isxdigit_l((unsigned char) wc, locale->lt); +#endif +} + +static bool wc_isdigit_libc_mb(pg_wchar wc, pg_locale_t locale) { return iswdigit_l((wint_t) wc, locale->lt); @@ -226,6 +236,16 @@ wc_isspace_libc_mb(pg_wchar wc, pg_locale_t locale) return iswspace_l((wint_t) wc, locale->lt); } +static bool +wc_isxdigit_libc_mb(pg_wchar wc, pg_locale_t locale) +{ +#ifndef WIN32 + return iswxdigit_l((wint_t) wc, locale->lt); +#else + return _iswxdigit_l((wint_t) wc, locale->lt); +#endif +} + static char char_tolower_libc(unsigned char ch, pg_locale_t locale) { @@ -313,6 +333,7 @@ static const struct ctype_methods ctype_methods_libc_sb = { .wc_isprint = wc_isprint_libc_sb, .wc_ispunct = wc_ispunct_libc_sb, .wc_isspace = wc_isspace_libc_sb, + .wc_isxdigit = wc_isxdigit_libc_sb, .char_is_cased = char_is_cased_libc, .char_tolower = char_tolower_libc, .wc_toupper = toupper_libc_sb, @@ -337,6 +358,7 @@ static const struct ctype_methods ctype_methods_libc_other_mb = { .wc_isprint = wc_isprint_libc_sb, .wc_ispunct = wc_ispunct_libc_sb, .wc_isspace = wc_isspace_libc_sb, + .wc_isxdigit = wc_isxdigit_libc_sb, .char_is_cased = char_is_cased_libc, .char_tolower = char_tolower_libc, .wc_toupper = toupper_libc_sb, @@ -357,6 +379,7 @@ static const struct ctype_methods ctype_methods_libc_utf8 = { .wc_isprint = wc_isprint_libc_mb, .wc_ispunct = wc_ispunct_libc_mb, .wc_isspace = wc_isspace_libc_mb, + .wc_isxdigit = wc_isxdigit_libc_mb, .char_is_cased = char_is_cased_libc, .char_tolower = char_tolower_libc, .wc_toupper = toupper_libc_mb, diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 890db7b08c2..4b8cd49df09 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -9351,8 +9351,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) * * We track in notnull_islocal whether the constraint was defined directly * in this table or via an ancestor, for binary upgrade. flagInhAttrs - * might modify this later; that routine is also in charge of determining - * the correct inhcount. + * might modify this later. */ if (fout->remoteVersion >= 180000) appendPQExpBufferStr(q, @@ -9369,7 +9368,10 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) "NULL AS notnull_comment,\n" "NULL AS notnull_invalidoid,\n" "false AS notnull_noinherit,\n" - "a.attislocal AS notnull_islocal,\n"); + "CASE WHEN a.attislocal THEN true\n" + " WHEN a.attnotnull AND NOT a.attislocal THEN true\n" + " ELSE false\n" + "END AS notnull_islocal,\n"); if (fout->remoteVersion >= 140000) appendPQExpBufferStr(q, diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index 2d02456664b..164c76e0864 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -385,7 +385,8 @@ DOTypeNameCompare(const void *p1, const void *p2) if (cmpval != 0) return cmpval; } - else if (obj1->objType == DO_CONSTRAINT) + else if (obj1->objType == DO_CONSTRAINT || + obj1->objType == DO_FK_CONSTRAINT) { ConstraintInfo *robj1 = *(ConstraintInfo *const *) p1; ConstraintInfo *robj2 = *(ConstraintInfo *const *) p2; diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h index 327274c2340..9622131ede6 100644 --- a/src/include/lib/simplehash.h +++ b/src/include/lib/simplehash.h @@ -1044,6 +1044,10 @@ SH_START_ITERATE_AT(SH_TYPE * tb, SH_ITERATOR * iter, uint32 at) SH_SCOPE SH_ELEMENT_TYPE * SH_ITERATE(SH_TYPE * tb, SH_ITERATOR * iter) { + /* validate sanity of the given iterator */ + Assert(iter->cur < tb->size); + Assert(iter->end < tb->size); + while (!iter->done) { SH_ELEMENT_TYPE *elem; diff --git a/src/include/nodes/memnodes.h b/src/include/nodes/memnodes.h index 5807ef805bd..f8a78095eb9 100644 --- a/src/include/nodes/memnodes.h +++ b/src/include/nodes/memnodes.h @@ -120,7 +120,7 @@ typedef struct MemoryContextData NodeTag type; /* identifies exact kind of context */ /* these two fields are placed here to minimize alignment wastage: */ - bool isReset; /* T = no space alloced since last reset */ + bool isReset; /* T = no space allocated since last reset */ bool allowInCritSection; /* allow palloc in critical section */ Size mem_allocated; /* track memory allocated for this context */ const MemoryContextMethods *methods; /* virtual function table */ diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h index 009f5334a87..86c48c34f26 100644 --- a/src/include/utils/pg_locale.h +++ b/src/include/utils/pg_locale.h @@ -110,6 +110,7 @@ struct ctype_methods bool (*wc_isprint) (pg_wchar wc, pg_locale_t locale); bool (*wc_ispunct) (pg_wchar wc, pg_locale_t locale); bool (*wc_isspace) (pg_wchar wc, pg_locale_t locale); + bool (*wc_isxdigit) (pg_wchar wc, pg_locale_t locale); pg_wchar (*wc_toupper) (pg_wchar wc, pg_locale_t locale); pg_wchar (*wc_tolower) (pg_wchar wc, pg_locale_t locale); @@ -175,6 +176,7 @@ struct pg_locale_struct }; extern void init_database_collation(void); +extern pg_locale_t pg_database_locale(void); extern pg_locale_t pg_newlocale_from_collation(Oid collid); extern char *get_collation_actual_version(char collprovider, const char *collcollate); @@ -217,6 +219,7 @@ extern bool pg_iswgraph(pg_wchar wc, pg_locale_t locale); extern bool pg_iswprint(pg_wchar wc, pg_locale_t locale); extern bool pg_iswpunct(pg_wchar wc, pg_locale_t locale); extern bool pg_iswspace(pg_wchar wc, pg_locale_t locale); +extern bool pg_iswxdigit(pg_wchar wc, pg_locale_t locale); extern pg_wchar pg_towupper(pg_wchar wc, pg_locale_t locale); extern pg_wchar pg_towlower(pg_wchar wc, pg_locale_t locale); diff --git a/src/test/regress/expected/constraints.out b/src/test/regress/expected/constraints.out index 3590d3274f0..dda67798cb3 100644 --- a/src/test/regress/expected/constraints.out +++ b/src/test/regress/expected/constraints.out @@ -1705,3 +1705,7 @@ DROP ROLE regress_constraint_comments_noaccess; CREATE DOMAIN constraint_comments_dom AS int; ALTER DOMAIN constraint_comments_dom ADD CONSTRAINT inv_ck CHECK (value > 0) NOT VALID; COMMENT ON CONSTRAINT inv_ck ON DOMAIN constraint_comments_dom IS 'comment on invalid constraint'; +-- Create a table that exercises pg_upgrade +CREATE TABLE regress_notnull1 (a integer); +CREATE TABLE regress_notnull2 () INHERITS (regress_notnull1); +ALTER TABLE ONLY regress_notnull2 ALTER COLUMN a SET NOT NULL; diff --git a/src/test/regress/sql/constraints.sql b/src/test/regress/sql/constraints.sql index 1f6dc8fd69f..0a6290bc571 100644 --- a/src/test/regress/sql/constraints.sql +++ b/src/test/regress/sql/constraints.sql @@ -1049,3 +1049,8 @@ CREATE DOMAIN constraint_comments_dom AS int; ALTER DOMAIN constraint_comments_dom ADD CONSTRAINT inv_ck CHECK (value > 0) NOT VALID; COMMENT ON CONSTRAINT inv_ck ON DOMAIN constraint_comments_dom IS 'comment on invalid constraint'; + +-- Create a table that exercises pg_upgrade +CREATE TABLE regress_notnull1 (a integer); +CREATE TABLE regress_notnull2 () INHERITS (regress_notnull1); +ALTER TABLE ONLY regress_notnull2 ALTER COLUMN a SET NOT NULL; |