[
https://issues.apache.org/jira/browse/IGNITE-29048?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Evgeny Stanilovsky reassigned IGNITE-29048:
-------------------------------------------
Assignee: Ripley Lorrin
> Preserve column aliases during dynamic schema updates
> -----------------------------------------------------
>
> Key: IGNITE-29048
> URL: https://issues.apache.org/jira/browse/IGNITE-29048
> Project: Ignite
> Issue Type: Bug
> Components: cache
> Affects Versions: 2.17, 2.18
> Reporter: Ripley Lorrin
> Assignee: Ripley Lorrin
> Priority: Major
> Labels: easyfix
> Fix For: 2.19
>
> Attachments:
> Changes_to_preserve_column_aliases_during_dynamic_schema_updates.patch
>
>
> When a Cache is starting, it is possible to configure an Alias to the SQL
> Columns in order to perform queries using this alias.
> However, in the event of a dynamic schema update using
> {{GridQueryProcessor#dynamicColumnAdd}} or
> {{{}GridQueryProcessor#dynamicColumnRemove{}}}, the underlying called method
> {{GridQueryProcessor#processDynamicAddColumn}} omits the "alias" argument
> while adding a {{{}QueryBinaryProperty{}}}. (it is always set to null).
> This results in an impossibility to properly set an alias during a dynamic
> schema change, thus a system that relies on aliases for queries will
> experience failures for dynamically added fields.
> The problem affects not only a dynamic column addition, but also the dynamic
> drop by causality: if a system uses aliases to dynamically delete a
> dynamically added column (that does not save their alias in the
> {{{}QueryBinaryProperty{}}}), Ignite will rightly say that the column does
> not exist.
> Here is my proposed solution to allow the preservation of column aliases
> during dynamic schema updates - it consists of two one-liners.
> h2. *{{GridQueryProcessor (ignite-core)}}*
> {color:#4c9aff}*Current snippet*{color}
>
> {code:java}
> private void processDynamicAddColumn(QueryTypeDescriptorImpl d,
> List<QueryField> cols)
> throws IgniteCheckedException {
> List<GridQueryProperty> props = new ArrayList<>(cols.size());
> for (QueryField col : cols) {
> try {
> props.add(new QueryBinaryProperty(
> ctx,
> col.name(),
> null,
> Class.forName(col.typeName()),
> false,
> null, // <-- this is where the alias should be injected
> !col.isNullable(),
> null,
> col.precision(),
> col.scale()));
> }
> catch (ClassNotFoundException e) {
> throw new SchemaOperationException("Class not found for new
> property: " + col.typeName());
> }
> } for (GridQueryProperty p : props)
> d.addProperty(p, true);
> } {code}
>
> *{color:#00875a}Proposed snippet{color}*
> {code:java}
> for (QueryField col : cols) {
> try {
> props.add(new QueryBinaryProperty(
> ctx,
> col.name(),
> null,
> Class.forName(col.typeName()),
> false,
> col.alias(),
> !col.isNullable(),
> null,
> col.precision(),
> col.scale()));
> }
> catch (ClassNotFoundException e) {
> throw new SchemaOperationException("Class not found for new property:
> " + col.typeName());
> }
> }{code}
> ----------------
> An edition should be done in ignite-indexing's {{GridH2Table}} to take into
> account that the column alias should be taken instead of the name if present.
> h2. {{*GridH2Table (ignite-indexing)*}}
> {color:#4c9aff}Current snippet{color}
> {code:java}
> // And now, let's add new columns
> for (QueryField col : cols) {
> if (doesColumnExist(col.name()))
> return;
> try {
> Column c = new Column(col.name(),
> DataType.getTypeFromClass(Class.forName(col.typeName())));
> c.setNullable(col.isNullable());
> newCols[pos++] = c;
> }
> catch (ClassNotFoundException e) {
> throw new IgniteSQLException("H2 data type not found for class: " +
> col.typeName(), e);
> }
> }{code}
>
> {color:#00875a}Proposed snippet{color}
>
> {code:java}
> // And now, let's add new columns
> for (QueryField col : cols) {
> if (doesColumnExist(col.alias()))
> return;
> try {
> Column c = new Column(col.alias(),
> DataType.getTypeFromClass(Class.forName(col.typeName())));
> c.setNullable(col.isNullable());
> newCols[pos++] = c;
> }
> catch (ClassNotFoundException e) {
> throw new IgniteSQLException("H2 data type not found for class: " +
> col.typeName(), e);
> }
> } {code}
>
>
> Replacing the name with the alias does not pose an issue for systems that
> rely on the 'name', because {{QueryFields}} conveniently set the name as the
> alias as a fallback.
> {code:java}
> /**
> * @return Field alias.
> */
> public String alias() {
> return alias != null ? alias : name;
> }{code}
>
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)