11package org .hypertrace .core .documentstore .postgres ;
22
3+ import static java .util .Map .entry ;
34import static org .hypertrace .core .documentstore .model .options .ReturnDocumentType .AFTER_UPDATE ;
45import static org .hypertrace .core .documentstore .model .options .ReturnDocumentType .BEFORE_UPDATE ;
56import static org .hypertrace .core .documentstore .model .subdoc .UpdateOperator .ADD ;
7+ import static org .hypertrace .core .documentstore .model .subdoc .UpdateOperator .ADD_TO_LIST_IF_ABSENT ;
8+ import static org .hypertrace .core .documentstore .model .subdoc .UpdateOperator .APPEND_TO_LIST ;
9+ import static org .hypertrace .core .documentstore .model .subdoc .UpdateOperator .REMOVE_ALL_FROM_LIST ;
610import static org .hypertrace .core .documentstore .model .subdoc .UpdateOperator .SET ;
11+ import static org .hypertrace .core .documentstore .model .subdoc .UpdateOperator .UNSET ;
712
813import com .fasterxml .jackson .databind .JsonNode ;
914import com .fasterxml .jackson .databind .ObjectMapper ;
4752import org .hypertrace .core .documentstore .postgres .query .v1 .parser .filter .nonjson .field .PostgresDataType ;
4853import org .hypertrace .core .documentstore .postgres .query .v1 .transformer .FlatPostgresFieldTransformer ;
4954import org .hypertrace .core .documentstore .postgres .query .v1 .transformer .LegacyFilterToQueryFilterTransformer ;
50- import org .hypertrace .core .documentstore .postgres .update .FlatUpdateContext ;
51- import org .hypertrace .core .documentstore .postgres .update .parser .FlatCollectionSubDocAddOperatorParser ;
52- import org .hypertrace .core .documentstore .postgres .update .parser .FlatCollectionSubDocSetOperatorParser ;
53- import org .hypertrace .core .documentstore .postgres .update .parser .FlatCollectionSubDocUpdateOperatorParser ;
55+ import org .hypertrace .core .documentstore .postgres .update .parser .PostgresAddToListIfAbsentParser ;
56+ import org .hypertrace .core .documentstore .postgres .update .parser .PostgresAddValueParser ;
57+ import org .hypertrace .core .documentstore .postgres .update .parser .PostgresAppendToListParser ;
58+ import org .hypertrace .core .documentstore .postgres .update .parser .PostgresRemoveAllFromListParser ;
59+ import org .hypertrace .core .documentstore .postgres .update .parser .PostgresSetValueParser ;
60+ import org .hypertrace .core .documentstore .postgres .update .parser .PostgresUnsetPathParser ;
61+ import org .hypertrace .core .documentstore .postgres .update .parser .PostgresUpdateOperationParser ;
62+ import org .hypertrace .core .documentstore .postgres .update .parser .PostgresUpdateOperationParser .UpdateParserInput ;
5463import org .hypertrace .core .documentstore .postgres .utils .PostgresUtils ;
5564import org .hypertrace .core .documentstore .query .Query ;
5665import org .postgresql .util .PSQLException ;
@@ -74,11 +83,14 @@ public class FlatPostgresCollection extends PostgresCollection {
7483 private static final String MISSING_COLUMN_STRATEGY_CONFIG = "missingColumnStrategy" ;
7584 private static final String DEFAULT_PRIMARY_KEY_COLUMN = "key" ;
7685
77- private static final Map <UpdateOperator , FlatCollectionSubDocUpdateOperatorParser >
78- SUB_DOC_UPDATE_PARSERS =
79- Map .of (
80- SET , new FlatCollectionSubDocSetOperatorParser (),
81- ADD , new FlatCollectionSubDocAddOperatorParser ());
86+ private static final Map <UpdateOperator , PostgresUpdateOperationParser > UPDATE_PARSER_MAP =
87+ Map .ofEntries (
88+ entry (SET , new PostgresSetValueParser ()),
89+ entry (UNSET , new PostgresUnsetPathParser ()),
90+ entry (ADD , new PostgresAddValueParser ()),
91+ entry (REMOVE_ALL_FROM_LIST , new PostgresRemoveAllFromListParser ()),
92+ entry (ADD_TO_LIST_IF_ABSENT , new PostgresAddToListIfAbsentParser ()),
93+ entry (APPEND_TO_LIST , new PostgresAppendToListParser ()));
8294
8395 private final PostgresLazyilyLoadedSchemaRegistry schemaRegistry ;
8496
@@ -624,7 +636,7 @@ private Map<String, String> resolvePathsToColumns(
624636 UpdateOperator operator = update .getOperator ();
625637
626638 Preconditions .checkArgument (
627- SUB_DOC_UPDATE_PARSERS .containsKey (operator ), "Unsupported UPDATE operator: " + operator );
639+ UPDATE_PARSER_MAP .containsKey (operator ), "Unsupported UPDATE operator: " + operator );
628640
629641 String path = update .getSubDocument ().getPath ();
630642 Optional <String > columnName = resolveColumnName (path , tableName );
@@ -744,20 +756,40 @@ private void executeUpdate(
744756 PostgresColumnMetadata colMeta =
745757 schemaRegistry .getColumnOrRefresh (tableName , columnName ).orElseThrow ();
746758
747- FlatUpdateContext context =
748- FlatUpdateContext .builder ()
749- .columnName (columnName )
750- // get the nested path. So for example, if colName is `customAttr` and full path is
751- // `customAttr.props`, then the nested path is `props`.
752- .nestedPath (getNestedPath (path , columnName ))
753- .columnType (colMeta .getPostgresType ())
754- .value (update .getSubDocumentValue ())
755- .params (params )
756- .build ();
757-
758- FlatCollectionSubDocUpdateOperatorParser operatorParser =
759- SUB_DOC_UPDATE_PARSERS .get (update .getOperator ());
760- String fragment = operatorParser .parse (context );
759+ String [] nestedPath = getNestedPath (path , columnName );
760+ boolean isTopLevel = nestedPath .length == 0 ;
761+ UpdateOperator operator = update .getOperator ();
762+
763+ Params .Builder paramsBuilder = Params .newBuilder ();
764+ PostgresUpdateOperationParser unifiedParser = UPDATE_PARSER_MAP .get (operator );
765+
766+ String fragment ;
767+
768+ if (isTopLevel ) {
769+ UpdateParserInput input =
770+ UpdateParserInput .builder ()
771+ .baseField (columnName )
772+ .path (new String [0 ])
773+ .update (update )
774+ .paramsBuilder (paramsBuilder )
775+ .columnType (colMeta .getPostgresType ())
776+ .build ();
777+ fragment = unifiedParser .parseNonJsonbField (input );
778+ } else {
779+ // parseInternal() returns just the value expression
780+ UpdateParserInput jsonbInput =
781+ UpdateParserInput .builder ()
782+ .baseField (String .format ("\" %s\" " , columnName ))
783+ .path (nestedPath )
784+ .update (update )
785+ .paramsBuilder (paramsBuilder )
786+ .columnType (colMeta .getPostgresType ())
787+ .build ();
788+ String valueExpr = unifiedParser .parseInternal (jsonbInput );
789+ fragment = String .format ("\" %s\" = %s" , columnName , valueExpr );
790+ }
791+ // Transfer params from builder to our list
792+ params .addAll (paramsBuilder .build ().getObjectParams ().values ());
761793 setFragments .add (fragment );
762794 }
763795
0 commit comments