postgresqlgoent

ent-go o2m upsert duplication


I am trying to upsert table A, with relations to table B - also, upserting via ent-go's framework with Postgres.

        
CmdbCiServerVmwareVirtualMachine:
        +----------------+--------------------------------+--------+----------+----------+---------+---------------+-----------+---------------------------------+------------+---------+
        |     Field      |              Type              | Unique | Optional | Nillable | Default | UpdateDefault | Immutable |            StructTag            | Validators | Comment |
        +----------------+--------------------------------+--------+----------+----------+---------+---------------+-----------+---------------------------------+------------+---------+
        | id             | uuid.UUID                      | false  | false    | false    | true    | false         | false     | json:"id,omitempty"             |          0 |         |
        | created_at     | time.Time                      | false  | false    | false    | true    | false         | true      | json:"created_at,omitempty"     |          0 |         |
        | updated_at     | time.Time                      | false  | false    | false    | true    | true          | false     | json:"updated_at,omitempty"     |          0 |         |
        | deleted_at     | time.Time                      | false  | true     | false    | false   | true          | false     | json:"deleted_at,omitempty"     |          0 |         |
        | sysId          | uuid.UUID                      | true   | false    | false    | false   | false         | false     | json:"sysId,omitempty"          |          0 |         |
        | name           | string                         | false  | true     | false    | false   | false         | false     | json:"name,omitempty"           |          0 |         |
        | vCpu           | int                            | false  | true     | false    | false   | false         | false     | json:"vCpu,omitempty"           |          0 |         |
        | coresPerSocket | int                            | false  | true     | false    | false   | false         | false     | json:"coresPerSocket,omitempty" |          0 |         |
        | memory         | int                            | false  | true     | false    | false   | false         | false     | json:"memory,omitempty"         |          0 |         |
        | hwVersion      | string                         | false  | true     | false    | false   | false         | false     | json:"hwVersion,omitempty"      |          0 |         |
        | guestOS        | string                         | false  | true     | false    | false   | false         | false     | json:"guestOS,omitempty"        |          0 |         |
        | guestOSFamily  | string                         | false  | true     | false    | false   | false         | false     | json:"guestOSFamily,omitempty"  |          0 |         |
        | guestOSFqdn    | string                         | false  | true     | false    | false   | false         | false     | json:"guestOSFqdn,omitempty"    |          0 |         |
        | powerState     | string                         | false  | true     | false    | false   | false         | false     | json:"powerState,omitempty"     |          0 |         |
        | customFields   | []struct { Key int             | false  | false    | false    | false   | false         | false     | json:"customFields,omitempty"   |          0 |         |
        |                | "json:\"Key\""; Value string   |        |          |          |         |               |           |                                 |            |         |
        |                | "json:\"Value\"" }             |        |          |          |         |               |           |                                 |            |         |
        | data           | vmware.VCenterVirtualMachine   | false  | true     | false    | false   | false         | false     | json:"data,omitempty"           |          0 |         |
        +----------------+--------------------------------+--------+----------+----------+---------+---------------+-----------+---------------------------------+------------+---------+
        +--------+---------------------------------------------+---------+---------+----------+--------+----------+---------+
        |  Edge  |                    Type                     | Inverse | BackRef | Relation | Unique | Optional | Comment |
        +--------+---------------------------------------------+---------+---------+----------+--------+----------+---------+
        | fields | CmdbCiServerVmwareVirtualMachineCustomField | false   |         | O2M      | false  | true     |         |
        +--------+---------------------------------------------+---------+---------+----------+--------+----------+---------+
        
CmdbCiServerVmwareVirtualMachineCustomField:
        +------------+-----------+--------+----------+----------+---------+---------------+-----------+-----------------------------+------------+---------+
        |   Field    |   Type    | Unique | Optional | Nillable | Default | UpdateDefault | Immutable |          StructTag          | Validators | Comment |
        +------------+-----------+--------+----------+----------+---------+---------------+-----------+-----------------------------+------------+---------+
        | id         | uuid.UUID | false  | false    | false    | true    | false         | false     | json:"id,omitempty"         |          0 |         |
        | created_at | time.Time | false  | false    | false    | true    | false         | true      | json:"created_at,omitempty" |          0 |         |
        | updated_at | time.Time | false  | false    | false    | true    | true          | false     | json:"updated_at,omitempty" |          0 |         |
        | deleted_at | time.Time | false  | true     | false    | false   | true          | false     | json:"deleted_at,omitempty" |          0 |         |
        | sysId      | uuid.UUID | false  | false    | false    | false   | false         | false     | json:"sysId,omitempty"      |          0 |         |
        | key        | int       | false  | false    | false    | false   | false         | false     | json:"key,omitempty"        |          0 |         |
        | value      | string    | false  | true     | false    | false   | false         | false     | json:"value,omitempty"      |          0 |         |
        +------------+-----------+--------+----------+----------+---------+---------------+-----------+-----------------------------+------------+---------+
        +----------------+----------------------------------+---------+---------+----------+--------+----------+---------+
        |      Edge      |               Type               | Inverse | BackRef | Relation | Unique | Optional | Comment |
        +----------------+----------------------------------+---------+---------+----------+--------+----------+---------+
        | virtualMachine | CmdbCiServerVmwareVirtualMachine | true    | fields  | M2O      | true   | true     |         |
        +----------------+----------------------------------+---------+---------+----------+--------+----------+---------+


As you can see, i have my Edge, and my index is unique for sys_id and key on the fields table.

// Indexes of the CmdbCiServerVmwareVirtualMachineCustomField.
func (CmdbCiServerVmwareVirtualMachineCustomField) Indexes() []ent.Index {
    return []ent.Index{
        index.Fields("key", "sysId").
            Edges("virtualMachine").Unique(),
    }
}

The following code seems to create the rows/relationships OK, however it will not upsert on the second run - only duplicate and give a NULL entry in the relationship column.

I am using the following code:

http://pastie.org/p/6vx6yugIWwlChKmSSJNPIs

enter image description here


Solution

  • func (CmdbCiServerVmwareVirtualMachineCustomField) Indexes() []ent.Index {
        return []ent.Index{
            index.Fields("key", "sysId").Unique(),
        }
    }
    

    The above index, combined with :

    ...
    .OnConflictColumns(                              
      cmdbciservervmwarevirtualmachinecustomfield.FieldSysId,
      cmdbciservervmwarevirtualmachinecustomfield.FieldKey).
    UpdateNewValues().
    ID(context.Background())
    

    was enough for this to work correctly.