[ 
https://issues.apache.org/jira/browse/IGNITE-26541?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Pavel Pereslegin updated IGNITE-26541:
--------------------------------------
    Description: 
If you add a new column type (in new Ignite version), the "old" thin client 
cannot work with such a table through table views.

{code:java}
// Schema has the following columns
// ID INT | VAL UNKNOWN
  RecordView<Tuple> view = client.tables()
          .table("TEST").recordView();
  
  Tuple key = Tuple.create().set("id", 1);

  // Attempt to find a row by key produces exception
  view.get(null, key);
{code}

Exception:

{noformat}
[2025-09-28T10:15:41,292][ERROR][main][TcpClientChannel] Failed to deserialize 
server response [remoteAddress=127.0.0.1:10800]: Invalid column type id: 14

org.apache.ignite.lang.IgniteException: Invalid column type id: 14
  at 
org.apache.ignite.internal.client.proto.ColumnTypeConverter.fromIdOrThrow(ColumnTypeConverter.java:39)
  at 
org.apache.ignite.internal.client.table.ClientTable.readSchema(ClientTable.java:272)
  at 
org.apache.ignite.internal.client.table.ClientTable.lambda$loadSchema$1(ClientTable.java:249)
  at 
org.apache.ignite.internal.client.TcpClientChannel.complete(TcpClientChannel.java:474)
  at 
org.apache.ignite.internal.client.TcpClientChannel.send(TcpClientChannel.java:409)
  at 
org.apache.ignite.internal.client.TcpClientChannel.serviceAsync(TcpClientChannel.java:335)
  at 
org.apache.ignite.internal.client.ReliableChannel.serviceAsyncInternal(ReliableChannel.java:360)
  at 
org.apache.ignite.internal.client.ReliableChannel.lambda$serviceAsync$1(ReliableChannel.java:268)
  at 
java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
  at 
java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2237)
  at 
org.apache.ignite.internal.client.ReliableChannel.lambda$serviceAsync$2(ReliableChannel.java:268)
  at 
org.apache.ignite.internal.client.ClientFutureUtils.doWithRetryAsync(ClientFutureUtils.java:56)
  at 
org.apache.ignite.internal.client.ClientFutureUtils.doWithRetryAsync(ClientFutureUtils.java:45)
  at 
org.apache.ignite.internal.client.ReliableChannel.serviceAsync(ReliableChannel.java:266)
  at 
org.apache.ignite.internal.client.ReliableChannel.serviceAsync(ReliableChannel.java:339)
  at 
org.apache.ignite.internal.client.table.ClientTable.loadSchema(ClientTable.java:227)
  at 
java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705)
  at 
org.apache.ignite.internal.client.table.ClientTable.getSchema(ClientTable.java:215)
  at 
org.apache.ignite.internal.client.table.ClientTable.doSchemaOutInOpAsync(ClientTable.java:456)
  at 
org.apache.ignite.internal.client.table.ClientTable.doSchemaOutInOpAsync(ClientTable.java:423)
  at 
org.apache.ignite.internal.client.table.ClientRecordBinaryView.getAsync(ClientRecordBinaryView.java:80)
  at 
org.apache.ignite.internal.client.table.ClientRecordBinaryView.get(ClientRecordBinaryView.java:72)
  at 
org.apache.ignite.internal.client.table.ClientRecordBinaryView.get(ClientRecordBinaryView.java:53)
  at 
org.apache.ignite.internal.client.table.api.PublicApiClientRecordView.lambda$get$0(PublicApiClientRecordView.java:52)
  at 
org.apache.ignite.internal.thread.PublicApiThreading.executeWithRole(PublicApiThreading.java:144)
  at 
org.apache.ignite.internal.thread.PublicApiThreading.execUserSyncOperation(PublicApiThreading.java:102)
  at 
org.apache.ignite.internal.client.table.api.PublicApiClientViewBase.executeSyncOp(PublicApiClientViewBase.java:101)
  at 
org.apache.ignite.internal.client.table.api.PublicApiClientRecordView.get(PublicApiClientRecordView.java:52)
{noformat}

We need to improve the readSchema method and map unknown column types to 
something like ColumnType.UNKNOWN (id=0?).
This way, we'll be able to work with the table until we try to access an 
unknown column.
When accessing a column of an unknown type, an exception with user-friendly 
text should be thrown.


Currently, DML queries can be executed via SQL (unless you specify a column of 
an unknown type).
However, this behavior needs to be improved to allow querying all columns 
(using '*'), and the error message seems to be improved.

For example:
{code:sql}
SELECT id FROM TEST; -- ok
SELECT * FROM TEST; -- fails
{code}

{noformat}
[2025-09-28T12:45:02,056][ERROR][ForkJoinPool.commonPool-worker-19][TcpClientChannel]
 Failed to deserialize server response [remoteAddress=127.0.0.1:10800]: Invalid 
column type id: 14

org.apache.ignite.lang.IgniteException: Invalid column type id: 14
  at 
org.apache.ignite.internal.client.proto.ColumnTypeConverter.fromIdOrThrow(ColumnTypeConverter.java:39)
  at 
org.apache.ignite.internal.client.sql.ClientResultSetMetadata.readColumn(ClientResultSetMetadata.java:60)
  at 
org.apache.ignite.internal.client.sql.ClientResultSetMetadata.read(ClientResultSetMetadata.java:47)
  at 
org.apache.ignite.internal.client.sql.ClientAsyncResultSet.<init>(ClientAsyncResultSet.java:112)
  at 
org.apache.ignite.internal.client.sql.ClientSql.lambda$payloadReader$5(ClientSql.java:345)
{noformat}

p.s. It is necessary to check the behavior of other thin clients (C#, C++) and 
improve it, if necessary, separately.

  was:
If you add a new column type, the thin client cannot work with such a table 
through table views.

{code:java}
// Schema has the following columns
// ID INT | VAL UNKNOWN
  RecordView<Tuple> view = client.tables()
          .table("TEST").recordView();
  
  Tuple key = Tuple.create().set("id", 1);

  // Attempt to find a row by key produces exception
  view.get(null, key);
{code}

Exception:

{noformat}
[2025-09-28T10:15:41,292][ERROR][main][TcpClientChannel] Failed to deserialize 
server response [remoteAddress=127.0.0.1:10800]: Invalid column type id: 14

org.apache.ignite.lang.IgniteException: Invalid column type id: 14
  at 
org.apache.ignite.internal.client.proto.ColumnTypeConverter.fromIdOrThrow(ColumnTypeConverter.java:39)
  at 
org.apache.ignite.internal.client.table.ClientTable.readSchema(ClientTable.java:272)
  at 
org.apache.ignite.internal.client.table.ClientTable.lambda$loadSchema$1(ClientTable.java:249)
  at 
org.apache.ignite.internal.client.TcpClientChannel.complete(TcpClientChannel.java:474)
  at 
org.apache.ignite.internal.client.TcpClientChannel.send(TcpClientChannel.java:409)
  at 
org.apache.ignite.internal.client.TcpClientChannel.serviceAsync(TcpClientChannel.java:335)
  at 
org.apache.ignite.internal.client.ReliableChannel.serviceAsyncInternal(ReliableChannel.java:360)
  at 
org.apache.ignite.internal.client.ReliableChannel.lambda$serviceAsync$1(ReliableChannel.java:268)
  at 
java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
  at 
java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2237)
  at 
org.apache.ignite.internal.client.ReliableChannel.lambda$serviceAsync$2(ReliableChannel.java:268)
  at 
org.apache.ignite.internal.client.ClientFutureUtils.doWithRetryAsync(ClientFutureUtils.java:56)
  at 
org.apache.ignite.internal.client.ClientFutureUtils.doWithRetryAsync(ClientFutureUtils.java:45)
  at 
org.apache.ignite.internal.client.ReliableChannel.serviceAsync(ReliableChannel.java:266)
  at 
org.apache.ignite.internal.client.ReliableChannel.serviceAsync(ReliableChannel.java:339)
  at 
org.apache.ignite.internal.client.table.ClientTable.loadSchema(ClientTable.java:227)
  at 
java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705)
  at 
org.apache.ignite.internal.client.table.ClientTable.getSchema(ClientTable.java:215)
  at 
org.apache.ignite.internal.client.table.ClientTable.doSchemaOutInOpAsync(ClientTable.java:456)
  at 
org.apache.ignite.internal.client.table.ClientTable.doSchemaOutInOpAsync(ClientTable.java:423)
  at 
org.apache.ignite.internal.client.table.ClientRecordBinaryView.getAsync(ClientRecordBinaryView.java:80)
  at 
org.apache.ignite.internal.client.table.ClientRecordBinaryView.get(ClientRecordBinaryView.java:72)
  at 
org.apache.ignite.internal.client.table.ClientRecordBinaryView.get(ClientRecordBinaryView.java:53)
  at 
org.apache.ignite.internal.client.table.api.PublicApiClientRecordView.lambda$get$0(PublicApiClientRecordView.java:52)
  at 
org.apache.ignite.internal.thread.PublicApiThreading.executeWithRole(PublicApiThreading.java:144)
  at 
org.apache.ignite.internal.thread.PublicApiThreading.execUserSyncOperation(PublicApiThreading.java:102)
  at 
org.apache.ignite.internal.client.table.api.PublicApiClientViewBase.executeSyncOp(PublicApiClientViewBase.java:101)
  at 
org.apache.ignite.internal.client.table.api.PublicApiClientRecordView.get(PublicApiClientRecordView.java:52)
{noformat}

We need to improve the readSchema method and map unknown column types to 
something like ColumnType.UNKNOWN (id=0?).
This way, we'll be able to work with the table until we try to access an 
unknown column.
When accessing a column of an unknown type, an exception with user-friendly 
text should be thrown.


Currently, DML queries can be executed via SQL (unless you specify a column of 
an unknown type).
However, this behavior needs to be improved to allow querying all columns 
(using '*'), and the error message seems to be improved.

For example:
{code:sql}
SELECT id FROM TEST; -- ok
SELECT * FROM TEST; -- fails
{code}

{noformat}
[2025-09-28T12:45:02,056][ERROR][ForkJoinPool.commonPool-worker-19][TcpClientChannel]
 Failed to deserialize server response [remoteAddress=127.0.0.1:10800]: Invalid 
column type id: 14

org.apache.ignite.lang.IgniteException: Invalid column type id: 14
  at 
org.apache.ignite.internal.client.proto.ColumnTypeConverter.fromIdOrThrow(ColumnTypeConverter.java:39)
  at 
org.apache.ignite.internal.client.sql.ClientResultSetMetadata.readColumn(ClientResultSetMetadata.java:60)
  at 
org.apache.ignite.internal.client.sql.ClientResultSetMetadata.read(ClientResultSetMetadata.java:47)
  at 
org.apache.ignite.internal.client.sql.ClientAsyncResultSet.<init>(ClientAsyncResultSet.java:112)
  at 
org.apache.ignite.internal.client.sql.ClientSql.lambda$payloadReader$5(ClientSql.java:345)
{noformat}

p.s. It is necessary to check the behavior of other thin clients (C#, C++) and 
improve it, if necessary, separately.


> Java Thin 3.0. Schema compatibility. Improve unknown column type handling.
> --------------------------------------------------------------------------
>
>                 Key: IGNITE-26541
>                 URL: https://issues.apache.org/jira/browse/IGNITE-26541
>             Project: Ignite
>          Issue Type: Improvement
>          Components: thin clients ai3
>            Reporter: Pavel Pereslegin
>            Priority: Major
>              Labels: ignite-3
>
> If you add a new column type (in new Ignite version), the "old" thin client 
> cannot work with such a table through table views.
> {code:java}
> // Schema has the following columns
> // ID INT | VAL UNKNOWN
>   RecordView<Tuple> view = client.tables()
>           .table("TEST").recordView();
>   
>   Tuple key = Tuple.create().set("id", 1);
>   // Attempt to find a row by key produces exception
>   view.get(null, key);
> {code}
> Exception:
> {noformat}
> [2025-09-28T10:15:41,292][ERROR][main][TcpClientChannel] Failed to 
> deserialize server response [remoteAddress=127.0.0.1:10800]: Invalid column 
> type id: 14
> org.apache.ignite.lang.IgniteException: Invalid column type id: 14
>   at 
> org.apache.ignite.internal.client.proto.ColumnTypeConverter.fromIdOrThrow(ColumnTypeConverter.java:39)
>   at 
> org.apache.ignite.internal.client.table.ClientTable.readSchema(ClientTable.java:272)
>   at 
> org.apache.ignite.internal.client.table.ClientTable.lambda$loadSchema$1(ClientTable.java:249)
>   at 
> org.apache.ignite.internal.client.TcpClientChannel.complete(TcpClientChannel.java:474)
>   at 
> org.apache.ignite.internal.client.TcpClientChannel.send(TcpClientChannel.java:409)
>   at 
> org.apache.ignite.internal.client.TcpClientChannel.serviceAsync(TcpClientChannel.java:335)
>   at 
> org.apache.ignite.internal.client.ReliableChannel.serviceAsyncInternal(ReliableChannel.java:360)
>   at 
> org.apache.ignite.internal.client.ReliableChannel.lambda$serviceAsync$1(ReliableChannel.java:268)
>   at 
> java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
>   at 
> java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2237)
>   at 
> org.apache.ignite.internal.client.ReliableChannel.lambda$serviceAsync$2(ReliableChannel.java:268)
>   at 
> org.apache.ignite.internal.client.ClientFutureUtils.doWithRetryAsync(ClientFutureUtils.java:56)
>   at 
> org.apache.ignite.internal.client.ClientFutureUtils.doWithRetryAsync(ClientFutureUtils.java:45)
>   at 
> org.apache.ignite.internal.client.ReliableChannel.serviceAsync(ReliableChannel.java:266)
>   at 
> org.apache.ignite.internal.client.ReliableChannel.serviceAsync(ReliableChannel.java:339)
>   at 
> org.apache.ignite.internal.client.table.ClientTable.loadSchema(ClientTable.java:227)
>   at 
> java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705)
>   at 
> org.apache.ignite.internal.client.table.ClientTable.getSchema(ClientTable.java:215)
>   at 
> org.apache.ignite.internal.client.table.ClientTable.doSchemaOutInOpAsync(ClientTable.java:456)
>   at 
> org.apache.ignite.internal.client.table.ClientTable.doSchemaOutInOpAsync(ClientTable.java:423)
>   at 
> org.apache.ignite.internal.client.table.ClientRecordBinaryView.getAsync(ClientRecordBinaryView.java:80)
>   at 
> org.apache.ignite.internal.client.table.ClientRecordBinaryView.get(ClientRecordBinaryView.java:72)
>   at 
> org.apache.ignite.internal.client.table.ClientRecordBinaryView.get(ClientRecordBinaryView.java:53)
>   at 
> org.apache.ignite.internal.client.table.api.PublicApiClientRecordView.lambda$get$0(PublicApiClientRecordView.java:52)
>   at 
> org.apache.ignite.internal.thread.PublicApiThreading.executeWithRole(PublicApiThreading.java:144)
>   at 
> org.apache.ignite.internal.thread.PublicApiThreading.execUserSyncOperation(PublicApiThreading.java:102)
>   at 
> org.apache.ignite.internal.client.table.api.PublicApiClientViewBase.executeSyncOp(PublicApiClientViewBase.java:101)
>   at 
> org.apache.ignite.internal.client.table.api.PublicApiClientRecordView.get(PublicApiClientRecordView.java:52)
> {noformat}
> We need to improve the readSchema method and map unknown column types to 
> something like ColumnType.UNKNOWN (id=0?).
> This way, we'll be able to work with the table until we try to access an 
> unknown column.
> When accessing a column of an unknown type, an exception with user-friendly 
> text should be thrown.
> Currently, DML queries can be executed via SQL (unless you specify a column 
> of an unknown type).
> However, this behavior needs to be improved to allow querying all columns 
> (using '*'), and the error message seems to be improved.
> For example:
> {code:sql}
> SELECT id FROM TEST; -- ok
> SELECT * FROM TEST; -- fails
> {code}
> {noformat}
> [2025-09-28T12:45:02,056][ERROR][ForkJoinPool.commonPool-worker-19][TcpClientChannel]
>  Failed to deserialize server response [remoteAddress=127.0.0.1:10800]: 
> Invalid column type id: 14
> org.apache.ignite.lang.IgniteException: Invalid column type id: 14
>   at 
> org.apache.ignite.internal.client.proto.ColumnTypeConverter.fromIdOrThrow(ColumnTypeConverter.java:39)
>   at 
> org.apache.ignite.internal.client.sql.ClientResultSetMetadata.readColumn(ClientResultSetMetadata.java:60)
>   at 
> org.apache.ignite.internal.client.sql.ClientResultSetMetadata.read(ClientResultSetMetadata.java:47)
>   at 
> org.apache.ignite.internal.client.sql.ClientAsyncResultSet.<init>(ClientAsyncResultSet.java:112)
>   at 
> org.apache.ignite.internal.client.sql.ClientSql.lambda$payloadReader$5(ClientSql.java:345)
> {noformat}
> p.s. It is necessary to check the behavior of other thin clients (C#, C++) 
> and improve it, if necessary, separately.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to