alex-plekhanov commented on code in PR #11618:
URL: https://github.com/apache/ignite/pull/11618#discussion_r1873158494
##########
modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java:
##########
@@ -3069,12 +3072,23 @@ public List<FieldsQueryCursor<List<?>>> querySqlFields(
failOnMultipleStmts
);
+ SessionContext sesCtx = null;
+
+ if (cctx != null) {
+ CacheOperationContext opCtx =
cctx.operationContextPerCall();
+
+ if (opCtx != null &&
opCtx.applicationAttributes() != null)
+ sesCtx = new
SessionContextImpl(opCtx.applicationAttributes());
+ }
+
QueryContext qryCtx = QueryContext.of(
qry,
cliCtx,
cancel,
qryProps,
- userTx == null ? null : userTx.xidVersion()
+ userTx == null ? null : userTx.xidVersion(),
+ ctx.resource(),
Review Comment:
Resource processor it's not a part of query context, it's a part of node
context, so it's weird to pass it like this.
##########
modules/core/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceSessionContextProviderInjector.java:
##########
@@ -0,0 +1,35 @@
+/*
+ * 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.resource;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.managers.deployment.GridDeployment;
+import org.apache.ignite.session.SessionContextProvider;
+
+/** {@link SessionContextProvider} injector. */
+public class GridResourceSessionContextProviderInjector extends
GridResourceBasicInjector<SessionContextProvider> {
Review Comment:
Why do we need this class if it's only delegate calls to superclass?
##########
modules/calcite/src/test/java/org/apache/ignite/testsuites/ExecutionTestSuite.java:
##########
@@ -55,6 +56,7 @@
RuntimeSortedIndexTest.class,
LimitExecutionTest.class,
TimeCalculationExecutionTest.class,
+ SessionContextSqlFunctionTest.class
Review Comment:
1. Comma at the EOL
2. It's not an execution test, it's integration test, should be placed to
corresponding suite
##########
modules/calcite/src/test/java/org/apache/ignite/internal/processors/cache/SessionContextSqlFunctionTest.java:
##########
@@ -0,0 +1,232 @@
+/*
+ * 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.cache;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cache.query.annotations.QuerySqlFunction;
+import org.apache.ignite.calcite.CalciteQueryEngineConfiguration;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.SqlConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.resources.SessionContextProviderResource;
+import org.apache.ignite.session.SessionContext;
+import org.apache.ignite.session.SessionContextProvider;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/** */
+@RunWith(Parameterized.class)
+public class SessionContextSqlFunctionTest extends GridCommonAbstractTest {
+ /** */
+ private static final String SESSION_ID = "sessionId";
+
+ /** */
+ private Ignite ign;
+
+ /** */
+ @Parameterized.Parameter
+ public CacheAtomicityMode mode;
+
+ /** */
+ @Parameterized.Parameter(1)
+ public boolean clnNode;
+
+ /** */
+ @Parameterized.Parameters(name = "mode={0}, clnNode={1}")
+ public static List<Object[]> parameters() {
+ List<Object[]> params = new ArrayList<>();
+
+ for (CacheAtomicityMode m: CacheAtomicityMode.values()) {
+ params.add(new Object[] {m, false});
+ params.add(new Object[] {m, true});
+ }
+
+ return params;
+ }
+
+ /** */
+ @Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ cfg.setSqlConfiguration(new SqlConfiguration()
+ .setQueryEnginesConfiguration(new
CalciteQueryEngineConfiguration()));
+
+ cfg.setCacheConfiguration(
+ new CacheConfiguration<>(DEFAULT_CACHE_NAME)
+ .setSqlSchema("PUBLIC")
+ .setSqlFunctionClasses(SessionContextSqlFunctions.class));
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ ign = startGrids(3);
+
+ if (clnNode)
+ ign = startClientGrid(3);
+
+ ignQuery(ign, "create table PUBLIC.MYTABLE(id int primary key,
sessionId varchar);");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() {
+ stopAllGrids();
+ }
+
+ /** */
+ @Test
+ public void testWhereClause() {
+ for (int i = 0; i < 100; i++) {
+ String sesId = i % 2 == 0 ? "1" : "2";
+
+ ignQuery(ign, "insert into PUBLIC.MYTABLE(id, sessionId) values
(?, ?);", i, sesId);
+ }
+
+ for (String sesId: F.asList("1", "2")) {
+ Ignite ignApp = ign.withApplicationAttributes(F.asMap(SESSION_ID,
sesId));
+
+ List<List<?>> rows = ignQuery(ignApp, "select * from
PUBLIC.MYTABLE where sessionId = sessionId();");
+
+ assertEquals(50, rows.size());
+
+ for (List<?> row: rows) {
+ String actSesId = row.get(1).toString();
+
+ assertEquals(sesId, actSesId);
+ }
+ }
+ }
+
+ /** */
+ @Test
+ public void testInsertClause() {
+ for (int i = 0; i < 100; i++) {
+ String sesId = i % 2 == 0 ? "1" : "2";
+
+ Ignite ignApp = ign.withApplicationAttributes(F.asMap(SESSION_ID,
sesId));
+
+ ignQuery(ignApp, "insert into PUBLIC.MYTABLE(id, sessionId) values
(" + i + ", sessionId());");
+ }
+
+ List<List<?>> res = ignQuery(ign, "select * from PUBLIC.MYTABLE where
sessionId = 1");
+
+ assertEquals(50, res.size());
+
+ res = ignQuery(ign, "select * from PUBLIC.MYTABLE where sessionId =
2");
+
+ assertEquals(50, res.size());
+ }
+
+ /** */
+ @Test
+ public void testNestedQuery() {
+ for (int i = 0; i < 100; i++) {
+ String sesId = i % 2 == 0 ? "1" : "2";
+
+ ignQuery(ign, "insert into PUBLIC.MYTABLE(id, sessionId) values
(?, ?);", i, sesId);
+ }
+
+ String sesId = "1";
+
+ Ignite ignApp = ign.withApplicationAttributes(F.asMap(SESSION_ID,
sesId));
+
+ List<List<?>> rows = ignQuery(ignApp, "select * from PUBLIC.MYTABLE
where sessionId = (select sessionId());");
+
+ int size = 0;
+
+ for (List<?> row: rows) {
+ String actSesId = row.get(1).toString();
+
+ assertEquals(sesId, actSesId);
+
+ size++;
+ }
+
+ assertEquals(50, size);
+ }
+
+ /** */
+ @Test
+ public void testOverwriteApplicationAttributes() {
+ Ignite ignApp = ign;
+
+ for (int i = 0; i < 100; i++) {
+ String sesId = i % 2 == 0 ? "1" : "2";
+
+ ignApp = ignApp.withApplicationAttributes(F.asMap(SESSION_ID,
sesId));
+
+ ignQuery(ignApp, "insert into PUBLIC.MYTABLE(id, sessionId) values
(" + i + ", sessionId());");
+ }
+
+ List<List<?>> res = ignQuery(ign, "select * from PUBLIC.MYTABLE where
sessionId = 1");
+
+ assertEquals(50, res.size());
+
+ res = ignQuery(ign, "select * from PUBLIC.MYTABLE where sessionId =
2");
+
+ assertEquals(50, res.size());
+ }
+
+ /** */
+ @Test
+ public void testMultithreadApplication() throws Exception {
+ String sesId = "1";
+
+ Ignite ignApp = ign.withApplicationAttributes(F.asMap(SESSION_ID,
sesId));
+
+ IgniteInternalFuture<?> insertFut = multithreadedAsync(() -> {
+ for (int i = 0; i < 100; i++)
+ ignQuery(ignApp, "insert into PUBLIC.MYTABLE(id, sessionId)
values (" + i + ", sessionId());");
+ }, 1, "insert");
+
+ insertFut.get(getTestTimeout());
+
+ List<List<?>> res = ignQuery(ign, "select * from PUBLIC.MYTABLE where
sessionId = " + sesId);
+
+ assertEquals(100, res.size());
+ }
+
+ /** */
+ private List<List<?>> ignQuery(Ignite ign, String sql, Object... args) {
Review Comment:
`ignQuery` - not a common abbreviation for Ignite. Perhaps just `query`? Or
just `sql`?
##########
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionContext.java:
##########
@@ -457,6 +471,31 @@ public IoTracker ioTracker() {
return ioTracker;
}
+ /**
+ * Return an object contained a user defined function. If not exist yet,
then instantiate the object and inject resources into it.
+ * Used by {@link ReflectiveCallNotNullImplementor} while it is preparing
user function call.
+ *
+ * @param udfClsName Classname of the class contained UDF.
+ * @return Object with injected resources.
+ */
+ public Object udfObject(String udfClsName) {
Review Comment:
`udfObject` for me - it's something that UDF creates and uses. I think
something like 'udfInstance` will be more clear (not used by UDF, but UDF
itself)
##########
modules/calcite/src/test/java/org/apache/ignite/internal/processors/cache/SessionContextSqlFunctionTest.java:
##########
@@ -0,0 +1,232 @@
+/*
+ * 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.cache;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cache.query.annotations.QuerySqlFunction;
+import org.apache.ignite.calcite.CalciteQueryEngineConfiguration;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.SqlConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.resources.SessionContextProviderResource;
+import org.apache.ignite.session.SessionContext;
+import org.apache.ignite.session.SessionContextProvider;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/** */
+@RunWith(Parameterized.class)
+public class SessionContextSqlFunctionTest extends GridCommonAbstractTest {
+ /** */
+ private static final String SESSION_ID = "sessionId";
+
+ /** */
+ private Ignite ign;
+
+ /** */
+ @Parameterized.Parameter
+ public CacheAtomicityMode mode;
+
+ /** */
+ @Parameterized.Parameter(1)
+ public boolean clnNode;
Review Comment:
`isClientNode`?
##########
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ReflectiveCallNotNullImplementor.java:
##########
@@ -55,10 +57,13 @@ public ReflectiveCallNotNullImplementor(Method method) {
callExpr = Expressions.call(method, translatedOperands);
else {
- // The UDF class must have a public zero-args constructor.
- // Assume that the validator checked already.
- final Expression target =
- Expressions.new_(method.getDeclaringClass());
+ final Expression target = Expressions.convert_(
+ Expressions.call(
+ translator.getRoot(),
+ Types.lookupMethod(ExecutionContext.class, "udfObject",
String.class),
Review Comment:
Let's add enum item to IgniteMethod class
--
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]