@@ -2,6 +2,7 @@ import 'package:clock/clock.dart';
22import 'package:logging/logging.dart' ;
33import 'package:meta/meta.dart' ;
44import 'package:postgres/postgres.dart' ;
5+
56// ignore: implementation_imports
67import 'package:postgres/src/types/type_registry.dart' show TypeRegistryExt;
78import 'package:postgres_utils/src/config.dart' ;
@@ -16,9 +17,16 @@ const whereIsNull = Object();
1617const whereIsNotNull = Object ();
1718
1819class OnConflictActionDoUpdate extends OnConflictAction {
19- OnConflictActionDoUpdate ({required this .indexColumns});
20+ OnConflictActionDoUpdate ({
21+ required this .indexColumns,
22+ this .concatColumns = const {},
23+ });
2024
25+ /// Columns which are used to identify uniqueness
2126 final List <String > indexColumns;
27+
28+ /// Columns which should not be overwritten, but concatenated.
29+ final Set <String > concatColumns;
2230}
2331
2432abstract class OnConflictAction {
@@ -56,8 +64,15 @@ class DatabaseTransactionBase<TABLES extends TablesBase> {
5664 if (onConflict is OnConflictActionDoUpdate ) {
5765 final set = entries
5866 .where ((element) => ! onConflict.indexColumns.contains (element.key))
59- .map ((e) => '${e .key } = EXCLUDED.${e .key }' )
60- .join (', ' );
67+ .map ((e) {
68+ if (onConflict.concatColumns.contains (e.key)) {
69+ return '''
70+ ${e .key } = CASE WHEN $table .${e .key } IS NULL THEN EXCLUDED.${e .key }
71+ ELSE $table .${e .key } || EXCLUDED.${e .key }
72+ END''' ;
73+ }
74+ return '${e .key } = EXCLUDED.${e .key }' ;
75+ }).join (', ' );
6176 final where = entries
6277 .where ((element) => onConflict.indexColumns.contains (element.key))
6378 .map ((e) => '$table .${e .key } = EXCLUDED.${e .key }' )
@@ -219,6 +234,7 @@ class CustomTypeBind extends CustomBind {
219234 type,
220235 );
221236 }
237+
222238 CustomTypeBind ._(String bind, Object value, Type type)
223239 : super (bind, value, type: type);
224240
0 commit comments