@@ -1849,16 +1849,12 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
18491849 * ExecPartitionCheck --- check that tuple meets the partition constraint.
18501850 *
18511851 * Exported in executor.h for outside use.
1852+ * Returns true if it meets the partition constraint, else returns false.
18521853 */
1853- void
1854+ bool
18541855ExecPartitionCheck (ResultRelInfo * resultRelInfo , TupleTableSlot * slot ,
18551856 EState * estate )
18561857{
1857- Relation rel = resultRelInfo -> ri_RelationDesc ;
1858- TupleDesc tupdesc = RelationGetDescr (rel );
1859- Bitmapset * modifiedCols ;
1860- Bitmapset * insertedCols ;
1861- Bitmapset * updatedCols ;
18621858 ExprContext * econtext ;
18631859
18641860 /*
@@ -1886,60 +1882,78 @@ ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
18861882 * As in case of the catalogued constraints, we treat a NULL result as
18871883 * success here, not a failure.
18881884 */
1889- if (!ExecCheck (resultRelInfo -> ri_PartitionCheckExpr , econtext ))
1890- {
1891- char * val_desc ;
1892- Relation orig_rel = rel ;
1885+ return ExecCheck (resultRelInfo -> ri_PartitionCheckExpr , econtext );
1886+ }
1887+
1888+ /*
1889+ * ExecPartitionCheckEmitError - Form and emit an error message after a failed
1890+ * partition constraint check.
1891+ */
1892+ void
1893+ ExecPartitionCheckEmitError (ResultRelInfo * resultRelInfo ,
1894+ TupleTableSlot * slot ,
1895+ EState * estate )
1896+ {
1897+ Relation rel = resultRelInfo -> ri_RelationDesc ;
1898+ Relation orig_rel = rel ;
1899+ TupleDesc tupdesc = RelationGetDescr (rel );
1900+ char * val_desc ;
1901+ Bitmapset * modifiedCols ;
1902+ Bitmapset * insertedCols ;
1903+ Bitmapset * updatedCols ;
18931904
1894- /* See the comment above. */
1895- if (resultRelInfo -> ri_PartitionRoot )
1905+ /*
1906+ * Need to first convert the tuple to the root partitioned table's row
1907+ * type. For details, check similar comments in ExecConstraints().
1908+ */
1909+ if (resultRelInfo -> ri_PartitionRoot )
1910+ {
1911+ HeapTuple tuple = ExecFetchSlotTuple (slot );
1912+ TupleDesc old_tupdesc = RelationGetDescr (rel );
1913+ TupleConversionMap * map ;
1914+
1915+ rel = resultRelInfo -> ri_PartitionRoot ;
1916+ tupdesc = RelationGetDescr (rel );
1917+ /* a reverse map */
1918+ map = convert_tuples_by_name (old_tupdesc , tupdesc ,
1919+ gettext_noop ("could not convert row type" ));
1920+ if (map != NULL )
18961921 {
1897- HeapTuple tuple = ExecFetchSlotTuple (slot );
1898- TupleDesc old_tupdesc = RelationGetDescr (rel );
1899- TupleConversionMap * map ;
1900-
1901- rel = resultRelInfo -> ri_PartitionRoot ;
1902- tupdesc = RelationGetDescr (rel );
1903- /* a reverse map */
1904- map = convert_tuples_by_name (old_tupdesc , tupdesc ,
1905- gettext_noop ("could not convert row type" ));
1906- if (map != NULL )
1907- {
1908- tuple = do_convert_tuple (tuple , map );
1909- ExecSetSlotDescriptor (slot , tupdesc );
1910- ExecStoreTuple (tuple , slot , InvalidBuffer , false);
1911- }
1922+ tuple = do_convert_tuple (tuple , map );
1923+ ExecSetSlotDescriptor (slot , tupdesc );
1924+ ExecStoreTuple (tuple , slot , InvalidBuffer , false);
19121925 }
1913-
1914- insertedCols = GetInsertedColumns (resultRelInfo , estate );
1915- updatedCols = GetUpdatedColumns (resultRelInfo , estate );
1916- modifiedCols = bms_union (insertedCols , updatedCols );
1917- val_desc = ExecBuildSlotValueDescription (RelationGetRelid (rel ),
1918- slot ,
1919- tupdesc ,
1920- modifiedCols ,
1921- 64 );
1922- ereport (ERROR ,
1923- (errcode (ERRCODE_CHECK_VIOLATION ),
1924- errmsg ("new row for relation \"%s\" violates partition constraint" ,
1925- RelationGetRelationName (orig_rel )),
1926- val_desc ? errdetail ("Failing row contains %s." , val_desc ) : 0 ));
19271926 }
1927+
1928+ insertedCols = GetInsertedColumns (resultRelInfo , estate );
1929+ updatedCols = GetUpdatedColumns (resultRelInfo , estate );
1930+ modifiedCols = bms_union (insertedCols , updatedCols );
1931+ val_desc = ExecBuildSlotValueDescription (RelationGetRelid (rel ),
1932+ slot ,
1933+ tupdesc ,
1934+ modifiedCols ,
1935+ 64 );
1936+ ereport (ERROR ,
1937+ (errcode (ERRCODE_CHECK_VIOLATION ),
1938+ errmsg ("new row for relation \"%s\" violates partition constraint" ,
1939+ RelationGetRelationName (orig_rel )),
1940+ val_desc ? errdetail ("Failing row contains %s." , val_desc ) : 0 ));
19281941}
19291942
19301943/*
19311944 * ExecConstraints - check constraints of the tuple in 'slot'
19321945 *
1933- * This checks the traditional NOT NULL and check constraints, as well as
1934- * the partition constraint, if any .
1946+ * This checks the traditional NOT NULL and check constraints, and if
1947+ * requested, checks the partition constraint.
19351948 *
19361949 * Note: 'slot' contains the tuple to check the constraints of, which may
19371950 * have been converted from the original input tuple after tuple routing.
19381951 * 'resultRelInfo' is the original result relation, before tuple routing.
19391952 */
19401953void
19411954ExecConstraints (ResultRelInfo * resultRelInfo ,
1942- TupleTableSlot * slot , EState * estate )
1955+ TupleTableSlot * slot , EState * estate ,
1956+ bool check_partition_constraint )
19431957{
19441958 Relation rel = resultRelInfo -> ri_RelationDesc ;
19451959 TupleDesc tupdesc = RelationGetDescr (rel );
@@ -2055,8 +2069,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
20552069 }
20562070 }
20572071
2058- if (resultRelInfo -> ri_PartitionCheck )
2059- ExecPartitionCheck (resultRelInfo , slot , estate );
2072+ if (check_partition_constraint && resultRelInfo -> ri_PartitionCheck &&
2073+ !ExecPartitionCheck (resultRelInfo , slot , estate ))
2074+ ExecPartitionCheckEmitError (resultRelInfo , slot , estate );
20602075}
20612076
20622077
0 commit comments