This is an automated email from the ASF dual-hosted git repository.

alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new f9e1ab3aa62 IGNITE-18832 Add CLIENT_CONNECTION_ATTRIBUTES system view 
- Fixes #10719.
f9e1ab3aa62 is described below

commit f9e1ab3aa62e95621afb2ce2be8a049e33d7d3bf
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Thu May 18 10:56:31 2023 +0300

    IGNITE-18832 Add CLIENT_CONNECTION_ATTRIBUTES system view - Fixes #10719.
    
    Signed-off-by: Aleksey Plekhanov <[email protected]>
---
 docs/_docs/monitoring-metrics/system-views.adoc    | 14 +++++
 .../internal/jdbc2/JdbcMetadataSelfTest.java       |  1 +
 .../ignite/jdbc/thin/JdbcThinMetadataSelfTest.java |  4 ++
 .../SystemViewRowAttributeWalkerGenerator.java     |  2 +
 .../apache/ignite/util/SystemViewCommandTest.java  |  1 +
 .../ClientConnectionAttributeViewWalker.java       | 67 ++++++++++++++++++++++
 .../ClientListenerAbstractConnectionContext.java   |  5 ++
 .../odbc/ClientListenerConnectionContext.java      |  6 ++
 .../processors/odbc/ClientListenerProcessor.java   | 49 ++++++++++++++++
 .../view/ClientConnectionAttributeView.java        | 66 +++++++++++++++++++++
 .../ignite/internal/metric/SystemViewSelfTest.java | 47 +++++++++++++++
 .../cache/metric/SqlViewExporterSpiTest.java       |  1 +
 .../processors/query/SqlSystemViewsSelfTest.java   | 41 +++++++++++++
 13 files changed, 304 insertions(+)

diff --git a/docs/_docs/monitoring-metrics/system-views.adoc 
b/docs/_docs/monitoring-metrics/system-views.adoc
index 22b7edc7007..cfa604d205f 100644
--- a/docs/_docs/monitoring-metrics/system-views.adoc
+++ b/docs/_docs/monitoring-metrics/system-views.adoc
@@ -389,6 +389,20 @@ This view exposes information about currently opened 
client connections: JDBC, O
 |VERSION | string |  Protocol version
 |===
 
+== CLIENT_CONNECTION_ATTRIBUTES
+
+
+The CLIENT_CONNECTION_ATTRIBUTES view exposes user defined attributes of 
client connections (thin, JDBC, ODBC). Attributes for the connection are 
provided by clients. For example, attributes for java thin client can be 
specified using `ClientConfiguration.setUserAttributes` method.
+
+[{table_opts}]
+|===
+| Column | Data Type | Description
+| CONNECTION_ID | long | ID of the connection
+| NAME | VARCHAR | Name of the attribute
+| VALUE | VARCHAR | Attribute value
+
+|===
+
 == STRIPED_THREADPOOL_QUEUE
 
 This view exposes information about tasks waiting for the execution in the 
system striped thread pool.
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
index 5de43a1b124..a8cf5bc812e 100755
--- 
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
@@ -342,6 +342,7 @@ public class JdbcMetadataSelfTest extends 
GridCommonAbstractTest {
             "JOBS",
             "SERVICES",
             "CLIENT_CONNECTIONS",
+            "CLIENT_CONNECTION_ATTRIBUTES",
             "TRANSACTIONS",
             "VIEWS",
             "TABLE_COLUMNS",
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
index 5fd123a22fa..e8df4956a40 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
@@ -437,6 +437,7 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
                 "SYS.NODE_ATTRIBUTES",
                 "SYS.TABLES",
                 "SYS.CLIENT_CONNECTIONS",
+                "SYS.CLIENT_CONNECTION_ATTRIBUTES",
                 "SYS.TRANSACTIONS",
                 "SYS.VIEWS",
                 "SYS.TABLE_COLUMNS",
@@ -928,6 +929,9 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
                 "SYS.CLIENT_CONNECTIONS.TYPE.null",
                 "SYS.CLIENT_CONNECTIONS.USER.null",
                 "SYS.CLIENT_CONNECTIONS.VERSION.null",
+                "SYS.CLIENT_CONNECTION_ATTRIBUTES.CONNECTION_ID.null",
+                "SYS.CLIENT_CONNECTION_ATTRIBUTES.NAME.null",
+                "SYS.CLIENT_CONNECTION_ATTRIBUTES.VALUE.null",
                 "SYS.TASKS.EXEC_NAME.null",
                 "SYS.TRANSACTIONS.LOCAL_NODE_ID.null",
                 "SYS.TRANSACTIONS.STATE.null",
diff --git 
a/modules/codegen/src/main/java/org/apache/ignite/codegen/SystemViewRowAttributeWalkerGenerator.java
 
b/modules/codegen/src/main/java/org/apache/ignite/codegen/SystemViewRowAttributeWalkerGenerator.java
index d57cd1e20cd..879b5f833fc 100644
--- 
a/modules/codegen/src/main/java/org/apache/ignite/codegen/SystemViewRowAttributeWalkerGenerator.java
+++ 
b/modules/codegen/src/main/java/org/apache/ignite/codegen/SystemViewRowAttributeWalkerGenerator.java
@@ -47,6 +47,7 @@ import org.apache.ignite.spi.systemview.view.CacheGroupIoView;
 import org.apache.ignite.spi.systemview.view.CacheGroupView;
 import org.apache.ignite.spi.systemview.view.CachePagesListView;
 import org.apache.ignite.spi.systemview.view.CacheView;
+import org.apache.ignite.spi.systemview.view.ClientConnectionAttributeView;
 import org.apache.ignite.spi.systemview.view.ClientConnectionView;
 import org.apache.ignite.spi.systemview.view.ClusterNodeView;
 import org.apache.ignite.spi.systemview.view.ComputeJobView;
@@ -118,6 +119,7 @@ public class SystemViewRowAttributeWalkerGenerator {
         gen.generateAndWrite(ComputeTaskView.class, DFLT_SRC_DIR);
         gen.generateAndWrite(ComputeJobView.class, DFLT_SRC_DIR);
         gen.generateAndWrite(ClientConnectionView.class, DFLT_SRC_DIR);
+        gen.generateAndWrite(ClientConnectionAttributeView.class, 
DFLT_SRC_DIR);
         gen.generateAndWrite(TransactionView.class, DFLT_SRC_DIR);
         gen.generateAndWrite(ContinuousQueryView.class, DFLT_SRC_DIR);
         gen.generateAndWrite(ClusterNodeView.class, DFLT_SRC_DIR);
diff --git 
a/modules/control-utility/src/test/java/org/apache/ignite/util/SystemViewCommandTest.java
 
b/modules/control-utility/src/test/java/org/apache/ignite/util/SystemViewCommandTest.java
index 0e29abe8c72..8393f49e44d 100644
--- 
a/modules/control-utility/src/test/java/org/apache/ignite/util/SystemViewCommandTest.java
+++ 
b/modules/control-utility/src/test/java/org/apache/ignite/util/SystemViewCommandTest.java
@@ -464,6 +464,7 @@ public class SystemViewCommandTest extends 
GridCommandHandlerClusterByClassAbstr
             "NODE_ATTRIBUTES",
             "TABLES",
             "CLIENT_CONNECTIONS",
+            "CLIENT_CONNECTION_ATTRIBUTES",
             "TABLE_COLUMNS",
             "VIEW_COLUMNS",
             "TRANSACTIONS",
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/ClientConnectionAttributeViewWalker.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/ClientConnectionAttributeViewWalker.java
new file mode 100644
index 00000000000..eeb528a82d6
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/managers/systemview/walker/ClientConnectionAttributeViewWalker.java
@@ -0,0 +1,67 @@
+/*
+ * 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.managers.systemview.walker;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.systemview.view.ClientConnectionAttributeView;
+import org.apache.ignite.spi.systemview.view.SystemViewRowAttributeWalker;
+
+/**
+ * Generated by {@code 
org.apache.ignite.codegen.SystemViewRowAttributeWalkerGenerator}.
+ * {@link ClientConnectionAttributeView} attributes walker.
+ * 
+ * @see ClientConnectionAttributeView
+ */
+public class ClientConnectionAttributeViewWalker implements 
SystemViewRowAttributeWalker<ClientConnectionAttributeView> {
+    /** Filter key for attribute "connectionId" */
+    public static final String CONNECTION_ID_FILTER = "connectionId";
+
+    /** Filter key for attribute "name" */
+    public static final String NAME_FILTER = "name";
+
+    /** List of filtrable attributes. */
+    private static final List<String> FILTRABLE_ATTRS = 
Collections.unmodifiableList(F.asList(
+        "connectionId", "name"
+    ));
+
+    /** {@inheritDoc} */
+    @Override public List<String> filtrableAttributes() {
+        return FILTRABLE_ATTRS;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void visitAll(AttributeVisitor v) {
+        v.accept(0, "connectionId", long.class);
+        v.accept(1, "name", String.class);
+        v.accept(2, "value", String.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void visitAll(ClientConnectionAttributeView row, 
AttributeWithValueVisitor v) {
+        v.acceptLong(0, "connectionId", row.connectionId());
+        v.accept(1, "name", String.class, row.name());
+        v.accept(2, "value", String.class, row.value());
+    }
+
+    /** {@inheritDoc} */
+    @Override public int count() {
+        return 3;
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerAbstractConnectionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerAbstractConnectionContext.java
index 710befbc7f3..fa7d4efa07c 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerAbstractConnectionContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerAbstractConnectionContext.java
@@ -148,4 +148,9 @@ public abstract class 
ClientListenerAbstractConnectionContext implements ClientL
     public String clientDescriptor() {
         return clientDesc;
     }
+
+    /** {@inheritDoc} */
+    @Override public Map<String, String> attributes() {
+        return F.isEmpty(userAttrs) ? Collections.emptyMap() : 
Collections.unmodifiableMap(userAttrs);
+    }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerConnectionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerConnectionContext.java
index 61432655bea..11a87649349 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerConnectionContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerConnectionContext.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.odbc;
 
+import java.util.Map;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 import org.apache.ignite.internal.processors.security.SecurityContext;
@@ -82,4 +83,9 @@ public interface ClientListenerConnectionContext {
      * @return Security context.
      */
     @Nullable SecurityContext securityContext();
+
+    /**
+     * Connection attributes.
+     */
+    Map<String, String> attributes();
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
index 5ddcccfd04b..3a502135905 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
@@ -22,9 +22,12 @@ import java.net.InetSocketAddress;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
 import javax.cache.configuration.Factory;
 import javax.management.JMException;
 import javax.management.ObjectName;
@@ -36,6 +39,7 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.OdbcConfiguration;
 import org.apache.ignite.configuration.SqlConnectorConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
+import 
org.apache.ignite.internal.managers.systemview.walker.ClientConnectionAttributeViewWalker;
 import 
org.apache.ignite.internal.managers.systemview.walker.ClientConnectionViewWalker;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
 import 
org.apache.ignite.internal.processors.configuration.distributed.DistributedThinClientConfiguration;
@@ -55,6 +59,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.mxbean.ClientProcessorMXBean;
 import org.apache.ignite.plugin.security.SecurityPermission;
 import org.apache.ignite.spi.IgnitePortProtocol;
+import org.apache.ignite.spi.systemview.view.ClientConnectionAttributeView;
 import org.apache.ignite.spi.systemview.view.ClientConnectionView;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -75,6 +80,12 @@ public class ClientListenerProcessor extends 
GridProcessorAdapter {
     /** */
     public static final String CLI_CONN_VIEW_DESC = "Client connections";
 
+    /** */
+    public static final String CLI_CONN_ATTR_VIEW = metricName("client", 
"connection", "attributes");
+
+    /** */
+    public static final String CLI_CONN_ATTR_VIEW_DESC = "Client connection 
attributes";
+
     /** */
     public static final String METRIC_ACTIVE = "ActiveSessions";
 
@@ -210,6 +221,12 @@ public class ClientListenerProcessor extends 
GridProcessorAdapter {
                     srv.sessions(),
                     ClientConnectionView::new);
 
+                ctx.systemView().registerFiltrableView(CLI_CONN_ATTR_VIEW, 
CLI_CONN_ATTR_VIEW_DESC,
+                    new ClientConnectionAttributeViewWalker(),
+                    this::connectionAttributeViewSupplier,
+                    Function.identity()
+                );
+
                 distrThinCfg = new DistributedThinClientConfiguration(ctx);
             }
             catch (Exception e) {
@@ -218,6 +235,38 @@ public class ClientListenerProcessor extends 
GridProcessorAdapter {
         }
     }
 
+    /** */
+    private Iterable<ClientConnectionAttributeView> 
connectionAttributeViewSupplier(Map<String, Object> filter) {
+        Long connId = 
(Long)filter.get(ClientConnectionAttributeViewWalker.CONNECTION_ID_FILTER);
+        String attrName = 
(String)filter.get(ClientConnectionAttributeViewWalker.NAME_FILTER);
+
+        Collection<? extends GridNioSession> sessions = srv.sessions();
+
+        return F.flat(F.iterator(sessions, ses -> {
+            ClientListenerConnectionContext ctx = ses.meta(CONN_CTX_META_KEY);
+
+            if (connId != null && connId != ctx.connectionId())
+                return Collections.emptyList();
+
+            Map<String, String> attrs = ctx.attributes();
+
+            if (attrName != null) {
+                String attrVal = attrs.get(attrName);
+
+                if (attrVal == null)
+                    return Collections.emptyList();
+
+                attrs = F.asMap(attrName, attrVal);
+            }
+
+            return F.iterator(
+                attrs.entrySet(),
+                attr -> new ClientConnectionAttributeView(ctx.connectionId(), 
attr.getKey(), attr.getValue()),
+                true
+            );
+        }, true));
+    }
+
     /** @param mreg Metric registry. */
     private void registerClientMetrics(MetricRegistry mreg) {
         for (int i = 0; i < CLI_TYPES.length; i++) {
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/ClientConnectionAttributeView.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/ClientConnectionAttributeView.java
new file mode 100644
index 00000000000..3cb8b820a30
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/ClientConnectionAttributeView.java
@@ -0,0 +1,66 @@
+/*
+ * 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.spi.systemview.view;
+
+import org.apache.ignite.internal.managers.systemview.walker.Filtrable;
+import org.apache.ignite.internal.managers.systemview.walker.Order;
+
+/**
+ * Client connection attribute system view row.
+ */
+public class ClientConnectionAttributeView {
+    /** Connection id. */
+    private final long connId;
+
+    /** Attribute name. */
+    private final String name;
+
+    /** Attribute value. */
+    private final String val;
+
+    /**
+     * @param connId Connection id.
+     * @param name Attribute name.
+     * @param val Attribute value.
+     */
+    public ClientConnectionAttributeView(long connId, String name, String val) 
{
+        this.connId = connId;
+        this.name = name;
+        this.val = val;
+    }
+
+    /** @return Connection id. */
+    @Order()
+    @Filtrable
+    public long connectionId() {
+        return connId;
+    }
+
+    /** @return Attribute name. */
+    @Order(1)
+    @Filtrable
+    public String name() {
+        return name;
+    }
+
+    /** @return Attribute value. */
+    @Order(2)
+    public String value() {
+        return val;
+    }
+}
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewSelfTest.java
index b6dc6e4b498..6044030c016 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewSelfTest.java
@@ -59,6 +59,7 @@ import 
org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
 import org.apache.ignite.cache.query.ContinuousQuery;
 import org.apache.ignite.cache.query.QueryCursor;
 import org.apache.ignite.cache.query.ScanQuery;
+import org.apache.ignite.client.Config;
 import org.apache.ignite.client.IgniteClient;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.cluster.ClusterState;
@@ -80,6 +81,7 @@ import 
org.apache.ignite.internal.binary.mutabletest.GridBinaryTestClasses.TestO
 import org.apache.ignite.internal.client.thin.ProtocolVersion;
 import 
org.apache.ignite.internal.managers.systemview.walker.BaselineNodeAttributeViewWalker;
 import 
org.apache.ignite.internal.managers.systemview.walker.CachePagesListViewWalker;
+import 
org.apache.ignite.internal.managers.systemview.walker.ClientConnectionAttributeViewWalker;
 import 
org.apache.ignite.internal.managers.systemview.walker.NodeAttributeViewWalker;
 import 
org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
 import 
org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
@@ -107,6 +109,7 @@ import 
org.apache.ignite.spi.systemview.view.CacheGroupIoView;
 import org.apache.ignite.spi.systemview.view.CacheGroupView;
 import org.apache.ignite.spi.systemview.view.CachePagesListView;
 import org.apache.ignite.spi.systemview.view.CacheView;
+import org.apache.ignite.spi.systemview.view.ClientConnectionAttributeView;
 import org.apache.ignite.spi.systemview.view.ClientConnectionView;
 import org.apache.ignite.spi.systemview.view.ClusterNodeView;
 import org.apache.ignite.spi.systemview.view.ComputeTaskView;
@@ -175,6 +178,7 @@ import static 
org.apache.ignite.internal.processors.datastructures.DataStructure
 import static 
org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor.STAMPED_VIEW;
 import static 
org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor.VOLATILE_DATA_REGION_NAME;
 import static 
org.apache.ignite.internal.processors.metastorage.persistence.DistributedMetaStorageImpl.DISTRIBUTED_METASTORE_VIEW;
+import static 
org.apache.ignite.internal.processors.odbc.ClientListenerProcessor.CLI_CONN_ATTR_VIEW;
 import static 
org.apache.ignite.internal.processors.odbc.ClientListenerProcessor.CLI_CONN_VIEW;
 import static 
org.apache.ignite.internal.processors.pool.PoolProcessor.STREAM_POOL_QUEUE_VIEW;
 import static 
org.apache.ignite.internal.processors.pool.PoolProcessor.SYS_POOL_QUEUE_VIEW;
@@ -588,6 +592,49 @@ public class SystemViewSelfTest extends 
GridCommonAbstractTest {
         }
     }
 
+    /** */
+    @Test
+    public void testClientConnectionAttributes() throws Exception {
+        try (IgniteEx g0 = startGrid(0)) {
+            SystemView<ClientConnectionAttributeView> view = 
g0.context().systemView().view(CLI_CONN_ATTR_VIEW);
+
+            try (
+                IgniteClient cl1 = Ignition.startClient(new 
ClientConfiguration().setAddresses(Config.SERVER)
+                    .setUserAttributes(F.asMap("attr1", "val1", "attr2", 
"val2")));
+                IgniteClient cl2 = Ignition.startClient(new 
ClientConfiguration().setAddresses(Config.SERVER)
+                    .setUserAttributes(F.asMap("attr1", "val2")));
+                IgniteClient cl3 = Ignition.startClient(new 
ClientConfiguration().setAddresses(Config.SERVER))
+            ) {
+                assertEquals(3, F.size(view.iterator()));
+
+                assertEquals(1, F.size(view.iterator(), row ->
+                    "attr1".equals(row.name()) && "val1".equals(row.value())));
+
+                // Test filtering.
+                assertTrue(view instanceof FiltrableSystemView);
+
+                Iterator<ClientConnectionAttributeView> iter = 
((FiltrableSystemView<ClientConnectionAttributeView>)view)
+                    
.iterator(F.asMap(ClientConnectionAttributeViewWalker.NAME_FILTER, "attr1"));
+
+                assertEquals(2, F.size(iter));
+
+                iter = 
((FiltrableSystemView<ClientConnectionAttributeView>)view).iterator(
+                    F.asMap(ClientConnectionAttributeViewWalker.NAME_FILTER, 
"attr2"));
+
+                assertTrue(iter.hasNext());
+
+                long connId = iter.next().connectionId();
+
+                assertFalse(iter.hasNext());
+
+                iter = 
((FiltrableSystemView<ClientConnectionAttributeView>)view).iterator(
+                    
F.asMap(ClientConnectionAttributeViewWalker.CONNECTION_ID_FILTER, connId));
+
+                assertEquals(2, F.size(iter));
+            }
+        }
+    }
+
     /** */
     @Test
     public void testContinuousQuery() throws Exception {
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
index d8cd04f86dd..74aa625cda0 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
@@ -431,6 +431,7 @@ public class SqlViewExporterSpiTest extends 
AbstractExporterSpiTest {
             "SNAPSHOT",
             "TABLES",
             "CLIENT_CONNECTIONS",
+            "CLIENT_CONNECTION_ATTRIBUTES",
             "VIEWS",
             "TABLE_COLUMNS",
             "VIEW_COLUMNS",
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
index bdbe98fad72..1bbb15ac935 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
@@ -40,6 +40,7 @@ import javax.cache.configuration.Factory;
 import com.google.common.collect.Sets;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.QueryEntity;
@@ -52,10 +53,13 @@ import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.cache.query.QueryCursor;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.cache.query.SqlQuery;
+import org.apache.ignite.client.Config;
+import org.apache.ignite.client.IgniteClient;
 import org.apache.ignite.cluster.ClusterMetrics;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.cluster.ClusterState;
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ClientConfiguration;
 import org.apache.ignite.configuration.DataRegionConfiguration;
 import org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
@@ -1048,6 +1052,43 @@ public class SqlSystemViewsSelfTest extends 
AbstractIndexingCommonTest {
         assertEquals("val0", res.get(0).get(2));
     }
 
+    /**
+     * Test client connections system view.
+     */
+    @Test
+    public void testClientConnectionViews() throws Exception {
+        startGrid(getConfiguration());
+
+        try (
+            IgniteClient cl1 = Ignition.startClient(new 
ClientConfiguration().setAddresses(Config.SERVER)
+                .setUserAttributes(F.asMap("attr1", "val1", "attr2", "val2")));
+            IgniteClient cl2 = Ignition.startClient(new 
ClientConfiguration().setAddresses(Config.SERVER)
+                .setUserAttributes(F.asMap("attr1", "val2")));
+            IgniteClient cl3 = Ignition.startClient(new 
ClientConfiguration().setAddresses(Config.SERVER))
+        ) {
+
+            List<List<?>> res = execSql("SELECT CONNECTION_ID FROM " + 
systemSchemaName() + ".CLIENT_CONNECTIONS");
+
+            assertEquals(3, res.size());
+
+            // Check join.
+            res = execSql("SELECT C.CONNECTION_ID, CA.NAME, CA.VALUE FROM " + 
systemSchemaName() +
+                ".CLIENT_CONNECTIONS C JOIN " + systemSchemaName() + 
".CLIENT_CONNECTION_ATTRIBUTES CA " +
+                "ON (C.CONNECTION_ID = CA.CONNECTION_ID)");
+
+            assertEquals(3, res.size());
+
+            // Check join and filtering.
+            res = execSql("SELECT C.CONNECTION_ID, CA.NAME, CA.VALUE FROM " + 
systemSchemaName() +
+                ".CLIENT_CONNECTIONS C JOIN " + systemSchemaName() + 
".CLIENT_CONNECTION_ATTRIBUTES CA " +
+                "ON (C.CONNECTION_ID = CA.CONNECTION_ID) WHERE CA.NAME = ?", 
"attr2");
+
+            assertEquals(1, res.size());
+            assertEquals("attr2", res.get(0).get(1));
+            assertEquals("val2", res.get(0).get(2));
+        }
+    }
+
     /**
      * Test snapshots system view.
      */

Reply via email to