diff --git a/core/trino-main/src/main/java/io/trino/execution/CallTask.java b/core/trino-main/src/main/java/io/trino/execution/CallTask.java index c7ecfa652620..1942126f2b5d 100644 --- a/core/trino-main/src/main/java/io/trino/execution/CallTask.java +++ b/core/trino-main/src/main/java/io/trino/execution/CallTask.java @@ -117,6 +117,9 @@ public ListenableFuture execute( Predicate hasName = argument -> argument.getName().isPresent(); boolean anyNamed = call.getArguments().stream().anyMatch(hasName); boolean allNamed = call.getArguments().stream().allMatch(hasName); + if (!allNamed && procedure.requiresNamedArguments()) { + throw semanticException(INVALID_ARGUMENTS, call, "Only named arguments are allowed for this procedure"); + } if (anyNamed && !allNamed) { throw semanticException(INVALID_ARGUMENTS, call, "Named and positional arguments cannot be mixed"); } diff --git a/core/trino-spi/src/main/java/io/trino/spi/procedure/Procedure.java b/core/trino-spi/src/main/java/io/trino/spi/procedure/Procedure.java index 3ea556422e67..5751f13ddefe 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/procedure/Procedure.java +++ b/core/trino-spi/src/main/java/io/trino/spi/procedure/Procedure.java @@ -34,14 +34,21 @@ public class Procedure private final String schema; private final String name; private final List arguments; + private final boolean requireNamedArguments; private final MethodHandle methodHandle; public Procedure(String schema, String name, List arguments, MethodHandle methodHandle) + { + this(schema, name, arguments, methodHandle, false); + } + + public Procedure(String schema, String name, List arguments, MethodHandle methodHandle, boolean requireNamedArguments) { this.schema = checkNotNullOrEmpty(schema, "schema").toLowerCase(ENGLISH); this.name = checkNotNullOrEmpty(name, "name").toLowerCase(ENGLISH); this.arguments = List.copyOf(requireNonNull(arguments, "arguments is null")); this.methodHandle = requireNonNull(methodHandle, "methodHandle is null"); + this.requireNamedArguments = requireNamedArguments; Set names = new HashSet<>(); for (Argument argument : arguments) { @@ -85,6 +92,11 @@ public MethodHandle getMethodHandle() return methodHandle; } + public boolean requiresNamedArguments() + { + return requireNamedArguments; + } + @Override public String toString() { diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/procedure/FlushHiveMetastoreCacheProcedure.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/procedure/FlushHiveMetastoreCacheProcedure.java index 937233e438ee..a05bc739937c 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/procedure/FlushHiveMetastoreCacheProcedure.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/procedure/FlushHiveMetastoreCacheProcedure.java @@ -60,15 +60,13 @@ public class FlushHiveMetastoreCacheProcedure static { try { - FLUSH_HIVE_METASTORE_CACHE = lookup().unreflect(FlushHiveMetastoreCacheProcedure.class.getMethod("flushMetadataCache", String.class, String.class, String.class, List.class, List.class)); + FLUSH_HIVE_METASTORE_CACHE = lookup().unreflect(FlushHiveMetastoreCacheProcedure.class.getMethod("flushMetadataCache", String.class, String.class, List.class, List.class)); } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } - private static final String FAKE_PARAM_DEFAULT_VALUE = "procedure should only be invoked with named parameters"; - private final Optional cachingHiveMetastore; @Inject @@ -84,17 +82,16 @@ public Procedure get() "system", PROCEDURE_NAME, ImmutableList.of( - new Procedure.Argument("$FAKE_FIRST_PARAMETER", VARCHAR, false, FAKE_PARAM_DEFAULT_VALUE), new Procedure.Argument(PARAM_SCHEMA_NAME, VARCHAR, false, null), new Procedure.Argument(PARAM_TABLE_NAME, VARCHAR, false, null), new Procedure.Argument(PARAM_PARTITION_COLUMN, new ArrayType(VARCHAR), false, null), new Procedure.Argument(PARAM_PARTITION_VALUE, new ArrayType(VARCHAR), false, null)), - FLUSH_HIVE_METASTORE_CACHE.bindTo(this)); + FLUSH_HIVE_METASTORE_CACHE.bindTo(this), + true); } - public void flushMetadataCache(String fakeParam, String schemaName, String tableName, List partitionColumn, List partitionValue) + public void flushMetadataCache(String schemaName, String tableName, List partitionColumn, List partitionValue) { - checkState(FAKE_PARAM_DEFAULT_VALUE.equals(fakeParam), "Procedure should only be invoked with named parameters. " + PROCEDURE_USAGE_EXAMPLES); try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(getClass().getClassLoader())) { doFlushMetadataCache( Optional.ofNullable(schemaName), diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/cache/TestCachingHiveMetastoreWithQueryRunner.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/cache/TestCachingHiveMetastoreWithQueryRunner.java index 35c03a451074..459f91cbcdd3 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/cache/TestCachingHiveMetastoreWithQueryRunner.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/cache/TestCachingHiveMetastoreWithQueryRunner.java @@ -143,16 +143,15 @@ public void testFlushHiveMetastoreCacheProcedureCallable() @Test public void testIllegalFlushHiveMetastoreCacheProcedureCalls() { - String illegalParameterMessage = "Illegal parameter set passed. "; - String validUsageExample = "Valid usages:\n - 'flush_metadata_cache()'\n - flush_metadata_cache(schema_name => ..., table_name => ..., partition_column => ARRAY['...'], partition_value => ARRAY['...'])"; + String illegalParameterMessage = "Illegal parameter set passed. Valid usages:\n - 'flush_metadata_cache()'\n - flush_metadata_cache(schema_name => ..., table_name => ..., partition_column => ARRAY['...'], partition_value => ARRAY['...'])"; assertThatThrownBy(() -> getQueryRunner().execute("CALL system.flush_metadata_cache('dummy_schema')")) - .hasMessage("Procedure should only be invoked with named parameters. " + validUsageExample); + .hasMessageContaining("Only named arguments are allowed for this procedure"); assertThatThrownBy(() -> getQueryRunner().execute("CALL system.flush_metadata_cache(schema_name => 'dummy_schema')")) - .hasMessage(illegalParameterMessage + validUsageExample); + .hasMessage(illegalParameterMessage); assertThatThrownBy(() -> getQueryRunner().execute("CALL system.flush_metadata_cache(schema_name => 'dummy_schema', table_name => 'dummy_table')")) - .hasMessage(illegalParameterMessage + validUsageExample); + .hasMessage(illegalParameterMessage); assertThatThrownBy(() -> getQueryRunner().execute("CALL system.flush_metadata_cache(schema_name => 'dummy_schema', table_name => 'dummy_table', partition_column => ARRAY['dummy_partition'])")) .hasMessage("Parameters partition_column and partition_value should have same length");