public static StatementExecutorResponse execute(
      final ConfiguredStatement<DescribeFunction> statement,
      final SessionProperties sessionProperties,
      final KsqlExecutionContext executionContext,
      final ServiceContext serviceContext
  ) {
    final DescribeFunction describeFunction = statement.getStatement();
    final FunctionName functionName = FunctionName.of(describeFunction.getFunctionName());

    if (executionContext.getMetaStore().isAggregate(functionName)) {
      return StatementExecutorResponse.handled(Optional.of(
          describeAggregateFunction(executionContext, functionName,
              statement.getMaskedStatementText())));
    }

    if (executionContext.getMetaStore().isTableFunction(functionName)) {
      return StatementExecutorResponse.handled(Optional.of(
          describeTableFunction(executionContext, functionName,
              statement.getMaskedStatementText())));
    }

    return StatementExecutorResponse.handled(Optional.of(
        describeNonAggregateFunction(executionContext, functionName,
            statement.getMaskedStatementText())));
  }
@Test
  public void shouldDescribeUDTF() {
    // When:
    final FunctionDescriptionList functionList = (FunctionDescriptionList)
        CustomExecutors.DESCRIBE_FUNCTION.execute(
            engine.configure("DESCRIBE FUNCTION TEST_UDTF1;"),
            mock(SessionProperties.class),
            engine.getEngine(),
            engine.getServiceContext()
        ).getEntity().orElseThrow(IllegalStateException::new);

    // Then:
    assertThat(functionList, new TypeSafeMatcher<FunctionDescriptionList>() {
      @Override
      protected boolean matchesSafely(final FunctionDescriptionList item) {
        return item.getName().equals("TEST_UDTF1")
            && item.getType().equals(FunctionType.TABLE);
      }

      @Override
      public void describeTo(final Description description) {
        description.appendText(functionList.getName());
      }
    });

    assertThat(functionList.getFunctions(), hasSize(2));

    FunctionInfo expected1 = new FunctionInfo(
        Arrays.asList(new ArgumentInfo("foo", "INT", "", false)),
        "INT", "test_udtf1 int");

    assertTrue(functionList.getFunctions().contains(expected1));

    FunctionInfo expected2 = new FunctionInfo(
        Arrays.asList(new ArgumentInfo("foo", "DOUBLE", "", false)),
        "DOUBLE", "test_udtf1 double");

    assertTrue(functionList.getFunctions().contains(expected2));

  }