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

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

commit a7f5f69e77c2bd1d70554c0f5fe006e9d2e29c39
Author: Peeyush Gupta <[email protected]>
AuthorDate: Fri Jun 27 07:39:56 2025 -0700

    [ASTERIXDB-3603][FUN] Added extra validation for transform functions
    
    - user model changes: no
    - storage format changes: no
    - interface changes: yes
    
    Ext-ref: MB-67056
    Change-Id: I14263c99da76ac006225baf9ff9d5722c528a5d5
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19994
    Integration-Tests: Jenkins <[email protected]>
    Tested-by: Peeyush Gupta <[email protected]>
    Reviewed-by: Ali Alsuliman <[email protected]>
---
 .../asterix/app/translator/QueryTranslator.java    | 26 +++++++++++++++++-----
 .../transform/negative/transform.006.ddl.sqlpp     | 25 +++++++++++++++++++++
 .../src/test/resources/runtimets/sqlpp_queries.xml |  2 ++
 .../asterix/lang/common/base/IQueryRewriter.java   |  3 ++-
 .../lang/sqlpp/rewrites/SqlppQueryRewriter.java    |  9 +-------
 5 files changed, 51 insertions(+), 14 deletions(-)

diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index 547afecd95..ad0cd5f0e8 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -113,15 +113,19 @@ import 
org.apache.asterix.external.util.ExternalDataConstants;
 import org.apache.asterix.external.util.ExternalDataUtils;
 import org.apache.asterix.external.util.WriterValidationUtil;
 import 
org.apache.asterix.external.writer.printer.parquet.SchemaConverterVisitor;
+import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.base.IQueryRewriter;
 import org.apache.asterix.lang.common.base.IReturningStatement;
 import org.apache.asterix.lang.common.base.IRewriterFactory;
 import org.apache.asterix.lang.common.base.IStatementRewriter;
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.lang.common.expression.IndexedTypeExpression;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
+import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.TypeExpression;
 import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.literal.MissingLiteral;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.AdapterDropStatement;
 import org.apache.asterix.lang.common.statement.AnalyzeDropStatement;
@@ -457,7 +461,7 @@ public class QueryTranslator extends AbstractLangTranslator 
implements IStatemen
                         break;
                     case CREATE_FUNCTION:
                         handleCreateFunctionStatement(metadataProvider, stmt, 
stmtRewriter, requestParameters,
-                                Creator.DEFAULT_CREATOR);
+                                Creator.DEFAULT_CREATOR, hcc);
                         break;
                     case FUNCTION_DROP:
                         handleFunctionDropStatement(metadataProvider, stmt, 
requestParameters);
@@ -3187,7 +3191,8 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
     }
 
     public void handleCreateFunctionStatement(MetadataProvider 
metadataProvider, Statement stmt,
-            IStatementRewriter stmtRewriter, IRequestParameters 
requestParameters, Creator creator) throws Exception {
+            IStatementRewriter stmtRewriter, IRequestParameters 
requestParameters, Creator creator,
+            IHyracksClientConnection hcc) throws Exception {
         CreateFunctionStatement cfs = (CreateFunctionStatement) stmt;
         FunctionSignature signature = cfs.getFunctionSignature();
         DataverseName funDataverse = signature.getDataverseName();
@@ -3220,7 +3225,7 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
         lockUtil.createFunctionBegin(lockManager, metadataProvider.getLocks(), 
databaseName, dataverseName,
                 signature.getName(), libraryDatabaseName, 
libraryDataverseName, libraryName);
         try {
-            doCreateFunction(metadataProvider, cfs, signature, stmtRewriter, 
requestParameters, creator);
+            doCreateFunction(metadataProvider, cfs, signature, stmtRewriter, 
requestParameters, creator, hcc);
         } finally {
             metadataProvider.getLocks().unlock();
             metadataProvider.setDefaultNamespace(activeNamespace);
@@ -3229,7 +3234,7 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
 
     protected CreateResult doCreateFunction(MetadataProvider metadataProvider, 
CreateFunctionStatement cfs,
             FunctionSignature functionSignature, IStatementRewriter 
stmtRewriter, IRequestParameters requestParameters,
-            Creator creator) throws Exception {
+            Creator creator, IHyracksClientConnection hcc) throws Exception {
         DataverseName dataverseName = functionSignature.getDataverseName();
         String databaseName = functionSignature.getDatabaseName();
         SourceLocation sourceLoc = cfs.getSourceLocation();
@@ -3373,7 +3378,15 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
                         cfs.isTransform());
                 fd.setSourceLocation(sourceLoc);
 
-                Query wrappedQuery = 
queryRewriter.createFunctionAccessorQuery(fd);
+                int arity = functionSignature.getArity();
+                List<Expression> args;
+                if (cfs.isTransform()) {
+                    args = Collections.singletonList(new 
RecordConstructor(Collections.emptyList()));
+                } else {
+                    args = arity == FunctionIdentifier.VARARGS ? 
Collections.emptyList()
+                            : Collections.nCopies(arity, new 
LiteralExpr(MissingLiteral.INSTANCE));
+                }
+                Query wrappedQuery = 
queryRewriter.createFunctionAccessorQuery(fd, args);
                 List<FunctionDecl> fdList = new 
ArrayList<>(declaredFunctions.size() + 1);
                 fdList.addAll(declaredFunctions);
                 fdList.add(fd);
@@ -3392,6 +3405,9 @@ public class QueryTranslator extends 
AbstractLangTranslator implements IStatemen
                                 "Transform function definition can not use 
collections/views");
                     }
                     validateTransformFunction(metadataProvider, 
rewrittenQuery, sourceLoc);
+                    apiFramework.compileQuery(hcc, metadataProvider, (Query) 
rewrittenQuery.first,
+                            rewrittenQuery.second, null, sessionOutput, null, 
null, responsePrinter, warningCollector,
+                            requestParameters, jobFlags);
                 }
                 appCtx.getReceptionist().ensureAuthorized(requestParameters, 
metadataProvider);
 
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/transform/negative/transform.006.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/transform/negative/transform.006.ddl.sqlpp
new file mode 100644
index 0000000000..b843222d28
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/function/transform/negative/transform.006.ddl.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+CREATE TRANSFORM FUNCTION transformTest(doc) {
+    SELECT * FROM doc d LIMIT 1
+};
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml 
b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
index 5e32d7c3b7..20a85c2caf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
@@ -14279,6 +14279,8 @@
         <expected-error>ASX1223: Failed to create transform function. 
Encountered error: 'Transform function definition can not use 
collections/views'</expected-error>
         <expected-error>ASX1223: Failed to create transform function. 
Encountered error: 'Transform function definition can not use 
collections/views'</expected-error>
         <expected-error>ASX1223: Failed to create transform function. 
Encountered error: 'Transform function cannot return more than one 
row'</expected-error>
+        <expected-error>ASX1091: Type mismatch: expected value of type 
multiset or array, but got the value of type object</expected-error>
+        <source-location>false</source-location>
       </compilation-unit>
     </test-case>
     <test-case FilePath="function/transform">
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
index 0f8e3e9c3a..d723dbb11f 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.lang.common.base;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 
 import org.apache.asterix.common.api.INamespaceResolver;
@@ -65,7 +66,7 @@ public interface IQueryRewriter {
 
     String toFunctionParameterName(VarIdentifier paramVar);
 
-    Query createFunctionAccessorQuery(FunctionDecl functionDecl);
+    Query createFunctionAccessorQuery(FunctionDecl functionDecl, 
List<Expression> args);
 
     Query createViewAccessorQuery(ViewDecl viewDecl, INamespaceResolver 
namespaceResolver);
 
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index 15865a2d9c..1aa0d7cfef 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -44,9 +44,7 @@ import 
org.apache.asterix.lang.common.base.IReturningStatement;
 import org.apache.asterix.lang.common.expression.AbstractCallExpression;
 import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.expression.FieldAccessor;
-import org.apache.asterix.lang.common.expression.LiteralExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.common.literal.MissingLiteral;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.DatasetDecl;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
@@ -95,7 +93,6 @@ import org.apache.asterix.om.types.IAType;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.common.utils.Triple;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.api.exceptions.SourceLocation;
 import org.apache.hyracks.util.LogRedactionUtil;
 import org.apache.logging.log4j.LogManager;
@@ -628,12 +625,8 @@ public class SqlppQueryRewriter implements IQueryRewriter {
     }
 
     @Override
-    public Query createFunctionAccessorQuery(FunctionDecl functionDecl) {
-        // dataverse_name.function_name(MISSING, ... MISSING)
+    public Query createFunctionAccessorQuery(FunctionDecl functionDecl, 
List<Expression> args) {
         FunctionSignature functionSignature = functionDecl.getSignature();
-        int arity = functionSignature.getArity();
-        List<Expression> args = arity == FunctionIdentifier.VARARGS ? 
Collections.emptyList()
-                : Collections.nCopies(arity, new 
LiteralExpr(MissingLiteral.INSTANCE));
         CallExpr fcall = new CallExpr(functionSignature, args);
         fcall.setSourceLocation(functionDecl.getSourceLocation());
         return ExpressionUtils.createWrappedQuery(fcall, 
functionDecl.getSourceLocation());

Reply via email to