[ 
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)

Reply via email to