88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.12 2000/08/04 04:16:07 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.13 2000/10/23 23:42:04 tgl Exp $
1212 *
1313 *
1414 * INTERFACE ROUTINES
@@ -247,6 +247,11 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
247247
248248/* ----------
249249 * Then collect information about the values given
250+ *
251+ * NOTE: toast_action[i] can have these values:
252+ *' 'default handling
253+ *'p'already processed --- don't touch it
254+ *'x'incompressible, but OK to move off
250255 * ----------
251256 */
252257memset (toast_action ,' ' ,numAttrs * sizeof (char ));
@@ -397,14 +402,15 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
397402int biggest_attno = -1 ;
398403int32 biggest_size = MAXALIGN (sizeof (varattrib ));
399404Datum old_value ;
405+ Datum new_value ;
400406
401407/* ----------
402408 * Search for the biggest yet uncompressed internal attribute
403409 * ----------
404410 */
405411for (i = 0 ;i < numAttrs ;i ++ )
406412{
407- if (toast_action [i ]== 'p ' )
413+ if (toast_action [i ]!= ' ' )
408414continue ;
409415if (VARATT_IS_EXTENDED (toast_values [i ]))
410416continue ;
@@ -421,20 +427,29 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
421427break ;
422428
423429/* ----------
424- *Compress it inline
430+ *Attempt to compress it inline
425431 * ----------
426432 */
427433i = biggest_attno ;
428434old_value = toast_values [i ];
435+ new_value = toast_compress_datum (old_value );
429436
430- toast_values [i ]= toast_compress_datum (toast_values [i ]);
431- if (toast_free [i ])
432- pfree (DatumGetPointer (old_value ));
433- toast_free [i ]= true;
434- toast_sizes [i ]= VARATT_SIZE (toast_values [i ]);
435-
436- need_change = true;
437- need_free = true;
437+ if (DatumGetPointer (new_value )!= NULL )
438+ {
439+ /* successful compression */
440+ if (toast_free [i ])
441+ pfree (DatumGetPointer (old_value ));
442+ toast_values [i ]= new_value ;
443+ toast_free [i ]= true;
444+ toast_sizes [i ]= VARATT_SIZE (toast_values [i ]);
445+ need_change = true;
446+ need_free = true;
447+ }
448+ else
449+ {
450+ /* incompressible data, ignore on subsequent compression passes */
451+ toast_action [i ]= 'x' ;
452+ }
438453}
439454
440455/* ----------
@@ -504,14 +519,15 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
504519int biggest_attno = -1 ;
505520int32 biggest_size = MAXALIGN (sizeof (varattrib ));
506521Datum old_value ;
522+ Datum new_value ;
507523
508524/* ----------
509525 * Search for the biggest yet uncompressed internal attribute
510526 * ----------
511527 */
512528for (i = 0 ;i < numAttrs ;i ++ )
513529{
514- if (toast_action [i ]== 'p ' )
530+ if (toast_action [i ]!= ' ' )
515531continue ;
516532if (VARATT_IS_EXTENDED (toast_values [i ]))
517533continue ;
@@ -528,22 +544,29 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
528544break ;
529545
530546/* ----------
531- *Compress it inline
547+ *Attempt to compress it inline
532548 * ----------
533549 */
534550i = biggest_attno ;
535551old_value = toast_values [i ];
552+ new_value = toast_compress_datum (old_value );
536553
537- toast_values [i ]= toast_compress_datum (toast_values [i ]);
538-
539- if (toast_free [i ])
540- pfree (DatumGetPointer (old_value ));
541-
542- toast_free [i ]= true;
543- toast_sizes [i ]= VARATT_SIZE (toast_values [i ]);
544-
545- need_change = true;
546- need_free = true;
554+ if (DatumGetPointer (new_value )!= NULL )
555+ {
556+ /* successful compression */
557+ if (toast_free [i ])
558+ pfree (DatumGetPointer (old_value ));
559+ toast_values [i ]= new_value ;
560+ toast_free [i ]= true;
561+ toast_sizes [i ]= VARATT_SIZE (toast_values [i ]);
562+ need_change = true;
563+ need_free = true;
564+ }
565+ else
566+ {
567+ /* incompressible data, ignore on subsequent compression passes */
568+ toast_action [i ]= 'x' ;
569+ }
547570}
548571
549572/* ----------
@@ -690,20 +713,33 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
690713 * toast_compress_datum -
691714 *
692715 *Create a compressed version of a varlena datum
716+ *
717+ *If we fail (ie, compressed result is actually bigger than original)
718+ *then return NULL. We must not use compressed data if it'd expand
719+ *the tuple!
693720 * ----------
694721 */
695722static Datum
696723toast_compress_datum (Datum value )
697724{
698725varattrib * tmp ;
699726
700- tmp = (varattrib * )palloc (sizeof (PGLZ_Header )+ VARATT_SIZE (value ));
727+ tmp = (varattrib * )palloc (sizeof (PGLZ_Header )+ VARATT_SIZE (value ));
701728pglz_compress (VARATT_DATA (value ),VARATT_SIZE (value )- VARHDRSZ ,
702- (PGLZ_Header * )tmp ,
703- PGLZ_strategy_default );
704- VARATT_SIZEP (tmp ) |=VARATT_FLAG_COMPRESSED ;
705-
706- return PointerGetDatum (tmp );
729+ (PGLZ_Header * )tmp ,
730+ PGLZ_strategy_default );
731+ if (VARATT_SIZE (tmp )< VARATT_SIZE (value ))
732+ {
733+ /* successful compression */
734+ VARATT_SIZEP (tmp ) |=VARATT_FLAG_COMPRESSED ;
735+ return PointerGetDatum (tmp );
736+ }
737+ else
738+ {
739+ /* incompressible data */
740+ pfree (tmp );
741+ return PointerGetDatum (NULL );
742+ }
707743}
708744
709745