~ubuntu-branches/ubuntu/quantal/postgresql-9.1/quantal-updates

« back to all changes in this revision

Viewing changes to contrib/dblink/dblink.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2012-06-04 06:47:45 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20120604064745-dvs00jnur0vgkwqs
Tags: 9.1.4-1
* Urgency medium due to security fixes.
* New upstream bug fix/security release:
  - Fix incorrect password transformation in "contrib/pgcrypto"'s DES
    crypt() function.
    If a password string contained the byte value 0x80, the remainder
    of the password was ignored, causing the password to be much weaker
    than it appeared. With this fix, the rest of the string is properly
    included in the DES hash. Any stored password values that are
    affected by this bug will thus no longer match, so the stored
    values may need to be updated. (CVE-2012-2143)
  - Ignore SECURITY DEFINER and SET attributes for a procedural
    language's call handler. Applying such attributes to a call handler
    could crash the server. (CVE-2012-2655)
  - Make "contrib/citext"'s upgrade script fix collations of citext
    arrays and domains over citext.
    Release 9.1.2 provided a fix for collations of citext columns and
    indexes in databases upgraded or reloaded from pre-9.1
    installations, but that fix was incomplete: it neglected to handle
    arrays and domains over citext. This release extends the module's
    upgrade script to handle these cases. As before, if you have
    already run the upgrade script, you'll need to run the collation
    update commands by hand instead. See the 9.1.2 release notes for
    more information about doing this.
  - Allow numeric timezone offsets in timestamp input to be up to 16
    hours away from UTC. Some historical time zones have offsets larger than
    15 hours, the previous limit. This could result in dumped data values
    being rejected during reload.
  - Fix timestamp conversion to cope when the given time is exactly the
    last DST transition time for the current timezone.
    This oversight has been there a long time, but was not noticed
    previously because most DST-using zones are presumed to have an
    indefinite sequence of future DST transitions.
  - Fix text to name and char to name casts to perform string
    truncation correctly in multibyte encodings.
  - Fix memory copying bug in to_tsquery().
  - Ensure txid_current() reports the correct epoch when executed in
    hot standby.
  - Fix planner's handling of outer PlaceHolderVars within subqueries.
    This bug concerns sub-SELECTs that reference variables coming from
    the nullable side of an outer join of the surrounding query. In
    9.1, queries affected by this bug would fail with "ERROR:
    Upper-level PlaceHolderVar found where not expected". But in 9.0
    and 8.4, you'd silently get possibly-wrong answers, since the value
    transmitted into the subquery wouldn't go to null when it should.
  - Fix planning of UNION ALL subqueries with output columns that are
    not simple variables.
    Planning of such cases got noticeably worse in 9.1 as a result of a
    misguided fix for "MergeAppend child's targetlist doesn't match
    MergeAppend" errors. Revert that fix and do it another way.
  - Fix slow session startup when pg_attribute is very large.
    If pg_attribute exceeds one-fourth of shared_buffers, cache
    rebuilding code that is sometimes needed during session start would
    trigger the synchronized-scan logic, causing it to take many times
    longer than normal. The problem was particularly acute if many new
    sessions were starting at once.
  - Ensure sequential scans check for query cancel reasonably often.
    A scan encountering many consecutive pages that contain no live
    tuples would not respond to interrupts meanwhile.
  - Ensure the Windows implementation of PGSemaphoreLock() clears
    ImmediateInterruptOK before returning.
    This oversight meant that a query-cancel interrupt received later
    in the same query could be accepted at an unsafe time, with
    unpredictable but not good consequences.
  - Show whole-row variables safely when printing views or rules.
    Corner cases involving ambiguous names (that is, the name could be
    either a table or column name of the query) were printed in an
    ambiguous way, risking that the view or rule would be interpreted
    differently after dump and reload. Avoid the ambiguous case by
    attaching a no-op cast.
  - Fix "COPY FROM" to properly handle null marker strings that
    correspond to invalid encoding.
    A null marker string such as E'\\0' should work, and did work in
    the past, but the case got broken in 8.4.
  - Fix "EXPLAIN VERBOSE" for writable CTEs containing RETURNING
    clauses.
  - Fix "PREPARE TRANSACTION" to work correctly in the presence of
    advisory locks.
    Historically, "PREPARE TRANSACTION" has simply ignored any
    session-level advisory locks the session holds, but this case was
    accidentally broken in 9.1.
  - Fix truncation of unlogged tables.
  - Ignore missing schemas during non-interactive assignments of
    search_path.
    This re-aligns 9.1's behavior with that of older branches.
    Previously 9.1 would throw an error for nonexistent schemas
    mentioned in search_path settings obtained from places such as
    "ALTER DATABASE SET".
  - Fix bugs with temporary or transient tables used in extension
    scripts.
    This includes cases such as a rewriting "ALTER TABLE" within an
    extension update script, since that uses a transient table behind
    the scenes.
  - Ensure autovacuum worker processes perform stack depth checking
    properly.
    Previously, infinite recursion in a function invoked by
    auto-"ANALYZE" could crash worker processes.
  - Fix logging collector to not lose log coherency under high load.
    The collector previously could fail to reassemble large messages if
    it got too busy.
  - Fix logging collector to ensure it will restart file rotation after
    receiving SIGHUP.
  - Fix "too many LWLocks taken" failure in GiST indexes.
  - Fix WAL replay logic for GIN indexes to not fail if the index was
    subsequently dropped.
  - Correctly detect SSI conflicts of prepared transactions after a
    crash.
  - Avoid synchronous replication delay when committing a transaction
    that only modified temporary tables.
    In such a case the transaction's commit record need not be flushed
    to standby servers, but some of the code didn't know that and
    waited for it to happen anyway.
  - Fix error handling in pg_basebackup.
  - Fix walsender to not go into a busy loop if connection is
    terminated.
  - Fix memory leak in PL/pgSQL's "RETURN NEXT" command.
  - Fix PL/pgSQL's "GET DIAGNOSTICS" command when the target is the
    function's first variable.
  - Ensure that PL/Perl package-qualifies the _TD variable.
    This bug caused trigger invocations to fail when they are nested
    within a function invocation that changes the current package.
  - Fix PL/Python functions returning composite types to accept a
    string for their result value.
    This case was accidentally broken by the 9.1 additions to allow a
    composite result value to be supplied in other formats, such as
    dictionaries.
  - Fix potential access off the end of memory in psql's expanded
    display ("\x") mode.
  - Fix several performance problems in pg_dump when the database
    contains many objects.
    pg_dump could get very slow if the database contained many schemas,
    or if many objects are in dependency loops, or if there are many
    owned sequences.
  - Fix memory and file descriptor leaks in pg_restore when reading a
    directory-format archive.
  - Fix pg_upgrade for the case that a database stored in a non-default
    tablespace contains a table in the cluster's default tablespace.
  - In ecpg, fix rare memory leaks and possible overwrite of one byte
    after the sqlca_t structure.
  - Fix "contrib/dblink"'s dblink_exec() to not leak temporary database
    connections upon error.
  - Fix "contrib/dblink" to report the correct connection name in error
    messages.
  - Fix "contrib/vacuumlo" to use multiple transactions when dropping
    many large objects.
    This change avoids exceeding max_locks_per_transaction when many
    objects need to be dropped. The behavior can be adjusted with the
    new -l (limit) option.
* debian/control: Bump debhelper build dependency to >= 8, as it does not
  build with earlier versions.
* debian/control: Move bzr branches to alioth, so that other members of
  pkg-postgresql can commit. Update Vcs-* tags.
* debian/control: Set Maintainer: to pkg-postgresql group, and move myself
  to Uploaders:.

Show diffs side-by-side

added added

removed removed

Lines of Context:
81
81
 * Internal declarations
82
82
 */
83
83
static Datum dblink_record_internal(FunctionCallInfo fcinfo, bool is_async);
 
84
static void prepTuplestoreResult(FunctionCallInfo fcinfo);
84
85
static void materializeResult(FunctionCallInfo fcinfo, PGresult *res);
85
86
static remoteConn *getConnectionByName(const char *name);
86
87
static HTAB *createConnHash(void);
167
168
        do { \
168
169
                        char *conname_or_str = text_to_cstring(PG_GETARG_TEXT_PP(0)); \
169
170
                        rconn = getConnectionByName(conname_or_str); \
170
 
                        if(rconn) \
 
171
                        if (rconn) \
171
172
                        { \
172
173
                                conn = rconn->conn; \
 
174
                                conname = conname_or_str; \
173
175
                        } \
174
176
                        else \
175
177
                        { \
197
199
 
198
200
#define DBLINK_GET_NAMED_CONN \
199
201
        do { \
200
 
                        char *conname = text_to_cstring(PG_GETARG_TEXT_PP(0)); \
 
202
                        conname = text_to_cstring(PG_GETARG_TEXT_PP(0)); \
201
203
                        rconn = getConnectionByName(conname); \
202
 
                        if(rconn) \
 
204
                        if (rconn) \
203
205
                                conn = rconn->conn; \
204
206
                        else \
205
207
                                DBLINK_CONN_NOT_AVAIL; \
508
510
Datum
509
511
dblink_fetch(PG_FUNCTION_ARGS)
510
512
{
511
 
        ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
512
513
        PGresult   *res = NULL;
513
514
        char       *conname = NULL;
514
515
        remoteConn *rconn = NULL;
518
519
        int                     howmany = 0;
519
520
        bool            fail = true;    /* default to backward compatible */
520
521
 
 
522
        prepTuplestoreResult(fcinfo);
 
523
 
521
524
        DBLINK_INIT;
522
525
 
523
526
        if (PG_NARGS() == 4)
564
567
        if (!conn)
565
568
                DBLINK_CONN_NOT_AVAIL;
566
569
 
567
 
        /* let the caller know we're sending back a tuplestore */
568
 
        rsinfo->returnMode = SFRM_Materialize;
569
 
        rsinfo->setResult = NULL;
570
 
        rsinfo->setDesc = NULL;
571
 
 
572
570
        initStringInfo(&buf);
573
571
        appendStringInfo(&buf, "FETCH %d FROM %s", howmany, curname);
574
572
 
612
610
Datum
613
611
dblink_send_query(PG_FUNCTION_ARGS)
614
612
{
 
613
        char       *conname = NULL;
615
614
        PGconn     *conn = NULL;
616
615
        char       *sql = NULL;
617
616
        remoteConn *rconn = NULL;
644
643
static Datum
645
644
dblink_record_internal(FunctionCallInfo fcinfo, bool is_async)
646
645
{
647
 
        ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
648
646
        char       *msg;
649
647
        PGresult   *res = NULL;
650
648
        PGconn     *conn = NULL;
655
653
        bool            fail = true;    /* default to backward compatible */
656
654
        bool            freeconn = false;
657
655
 
658
 
        /* check to see if caller supports us returning a tuplestore */
659
 
        if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
660
 
                ereport(ERROR,
661
 
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
662
 
                                 errmsg("set-valued function called in context that cannot accept a set")));
663
 
        if (!(rsinfo->allowedModes & SFRM_Materialize))
664
 
                ereport(ERROR,
665
 
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
666
 
                                 errmsg("materialize mode required, but it is not " \
667
 
                                                "allowed in this context")));
 
656
        prepTuplestoreResult(fcinfo);
668
657
 
669
658
        DBLINK_INIT;
670
659
 
724
713
        if (!conn)
725
714
                DBLINK_CONN_NOT_AVAIL;
726
715
 
727
 
        /* let the caller know we're sending back a tuplestore */
728
 
        rsinfo->returnMode = SFRM_Materialize;
729
 
        rsinfo->setResult = NULL;
730
 
        rsinfo->setDesc = NULL;
731
 
 
732
716
        /* synchronous query, or async result retrieval */
733
717
        if (!is_async)
734
718
                res = PQexec(conn, sql);
757
741
}
758
742
 
759
743
/*
760
 
 * Materialize the PGresult to return them as the function result.
761
 
 * The res will be released in this function.
 
744
 * Verify function caller can handle a tuplestore result, and set up for that.
 
745
 *
 
746
 * Note: if the caller returns without actually creating a tuplestore, the
 
747
 * executor will treat the function result as an empty set.
 
748
 */
 
749
static void
 
750
prepTuplestoreResult(FunctionCallInfo fcinfo)
 
751
{
 
752
        ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
 
753
 
 
754
        /* check to see if query supports us returning a tuplestore */
 
755
        if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
 
756
                ereport(ERROR,
 
757
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
758
                                 errmsg("set-valued function called in context that cannot accept a set")));
 
759
        if (!(rsinfo->allowedModes & SFRM_Materialize))
 
760
                ereport(ERROR,
 
761
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
762
                                 errmsg("materialize mode required, but it is not allowed in this context")));
 
763
 
 
764
        /* let the executor know we're sending back a tuplestore */
 
765
        rsinfo->returnMode = SFRM_Materialize;
 
766
 
 
767
        /* caller must fill these to return a non-empty result */
 
768
        rsinfo->setResult = NULL;
 
769
        rsinfo->setDesc = NULL;
 
770
}
 
771
 
 
772
/*
 
773
 * Copy the contents of the PGresult into a tuplestore to be returned
 
774
 * as the result of the current function.
 
775
 * The PGresult will be released in this function.
762
776
 */
763
777
static void
764
778
materializeResult(FunctionCallInfo fcinfo, PGresult *res)
765
779
{
766
780
        ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
767
781
 
 
782
        /* prepTuplestoreResult must have been called previously */
768
783
        Assert(rsinfo->returnMode == SFRM_Materialize);
769
784
 
770
785
        PG_TRY();
933
948
Datum
934
949
dblink_is_busy(PG_FUNCTION_ARGS)
935
950
{
 
951
        char       *conname = NULL;
936
952
        PGconn     *conn = NULL;
937
953
        remoteConn *rconn = NULL;
938
954
 
959
975
dblink_cancel_query(PG_FUNCTION_ARGS)
960
976
{
961
977
        int                     res = 0;
 
978
        char       *conname = NULL;
962
979
        PGconn     *conn = NULL;
963
980
        remoteConn *rconn = NULL;
964
981
        PGcancel   *cancel;
993
1010
dblink_error_message(PG_FUNCTION_ARGS)
994
1011
{
995
1012
        char       *msg;
 
1013
        char       *conname = NULL;
996
1014
        PGconn     *conn = NULL;
997
1015
        remoteConn *rconn = NULL;
998
1016
 
1013
1031
Datum
1014
1032
dblink_exec(PG_FUNCTION_ARGS)
1015
1033
{
1016
 
        char       *msg;
1017
 
        PGresult   *res = NULL;
1018
 
        text       *sql_cmd_status = NULL;
1019
 
        PGconn     *conn = NULL;
1020
 
        char       *connstr = NULL;
1021
 
        char       *sql = NULL;
1022
 
        char       *conname = NULL;
1023
 
        remoteConn *rconn = NULL;
1024
 
        bool            freeconn = false;
1025
 
        bool            fail = true;    /* default to backward compatible behavior */
 
1034
        text       *volatile sql_cmd_status = NULL;
 
1035
        PGconn     *volatile conn = NULL;
 
1036
        volatile bool freeconn = false;
1026
1037
 
1027
1038
        DBLINK_INIT;
1028
1039
 
1029
 
        if (PG_NARGS() == 3)
1030
 
        {
1031
 
                /* must be text,text,bool */
1032
 
                DBLINK_GET_CONN;
1033
 
                sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
1034
 
                fail = PG_GETARG_BOOL(2);
1035
 
        }
1036
 
        else if (PG_NARGS() == 2)
1037
 
        {
1038
 
                /* might be text,text or text,bool */
1039
 
                if (get_fn_expr_argtype(fcinfo->flinfo, 1) == BOOLOID)
1040
 
                {
 
1040
        PG_TRY();
 
1041
        {
 
1042
                char       *msg;
 
1043
                PGresult   *res = NULL;
 
1044
                char       *connstr = NULL;
 
1045
                char       *sql = NULL;
 
1046
                char       *conname = NULL;
 
1047
                remoteConn *rconn = NULL;
 
1048
                bool            fail = true;    /* default to backward compatible behavior */
 
1049
 
 
1050
                if (PG_NARGS() == 3)
 
1051
                {
 
1052
                        /* must be text,text,bool */
 
1053
                        DBLINK_GET_CONN;
 
1054
                        sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 
1055
                        fail = PG_GETARG_BOOL(2);
 
1056
                }
 
1057
                else if (PG_NARGS() == 2)
 
1058
                {
 
1059
                        /* might be text,text or text,bool */
 
1060
                        if (get_fn_expr_argtype(fcinfo->flinfo, 1) == BOOLOID)
 
1061
                        {
 
1062
                                conn = pconn->conn;
 
1063
                                sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
 
1064
                                fail = PG_GETARG_BOOL(1);
 
1065
                        }
 
1066
                        else
 
1067
                        {
 
1068
                                DBLINK_GET_CONN;
 
1069
                                sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
 
1070
                        }
 
1071
                }
 
1072
                else if (PG_NARGS() == 1)
 
1073
                {
 
1074
                        /* must be single text argument */
1041
1075
                        conn = pconn->conn;
1042
1076
                        sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
1043
 
                        fail = PG_GETARG_BOOL(1);
1044
 
                }
1045
 
                else
1046
 
                {
1047
 
                        DBLINK_GET_CONN;
1048
 
                        sql = text_to_cstring(PG_GETARG_TEXT_PP(1));
1049
 
                }
1050
 
        }
1051
 
        else if (PG_NARGS() == 1)
1052
 
        {
1053
 
                /* must be single text argument */
1054
 
                conn = pconn->conn;
1055
 
                sql = text_to_cstring(PG_GETARG_TEXT_PP(0));
1056
 
        }
1057
 
        else
1058
 
                /* shouldn't happen */
1059
 
                elog(ERROR, "wrong number of arguments");
1060
 
 
1061
 
        if (!conn)
1062
 
                DBLINK_CONN_NOT_AVAIL;
1063
 
 
1064
 
        res = PQexec(conn, sql);
1065
 
        if (!res ||
1066
 
                (PQresultStatus(res) != PGRES_COMMAND_OK &&
1067
 
                 PQresultStatus(res) != PGRES_TUPLES_OK))
1068
 
        {
1069
 
                dblink_res_error(conname, res, "could not execute command", fail);
1070
 
 
1071
 
                /*
1072
 
                 * and save a copy of the command status string to return as our
1073
 
                 * result tuple
1074
 
                 */
1075
 
                sql_cmd_status = cstring_to_text("ERROR");
1076
 
        }
1077
 
        else if (PQresultStatus(res) == PGRES_COMMAND_OK)
1078
 
        {
1079
 
                /*
1080
 
                 * and save a copy of the command status string to return as our
1081
 
                 * result tuple
1082
 
                 */
1083
 
                sql_cmd_status = cstring_to_text(PQcmdStatus(res));
1084
 
                PQclear(res);
1085
 
        }
1086
 
        else
1087
 
        {
1088
 
                PQclear(res);
1089
 
                ereport(ERROR,
1090
 
                                (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
1091
 
                                 errmsg("statement returning results not allowed")));
1092
 
        }
1093
 
 
1094
 
        /* if needed, close the connection to the database and cleanup */
 
1077
                }
 
1078
                else
 
1079
                        /* shouldn't happen */
 
1080
                        elog(ERROR, "wrong number of arguments");
 
1081
 
 
1082
                if (!conn)
 
1083
                        DBLINK_CONN_NOT_AVAIL;
 
1084
 
 
1085
                res = PQexec(conn, sql);
 
1086
                if (!res ||
 
1087
                        (PQresultStatus(res) != PGRES_COMMAND_OK &&
 
1088
                         PQresultStatus(res) != PGRES_TUPLES_OK))
 
1089
                {
 
1090
                        dblink_res_error(conname, res, "could not execute command", fail);
 
1091
 
 
1092
                        /*
 
1093
                         * and save a copy of the command status string to return as our
 
1094
                         * result tuple
 
1095
                         */
 
1096
                        sql_cmd_status = cstring_to_text("ERROR");
 
1097
                }
 
1098
                else if (PQresultStatus(res) == PGRES_COMMAND_OK)
 
1099
                {
 
1100
                        /*
 
1101
                         * and save a copy of the command status string to return as our
 
1102
                         * result tuple
 
1103
                         */
 
1104
                        sql_cmd_status = cstring_to_text(PQcmdStatus(res));
 
1105
                        PQclear(res);
 
1106
                }
 
1107
                else
 
1108
                {
 
1109
                        PQclear(res);
 
1110
                        ereport(ERROR,
 
1111
                                  (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
 
1112
                                   errmsg("statement returning results not allowed")));
 
1113
                }
 
1114
        }
 
1115
        PG_CATCH();
 
1116
        {
 
1117
                /* if needed, close the connection to the database */
 
1118
                if (freeconn)
 
1119
                        PQfinish(conn);
 
1120
                PG_RE_THROW();
 
1121
        }
 
1122
        PG_END_TRY();
 
1123
 
 
1124
        /* if needed, close the connection to the database */
1095
1125
        if (freeconn)
1096
1126
                PQfinish(conn);
1097
1127
 
1502
1532
Datum
1503
1533
dblink_get_notify(PG_FUNCTION_ARGS)
1504
1534
{
 
1535
        char       *conname = NULL;
1505
1536
        PGconn     *conn = NULL;
1506
1537
        remoteConn *rconn = NULL;
1507
1538
        PGnotify   *notify;
1511
1542
        MemoryContext per_query_ctx;
1512
1543
        MemoryContext oldcontext;
1513
1544
 
 
1545
        prepTuplestoreResult(fcinfo);
 
1546
 
1514
1547
        DBLINK_INIT;
1515
1548
        if (PG_NARGS() == 1)
1516
1549
                DBLINK_GET_NAMED_CONN;
1517
1550
        else
1518
1551
                conn = pconn->conn;
1519
1552
 
1520
 
        /* create the tuplestore */
 
1553
        /* create the tuplestore in per-query memory */
1521
1554
        per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
1522
1555
        oldcontext = MemoryContextSwitchTo(per_query_ctx);
1523
1556
 
1530
1563
                                           TEXTOID, -1, 0);
1531
1564
 
1532
1565
        tupstore = tuplestore_begin_heap(true, false, work_mem);
1533
 
        rsinfo->returnMode = SFRM_Materialize;
1534
1566
        rsinfo->setResult = tupstore;
1535
1567
        rsinfo->setDesc = tupdesc;
1536
1568