Skip to content

Conversation

@XingY
Copy link
Contributor

@XingY XingY commented Jan 22, 2026

Rationale

This pr supports converting Multi Choice field types to/from other field types (primarily text, text choice).

Related Pull Requests

Changes

  • Added PostgreSQL-specific SQL transformation logic for converting between text[] (MULTI_CHOICE) and text types
  • Extended the QueryChangeListener interface to support column type changes.
  • Implemented automatic filter operator translation in custom views when Multi Choice fields are converted (e.g., arraycontainsany → in)
  • Remove experimental flag for MVTC fields

This comment was marked as resolved.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@XingY XingY requested a review from labkey-adam February 2, 2026 18:26
Copy link
Contributor

@labkey-adam labkey-adam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few questions and minor suggestions (that you can ignore)

@Override
public boolean meetsCriteria(ColumnRenderProperties col, Object value, Object[] filterValues)
{
throw new UnsupportedOperationException("Conditional formatting not yet supported for Multi Choices");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like "arrays" would be the more general term (vs. "Multi Choices") since these operators could be used in other scenarios. But I see that "Multi Choices" is what we're using in all the existing CompareTypes, so I guess it's fine.

ColumnInfo columnInfo = getFieldMap().get(key);
if (columnInfo != null && columnInfo.getPropertyType() == PropertyType.MULTI_CHOICE && value instanceof String strVal)
{
// Multi-choice values array is converted to string: "{value1,value2,...}", so strip off the braces before converting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these comma separated or semi-colon separated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This '{a, b}' format is what's returned by MVFK when casting array to string array_to_string(core.sort(array_agg(field))). @labkey-matthewb did mention possibly have MVFK to return ARRAY[] instead of string for the array type columns in the future.

// Multi-choice values array is converted to string: "{value1,value2,...}", so strip off the braces before converting
if (strVal.startsWith("{") && strVal.endsWith("}"))
return ConvertUtils.convert(strVal.substring(1, strVal.length() - 1), columnInfo.getJavaClass());
// TODO: return columnInfo.convert(strVal.substring(1, strVal.length() - 1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this TODO for later? Or can it be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to be updated after merging in the related branch that refactored ConverterUtil.

* @param changes The set of change events. Each QueryPropertyChange is associated with a single table or query.
*/
void queryChanged(User user, Container container, ContainerFilter scope, SchemaKey schema, @NotNull QueryProperty property, @NotNull Collection<QueryPropertyChange<?>> changes);
void queryChanged(User user, Container container, ContainerFilter scope, SchemaKey schema, @Nullable String queryName, @NotNull QueryProperty property, @NotNull Collection<QueryPropertyChange<?>> changes);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious why queryName had to be added. Each QueryPropertyChange has a QueryDefinition with the name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll revert this change and have the queryDef pass the info instead.

return filterStr;

// Only act when changing away from MULTI_CHOICE
if (oldType.getPropertyType() != PropertyType.MULTI_CHOICE || newType.getPropertyType() == PropertyType.MULTI_CHOICE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is called only when oldType.getPropertyType() == PropertyType.MULTI_CHOICE, so the first check isn't technically needed.

return filterStr;

// Only act when changing to MULTI_CHOICE
if (oldType.getPropertyType() == PropertyType.MULTI_CHOICE || newType.getPropertyType() != PropertyType.MULTI_CHOICE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is called only when newType.getPropertyType() == PropertyType.MULTI_CHOICE, so the second check isn't technically needed.

SQLFragment rename = new SQLFragment("ALTER TABLE ");
rename.appendIdentifier(change.getSchemaName()).append(".").appendIdentifier(change.getTableName());
rename.append(" RENAME COLUMN ").appendIdentifier(tempColumnIdent).append(" TO ").appendIdentifier(columnIdent);
statements.add(rename);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are admins allowed to add indexes or unique constraints to multichoice fields? I hope not, but obviously they'd get dropped here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't allow creating index on UI for MC field types. We also show a warning when converting from/to multi choice that configured conditional formatting will be lost. We can modify the message to say that index will be lost as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say don't bother updating the message. It's pretty obscure and few would expect indexes or unique constraints to be maintained on a multi-choice.

}
else if (column.getJdbcType() == JdbcType.ARRAY)
{
// Converting from text to text[] requires an intermediate column and transformation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admin could have created an index or unique constraint on this text field, right? Is it okay if the index/constraint is dropped?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants