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

« back to all changes in this revision

Viewing changes to src/backend/access/heap/tuptoaster.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2011-12-02 14:39:18 UTC
  • mfrom: (12.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20111202143918-1ftj0oo87w0y8m8d
* New upstream bug fix release:
  - Fix bugs in information_schema.referential_constraints view.
    This view was being insufficiently careful about matching the
    foreign-key constraint to the depended-on primary or unique key
    constraint. That could result in failure to show a foreign key
    constraint at all, or showing it multiple times, or claiming that
    it depends on a different constraint than the one it really does.
    Since the view definition is installed by initdb, merely upgrading
    will not fix the problem. If you need to fix this in an existing
    installation, you can (as a superuser) drop the information_schema
    schema then re-create it by sourcing
    "SHAREDIR/information_schema.sql". (Run pg_config --sharedir if
    you're uncertain where "SHAREDIR" is.) This must be repeated in
    each database to be fixed.
  - Make "contrib/citext"'s upgrade script fix collations of citext
    columns and indexes.
    Existing citext columns and indexes aren't correctly marked as
    being of a collatable data type during pg_upgrade from a pre-9.1
    server. That leads to operations on them failing with errors such
    as "could not determine which collation to use for string
    comparison". This change allows them to be fixed by the same script
    that upgrades the citext module into a proper 9.1 extension during
    CREATE EXTENSION citext FROM unpackaged.
    If you have a previously-upgraded database that is suffering from
    this problem, and you already ran the "CREATE EXTENSION" command,
    you can manually run (as superuser) the "UPDATE" commands found at
    the end of "SHAREDIR/extension/citext--unpackaged--1.0.sql". (Run
    pg_config --sharedir if you're uncertain where "SHAREDIR" is.)
  - Fix possible crash during "UPDATE" or "DELETE" that joins to the
    output of a scalar-returning function.
  - Fix incorrect replay of WAL records for GIN index updates.
  - Fix TOAST-related data corruption during CREATE TABLE dest AS
    SELECT - FROM src or INSERT INTO dest SELECT * FROM src.
  - Fix possible failures during hot standby startup.
  - Start hot standby faster when initial snapshot is incomplete.
  - Fix race condition during toast table access from stale syscache
    entries. The typical symptom was transient errors like "missing chunk
    number 0 for toast value NNNNN in pg_toast_2619", where the cited toast
    table would always belong to a system catalog.
  - Track dependencies of functions on items used in parameter default
    expressions. Previously, a referenced object could be dropped without
    having dropped or modified the function, leading to misbehavior when
    the function was used. Note that merely installing this update will not
    fix the missing dependency entries; to do that, you'd need to
    "CREATE OR REPLACE" each such function afterwards. If you have
    functions whose defaults depend on non-built-in objects, doing so
    is recommended.
  - Fix incorrect management of placeholder variables in nestloop joins.
    This bug is known to lead to "variable not found in subplan target
    list" planner errors, and could possibly result in wrong query
    output when outer joins are involved.
  - Fix window functions that sort by expressions involving aggregates.
  - Fix "MergeAppend child's targetlist doesn't match MergeAppend"
    planner errors.
  - Fix index matching for operators with both collatable and
    noncollatable inputs. In 9.1.0, an indexable operator that has a
    non-collatable left-hand input type and a collatable right-hand input
    type would not be recognized as matching the left-hand column's index.
    An example is the hstore ? text operator.
  - Allow inlining of set-returning SQL functions with multiple OUT
    parameters.
  - Don't trust deferred-unique indexes for join removal.
  - Make DatumGetInetP() unpack inet datums that have a 1-byte header,
    and add a new macro, DatumGetInetPP(), that does not.
  - Improve locale support in money type's input and output.
    Aside from not supporting all standard lc_monetary formatting
    options, the input and output functions were inconsistent, meaning
    there were locales in which dumped money values could not be
    re-read.
  - Don't let transform_null_equals affect CASE foo WHEN NULL ...
    constructs.  transform_null_equals is only supposed to affect foo =
    NULL expressions written directly by the user, not equality checks
    generated internally by this form of CASE.
  - Change foreign-key trigger creation order to better support
    self-referential foreign keys.
  - Fix IF EXISTS to work correctly in "DROP OPERATOR FAMILY".
  - Disallow dropping of an extension from within its own script.
  - Don't mark auto-generated types as extension members.
  - Cope with invalid pre-existing search_path settings during "CREATE
    EXTENSION".
  - Avoid floating-point underflow while tracking buffer allocation
    rate.
  - Prevent autovacuum transactions from running in serializable mode.
    Autovacuum formerly used the cluster-wide default transaction
    isolation level, but there is no need for it to use anything higher
    than READ COMMITTED, and using SERIALIZABLE could result in
    unnecessary delays for other processes.
  - Ensure walsender processes respond promptly to SIGTERM.
  - Exclude "postmaster.opts" from base backups.
  - Fix incorrect field alignment in ecpg's SQLDA area.
  - Preserve blank lines within commands in psql's command history.
    The former behavior could cause problems if an empty line was
    removed from within a string literal, for example.
  - Avoid platform-specific infinite loop in pg_dump.
  - Fix compression of plain-text output format in pg_dump.
    pg_dump has historically understood -Z with no -F switch to mean
    that it should emit a gzip-compressed version of its plain text
    output. Restore that behavior.
  - Fix pg_dump to dump user-defined casts between auto-generated
    types, such as table rowtypes.
  - Fix missed quoting of foreign server names in pg_dump.
  - Assorted fixes for pg_upgrade. Handle exclusion constraints correctly,
    avoid failures on Windows, don't complain about mismatched toast table
    names in 8.4 databases.
  - In PL/pgSQL, allow foreign tables to define row types.
  - Fix up conversions of PL/Perl functions' results.
    Restore the pre-9.1 behavior that PL/Perl functions returning void
    ignore the result value of their last Perl statement; 9.1.0 would
    throw an error if that statement returned a reference. Also, make
    sure it works to return a string value for a composite type, so
    long as the string meets the type's input format. In addition,
    throw errors for attempts to return Perl arrays or hashes when the
    function's declared result type is not an array or composite type,
    respectively. (Pre-9.1 versions rather uselessly returned strings
    like ARRAY(0x221a9a0) or HASH(0x221aa90) in such cases.)
  - Ensure PL/Perl strings are always correctly UTF8-encoded.
  - Use the preferred version of xsubpp to build PL/Perl, not
    necessarily the operating system's main copy.
  - Correctly propagate SQLSTATE in PL/Python exceptions.
  - Do not install PL/Python extension files for Python major versions
    other than the one built against.
  - Change all the "contrib" extension script files to report a useful
    error message if they are fed to psql. This should help teach people
    about the new method of using "CREATE EXTENSION" to load these files.
    In most cases, sourcing the scripts directly would fail anyway, but
    with harder-to-interpret messages.
  - Fix incorrect coding in "contrib/dict_int" and "contrib/dict_xsyn".
  - Remove "contrib/sepgsql" tests from the regular regression test
    mechanism. Since these tests require root privileges for setup, they're
    impractical to run automatically. Switch over to a manual approach
    instead, and provide a testing script to help with that.
  - Fix assorted errors in "contrib/unaccent"'s configuration file
    parsing.
  - Honor query cancel interrupts promptly in pgstatindex().
  - Revert unintentional enabling of WAL_DEBUG. Fortunately, as debugging
    tools go, this one is pretty cheap; but it's not intended to be enabled
    by default, so revert.
  - Ensure VPATH builds properly install all server header files.
  - Shorten file names reported in verbose error messages.
    Regular builds have always reported just the name of the C file
    containing the error message call, but VPATH builds formerly
    reported an absolute path name.
* debian/rules: Fix build failure for binary-indep-only builds.
  (Closes: #646079)

Show diffs side-by-side

added added

removed removed

Lines of Context:
597
597
        if (newtup->t_data->t_infomask & HEAP_HASOID)
598
598
                hoff += sizeof(Oid);
599
599
        hoff = MAXALIGN(hoff);
600
 
        Assert(hoff == newtup->t_data->t_hoff);
601
600
        /* now convert to a limit on the tuple data size */
602
601
        maxDataLen = TOAST_TUPLE_TARGET - hoff;
603
602
 
864
863
        {
865
864
                HeapTupleHeader olddata = newtup->t_data;
866
865
                HeapTupleHeader new_data;
867
 
                int32           new_len;
 
866
                int32           new_header_len;
868
867
                int32           new_data_len;
 
868
                int32           new_tuple_len;
869
869
 
870
870
                /*
871
 
                 * Calculate the new size of the tuple.  Header size should not
872
 
                 * change, but data size might.
 
871
                 * Calculate the new size of the tuple.
 
872
                 *
 
873
                 * Note: we used to assume here that the old tuple's t_hoff must equal
 
874
                 * the new_header_len value, but that was incorrect.  The old tuple
 
875
                 * might have a smaller-than-current natts, if there's been an ALTER
 
876
                 * TABLE ADD COLUMN since it was stored; and that would lead to a
 
877
                 * different conclusion about the size of the null bitmap, or even
 
878
                 * whether there needs to be one at all.
873
879
                 */
874
 
                new_len = offsetof(HeapTupleHeaderData, t_bits);
 
880
                new_header_len = offsetof(HeapTupleHeaderData, t_bits);
875
881
                if (has_nulls)
876
 
                        new_len += BITMAPLEN(numAttrs);
 
882
                        new_header_len += BITMAPLEN(numAttrs);
877
883
                if (olddata->t_infomask & HEAP_HASOID)
878
 
                        new_len += sizeof(Oid);
879
 
                new_len = MAXALIGN(new_len);
880
 
                Assert(new_len == olddata->t_hoff);
 
884
                        new_header_len += sizeof(Oid);
 
885
                new_header_len = MAXALIGN(new_header_len);
881
886
                new_data_len = heap_compute_data_size(tupleDesc,
882
887
                                                                                          toast_values, toast_isnull);
883
 
                new_len += new_data_len;
 
888
                new_tuple_len = new_header_len + new_data_len;
884
889
 
885
890
                /*
886
891
                 * Allocate and zero the space needed, and fill HeapTupleData fields.
887
892
                 */
888
 
                result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_len);
889
 
                result_tuple->t_len = new_len;
 
893
                result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_tuple_len);
 
894
                result_tuple->t_len = new_tuple_len;
890
895
                result_tuple->t_self = newtup->t_self;
891
896
                result_tuple->t_tableOid = newtup->t_tableOid;
892
897
                new_data = (HeapTupleHeader) ((char *) result_tuple + HEAPTUPLESIZE);
893
898
                result_tuple->t_data = new_data;
894
899
 
895
900
                /*
896
 
                 * Put the existing tuple header and the changed values into place
 
901
                 * Copy the existing tuple header, but adjust natts and t_hoff.
897
902
                 */
898
 
                memcpy(new_data, olddata, olddata->t_hoff);
 
903
                memcpy(new_data, olddata, offsetof(HeapTupleHeaderData, t_bits));
 
904
                HeapTupleHeaderSetNatts(new_data, numAttrs);
 
905
                new_data->t_hoff = new_header_len;
 
906
                if (olddata->t_infomask & HEAP_HASOID)
 
907
                        HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(olddata));
899
908
 
 
909
                /* Copy over the data, and fill the null bitmap if needed */
900
910
                heap_fill_tuple(tupleDesc,
901
911
                                                toast_values,
902
912
                                                toast_isnull,
903
 
                                                (char *) new_data + olddata->t_hoff,
 
913
                                                (char *) new_data + new_header_len,
904
914
                                                new_data_len,
905
915
                                                &(new_data->t_infomask),
906
916
                                                has_nulls ? new_data->t_bits : NULL);
929
939
 
930
940
 
931
941
/* ----------
 
942
 * toast_flatten_tuple -
 
943
 *
 
944
 *      "Flatten" a tuple to contain no out-of-line toasted fields.
 
945
 *      (This does not eliminate compressed or short-header datums.)
 
946
 * ----------
 
947
 */
 
948
HeapTuple
 
949
toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
 
950
{
 
951
        HeapTuple       new_tuple;
 
952
        Form_pg_attribute *att = tupleDesc->attrs;
 
953
        int                     numAttrs = tupleDesc->natts;
 
954
        int                     i;
 
955
        Datum           toast_values[MaxTupleAttributeNumber];
 
956
        bool            toast_isnull[MaxTupleAttributeNumber];
 
957
        bool            toast_free[MaxTupleAttributeNumber];
 
958
 
 
959
        /*
 
960
         * Break down the tuple into fields.
 
961
         */
 
962
        Assert(numAttrs <= MaxTupleAttributeNumber);
 
963
        heap_deform_tuple(tup, tupleDesc, toast_values, toast_isnull);
 
964
 
 
965
        memset(toast_free, 0, numAttrs * sizeof(bool));
 
966
 
 
967
        for (i = 0; i < numAttrs; i++)
 
968
        {
 
969
                /*
 
970
                 * Look at non-null varlena attributes
 
971
                 */
 
972
                if (!toast_isnull[i] && att[i]->attlen == -1)
 
973
                {
 
974
                        struct varlena *new_value;
 
975
 
 
976
                        new_value = (struct varlena *) DatumGetPointer(toast_values[i]);
 
977
                        if (VARATT_IS_EXTERNAL(new_value))
 
978
                        {
 
979
                                new_value = toast_fetch_datum(new_value);
 
980
                                toast_values[i] = PointerGetDatum(new_value);
 
981
                                toast_free[i] = true;
 
982
                        }
 
983
                }
 
984
        }
 
985
 
 
986
        /*
 
987
         * Form the reconfigured tuple.
 
988
         */
 
989
        new_tuple = heap_form_tuple(tupleDesc, toast_values, toast_isnull);
 
990
 
 
991
        /*
 
992
         * Be sure to copy the tuple's OID and identity fields.  We also make a
 
993
         * point of copying visibility info, just in case anybody looks at those
 
994
         * fields in a syscache entry.
 
995
         */
 
996
        if (tupleDesc->tdhasoid)
 
997
                HeapTupleSetOid(new_tuple, HeapTupleGetOid(tup));
 
998
 
 
999
        new_tuple->t_self = tup->t_self;
 
1000
        new_tuple->t_tableOid = tup->t_tableOid;
 
1001
 
 
1002
        new_tuple->t_data->t_choice = tup->t_data->t_choice;
 
1003
        new_tuple->t_data->t_ctid = tup->t_data->t_ctid;
 
1004
        new_tuple->t_data->t_infomask &= ~HEAP_XACT_MASK;
 
1005
        new_tuple->t_data->t_infomask |=
 
1006
                tup->t_data->t_infomask & HEAP_XACT_MASK;
 
1007
        new_tuple->t_data->t_infomask2 &= ~HEAP2_XACT_MASK;
 
1008
        new_tuple->t_data->t_infomask2 |=
 
1009
                tup->t_data->t_infomask2 & HEAP2_XACT_MASK;
 
1010
 
 
1011
        /*
 
1012
         * Free allocated temp values
 
1013
         */
 
1014
        for (i = 0; i < numAttrs; i++)
 
1015
                if (toast_free[i])
 
1016
                        pfree(DatumGetPointer(toast_values[i]));
 
1017
 
 
1018
        return new_tuple;
 
1019
}
 
1020
 
 
1021
 
 
1022
/* ----------
932
1023
 * toast_flatten_tuple_attribute -
933
1024
 *
934
1025
 *      If a Datum is of composite type, "flatten" it to contain no toasted fields.
947
1038
        TupleDesc       tupleDesc;
948
1039
        HeapTupleHeader olddata;
949
1040
        HeapTupleHeader new_data;
950
 
        int32           new_len;
 
1041
        int32           new_header_len;
951
1042
        int32           new_data_len;
 
1043
        int32           new_tuple_len;
952
1044
        HeapTupleData tmptup;
953
1045
        Form_pg_attribute *att;
954
1046
        int                     numAttrs;
1019
1111
        }
1020
1112
 
1021
1113
        /*
1022
 
         * Calculate the new size of the tuple.  Header size should not change,
1023
 
         * but data size might.
 
1114
         * Calculate the new size of the tuple.
 
1115
         *
 
1116
         * This should match the reconstruction code in toast_insert_or_update.
1024
1117
         */
1025
 
        new_len = offsetof(HeapTupleHeaderData, t_bits);
 
1118
        new_header_len = offsetof(HeapTupleHeaderData, t_bits);
1026
1119
        if (has_nulls)
1027
 
                new_len += BITMAPLEN(numAttrs);
 
1120
                new_header_len += BITMAPLEN(numAttrs);
1028
1121
        if (olddata->t_infomask & HEAP_HASOID)
1029
 
                new_len += sizeof(Oid);
1030
 
        new_len = MAXALIGN(new_len);
1031
 
        Assert(new_len == olddata->t_hoff);
 
1122
                new_header_len += sizeof(Oid);
 
1123
        new_header_len = MAXALIGN(new_header_len);
1032
1124
        new_data_len = heap_compute_data_size(tupleDesc,
1033
1125
                                                                                  toast_values, toast_isnull);
1034
 
        new_len += new_data_len;
 
1126
        new_tuple_len = new_header_len + new_data_len;
1035
1127
 
1036
 
        new_data = (HeapTupleHeader) palloc0(new_len);
 
1128
        new_data = (HeapTupleHeader) palloc0(new_tuple_len);
1037
1129
 
1038
1130
        /*
1039
 
         * Put the tuple header and the changed values into place
 
1131
         * Copy the existing tuple header, but adjust natts and t_hoff.
1040
1132
         */
1041
 
        memcpy(new_data, olddata, olddata->t_hoff);
1042
 
 
1043
 
        HeapTupleHeaderSetDatumLength(new_data, new_len);
1044
 
 
 
1133
        memcpy(new_data, olddata, offsetof(HeapTupleHeaderData, t_bits));
 
1134
        HeapTupleHeaderSetNatts(new_data, numAttrs);
 
1135
        new_data->t_hoff = new_header_len;
 
1136
        if (olddata->t_infomask & HEAP_HASOID)
 
1137
                HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(olddata));
 
1138
 
 
1139
        /* Reset the datum length field, too */
 
1140
        HeapTupleHeaderSetDatumLength(new_data, new_tuple_len);
 
1141
 
 
1142
        /* Copy over the data, and fill the null bitmap if needed */
1045
1143
        heap_fill_tuple(tupleDesc,
1046
1144
                                        toast_values,
1047
1145
                                        toast_isnull,
1048
 
                                        (char *) new_data + olddata->t_hoff,
 
1146
                                        (char *) new_data + new_header_len,
1049
1147
                                        new_data_len,
1050
1148
                                        &(new_data->t_infomask),
1051
1149
                                        has_nulls ? new_data->t_bits : NULL);