diff options
author | Kevin Grittner | 2011-08-09 14:06:50 +0000 |
---|---|---|
committer | Kevin Grittner | 2011-08-09 14:06:50 +0000 |
commit | 4ab003fa8692a7c88300435ccc864efd1cf5e896 (patch) | |
tree | 508aecca2f196e92970dc96225d10bac4d735947 | |
parent | cfa9d7f040ae1a9d1fe8fbf32b6a003d251a59f0 (diff) | |
parent | 77949a2913b3cbaa7b2e2a73f014d541e251f18b (diff) |
Merge branch 'master' into bug6123bug6123
-rw-r--r-- | doc/src/sgml/ref/psql-ref.sgml | 19 | ||||
-rw-r--r-- | src/backend/access/common/reloptions.c | 39 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/path/equivclass.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 27 | ||||
-rw-r--r-- | src/backend/optimizer/util/placeholder.c | 84 | ||||
-rw-r--r-- | src/backend/postmaster/postmaster.c | 3 | ||||
-rw-r--r-- | src/bin/psql/command.c | 4 | ||||
-rw-r--r-- | src/bin/psql/describe.c | 129 | ||||
-rw-r--r-- | src/bin/psql/describe.h | 4 | ||||
-rw-r--r-- | src/bin/psql/help.c | 4 | ||||
-rw-r--r-- | src/include/access/reloptions.h | 2 | ||||
-rw-r--r-- | src/include/optimizer/placeholder.h | 4 | ||||
-rw-r--r-- | src/include/optimizer/planmain.h | 2 | ||||
-rw-r--r-- | src/test/regress/expected/foreign_data.out | 306 | ||||
-rw-r--r-- | src/test/regress/expected/join.out | 45 | ||||
-rw-r--r-- | src/test/regress/sql/join.sql | 37 |
17 files changed, 442 insertions, 271 deletions
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index e2e2abe4d3..db97df13c4 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -954,7 +954,7 @@ testdb=> <varlistentry> - <term><literal>\dc[S] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term> + <term><literal>\dc[S+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term> <listitem> <para> Lists conversions between character-set encodings. @@ -964,6 +964,8 @@ testdb=> By default, only user-created objects are shown; supply a pattern or the <literal>S</literal> modifier to include system objects. + If <literal>+</literal> is appended to the command name, each object + is listed with its associated description. </para> </listitem> </varlistentry> @@ -977,6 +979,8 @@ testdb=> If <replaceable class="parameter">pattern</replaceable> is specified, only casts whose source or target types match the pattern are listed. + If <literal>+</literal> is appended to the command name, each object + is listed with its associated description. </para> </listitem> </varlistentry> @@ -1038,7 +1042,7 @@ testdb=> <varlistentry> - <term><literal>\dD[S] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term> + <term><literal>\dD[S+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term> <listitem> <para> Lists domains. If <replaceable @@ -1047,6 +1051,8 @@ testdb=> By default, only user-created objects are shown; supply a pattern or the <literal>S</literal> modifier to include system objects. + If <literal>+</literal> is appended to the command name, each object + is listed with its associated description. </para> </listitem> </varlistentry> @@ -1092,7 +1098,7 @@ testdb=> specified, only those servers whose name matches the pattern are listed. If the form <literal>\des+</literal> is used, a full description of each server is shown, including the - server's ACL, type, version, and options. + server's ACL, type, version, options, and description. </para> </listitem> </varlistentry> @@ -1106,7 +1112,8 @@ testdb=> If <replaceable class="parameter">pattern</replaceable> is specified, only entries whose table name or schema name matches the pattern are listed. If the form <literal>\det+</literal> - is used, generic options are also displayed. + is used, generic options and the foreign table description + are also displayed. </para> </listitem> </varlistentry> @@ -1144,8 +1151,8 @@ testdb=> If <replaceable class="parameter">pattern</replaceable> is specified, only those foreign-data wrappers whose name matches the pattern are listed. If the form <literal>\dew+</literal> - is used, the ACL and options of the foreign-data wrapper are - also shown. + is used, the ACL, options, and description of the foreign-data + wrapper are also shown. </para> </listitem> </varlistentry> diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 465742556f..900b222865 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -371,8 +371,6 @@ allocate_reloption(bits32 kinds, int type, char *name, char *desc) size_t size; relopt_gen *newoption; - Assert(type != RELOPT_TYPE_STRING); - oldcxt = MemoryContextSwitchTo(TopMemoryContext); switch (type) @@ -386,6 +384,9 @@ allocate_reloption(bits32 kinds, int type, char *name, char *desc) case RELOPT_TYPE_REAL: size = sizeof(relopt_real); break; + case RELOPT_TYPE_STRING: + size = sizeof(relopt_string); + break; default: elog(ERROR, "unsupported option type"); return NULL; /* keep compiler quiet */ @@ -474,45 +475,29 @@ void add_string_reloption(bits32 kinds, char *name, char *desc, char *default_val, validate_string_relopt validator) { - MemoryContext oldcxt; relopt_string *newoption; - int default_len = 0; - - oldcxt = MemoryContextSwitchTo(TopMemoryContext); - - if (default_val) - default_len = strlen(default_val); - newoption = palloc0(sizeof(relopt_string) + default_len); + /* make sure the validator/default combination is sane */ + if (validator) + (validator) (default_val); - newoption->gen.name = pstrdup(name); - if (desc) - newoption->gen.desc = pstrdup(desc); - else - newoption->gen.desc = NULL; - newoption->gen.kinds = kinds; - newoption->gen.namelen = strlen(name); - newoption->gen.type = RELOPT_TYPE_STRING; + newoption = (relopt_string *) allocate_reloption(kinds, RELOPT_TYPE_STRING, + name, desc); newoption->validate_cb = validator; if (default_val) { - strcpy(newoption->default_val, default_val); - newoption->default_len = default_len; + newoption->default_val = MemoryContextStrdup(TopMemoryContext, + default_val); + newoption->default_len = strlen(default_val); newoption->default_isnull = false; } else { - newoption->default_val[0] = '\0'; + newoption->default_val = ""; newoption->default_len = 0; newoption->default_isnull = true; } - /* make sure the validator/default combination is sane */ - if (newoption->validate_cb) - (newoption->validate_cb) (newoption->default_val); - - MemoryContextSwitchTo(oldcxt); - add_reloption((relopt_gen *) newoption); } diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index bb38768bd4..1b264a29e2 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -3491,7 +3491,7 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel) else if (IsA(node, PlaceHolderVar)) { PlaceHolderVar *phv = (PlaceHolderVar *) node; - PlaceHolderInfo *phinfo = find_placeholder_info(root, phv); + PlaceHolderInfo *phinfo = find_placeholder_info(root, phv, false); tuple_width += phinfo->ph_width; } diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index f2beb410e7..acc4fb1a18 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -850,7 +850,7 @@ generate_base_implied_equalities_no_const(PlannerInfo *root, PVC_RECURSE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS); - add_vars_to_targetlist(root, vars, ec->ec_relids); + add_vars_to_targetlist(root, vars, ec->ec_relids, false); list_free(vars); } } diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 394cda32e5..9cfc56ea54 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -137,7 +137,7 @@ build_base_rel_tlists(PlannerInfo *root, List *final_tlist) if (tlist_vars != NIL) { - add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0)); + add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0), true); list_free(tlist_vars); } } @@ -151,10 +151,15 @@ build_base_rel_tlists(PlannerInfo *root, List *final_tlist) * * The list may also contain PlaceHolderVars. These don't necessarily * have a single owning relation; we keep their attr_needed info in - * root->placeholder_list instead. + * root->placeholder_list instead. If create_new_ph is true, it's OK + * to create new PlaceHolderInfos, and we also have to update ph_may_need; + * otherwise, the PlaceHolderInfos must already exist, and we should only + * update their ph_needed. (It should be true before deconstruct_jointree + * begins, and false after that.) */ void -add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed) +add_vars_to_targetlist(PlannerInfo *root, List *vars, + Relids where_needed, bool create_new_ph) { ListCell *temp; @@ -185,18 +190,20 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed) else if (IsA(node, PlaceHolderVar)) { PlaceHolderVar *phv = (PlaceHolderVar *) node; - PlaceHolderInfo *phinfo = find_placeholder_info(root, phv); + PlaceHolderInfo *phinfo = find_placeholder_info(root, phv, + create_new_ph); + /* Always adjust ph_needed */ phinfo->ph_needed = bms_add_members(phinfo->ph_needed, where_needed); /* - * Update ph_may_need too. This is currently only necessary when - * being called from build_base_rel_tlists, but we may as well do - * it always. + * If we are creating PlaceHolderInfos, mark them with the + * correct maybe-needed locations. Otherwise, it's too late to + * change that. */ - phinfo->ph_may_need = bms_add_members(phinfo->ph_may_need, - where_needed); + if (create_new_ph) + mark_placeholder_maybe_needed(root, phinfo, where_needed); } else elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); @@ -1035,7 +1042,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, PVC_RECURSE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS); - add_vars_to_targetlist(root, vars, relids); + add_vars_to_targetlist(root, vars, relids, false); list_free(vars); } diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c index 19862f39be..8b65245b51 100644 --- a/src/backend/optimizer/util/placeholder.c +++ b/src/backend/optimizer/util/placeholder.c @@ -24,7 +24,7 @@ /* Local functions */ static Relids find_placeholders_recurse(PlannerInfo *root, Node *jtnode); -static void find_placeholders_in_qual(PlannerInfo *root, Node *qual, +static void mark_placeholders_in_expr(PlannerInfo *root, Node *expr, Relids relids); @@ -50,7 +50,10 @@ make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels) /* * find_placeholder_info - * Fetch the PlaceHolderInfo for the given PHV; create it if not found + * Fetch the PlaceHolderInfo for the given PHV + * + * If the PlaceHolderInfo doesn't exist yet, create it if create_new_ph is + * true, else throw an error. * * This is separate from make_placeholder_expr because subquery pullup has * to make PlaceHolderVars for expressions that might not be used at all in @@ -58,10 +61,13 @@ make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels) * We build PlaceHolderInfos only for PHVs that are still present in the * simplified query passed to query_planner(). * - * Note: this should only be called after query_planner() has started. + * Note: this should only be called after query_planner() has started. Also, + * create_new_ph must not be TRUE after deconstruct_jointree begins, because + * make_outerjoininfo assumes that we already know about all placeholders. */ PlaceHolderInfo * -find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv) +find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv, + bool create_new_ph) { PlaceHolderInfo *phinfo; ListCell *lc; @@ -77,6 +83,9 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv) } /* Not found, so create it */ + if (!create_new_ph) + elog(ERROR, "too late to create a new PlaceHolderInfo"); + phinfo = makeNode(PlaceHolderInfo); phinfo->phid = phv->phid; @@ -157,7 +166,7 @@ find_placeholders_recurse(PlannerInfo *root, Node *jtnode) /* * Now process the top-level quals. */ - find_placeholders_in_qual(root, f->quals, jtrelids); + mark_placeholders_in_expr(root, f->quals, jtrelids); } else if (IsA(jtnode, JoinExpr)) { @@ -173,7 +182,7 @@ find_placeholders_recurse(PlannerInfo *root, Node *jtnode) jtrelids = bms_join(leftids, rightids); /* Process the qual clauses */ - find_placeholders_in_qual(root, j->quals, jtrelids); + mark_placeholders_in_expr(root, j->quals, jtrelids); } else { @@ -185,14 +194,15 @@ find_placeholders_recurse(PlannerInfo *root, Node *jtnode) } /* - * find_placeholders_in_qual - * Process a qual clause for find_placeholders_in_jointree. + * mark_placeholders_in_expr + * Find all PlaceHolderVars in the given expression, and mark them + * as possibly needed at the specified join level. * * relids is the syntactic join level to mark as the "maybe needed" level - * for each PlaceHolderVar found in the qual clause. + * for each PlaceHolderVar found in the expression. */ static void -find_placeholders_in_qual(PlannerInfo *root, Node *qual, Relids relids) +mark_placeholders_in_expr(PlannerInfo *root, Node *expr, Relids relids) { List *vars; ListCell *vl; @@ -201,7 +211,7 @@ find_placeholders_in_qual(PlannerInfo *root, Node *qual, Relids relids) * pull_var_clause does more than we need here, but it'll do and it's * convenient to use. */ - vars = pull_var_clause(qual, + vars = pull_var_clause(expr, PVC_RECURSE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS); foreach(vl, vars) @@ -214,26 +224,48 @@ find_placeholders_in_qual(PlannerInfo *root, Node *qual, Relids relids) continue; /* Create a PlaceHolderInfo entry if there's not one already */ - phinfo = find_placeholder_info(root, phv); - - /* Mark the PHV as possibly needed at the qual's syntactic level */ - phinfo->ph_may_need = bms_add_members(phinfo->ph_may_need, relids); + phinfo = find_placeholder_info(root, phv, true); - /* - * This is a bit tricky: the PHV's contained expression may contain - * other, lower-level PHVs. We need to get those into the - * PlaceHolderInfo list, but they aren't going to be needed where the - * outer PHV is referenced. Rather, they'll be needed where the outer - * PHV is evaluated. We can estimate that (conservatively) as the - * syntactic location of the PHV's expression. Recurse to take care - * of any such PHVs. - */ - find_placeholders_in_qual(root, (Node *) phv->phexpr, phv->phrels); + /* Mark it, and recursively process any contained placeholders */ + mark_placeholder_maybe_needed(root, phinfo, relids); } list_free(vars); } /* + * mark_placeholder_maybe_needed + * Mark a placeholder as possibly needed at the specified join level. + * + * relids is the syntactic join level to mark as the "maybe needed" level + * for the placeholder. + * + * This is called during an initial scan of the query's targetlist and quals + * before we begin deconstruct_jointree. Once we begin deconstruct_jointree, + * all active placeholders must be present in root->placeholder_list with + * their correct ph_may_need values, because make_outerjoininfo and + * update_placeholder_eval_levels require this info to be available while + * we crawl up the join tree. + */ +void +mark_placeholder_maybe_needed(PlannerInfo *root, PlaceHolderInfo *phinfo, + Relids relids) +{ + /* Mark the PHV as possibly needed at the given syntactic level */ + phinfo->ph_may_need = bms_add_members(phinfo->ph_may_need, relids); + + /* + * This is a bit tricky: the PHV's contained expression may contain other, + * lower-level PHVs. We need to get those into the PlaceHolderInfo list, + * but they aren't going to be needed where the outer PHV is referenced. + * Rather, they'll be needed where the outer PHV is evaluated. We can + * estimate that (conservatively) as the syntactic location of the PHV's + * expression. Recurse to take care of any such PHVs. + */ + mark_placeholders_in_expr(root, (Node *) phinfo->ph_var->phexpr, + phinfo->ph_var->phrels); +} + +/* * update_placeholder_eval_levels * Adjust the target evaluation levels for placeholders * @@ -353,7 +385,7 @@ fix_placeholder_input_needed_levels(PlannerInfo *root) PVC_RECURSE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS); - add_vars_to_targetlist(root, vars, eval_at); + add_vars_to_targetlist(root, vars, eval_at, false); list_free(vars); } } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 412bc96465..0696ae0182 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -2331,8 +2331,7 @@ reaper(SIGNAL_ARGS) if (max_wal_senders > 0) { ereport(LOG, - (errmsg("terminating walsender all processes to force cascaded" - "standby(s) to update timeline and reconnect"))); + (errmsg("terminating all walsender processes to force cascaded standby(s) to update timeline and reconnect"))); SignalSomeChildren(SIGUSR2, BACKEND_TYPE_WALSND); } diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 84e031dd53..d6a925e435 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -378,7 +378,7 @@ exec_command(const char *cmd, success = describeTablespaces(pattern, show_verbose); break; case 'c': - success = listConversions(pattern, show_system); + success = listConversions(pattern, show_verbose, show_system); break; case 'C': success = listCasts(pattern, show_verbose); @@ -390,7 +390,7 @@ exec_command(const char *cmd, success = objectDescription(pattern, show_system); break; case 'D': - success = listDomains(pattern, show_system); + success = listDomains(pattern, show_verbose, show_system); break; case 'f': /* function subsystem */ switch (cmd[2]) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index a8d5ddc96c..f08f917501 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2665,10 +2665,8 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) gettext_noop("Owner")); appendPQExpBuffer(&buf, - " l.lanpltrusted AS \"%s\",\n" - " d.description AS \"%s\"", - gettext_noop("Trusted"), - gettext_noop("Description")); + " l.lanpltrusted AS \"%s\"", + gettext_noop("Trusted")); if (verbose) { @@ -2686,10 +2684,12 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) } appendPQExpBuffer(&buf, + ",\n d.description AS \"%s\"" "\nFROM pg_catalog.pg_language l\n" "LEFT JOIN pg_catalog.pg_description d\n" " ON d.classoid = l.tableoid AND d.objoid = l.oid\n" - " AND d.objsubid = 0\n"); + " AND d.objsubid = 0\n", + gettext_noop("Description")); if (pattern) processSQLNamePattern(pset.db, &buf, pattern, false, false, @@ -2723,7 +2723,7 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) * Describes domains. */ bool -listDomains(const char *pattern, bool showSystem) +listDomains(const char *pattern, bool verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -2746,17 +2746,30 @@ listDomains(const char *pattern, bool showSystem) appendPQExpBuffer(&buf, " CASE WHEN t.typnotnull THEN ' not null' ELSE '' END ||\n" " CASE WHEN t.typdefault IS NOT NULL THEN ' default ' || t.typdefault ELSE '' END\n" - " ) as \"%s\",\n", - gettext_noop("Modifier")); - appendPQExpBuffer(&buf, + " ) as \"%s\",\n" " pg_catalog.array_to_string(ARRAY(\n" " SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid\n" - " ), ' ') as \"%s\"\n" - "FROM pg_catalog.pg_type t\n" - " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n" - "WHERE t.typtype = 'd'\n", + " ), ' ') as \"%s\"", + gettext_noop("Modifier"), gettext_noop("Check")); + if (verbose) + appendPQExpBuffer(&buf, + ",\n d.description as \"%s\"", + gettext_noop("Description")); + + appendPQExpBuffer(&buf, + "\nFROM pg_catalog.pg_type t\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n"); + + if (verbose) + appendPQExpBuffer(&buf, + " LEFT JOIN pg_catalog.pg_description d " + "ON d.classoid = t.tableoid AND d.objoid = t.oid " + "AND d.objsubid = 0\n"); + + appendPQExpBuffer(&buf, "WHERE t.typtype = 'd'\n"); + if (!showSystem && !pattern) appendPQExpBuffer(&buf, " AND n.nspname <> 'pg_catalog'\n" " AND n.nspname <> 'information_schema'\n"); @@ -2788,7 +2801,7 @@ listDomains(const char *pattern, bool showSystem) * Describes conversions. */ bool -listConversions(const char *pattern, bool showSystem) +listConversions(const char *pattern, bool verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -2803,9 +2816,7 @@ listConversions(const char *pattern, bool showSystem) " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n" " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n" " CASE WHEN c.condefault THEN '%s'\n" - " ELSE '%s' END AS \"%s\"\n" - "FROM pg_catalog.pg_conversion c, pg_catalog.pg_namespace n\n" - "WHERE n.oid = c.connamespace\n", + " ELSE '%s' END AS \"%s\"", gettext_noop("Schema"), gettext_noop("Name"), gettext_noop("Source"), @@ -2813,9 +2824,28 @@ listConversions(const char *pattern, bool showSystem) gettext_noop("yes"), gettext_noop("no"), gettext_noop("Default?")); + if (verbose) + appendPQExpBuffer(&buf, + ",\n d.description AS \"%s\"", + gettext_noop("Description")); + + appendPQExpBuffer(&buf, + "\nFROM pg_catalog.pg_conversion c\n" + " JOIN pg_catalog.pg_namespace n " + "ON n.oid = c.connamespace\n"); + + if (verbose) + appendPQExpBuffer(&buf, + "LEFT JOIN pg_catalog.pg_description d " + "ON d.classoid = c.tableoid\n" + " AND d.objoid = c.oid " + "AND d.objsubid = 0\n"); + + appendPQExpBuffer(&buf, "WHERE true\n"); + if (!showSystem && !pattern) - appendPQExpBuffer(&buf, " AND n.nspname <> 'pg_catalog'\n" - " AND n.nspname <> 'information_schema'\n"); + appendPQExpBuffer(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); processSQLNamePattern(pset.db, &buf, pattern, true, false, "n.nspname", "c.conname", NULL, @@ -3650,16 +3680,16 @@ listForeignDataWrappers(const char *pattern, bool verbose) initPQExpBuffer(&buf); printfPQExpBuffer(&buf, - "SELECT fdwname AS \"%s\",\n" - " pg_catalog.pg_get_userbyid(fdwowner) AS \"%s\",\n", + "SELECT fdw.fdwname AS \"%s\",\n" + " pg_catalog.pg_get_userbyid(fdw.fdwowner) AS \"%s\",\n", gettext_noop("Name"), gettext_noop("Owner")); if (pset.sversion >= 90100) appendPQExpBuffer(&buf, - " fdwhandler::pg_catalog.regproc AS \"%s\",\n", + " fdw.fdwhandler::pg_catalog.regproc AS \"%s\",\n", gettext_noop("Handler")); appendPQExpBuffer(&buf, - " fdwvalidator::pg_catalog.regproc AS \"%s\"", + " fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"", gettext_noop("Validator")); if (verbose) @@ -3669,9 +3699,20 @@ listForeignDataWrappers(const char *pattern, bool verbose) appendPQExpBuffer(&buf, ",\n fdwoptions AS \"%s\"", gettext_noop("Options")); + + if (pset.sversion >= 90100) + appendPQExpBuffer(&buf, + ",\n d.description AS \"%s\" ", + gettext_noop("Description")); } - appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper\n"); + appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n"); + + if (verbose && pset.sversion >= 90100) + appendPQExpBuffer(&buf, + "LEFT JOIN pg_catalog.pg_description d\n" + " ON d.classoid = fdw.tableoid " + "AND d.objoid = fdw.oid AND d.objsubid = 0\n"); processSQLNamePattern(pset.db, &buf, pattern, false, false, NULL, "fdwname", NULL, NULL); @@ -3729,16 +3770,24 @@ listForeignServers(const char *pattern, bool verbose) ",\n" " s.srvtype AS \"%s\",\n" " s.srvversion AS \"%s\",\n" - " s.srvoptions AS \"%s\"", + " s.srvoptions AS \"%s\",\n" + " d.description AS \"%s\"", gettext_noop("Type"), gettext_noop("Version"), - gettext_noop("Options")); + gettext_noop("Options"), + gettext_noop("Description")); } appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_foreign_server s\n" " JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n"); + if (verbose) + appendPQExpBuffer(&buf, + "LEFT JOIN pg_description d\n " + "ON d.classoid = s.tableoid AND d.objoid = s.oid " + "AND d.objsubid = 0\n"); + processSQLNamePattern(pset.db, &buf, pattern, false, false, NULL, "s.srvname", NULL, NULL); @@ -3842,18 +3891,26 @@ listForeignTables(const char *pattern, bool verbose) if (verbose) appendPQExpBuffer(&buf, - ",\n ft.ftoptions AS \"%s\"", - gettext_noop("Options")); + ",\n ft.ftoptions AS \"%s\",\n" + " d.description AS \"%s\"", + gettext_noop("Options"), + gettext_noop("Description")); - appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_foreign_table ft,"); - appendPQExpBuffer(&buf, "\n pg_catalog.pg_class c,"); - appendPQExpBuffer(&buf, "\n pg_catalog.pg_namespace n,"); - appendPQExpBuffer(&buf, "\n pg_catalog.pg_foreign_server s\n"); - appendPQExpBuffer(&buf, "\nWHERE c.oid = ft.ftrelid"); - appendPQExpBuffer(&buf, "\nAND s.oid = ft.ftserver\n"); - appendPQExpBuffer(&buf, "\nAND n.oid = c.relnamespace\n"); + appendPQExpBuffer(&buf, + "\nFROM pg_catalog.pg_foreign_table ft\n" + " INNER JOIN pg_catalog.pg_class c" + " ON c.oid = ft.ftrelid\n" + " INNER JOIN pg_catalog.pg_namespace n" + " ON n.oid = c.relnamespace\n" + " INNER JOIN pg_catalog.pg_foreign_server s" + " ON s.oid = ft.ftserver\n"); + if (verbose) + appendPQExpBuffer(&buf, + " LEFT JOIN pg_catalog.pg_description d\n" + " ON d.classoid = c.tableoid AND " + "d.objoid = c.oid AND d.objsubid = 0\n"); - processSQLNamePattern(pset.db, &buf, pattern, true, false, + processSQLNamePattern(pset.db, &buf, pattern, false, false, NULL, "n.nspname", "c.relname", NULL); appendPQExpBuffer(&buf, "ORDER BY 1, 2;"); diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 7dc9a2c154..bf4c31265e 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -61,10 +61,10 @@ extern bool listAllDbs(bool verbose); extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); /* \dD */ -extern bool listDomains(const char *pattern, bool showSystem); +extern bool listDomains(const char *pattern, bool verbose, bool showSystem); /* \dc */ -extern bool listConversions(const char *pattern, bool showSystem); +extern bool listConversions(const char *pattern, bool verbose, bool showSystem); /* \dC */ extern bool listCasts(const char *pattern, bool verbose); diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index d3b8c170fa..b99ba3acfb 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -195,11 +195,11 @@ slashUsage(unsigned short int pager) fprintf(output, _(" \\d[S+] NAME describe table, view, sequence, or index\n")); fprintf(output, _(" \\da[S] [PATTERN] list aggregates\n")); fprintf(output, _(" \\db[+] [PATTERN] list tablespaces\n")); - fprintf(output, _(" \\dc[S] [PATTERN] list conversions\n")); + fprintf(output, _(" \\dc[S+] [PATTERN] list conversions\n")); fprintf(output, _(" \\dC[+] [PATTERN] list casts\n")); fprintf(output, _(" \\dd[S] [PATTERN] show comments on objects\n")); fprintf(output, _(" \\ddp [PATTERN] list default privileges\n")); - fprintf(output, _(" \\dD[S] [PATTERN] list domains\n")); + fprintf(output, _(" \\dD[S+] [PATTERN] list domains\n")); fprintf(output, _(" \\det[+] [PATTERN] list foreign tables\n")); fprintf(output, _(" \\des[+] [PATTERN] list foreign servers\n")); fprintf(output, _(" \\deu[+] [PATTERN] list user mappings\n")); diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index c7709cc058..14f50345bb 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -108,7 +108,7 @@ typedef struct relopt_string int default_len; bool default_isnull; validate_string_relopt validate_cb; - char default_val[1]; /* variable length, zero-terminated */ + char *default_val; } relopt_string; /* This is the table datatype for fillRelOptions */ diff --git a/src/include/optimizer/placeholder.h b/src/include/optimizer/placeholder.h index cce9e1ef1b..f112419fd5 100644 --- a/src/include/optimizer/placeholder.h +++ b/src/include/optimizer/placeholder.h @@ -20,8 +20,10 @@ extern PlaceHolderVar *make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels); extern PlaceHolderInfo *find_placeholder_info(PlannerInfo *root, - PlaceHolderVar *phv); + PlaceHolderVar *phv, bool create_new_ph); extern void find_placeholders_in_jointree(PlannerInfo *root); +extern void mark_placeholder_maybe_needed(PlannerInfo *root, + PlaceHolderInfo *phinfo, Relids relids); extern void update_placeholder_eval_levels(PlannerInfo *root, SpecialJoinInfo *new_sjinfo); extern void fix_placeholder_input_needed_levels(PlannerInfo *root); diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 5261691af6..69ba6b6923 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -92,7 +92,7 @@ extern int join_collapse_limit; extern void add_base_rels_to_query(PlannerInfo *root, Node *jtnode); extern void build_base_rel_tlists(PlannerInfo *root, List *final_tlist); extern void add_vars_to_targetlist(PlannerInfo *root, List *vars, - Relids where_needed); + Relids where_needed, bool create_new_ph); extern List *deconstruct_jointree(PlannerInfo *root); extern void distribute_restrictinfo_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo); diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out index 45292b5fde..ef13f2729f 100644 --- a/src/test/regress/expected/foreign_data.out +++ b/src/test/regress/expected/foreign_data.out @@ -52,12 +52,12 @@ ERROR: foreign-data wrapper "foo" already exists DROP FOREIGN DATA WRAPPER foo; CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1'); \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+------------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | - | | {testing=1} - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+-------------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | - | | {testing=1} | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) DROP FOREIGN DATA WRAPPER foo; @@ -65,12 +65,12 @@ CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', testing '2'); -- ERROR ERROR: option "testing" provided more than once CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', another '2'); \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+----------------------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | - | | {testing=1,another=2} - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+-----------------------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | - | | {testing=1,another=2} | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) DROP FOREIGN DATA WRAPPER foo; @@ -81,12 +81,12 @@ HINT: Must be superuser to create a foreign-data wrapper. RESET ROLE; CREATE FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator; \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+--------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | postgresql_fdw_validator | | - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+---------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | postgresql_fdw_validator | | | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) -- ALTER FOREIGN DATA WRAPPER @@ -98,12 +98,12 @@ ALTER FOREIGN DATA WRAPPER foo VALIDATOR bar; -- ERROR ERROR: function bar(text[], oid) does not exist ALTER FOREIGN DATA WRAPPER foo NO VALIDATOR; \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+--------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | - | | - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+---------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | - | | | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '1', b '2'); @@ -113,34 +113,34 @@ ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP c); -- ERROR ERROR: option "c" not found ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD x '1', DROP x); \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+----------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | - | | {a=1,b=2} - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+-----------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | - | | {a=1,b=2} | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP a, SET b '3', ADD c '4'); \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+----------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | - | | {b=3,c=4} - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+-----------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | - | | {b=3,c=4} | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '2'); ALTER FOREIGN DATA WRAPPER foo OPTIONS (b '4'); -- ERROR ERROR: option "b" provided more than once \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+--------------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | - | | {b=3,c=4,a=2} - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+---------------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | - | | {b=3,c=4,a=2} | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) SET ROLE regress_test_role; @@ -150,12 +150,12 @@ HINT: Must be superuser to alter a foreign-data wrapper. SET ROLE regress_test_role_super; ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD d '5'); \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+------------------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | - | | {b=3,c=4,a=2,d=5} - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+-------------------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | - | | {b=3,c=4,a=2,d=5} | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) ALTER FOREIGN DATA WRAPPER foo OWNER TO regress_test_role; -- ERROR @@ -169,12 +169,12 @@ ERROR: permission denied to alter foreign-data wrapper "foo" HINT: Must be superuser to alter a foreign-data wrapper. RESET ROLE; \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------------+---------+--------------------------+-------------------+------------------- - dummy | foreign_data_user | - | - | | - foo | regress_test_role_super | - | - | | {b=3,c=4,a=2,d=5} - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------------+---------+--------------------------+-------------------+-------------------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | regress_test_role_super | - | - | | {b=3,c=4,a=2,d=5} | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) -- DROP FOREIGN DATA WRAPPER @@ -183,12 +183,12 @@ ERROR: foreign-data wrapper "nonexistent" does not exist DROP FOREIGN DATA WRAPPER IF EXISTS nonexistent; NOTICE: foreign-data wrapper "nonexistent" does not exist, skipping \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------------+---------+--------------------------+-------------------+------------------- - dummy | foreign_data_user | - | - | | - foo | regress_test_role_super | - | - | | {b=3,c=4,a=2,d=5} - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------------+---------+--------------------------+-------------------+-------------------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | regress_test_role_super | - | - | | {b=3,c=4,a=2,d=5} | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) DROP ROLE regress_test_role_super; -- ERROR @@ -203,11 +203,11 @@ ALTER ROLE regress_test_role_super SUPERUSER; DROP FOREIGN DATA WRAPPER foo; DROP ROLE regress_test_role_super; \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+--------- - dummy | foreign_data_user | - | - | | - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+---------+------------- + dummy | foreign_data_user | - | - | | | useless + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (2 rows) CREATE FOREIGN DATA WRAPPER foo; @@ -215,19 +215,19 @@ CREATE SERVER s1 FOREIGN DATA WRAPPER foo; COMMENT ON SERVER s1 IS 'foreign server'; CREATE USER MAPPING FOR current_user SERVER s1; \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+--------- - dummy | foreign_data_user | - | - | | - foo | foreign_data_user | - | - | | - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+---------+------------- + dummy | foreign_data_user | - | - | | | useless + foo | foreign_data_user | - | - | | | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) \des+ - List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options -------+-------------------+----------------------+-------------------+------+---------+--------- - s1 | foreign_data_user | foo | | | | + List of foreign servers + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options | Description +------+-------------------+----------------------+-------------------+------+---------+---------+---------------- + s1 | foreign_data_user | foo | | | | | foreign server (1 row) \deu+ @@ -252,17 +252,17 @@ NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to server s1 drop cascades to user mapping for foreign_data_user \dew+ - List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | Options -------------+-------------------+---------+--------------------------+-------------------+--------- - dummy | foreign_data_user | - | - | | - postgresql | foreign_data_user | - | postgresql_fdw_validator | | + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | Options | Description +------------+-------------------+---------+--------------------------+-------------------+---------+------------- + dummy | foreign_data_user | - | - | | | useless + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (2 rows) \des+ - List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options -------+-------+----------------------+-------------------+------+---------+--------- + List of foreign servers + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options | Description +------+-------+----------------------+-------------------+------+---------+---------+------------- (0 rows) \deu+ @@ -289,17 +289,17 @@ ERROR: invalid option "foo" HINT: Valid options in this context are: authtype, service, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (host 'localhost', dbname 's8db'); \des+ - List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options -------+-------------------+----------------------+-------------------+--------+---------+------------------------------ - s1 | foreign_data_user | foo | | | | - s2 | foreign_data_user | foo | | | | {host=a,dbname=b} - s3 | foreign_data_user | foo | | oracle | | - s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} - s5 | foreign_data_user | foo | | | 15.0 | - s6 | foreign_data_user | foo | | | 16.0 | {host=a,dbname=b} - s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} - s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} + List of foreign servers + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options | Description +------+-------------------+----------------------+-------------------+--------+---------+------------------------------+------------- + s1 | foreign_data_user | foo | | | | | + s2 | foreign_data_user | foo | | | | {host=a,dbname=b} | + s3 | foreign_data_user | foo | | oracle | | | + s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} | + s5 | foreign_data_user | foo | | | 15.0 | | + s6 | foreign_data_user | foo | | | 16.0 | {host=a,dbname=b} | + s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} | + s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} | (8 rows) SET ROLE regress_test_role; @@ -311,18 +311,18 @@ SET ROLE regress_test_role; CREATE SERVER t1 FOREIGN DATA WRAPPER foo; RESET ROLE; \des+ - List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options -------+-------------------+----------------------+-------------------+--------+---------+------------------------------ - s1 | foreign_data_user | foo | | | | - s2 | foreign_data_user | foo | | | | {host=a,dbname=b} - s3 | foreign_data_user | foo | | oracle | | - s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} - s5 | foreign_data_user | foo | | | 15.0 | - s6 | foreign_data_user | foo | | | 16.0 | {host=a,dbname=b} - s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} - s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} - t1 | regress_test_role | foo | | | | + List of foreign servers + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options | Description +------+-------------------+----------------------+-------------------+--------+---------+------------------------------+------------- + s1 | foreign_data_user | foo | | | | | + s2 | foreign_data_user | foo | | | | {host=a,dbname=b} | + s3 | foreign_data_user | foo | | oracle | | | + s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} | + s5 | foreign_data_user | foo | | | 15.0 | | + s6 | foreign_data_user | foo | | | 16.0 | {host=a,dbname=b} | + s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} | + s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} | + t1 | regress_test_role | foo | | | | | (9 rows) REVOKE USAGE ON FOREIGN DATA WRAPPER foo FROM regress_test_role; @@ -335,19 +335,19 @@ GRANT regress_test_indirect TO regress_test_role; SET ROLE regress_test_role; CREATE SERVER t2 FOREIGN DATA WRAPPER foo; \des+ - List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options -------+-------------------+----------------------+-------------------+--------+---------+------------------------------ - s1 | foreign_data_user | foo | | | | - s2 | foreign_data_user | foo | | | | {host=a,dbname=b} - s3 | foreign_data_user | foo | | oracle | | - s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} - s5 | foreign_data_user | foo | | | 15.0 | - s6 | foreign_data_user | foo | | | 16.0 | {host=a,dbname=b} - s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} - s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} - t1 | regress_test_role | foo | | | | - t2 | regress_test_role | foo | | | | + List of foreign servers + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options | Description +------+-------------------+----------------------+-------------------+--------+---------+------------------------------+------------- + s1 | foreign_data_user | foo | | | | | + s2 | foreign_data_user | foo | | | | {host=a,dbname=b} | + s3 | foreign_data_user | foo | | oracle | | | + s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} | + s5 | foreign_data_user | foo | | | 15.0 | | + s6 | foreign_data_user | foo | | | 16.0 | {host=a,dbname=b} | + s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} | + s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} | + t1 | regress_test_role | foo | | | | | + t2 | regress_test_role | foo | | | | | (10 rows) RESET ROLE; @@ -365,21 +365,21 @@ ALTER SERVER s3 OPTIONS (tnsname 'orcl', port '1521'); GRANT USAGE ON FOREIGN SERVER s1 TO regress_test_role; GRANT USAGE ON FOREIGN SERVER s6 TO regress_test_role2 WITH GRANT OPTION; \des+ - List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options -------+-------------------+----------------------+-----------------------------------------+--------+---------+------------------------------ - s1 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 1.0 | {servername=s1} - | | | regress_test_role=U/foreign_data_user | | | - s2 | foreign_data_user | foo | | | 1.1 | {host=a,dbname=b} - s3 | foreign_data_user | foo | | oracle | | {tnsname=orcl,port=1521} - s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} - s5 | foreign_data_user | foo | | | 15.0 | - s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 16.0 | {host=a,dbname=b} - | | | regress_test_role2=U*/foreign_data_user | | | - s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} - s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} - t1 | regress_test_role | foo | | | | - t2 | regress_test_role | foo | | | | + List of foreign servers + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options | Description +------+-------------------+----------------------+-----------------------------------------+--------+---------+------------------------------+------------- + s1 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 1.0 | {servername=s1} | + | | | regress_test_role=U/foreign_data_user | | | | + s2 | foreign_data_user | foo | | | 1.1 | {host=a,dbname=b} | + s3 | foreign_data_user | foo | | oracle | | {tnsname=orcl,port=1521} | + s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} | + s5 | foreign_data_user | foo | | | 15.0 | | + s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 16.0 | {host=a,dbname=b} | + | | | regress_test_role2=U*/foreign_data_user | | | | + s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} | + s8 | foreign_data_user | postgresql | | | | {host=localhost,dbname=s8db} | + t1 | regress_test_role | foo | | | | | + t2 | regress_test_role | foo | | | | | (10 rows) SET ROLE regress_test_role; @@ -416,21 +416,21 @@ ERROR: role "regress_test_indirect" cannot be dropped because some objects depe DETAIL: owner of server s1 privileges for foreign-data wrapper foo \des+ - List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options -------+-----------------------+----------------------+-----------------------------------------+--------+---------+--------------------------------- - s1 | regress_test_indirect | foo | foreign_data_user=U/foreign_data_user +| | 1.1 | {servername=s1} - | | | regress_test_role=U/foreign_data_user | | | - s2 | foreign_data_user | foo | | | 1.1 | {host=a,dbname=b} - s3 | foreign_data_user | foo | | oracle | | {tnsname=orcl,port=1521} - s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} - s5 | foreign_data_user | foo | | | 15.0 | - s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 16.0 | {host=a,dbname=b} - | | | regress_test_role2=U*/foreign_data_user | | | - s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} - s8 | foreign_data_user | postgresql | | | | {dbname=db1,connect_timeout=30} - t1 | regress_test_role | foo | | | | - t2 | regress_test_role | foo | | | | + List of foreign servers + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | Options | Description +------+-----------------------+----------------------+-----------------------------------------+--------+---------+---------------------------------+------------- + s1 | regress_test_indirect | foo | foreign_data_user=U/foreign_data_user +| | 1.1 | {servername=s1} | + | | | regress_test_role=U/foreign_data_user | | | | + s2 | foreign_data_user | foo | | | 1.1 | {host=a,dbname=b} | + s3 | foreign_data_user | foo | | oracle | | {tnsname=orcl,port=1521} | + s4 | foreign_data_user | foo | | oracle | | {host=a,dbname=b} | + s5 | foreign_data_user | foo | | | 15.0 | | + s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 16.0 | {host=a,dbname=b} | + | | | regress_test_role2=U*/foreign_data_user | | | | + s7 | foreign_data_user | foo | | oracle | 17.0 | {host=a,dbname=b} | + s8 | foreign_data_user | postgresql | | | | {dbname=db1,connect_timeout=30} | + t1 | regress_test_role | foo | | | | | + t2 | regress_test_role | foo | | | | | (10 rows) -- DROP SERVER @@ -663,10 +663,10 @@ Server: sc Has OIDs: no \det+ - List of foreign tables - Schema | Table | Server | Options ---------+-------+--------+---------------------------- - public | ft1 | sc | {"delimiter=,","quote=\""} + List of foreign tables + Schema | Table | Server | Options | Description +--------+-------+--------+----------------------------+------------- + public | ft1 | sc | {"delimiter=,","quote=\""} | ft1 (1 row) CREATE INDEX id_ft1_c2 ON ft1 (c2); -- ERROR diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 178214b4b9..a54000b27b 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -2489,6 +2489,51 @@ order by c.name; rollback; -- +-- test incorrect handling of placeholders that only appear in targetlists, +-- per bug #6154 +-- +SELECT * FROM +( SELECT 1 as key1 ) sub1 +LEFT JOIN +( SELECT sub3.key3, sub4.value2, COALESCE(sub4.value2, 66) as value3 FROM + ( SELECT 1 as key3 ) sub3 + LEFT JOIN + ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM + ( SELECT 1 as key5 ) sub5 + LEFT JOIN + ( SELECT 2 as key6, 42 as value1 ) sub6 + ON sub5.key5 = sub6.key6 + ) sub4 + ON sub4.key5 = sub3.key3 +) sub2 +ON sub1.key1 = sub2.key3; + key1 | key3 | value2 | value3 +------+------+--------+-------- + 1 | 1 | 1 | 1 +(1 row) + +-- test the path using join aliases, too +SELECT * FROM +( SELECT 1 as key1 ) sub1 +LEFT JOIN +( SELECT sub3.key3, value2, COALESCE(value2, 66) as value3 FROM + ( SELECT 1 as key3 ) sub3 + LEFT JOIN + ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM + ( SELECT 1 as key5 ) sub5 + LEFT JOIN + ( SELECT 2 as key6, 42 as value1 ) sub6 + ON sub5.key5 = sub6.key6 + ) sub4 + ON sub4.key5 = sub3.key3 +) sub2 +ON sub1.key1 = sub2.key3; + key1 | key3 | value2 | value3 +------+------+--------+-------- + 1 | 1 | 1 | 1 +(1 row) + +-- -- test the corner cases FULL JOIN ON TRUE and FULL JOIN ON FALSE -- select * from int4_tbl a full join int4_tbl b on true; diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 3012031fce..1be80b8aeb 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -603,6 +603,43 @@ order by c.name; rollback; -- +-- test incorrect handling of placeholders that only appear in targetlists, +-- per bug #6154 +-- +SELECT * FROM +( SELECT 1 as key1 ) sub1 +LEFT JOIN +( SELECT sub3.key3, sub4.value2, COALESCE(sub4.value2, 66) as value3 FROM + ( SELECT 1 as key3 ) sub3 + LEFT JOIN + ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM + ( SELECT 1 as key5 ) sub5 + LEFT JOIN + ( SELECT 2 as key6, 42 as value1 ) sub6 + ON sub5.key5 = sub6.key6 + ) sub4 + ON sub4.key5 = sub3.key3 +) sub2 +ON sub1.key1 = sub2.key3; + +-- test the path using join aliases, too +SELECT * FROM +( SELECT 1 as key1 ) sub1 +LEFT JOIN +( SELECT sub3.key3, value2, COALESCE(value2, 66) as value3 FROM + ( SELECT 1 as key3 ) sub3 + LEFT JOIN + ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM + ( SELECT 1 as key5 ) sub5 + LEFT JOIN + ( SELECT 2 as key6, 42 as value1 ) sub6 + ON sub5.key5 = sub6.key6 + ) sub4 + ON sub4.key5 = sub3.key3 +) sub2 +ON sub1.key1 = sub2.key3; + +-- -- test the corner cases FULL JOIN ON TRUE and FULL JOIN ON FALSE -- select * from int4_tbl a full join int4_tbl b on true; |