anton-vinogradov commented on code in PR #13236: URL: https://github.com/apache/ignite/pull/13236#discussion_r3475936038
########## modules/core/src/main/java/org/apache/ignite/internal/processors/query/schema/message/QueryEntityExMessage.java: ########## @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.query.schema.message; + +import org.apache.ignite.cache.QueryEntity; +import org.apache.ignite.internal.Order; +import org.apache.ignite.internal.processors.query.QueryEntityEx; + +/** + * Message for {@link QueryEntityEx} transfer. + */ +public class QueryEntityExMessage extends QueryEntityMessage { + /** Whether to preserve order specified by 'keyFields' or not. */ + @Order(0) + boolean preserveKeysOrder; + + /** Whether a primary key should be autocreated or not. */ + @Order(1) + boolean implicitPk; + + /** Whether absent PK parts should be filled with defaults or not. */ + @Order(2) + boolean fillAbsentPKsWithDefaults; + + /** INLINE_SIZE for PK index. */ + @Order(3) + int pkInlineSize; + + /** INLINE_SIZE for affinity field index. */ + @Order(4) + int affKeyInlineSize; + + /** Whether query entity was created by SQL. */ + @Order(5) + boolean sql; + + /** */ + public QueryEntityExMessage() { } + + /** + * @param qryEntity Original {@link QueryEntity}. + */ + public QueryEntityExMessage(QueryEntityEx qryEntity) { + super(qryEntity); + + preserveKeysOrder = qryEntity.isPreserveKeysOrder(); + implicitPk = qryEntity.implicitPk(); + fillAbsentPKsWithDefaults = qryEntity.fillAbsentPKsWithDefaults(); + + pkInlineSize = qryEntity.getPrimaryKeyInlineSize() != null ? qryEntity.getPrimaryKeyInlineSize() : -1; + + affKeyInlineSize = qryEntity.getAffinityKeyInlineSize() != null ? qryEntity.getAffinityKeyInlineSize() : -1; + + sql = qryEntity.sql(); + } + + /** {@inheritDoc} */ + @Override public QueryEntity toEntity() { + QueryEntityEx qryEntity = new QueryEntityEx(super.toEntity()); Review Comment: Follow-up to my earlier review (the "add tests" comment): while writing a round-trip test I hit a real asymmetry here that I think is worth a look. `QueryEntityEx` overrides `getNotNullFields()`/`setNotNullFields()` to use its own `notNullFields` field, which shadows the base `QueryEntity._notNullFields`. `super.toEntity()` (line 74) populates the *base* `_notNullFields` from the message, and line 76 then sets the *Ex* field — so after a round-trip a `QueryEntityEx` always has `base._notNullFields == ex.notNullFields`. But a normally-built `QueryEntityEx` has `base._notNullFields == null` (the Ex setter only touches the Ex field) while `ex.notNullFields` is set. The old Java-serialized path preserved both fields independently; this DTO path normalizes the base field. Net effect: **a normally-built `QueryEntityEx` is no longer `.equals()` to its round-tripped copy**, because `QueryEntity.equals()`/`hashCode()` compare the shadowed base `_notNullFields`. It's easy to miss because `QueryEntityEx.toString()` doesn't print that field — the two objects render identically while being unequal. Verified with a round-trip test: consistent `base == ex` notNullFields passes; `ex.setNotNullFields(...)` only (the natural case) fails `assertEquals(orig, roundTripped)` with identical toString. Impact depends on whether anything compares a `QueryEntityEx` via `equals()`/`hashCode()` across (de)serialization (e.g. QueryEntity/schema conflict checks on join or cache start). Two ways out: don't populate the round-tripped Ex's base `_notNullFields` from the Ex value (keep it consistent with how the original was built), or stop letting the shadowed base field participate in equality. Happy to add a regression test once you pick a direction. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
