{"record":{"id":"a45e8136822739f5","repo":"SonarSource/sonarqube","slug":"this-builder-should-not-be-used-with-primary-keys","errorCode":null,"errorMessage":"This builder should not be used with primary keys","messagePattern":"This builder should not be used with primary keys","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/DropConstraintBuilder.java","lineNumber":55,"sourceCode":" */\npublic class DropConstraintBuilder {\n\n  private final Dialect dialect;\n  private String tableName;\n  private String constraintName;\n\n  public DropConstraintBuilder(Dialect dialect) {\n    this.dialect = dialect;\n  }\n\n  public DropConstraintBuilder setTable(String s) {\n    this.tableName = s;\n    return this;\n  }\n\n  public DropConstraintBuilder setName(String s) {\n    if (s.startsWith(\"pk_\")) {\n      throw new IllegalArgumentException(\"This builder should not be used with primary keys\");\n    }\n    this.constraintName = s;\n    return this;\n  }\n\n  public List<String> build() {\n    validateTableName(tableName);\n    validateIndexName(constraintName);\n    return singletonList(createSqlStatement());\n  }\n\n  private String createSqlStatement() {\n    return switch (dialect.getId()) {\n      case MsSql.ID, Oracle.ID, PostgreSql.ID, H2.ID -> \"ALTER TABLE \" + tableName + \" DROP CONSTRAINT \" + constraintName;\n      default -> throw new IllegalStateException(\"Unsupported dialect for drop of constraint: \" + dialect);\n    };\n  }\n}","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/DropConstraintBuilder.java#L37-L73","documentation":"DropConstraintBuilder intentionally refuses constraint names starting with 'pk_'. Primary keys are handled by a dedicated finder/dropper because their SQL differs (sometimes requiring sequence handling on PostgreSQL), so using this builder for a PK would produce wrong statements.","triggerScenarios":"Calling setName(\"pk_issues\") or any name starting with lowercase 'pk_' before build().","commonSituations":"Migration author loops over all constraints of a table and tries to drop PKs with the generic builder; copy-pasted constraint name; case confusion since only lowercase 'pk_' prefix is rejected.","solutions":["Use the primary-key specific removal path (DbPrimaryKeyConstraintFinder + dedicated PK drop) instead of DropConstraintBuilder for 'pk_' constraints.","Only pass non-primary-key constraint names to setName().","Normalize name casing so real PK names aren't missed if your DB stores them uppercase."],"exampleFix":"// before\nnew DropConstraintBuilder(dialect, \"issues\").setName(\"pk_issues\")...\n// after\nString pk = constraintFinder.constraintQuery(\"issues\"); // use PK-specific handling\nnew DropConstraintBuilder(dialect, \"issues\").setName(\"fk_issues_user\")...","handlingStrategy":"validation","validationCode":"if (constraintName.toLowerCase().startsWith(\"pk_\")) { usePrimaryKeyRemovalPath(table); } else { new DropConstraintBuilder(dialect, table).setName(constraintName); }","typeGuard":"boolean isPrimaryKeyConstraint(String name) { return name != null && name.toLowerCase().startsWith(\"pk_\"); }","tryCatchPattern":null,"preventionTips":["Route 'pk_' constraints to the dedicated PK drop logic","Inspect constraint names before iterating drops","Be careful with case: the guard only rejects lowercase 'pk_' prefix"],"tags":["database","migration","constraint","primary-key"],"backgroundTag":"unsupported-operation","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}