~ubuntu-branches/ubuntu/lucid/postgresql-8.4/lucid-proposed

« back to all changes in this revision

Viewing changes to src/backend/parser/analyze.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt, Peter Eisentraut, Martin Pitt
  • Date: 2009-12-14 19:02:38 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20091214190238-ubwqbnzwbhbc9b9f
Tags: 8.4.2-1
Medium urgency due to security fixes.

[ Peter Eisentraut ]
* debian/control: Added Homepage
* debian/control: Added ${misc:Depends} on all packages, per lintian
* debian/control: Added versioned dependencies on the shared libraries used 
  by the libecpg-dev package
* debian/control: Removed obsolete build dependency bzip2
* debian/control: Added Vcs fields

[ Martin Pitt ]
* New upstream security/bug fix release:
  - Protect against indirect security threats caused by index functions
    changing session-local state. This change prevents allegedly-immutable
    index functions from possibly subverting a superuser's session
    (CVE-2009-4136).
  - Reject SSL certificates containing an embedded null byte in the
    common name (CN) field. This prevents unintended matching of a
    certificate to a server or client name during SSL validation
    (CVE-2009-4034).
  - Fix hash index corruption. The 8.4 change that made hash indexes keep
    entries sorted by hash value failed to update the bucket splitting and
    compaction routines to preserve the ordering. So application of either
    of those operations could lead to permanent corruption of an index, in
    the sense that searches might fail to find entries that are present. To
    deal with this, it is recommended to REINDEX any hash indexes you may
    have after installing this update.
  - Fix possible crash during backend-startup-time cache initialization.
  - Avoid crash on empty thesaurus dictionary.
  - Prevent signals from interrupting VACUUM at unsafe times.
  - Fix possible crash due to integer overflow in hash table size
    calculation.
  - Fix crash if a DROP is attempted on an internally-dependent object.
  - Fix very rare crash in inet/cidr comparisons.
  - Ensure that shared tuple-level locks held by prepared transactions
    are not ignored.
  - Fix premature drop of temporary files used for a cursor that is
    accessed within a subtransaction.
  - Fix memory leak in syslogger process when rotating to a new CSV
    logfile.
  - Fix memory leak in postmaster when re-parsing "pg_hba.conf".
  - Make FOR UPDATE/SHARE in the primary query not propagate into WITH
    queries.
  - Fix bug with a WITH RECURSIVE query immediately inside another one.
  - Fix concurrency bug in hash indexes.
  - Fix incorrect logic for GiST index page splits, when the split
    depends on a non-first column of the index.
  - Fix wrong search results for a multi-column GIN index with
    fastupdate enabled.
  - Fix bugs in WAL entry creation for GIN indexes.
  - Don't error out if recycling or removing an old WAL file fails at
    the end of checkpoint.
  - Fix PAM password processing to be more robust.
    The previous code is known to fail with the combination of the
    Linux pam_krb5 PAM module with Microsoft Active Directory as the
    domain controller. It might have problems elsewhere too, since it
    was making unjustified assumptions about what arguments the PAM
    stack would pass to it.
  - Raise the maximum authentication token (Kerberos ticket) size in
    GSSAPI and SSPI authentication methods. While the old 2000-byte limit
    was more than enough for Unix Kerberos implementations, tickets issued
    by Windows Domain Controllers can be much larger.
  - Ensure that domain constraints are enforced in constructs like
    ARRAY[...]::domain, where the domain is over an array type.
  - Fix foreign-key logic for some cases involving composite-type
    columns as foreign keys.
  - Ensure that a cursor's snapshot is not modified after it is created.
  - Fix CREATE TABLE to properly merge default expressions coming from
    different inheritance parent tables. This used to work but was broken in
    8.4.
  - Re-enable collection of access statistics for sequences. This used to
    work but was broken in 8.3.
  - Fix processing of ownership dependencies during CREATE OR REPLACE
    FUNCTION.
  - Fix incorrect handling of WHERE "x"="x" conditions.
    In some cases these could get ignored as redundant, but they aren't
    -- they're equivalent to "x" IS NOT NULL.
  - Fix incorrect plan construction when using hash aggregation to
    implement DISTINCT for textually identical volatile expressions
  - Fix Assert failure for a volatile SELECT DISTINCT ON expression
  - Fix ts_stat() to not fail on an empty tsvector value
  - Make text search parser accept underscores in XML attributes
  - Fix encoding handling in xml binary input.
    If the XML header doesn't specify an encoding, we now assume UTF-8
    by default; the previous handling was inconsistent.
  - Fix bug with calling plperl from plperlu or vice versa.
  - Fix session-lifespan memory leak when a PL/Perl function is
    redefined.
  - Ensure that Perl arrays are properly converted to PostgreSQL arrays
    when returned by a set-returning PL/Perl function.
  - Fix rare crash in exception processing in PL/Python.
  - Fix ecpg problem with comments in DECLARE CURSOR statements
  - Fix ecpg to not treat recently-added keywords as reserved words
    This affected the keywords CALLED, CATALOG, DEFINER, ENUM,
    FOLLOWING, INVOKER, OPTIONS, PARTITION, PRECEDING, RANGE, SECURITY,
    SERVER, UNBOUNDED, and WRAPPER.
  - Re-allow regular expression special characters in psql's \df
    function name parameter.
  - Put FREEZE and VERBOSE options in the right order in the VACUUM
    command that "contrib/vacuumdb" produces.
  - Fix possible leak of connections when "contrib/dblink" encounters
    an error
  - Make the postmaster ignore any application_name parameter in
    connection request packets, to improve compatibility with future
    libpq versions.
* debian/control: libreadline5-dev → libreadline-dev. (Closes: #553831)
* Add 03-sh-architecture.patch: Support Renesas' SuperH architecture, thanks
  Nobuhiro Iwamatsu! (Closes: #548847)

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
18
18
 * Portions Copyright (c) 1994, Regents of the University of California
19
19
 *
20
 
 *      $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.389.2.1 2009/08/27 20:08:12 tgl Exp $
 
20
 *      $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.389.2.3 2009/10/27 17:11:30 tgl Exp $
21
21
 *
22
22
 *-------------------------------------------------------------------------
23
23
 */
50
50
static Query *transformValuesClause(ParseState *pstate, SelectStmt *stmt);
51
51
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
52
52
static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
53
 
                                                  List **colInfo);
 
53
                                                  bool isTopLevel, List **colInfo);
 
54
static void determineRecursiveColTypes(ParseState *pstate,
 
55
                                                                           Node *larg, List *lcolinfo);
54
56
static void applyColumnNames(List *dst, List *src);
55
57
static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
56
58
static List *transformReturningList(ParseState *pstate, List *returningList);
135
137
 *              Entry point for recursively analyzing a sub-statement.
136
138
 */
137
139
Query *
138
 
parse_sub_analyze(Node *parseTree, ParseState *parentParseState)
 
140
parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
 
141
                                  CommonTableExpr *parentCTE,
 
142
                                  bool locked_from_parent)
139
143
{
140
144
        ParseState *pstate = make_parsestate(parentParseState);
141
145
        Query      *query;
142
146
 
 
147
        pstate->p_parent_cte = parentCTE;
 
148
        pstate->p_locked_from_parent = locked_from_parent;
 
149
 
143
150
        query = transformStmt(pstate, parseTree);
144
151
 
145
152
        free_parsestate(pstate);
1199
1206
         * Recursively transform the components of the tree.
1200
1207
         */
1201
1208
        sostmt = (SetOperationStmt *) transformSetOperationTree(pstate, stmt,
 
1209
                                                                                                                        true,
1202
1210
                                                                                                                        &socolinfo);
1203
1211
        Assert(sostmt && IsA(sostmt, SetOperationStmt));
1204
1212
        qry->setOperations = (Node *) sostmt;
1359
1367
 */
1360
1368
static Node *
1361
1369
transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
1362
 
                                                  List **colInfo)
 
1370
                                                  bool isTopLevel, List **colInfo)
1363
1371
{
1364
1372
        bool            isLeaf;
1365
1373
 
1418
1426
                 * of this sub-query, because they are not in the toplevel pstate's
1419
1427
                 * namespace list.
1420
1428
                 */
1421
 
                selectQuery = parse_sub_analyze((Node *) stmt, pstate);
 
1429
                selectQuery = parse_sub_analyze((Node *) stmt, pstate, NULL, false);
1422
1430
 
1423
1431
                /*
1424
1432
                 * Check for bogus references to Vars on the current query level (but
1485
1493
                op->all = stmt->all;
1486
1494
 
1487
1495
                /*
1488
 
                 * Recursively transform the child nodes.
 
1496
                 * Recursively transform the left child node.
1489
1497
                 */
1490
1498
                op->larg = transformSetOperationTree(pstate, stmt->larg,
 
1499
                                                                                         false,
1491
1500
                                                                                         &lcolinfo);
 
1501
 
 
1502
                /*
 
1503
                 * If we are processing a recursive union query, now is the time
 
1504
                 * to examine the non-recursive term's output columns and mark the
 
1505
                 * containing CTE as having those result columns.  We should do this
 
1506
                 * only at the topmost setop of the CTE, of course.
 
1507
                 */
 
1508
                if (isTopLevel &&
 
1509
                        pstate->p_parent_cte &&
 
1510
                        pstate->p_parent_cte->cterecursive)
 
1511
                        determineRecursiveColTypes(pstate, op->larg, lcolinfo);
 
1512
 
 
1513
                /*
 
1514
                 * Recursively transform the right child node.
 
1515
                 */
1492
1516
                op->rarg = transformSetOperationTree(pstate, stmt->rarg,
 
1517
                                                                                         false,
1493
1518
                                                                                         &rcolinfo);
1494
1519
 
1495
1520
                /*
1585
1610
}
1586
1611
 
1587
1612
/*
 
1613
 * Process the outputs of the non-recursive term of a recursive union
 
1614
 * to set up the parent CTE's columns
 
1615
 */
 
1616
static void
 
1617
determineRecursiveColTypes(ParseState *pstate, Node *larg, List *lcolinfo)
 
1618
{
 
1619
        Node       *node;
 
1620
        int                     leftmostRTI;
 
1621
        Query      *leftmostQuery;
 
1622
        List       *targetList;
 
1623
        ListCell   *left_tlist;
 
1624
        ListCell   *lci;
 
1625
        int                     next_resno;
 
1626
 
 
1627
        /*
 
1628
         * Find leftmost leaf SELECT
 
1629
         */
 
1630
        node = larg;
 
1631
        while (node && IsA(node, SetOperationStmt))
 
1632
                node = ((SetOperationStmt *) node)->larg;
 
1633
        Assert(node && IsA(node, RangeTblRef));
 
1634
        leftmostRTI = ((RangeTblRef *) node)->rtindex;
 
1635
        leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
 
1636
        Assert(leftmostQuery != NULL);
 
1637
 
 
1638
        /*
 
1639
         * Generate dummy targetlist using column names of leftmost select
 
1640
         * and dummy result expressions of the non-recursive term.
 
1641
         */
 
1642
        targetList = NIL;
 
1643
        left_tlist = list_head(leftmostQuery->targetList);
 
1644
        next_resno = 1;
 
1645
 
 
1646
        foreach(lci, lcolinfo)
 
1647
        {
 
1648
                Expr       *lcolexpr = (Expr *) lfirst(lci);
 
1649
                TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
 
1650
                char       *colName;
 
1651
                TargetEntry *tle;
 
1652
 
 
1653
                Assert(!lefttle->resjunk);
 
1654
                colName = pstrdup(lefttle->resname);
 
1655
                tle = makeTargetEntry(lcolexpr,
 
1656
                                                          next_resno++,
 
1657
                                                          colName,
 
1658
                                                          false);
 
1659
                targetList = lappend(targetList, tle);
 
1660
                left_tlist = lnext(left_tlist);
 
1661
        }
 
1662
 
 
1663
        /* Now build CTE's output column info using dummy targetlist */
 
1664
        analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
 
1665
}
 
1666
 
 
1667
/*
1588
1668
 * Attach column names from a ColumnDef list to a TargetEntry list
1589
1669
 * (for CREATE TABLE AS)
1590
1670
 */
1965
2045
 * This basically involves replacing names by integer relids.
1966
2046
 *
1967
2047
 * NB: if you need to change this, see also markQueryForLocking()
1968
 
 * in rewriteHandler.c, and isLockedRel() in parse_relation.c.
 
2048
 * in rewriteHandler.c, and isLockedRefname() in parse_relation.c.
1969
2049
 */
1970
2050
static void
1971
2051
transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc)
2007
2087
                                         */
2008
2088
                                        transformLockingClause(pstate, rte->subquery, allrels);
2009
2089
                                        break;
2010
 
                                case RTE_CTE:
2011
 
                                        {
2012
 
                                                /*
2013
 
                                                 * We allow FOR UPDATE/SHARE of a WITH query to be
2014
 
                                                 * propagated into the WITH, but it doesn't seem very
2015
 
                                                 * sane to allow this for a reference to an
2016
 
                                                 * outer-level WITH.  And it definitely wouldn't work
2017
 
                                                 * for a self-reference, since we're not done
2018
 
                                                 * analyzing the CTE anyway.
2019
 
                                                 */
2020
 
                                                CommonTableExpr *cte;
2021
 
 
2022
 
                                                if (rte->ctelevelsup > 0 || rte->self_reference)
2023
 
                                                        ereport(ERROR,
2024
 
                                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2025
 
                                                                         errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query")));
2026
 
                                                cte = GetCTEForRTE(pstate, rte, -1);
2027
 
                                                /* should be analyzed by now */
2028
 
                                                Assert(IsA(cte->ctequery, Query));
2029
 
                                                transformLockingClause(pstate,
2030
 
                                                                                           (Query *) cte->ctequery,
2031
 
                                                                                           allrels);
2032
 
                                        }
2033
 
                                        break;
2034
2090
                                default:
2035
 
                                        /* ignore JOIN, SPECIAL, FUNCTION RTEs */
 
2091
                                        /* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */
2036
2092
                                        break;
2037
2093
                        }
2038
2094
                }
2099
2155
                                                         parser_errposition(pstate, thisrel->location)));
2100
2156
                                                        break;
2101
2157
                                                case RTE_CTE:
2102
 
                                                        {
2103
 
                                                                /*
2104
 
                                                                 * We allow FOR UPDATE/SHARE of a WITH query
2105
 
                                                                 * to be propagated into the WITH, but it
2106
 
                                                                 * doesn't seem very sane to allow this for a
2107
 
                                                                 * reference to an outer-level WITH.  And it
2108
 
                                                                 * definitely wouldn't work for a
2109
 
                                                                 * self-reference, since we're not done
2110
 
                                                                 * analyzing the CTE anyway.
2111
 
                                                                 */
2112
 
                                                                CommonTableExpr *cte;
2113
 
 
2114
 
                                                                if (rte->ctelevelsup > 0 || rte->self_reference)
2115
 
                                                                        ereport(ERROR,
2116
 
                                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2117
 
                                                                          errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query"),
2118
 
                                                                          parser_errposition(pstate, thisrel->location)));
2119
 
                                                                cte = GetCTEForRTE(pstate, rte, -1);
2120
 
                                                                /* should be analyzed by now */
2121
 
                                                                Assert(IsA(cte->ctequery, Query));
2122
 
                                                                transformLockingClause(pstate,
2123
 
                                                                                                         (Query *) cte->ctequery,
2124
 
                                                                                                           allrels);
2125
 
                                                        }
 
2158
                                                        ereport(ERROR,
 
2159
                                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
2160
                                                                         errmsg("SELECT FOR UPDATE/SHARE cannot be applied to a WITH query"),
 
2161
                                                         parser_errposition(pstate, thisrel->location)));
2126
2162
                                                        break;
2127
2163
                                                default:
2128
2164
                                                        elog(ERROR, "unrecognized RTE type: %d",