/// Apply a metadata operation in Postgres.
Apply a metadata operation in Postgres.
Apply a metadata operation in Postgres .
fn apply_metadata_operation(
        &self,
        conn: &e::Connection,
        operation: MetadataOperation,
    ) -> Result<i32, StoreError> {
        match operation {
            MetadataOperation::Set { entity, id, data } => {
                let key = MetadataOperation::entity_key(entity, id);
                self.check_interface_entity_uniqueness(conn, &key)?;
                // Load the entity if exists
                let entity = self
                    .get_entity(conn, &key.subgraph_id, &key.entity_type, &key.entity_id)
                    .map_err(Error::from)?;
                // Identify whether this is an insert or an update operation and
                // merge the changes into the entity.
                let result = match entity {
                    Some(mut entity) => {
                        entity.merge_remove_null_fields(data);
                        conn.update(&key, &entity, None).map(|_| 0)
                    }
                    None => {
                        // Merge with a new entity since that removes values that
                        // were set to Value::Null
                        let mut entity = Entity::new();
                        entity.merge_remove_null_fields(data);
                        conn.insert(&key, &entity, None).map(|_| 1)
                    }
                };
                result.map_err(|e| {
                    format_err!(
                        "Failed to set entity ({}, {}, {}): {}",
                        key.subgraph_id,
                        key.entity_type,
                        key.entity_id,
                        e
                    )
                    .into()
                })
            }
            MetadataOperation::Update { entity, id, data } => {
                let key = MetadataOperation::entity_key(entity, id);
                self.check_interface_entity_uniqueness(conn, &key)?;
                // Update the entity in Postgres
                match conn.update_metadata(&key, &data)? {
                    0 => Err(TransactionAbortError::AbortUnless {
                        expected_entity_ids: vec![key.entity_id.clone()],
                        actual_entity_ids: vec![],
                        description: format!("update for entity {:?} with data {:?} did not change any rows", key, data),
                    }
                    .into()),
                    1 => Ok(0),
                    res => Err(TransactionAbortError::AbortUnless {
                        expected_entity_ids: vec![key.entity_id.clone()],
                        actual_entity_ids: vec![],
                        description: format!(
                            "update for entity {:?} with data {:?} changed {} rows instead of just one",
                            key, data, res
                        ),
                    }
                    .into()),
                }
            }
            MetadataOperation::Remove { entity, id } => {
                let key = MetadataOperation::entity_key(entity, id);
                conn.delete(&key, None)
                    // This conversion is ok since n will only be 0 or 1
                    .map(|n| -(n as i32))
                    .map_err(|e| {
                        format_err!(
                            "Failed to remove entity ({}, {}, {}): {}",
                            key.subgraph_id,
                            key.entity_type,
                            key.entity_id,
                            e
                        )
                        .into()
                    })
            }
            MetadataOperation::AbortUnless {
                description,
                query,
                entity_ids: mut expected_entity_ids,
            } => {
                // Execute query
                let actual_entities = self.execute_query(conn, query.clone()).map_err(|e| {
                    format_err!(
                        "AbortUnless ({}): query execution error: {:?}, {}",
                        description,
                        query,
                        e
                    )
                })?;
                // Extract IDs from entities
                let mut actual_entity_ids: Vec<String> = actual_entities
                    .into_iter()
                    .map(|entity| entity.id())
                    .collect::<Result<_, _>>()?;
                // Sort entity IDs lexicographically if and only if no sort order is specified.
                // When no sort order is specified, the entity ordering is arbitrary and should not be a
                // factor in deciding whether or not to abort.
                if query.order_by.is_none() {
                    expected_entity_ids.sort();
                    actual_entity_ids.sort();
                }
                // Abort if actual IDs do not match expected
                if actual_entity_ids != expected_entity_ids {
                    return Err(TransactionAbortError::AbortUnless {
                        expected_entity_ids,
                        actual_entity_ids,
                        description,
                    }
                    .into());
                }
                // Safe to continue
                Ok(0)
            }
        }
    }
fn apply_metadata_operation ( & self , conn : & e :: Connection , operation : MetadataOperation , ) -> Result < i32 , StoreError > { match operation { MetadataOperation :: Set { entity , id , data } => { let key = MetadataOperation :: entity_key ( entity , id ) ; self . check_interface_entity_uniqueness ( conn , & key ) ? ; // Load the entity if exists let entity = self . get_entity ( conn , & key . subgraph_id , & key . entity_type , & key . entity_id ) . map_err ( Error :: from ) ? ; // Identify whether this is an insert or an update operation and // merge the changes into the entity. let result = match entity { Some ( mut entity ) => { entity . merge_remove_null_fields ( data ) ; conn . update ( & key , & entity , None ) . map ( | _ | 0 ) } None => { // Merge with a new entity since that removes values that // were set to Value::Null let mut entity = Entity :: new ( ) ; entity . merge_remove_null_fields ( data ) ; conn . insert ( & key , & entity , None ) . map ( | _ | 1 ) } } ; result . map_err ( | e | { format_err ! ( " " key subgraph_id key entity_type key entity_id e ) . into ( ) } ) } MetadataOperation :: Update { entity , id , data } => { let key = MetadataOperation :: entity_key ( entity , id ) ; self . check_interface_entity_uniqueness ( conn , & key ) ? ; // Update the entity in Postgres match conn . update_metadata ( & key , & data ) ? { 0 => Err ( TransactionAbortError :: AbortUnless { expected_entity_ids : vec ! [ key entity_id clone ( ) ] , actual_entity_ids : vec ! [ ] , description : format ! ( " " key data ) , } . into ( ) ) , 1 => Ok ( 0 ) , res => Err ( TransactionAbortError :: AbortUnless { expected_entity_ids : vec ! [ key entity_id clone ( ) ] , actual_entity_ids : vec ! [ ] , description : format ! ( " " key data res ) , } . into ( ) ) , } } MetadataOperation :: Remove { entity , id } => { let key = MetadataOperation :: entity_key ( entity , id ) ; conn . delete ( & key , None ) // This conversion is ok since n will only be 0 or 1 . map ( | n | - ( n as i32 ) ) . map_err ( | e | { format_err ! ( " " key subgraph_id key entity_type key entity_id e ) . into ( ) } ) } MetadataOperation :: AbortUnless { description , query , entity_ids : mut expected_entity_ids , } => { // Execute query let actual_entities = self . execute_query ( conn , query . clone ( ) ) . map_err ( | e | { format_err ! ( " " description query e ) } ) ? ; // Extract IDs from entities let mut actual_entity_ids : Vec < String > = actual_entities . into_iter ( ) . map ( | entity | entity . id ( ) ) . collect :: < Result < _ , _ > > ( ) ? ; // Sort entity IDs lexicographically if and only if no sort order is specified. // When no sort order is specified, the entity ordering is arbitrary and should not be a // factor in deciding whether or not to abort. if query . order_by . is_none ( ) { expected_entity_ids . sort ( ) ; actual_entity_ids . sort ( ) ; } // Abort if actual IDs do not match expected if actual_entity_ids != expected_entity_ids { return Err ( TransactionAbortError :: AbortUnless { expected_entity_ids , actual_entity_ids , description , } . into ( ) ) ; } // Safe to continue Ok ( 0 ) } } }
Apply a metadata operation in Postgres.
Apply a metadata operation in Postgres .
&self
conn
&e::Connection
operation
MetadataOperation