Creating new PersistentRecord and validating unique constraints

I’m working on a driver-type module and would like to create a scripting function similar to system.device.addDevice. I have several different driver types, so I’m using the ExtensionPoint system.

Here’s what I’ve got so far - it seems to be working, but it’s letting me add multiple connections with the same name, which violates the unique constraint on the BaseConnectionRecord.Name field.

public void addConnection(String connectionType, String connectionName, PyDictionary connectionProps) {
    ExtensionPointManager epm = ConnectionExtensionPointManager.get();
    ExtensionPointType type = epm.getExtensionPoint(connectionType);
    if (type != null) {
  
        PersistentRecord baseRecord = context.getPersistenceInterface().createNew(BaseConnectionRecord.META);
        baseRecord.setString(BaseConnectionRecord.Name, connectionName);
        baseRecord.setString(BaseConnectionRecord.Type, connectionType);
        baseRecord.getMeta().getFieldMetas().forEach(fieldMeta -> {
            String fieldName = fieldMeta.getFieldName();
            if (connectionProps.containsKey(fieldName)) {
                baseRecord.setObject(fieldMeta, connectionProps.get(fieldName));
            }
        });
  
        PersistentRecord record = context.getPersistenceInterface().createNew(type.getSettingsRecordType());
        record.setReference(type.getSettingsRecordForeignKey(), baseRecord);
        record.getMeta().getFieldMetas().forEach(fieldMeta -> {
            String fieldName = fieldMeta.getFieldName();
            if (connectionProps.containsKey(fieldName)) {
                record.setObject(fieldMeta, connectionProps.get(fieldName));
            }
        });
  
        context.getPersistenceInterface().save(baseRecord);
        context.getPersistenceInterface().save(record);
    }
}

And in BaseConnectionRecord.java

  public static final IdentityField Id = new IdentityField(META);
  public static final StringField Name = new StringField(META, "Name", SFieldFlags.SMANDATORY, SFieldFlags.SDESCRIPTIVE);
  public static final StringField Type = new StringField(META, "Type", SFieldFlags.SMANDATORY, SFieldFlags.SDESCRIPTIVE);
  public static final StringField Description = new StringField(META, "Description", SFieldFlags.SDESCRIPTIVE);
  public static final BooleanField Enabled = new BooleanField(META, "Enabled", SFieldFlags.SDESCRIPTIVE).setDefault(true);

  static {
      Name.setUnique(true);
      Type.getFormMeta().setVisible(false);
  }
  1. Is my approach of creating/linking to the base record correct?
  2. What do I need to do to get this to respect the unique BaseConnectionRecord.Name constraint?

Did you add the unique constraint after you’d already generated your table in the .idb once? If you examine your config.idb in a SQLite viewer, does it actually have a unique constraint applied?

For complicated reasons, SQLite alterations to columns that already exist basically don’t get made, so the ‘Unique’ constraint might only be applied to editing via the web interface, and not actually applied at the persistence layer.

Yup, I did. In order to recreate the tables I uninstalled my module, shutdown the gateway, dropped all the tables, then reinstalled.

No, it doesn't. In fact, none of the default tables seem to have unique name constraints either.
I'm running an old nightly, b2022032113.

My BaseConnectionRecord table:

Some default tables:


Huh, yeah, so it doesn’t. It looks like there’s an intention to apply the unique constraint to the table, but it’s not actually ever making it there.

With system.device.addDevice, we just do a manual check for duplicate names :man_shrugging:

Roger, that’s what I’ll do then.