[
https://issues.apache.org/jira/browse/IGNITE-28930?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18102139#comment-18102139
]
Ignite TC Bot commented on IGNITE-28930:
----------------------------------------
"SQL: Fixed loss of column default values on remote nodes when a query entity
is added dynamically."
The Release Note field has been filled with the wording above. Please review it
and edit it if needed.
> Default field values are lost on remote nodes when a query entity is added
> dynamically
> --------------------------------------------------------------------------------------
>
> Key: IGNITE-28930
> URL: https://issues.apache.org/jira/browse/IGNITE-28930
> Project: Ignite
> Issue Type: Task
> Reporter: Anton Vinogradov
> Assignee: Dmitry Werner
> Priority: Major
> Labels: IEP-132, ise
> Fix For: 2.19
>
> Time Spent: 1h
> Remaining Estimate: 0h
>
> GridQueryProcessor#dynamicAddQueryEntity delivers its QueryEntity list to the
> other nodes inside
> SchemaAddQueryEntityOperation, whose entitiesMsgs field is a lazy view:
> entitiesMsgs = F.viewReadOnly(entities, this::makeEntityMessage); //
> SchemaAddQueryEntityOperation:70
> F.viewReadOnly returns a TransformCollectionView, so every traversal runs the
> closure again and hands out
> fresh QueryEntityMessage instances. TcpDiscoveryIoSession#serializeMessage
> traverses the message twice:
> MessageMarshalling.marshal(m, ...); //
> TcpDiscoveryIoSession:244
> MessageSerialization.writeTo(spi.messageFactory(), m, msgWriter); //
> TcpDiscoveryIoSession:255
> The first traversal fills dfltFieldValuesBytes on instances that are dropped
> right away; the second one
> builds new instances whose companion is still null, and writes those. The
> default values never leave the
> initiator. Every other field of the same entity arrives intact, because
> dfltFieldValues is the only one
> that needs a marshalling step.
> Reproduced on two nodes:
> n0: dynamicAddQueryEntity("C", "PUBLIC", <entity with
> defaultFieldValues=\{NAME=unknown}>, null, true)
> n0: getDefaultFieldValues() -> \{NAME=unknown}
> n1: getDefaultFieldValues() -> {} <- lost
> n1: notNullFields -> [ID] <- a plain field of the same
> entity arrives
> Same through SQL, when the cache already exists:
> CREATE TABLE PERSON (ID INT PRIMARY KEY, NAME VARCHAR DEFAULT 'unknown')
> WITH "cache_name=C"
> User visible effect: an INSERT that omits the column writes NULL instead of
> the default on every node
> except the one that ran the statement.
> n1: INSERT INTO PERSON(ID) VALUES(2) -> SELECT NAME -> null
> n0: INSERT INTO PERSON(ID) VALUES(1) -> SELECT NAME -> 'unknown'
> Remote nodes also lose the defaults from their stored cache configuration, so
> a restart does not recover
> them.
> A plain CREATE TABLE (GridQueryProcessor#dynamicTableCreate) is not affected:
> the defaults reach both the
> running nodes and a node that joins afterwards. Statically configured
> QueryEntity is not affected either.
> The fix is to materialize the collection:
> entitiesMsgs = F.transform(entities, this::makeEntityMessage);
> More generally, an @Order field holding messages that carry marshalling state
> must not be a lazy view,
> because marshal and writeTo traverse it independently.
> QueryEntityMessage#idxs is such a view today and
> is harmless only because QueryIndexMessage has no marshalling state - one
> @Marshalled field there would
> break it the same way.
> Introduced by bc1e3d277e3 (IGNITE-28767), which replaced the operation's own
> byte[] field - stable across
> traversals - with the lazy view. The commit is in no release tag, so master
> is the only affected version.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)