Beispiel #1
0
 protected FunctionMethod addAggregatePushDownFunction(
     String qualifier, String name, String returnType, String... paramTypes) {
   FunctionMethod method = addPushDownFunction(qualifier, name, returnType, paramTypes);
   AggregateAttributes attr = new AggregateAttributes();
   attr.setAnalytic(true);
   method.setAggregateAttributes(attr);
   return method;
 }
 /**
  * Adds a pushdown function.
  *
  * @param qualifier will be pre-pended to the name
  * @param name
  * @param returnType see {@link RUNTIME_NAMES} for type names
  * @param paramTypes see {@link RUNTIME_NAMES} for type names
  * @return the FunctionMethod created.
  */
 protected FunctionMethod addPushDownFunction(
     String qualifier, String name, String returnType, String... paramTypes) {
   FunctionMethod method =
       FunctionMethod.createFunctionMethod(
           qualifier + '.' + name, name, qualifier, returnType, paramTypes);
   method.setNameInSource(name);
   pushdownFunctionMethods.add(method);
   return method;
 }
Beispiel #3
0
  @Test
  public void testMixedCaseTypes() throws Exception {
    String ddl = "CREATE FUNCTION SourceFunc(flag Boolean) RETURNS varchaR options (UUID 'z')";

    Schema s = helpParse(ddl, "model").getSchema();

    FunctionMethod fm = s.getFunction("z");
    assertEquals("boolean", fm.getInputParameters().get(0).getType());
  }
Beispiel #4
0
  @Test(expected = MetadataException.class)
  public void testInvalidProcedureBody() throws Exception {
    String ddl = "CREATE FOREIGN PROCEDURE SourceFunc(flag boolean) RETURNS varchar AS SELECT 'a';";

    Schema s = helpParse(ddl, "model").getSchema();

    FunctionMethod fm = s.getFunction("z");
    assertTrue(fm.getInputParameters().get(0).isVarArg());
  }
Beispiel #5
0
  @Test
  public void testVarArgs() throws Exception {
    String ddl =
        "CREATE FUNCTION SourceFunc(flag boolean) RETURNS varchar options (varargs 'true', UUID 'z')";

    Schema s = helpParse(ddl, "model").getSchema();

    FunctionMethod fm = s.getFunction("z");
    assertTrue(fm.getInputParameters().get(0).isVarArg());
  }
Beispiel #6
0
  @Test
  public void testPushdownFunctionNoArgs() throws Exception {
    String ddl =
        "CREATE FOREIGN FUNCTION SourceFunc() RETURNS integer OPTIONS (UUID 'hello world')";

    Schema s = helpParse(ddl, "model").getSchema();

    FunctionMethod fm = s.getFunction("hello world");
    assertNotNull(fm);
    assertEquals("integer", fm.getOutputParameter().getType());
    assertEquals(FunctionMethod.PushDown.MUST_PUSHDOWN, fm.getPushdown());
  }
 public Object newInstance() {
   try {
     return invocationMethod.getDeclaringClass().newInstance();
   } catch (InstantiationException e) {
     throw new TeiidRuntimeException(
         QueryPlugin.Event.TEIID30602,
         QueryPlugin.Util.gs(
             QueryPlugin.Event.TEIID30602, method.getName(), method.getInvocationClass()));
   } catch (IllegalAccessException e) {
     throw new TeiidRuntimeException(
         QueryPlugin.Event.TEIID30602,
         QueryPlugin.Util.gs(
             QueryPlugin.Event.TEIID30602, method.getName(), method.getInvocationClass()));
   }
 }
Beispiel #8
0
 public ConnectorManager(
     String translatorName, String connectionName, ExecutionFactory<Object, Object> ef) {
   this.translatorName = translatorName;
   this.connectionName = connectionName;
   if (this.connectionName != null) {
     if (!this.connectionName.startsWith(JAVA_CONTEXT)) {
       jndiName = JAVA_CONTEXT + this.connectionName;
     } else {
       jndiName = this.connectionName;
     }
   } else {
     jndiName = null;
   }
   this.executionFactory = ef;
   this.id = Arrays.asList(translatorName, connectionName);
   if (ef != null) {
     ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
     try {
       Thread.currentThread().setContextClassLoader(ef.getClass().getClassLoader());
       functions = ef.getPushDownFunctions();
     } finally {
       Thread.currentThread().setContextClassLoader(originalCL);
     }
     if (functions != null) {
       // set the specific name to match against imported versions of
       // the same function
       for (FunctionMethod functionMethod : functions) {
         functionMethod.setProperty(FunctionMethod.SYSTEM_NAME, functionMethod.getName());
       }
       ValidatorReport report = new ValidatorReport("Function Validation"); // $NON-NLS-1$
       FunctionMetadataValidator.validateFunctionMethods(functions, report);
       if (report.hasItems()) {
         throw new TeiidRuntimeException(report.getFailureMessage());
       }
     }
   }
 }
Beispiel #9
0
  private void visit(FunctionMethod function) {
    if (this.filter != null && !filter.matcher(function.getName()).matches()) {
      return;
    }
    append(CREATE).append(SPACE);
    if (function.getPushdown().equals(FunctionMethod.PushDown.MUST_PUSHDOWN)) {
      append(FOREIGN);
    } else {
      append(VIRTUAL);
    }
    append(SPACE)
        .append(FUNCTION)
        .append(SPACE)
        .append(SQLStringVisitor.escapeSinglePart(function.getName()));
    append(LPAREN);

    boolean first = true;
    for (FunctionParameter fp : function.getInputParameters()) {
      if (first) {
        first = false;
      } else {
        append(COMMA).append(SPACE);
      }
      visit(fp);
    }
    append(RPAREN);

    append(SPACE).append(RETURNS);
    appendOptions(function.getOutputParameter());
    append(SPACE);
    append(function.getOutputParameter().getType());

    // options
    String options = buildFunctionOptions(function);
    if (!options.isEmpty()) {
      append(NEWLINE).append(OPTIONS).append(SPACE).append(LPAREN).append(options).append(RPAREN);
    }

    /*if (function.getDefinition() != null) {
    	append(NEWLINE).append(SQLConstants.Reserved.AS).append(NEWLINE);
    	append(function.getDefinition());
    }*/

    append(SQLConstants.Tokens.SEMICOLON);
  }
Beispiel #10
0
  private String buildFunctionOptions(FunctionMethod function) {
    StringBuilder options = new StringBuilder();
    addCommonOptions(options, function);

    if (function.getCategory() != null) {
      addOption(options, CATEGORY, function.getCategory());
    }

    if (!function.getDeterminism().equals(Determinism.DETERMINISTIC)) {
      addOption(options, DETERMINISM, function.getDeterminism().name());
    }

    if (function.getInvocationClass() != null) {
      addOption(options, JAVA_CLASS, function.getInvocationClass());
    }

    if (function.getInvocationMethod() != null) {
      addOption(options, JAVA_METHOD, function.getInvocationMethod());
    }

    if (!function.getProperties().isEmpty()) {
      for (String key : function.getProperties().keySet()) {
        addOption(options, key, function.getProperty(key, false));
      }
    }

    return options.toString();
  }
  /**
   * Invoke the function described in the function descriptor, using the values provided. Return the
   * result of the function.
   *
   * @param values Values that should match 1-to-1 with the types described in the function
   *     descriptor
   * @param context
   * @param functionTarget TODO
   * @param fd Function descriptor describing the name and types of the arguments
   * @return Result of invoking the function
   */
  public Object invokeFunction(Object[] values, CommandContext context, Object functionTarget)
      throws FunctionExecutionException, BlockedException {
    if (!isNullDependent()) {
      for (int i = requiresContext ? 1 : 0; i < values.length; i++) {
        if (values[i] == null) {
          return null;
        }
      }
    }

    // If descriptor is missing invokable method, find this VM's descriptor
    // give name and types from fd
    if (invocationMethod == null) {
      throw new FunctionExecutionException(
          QueryPlugin.Event.TEIID30382,
          QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30382, getFullName()));
    }

    // Invoke the method and return the result
    try {
      if (hasWrappedArgs) {
        for (int i = 0; i < values.length; i++) {
          Object val = values[i];
          if (val != null && types[i] == DataTypeManager.DefaultDataClasses.VARBINARY) {
            values[i] = ((BinaryType) val).getBytesDirect();
          }
        }
      }
      if (method.isVarArgs()) {
        if (calledWithVarArgArrayParam) {
          ArrayImpl av = (ArrayImpl) values[values.length - 1];
          if (av != null) {
            Object[] vals = av.getValues();
            values[values.length - 1] = vals;
            if (hasWrappedArgs
                && types[types.length - 1] == DataTypeManager.DefaultDataClasses.VARBINARY) {
              vals = Arrays.copyOf(vals, vals.length);
              for (int i = 0; i < vals.length; i++) {
                if (vals[i] != null) {
                  vals[i] = ((BinaryType) vals[i]).getBytesDirect();
                }
              }
              values[values.length - 1] = vals;
            }
            Class<?> arrayType = invocationMethod.getParameterTypes()[types.length - 1];
            if (arrayType.getComponentType() != Object.class && vals.getClass() != arrayType) {
              Object varArgs = Array.newInstance(arrayType.getComponentType(), vals.length);
              for (int i = 0; i < vals.length; i++) {
                Array.set(varArgs, i, vals[i]);
              }
              values[values.length - 1] = varArgs;
            }
          }
        } else {
          int i = invocationMethod.getParameterTypes().length;
          Object[] newValues = Arrays.copyOf(values, i);
          Object varArgs = null;
          if (invocationMethod.getParameterTypes()[i - 1].getComponentType() != Object.class) {
            int varArgCount = values.length - i + 1;
            varArgs =
                Array.newInstance(
                    invocationMethod.getParameterTypes()[i - 1].getComponentType(), varArgCount);
            for (int j = 0; j < varArgCount; j++) {
              Array.set(varArgs, j, values[i - 1 + j]);
            }
          } else {
            varArgs = Arrays.copyOfRange(values, i - 1, values.length);
          }
          newValues[i - 1] = varArgs;
          values = newValues;
        }
      }
      Object result = invocationMethod.invoke(functionTarget, values);
      if (context != null
          && getDeterministic().ordinal() <= Determinism.USER_DETERMINISTIC.ordinal()) {
        context.setDeterminismLevel(getDeterministic());
      }
      return importValue(result, getReturnType());
    } catch (ArithmeticException e) {
      throw new FunctionExecutionException(
          QueryPlugin.Event.TEIID30384,
          e,
          QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30384, getFullName()));
    } catch (InvocationTargetException e) {
      if (e.getTargetException() instanceof BlockedException) {
        throw (BlockedException) e.getTargetException();
      }
      throw new FunctionExecutionException(
          QueryPlugin.Event.TEIID30384,
          e.getTargetException(),
          QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30384, getFullName()));
    } catch (IllegalAccessException e) {
      throw new FunctionExecutionException(
          QueryPlugin.Event.TEIID30385,
          e,
          QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30385, method.toString()));
    } catch (TransformationException e) {
      throw new FunctionExecutionException(e);
    }
  }
Beispiel #12
0
  @Test
  public void testUDAggregate() throws Exception {
    String ddl =
        "CREATE VIRTUAL FUNCTION SourceFunc(flag boolean, msg varchar) RETURNS varchar "
            + "OPTIONS(CATEGORY 'misc', AGGREGATE 'true', \"allows-distinct\" 'true', UUID 'y')";

    Schema s = helpParse(ddl, "model").getSchema();

    FunctionMethod fm = s.getFunction("y");
    assertNotNull(fm);
    assertEquals("string", fm.getOutputParameter().getType());
    assertEquals(FunctionMethod.PushDown.CAN_PUSHDOWN, fm.getPushdown());
    assertEquals(2, fm.getInputParameterCount());
    assertEquals("flag", fm.getInputParameters().get(0).getName());
    assertEquals("boolean", fm.getInputParameters().get(0).getType());
    assertEquals("msg", fm.getInputParameters().get(1).getName());
    assertEquals("string", fm.getInputParameters().get(1).getType());
    assertFalse(fm.getInputParameters().get(1).isVarArg());
    assertNotNull(fm.getAggregateAttributes());
    assertTrue(fm.getAggregateAttributes().allowsDistinct());
    assertEquals(FunctionMethod.Determinism.DETERMINISTIC, fm.getDeterminism());
    assertEquals("misc", fm.getCategory());
    assertFalse(fm.isNullOnNull());
  }
Beispiel #13
0
  @Test
  public void testUDF() throws Exception {
    String ddl =
        "CREATE VIRTUAL FUNCTION SourceFunc(flag boolean, msg varchar) RETURNS varchar "
            + "OPTIONS(CATEGORY 'misc', DETERMINISM 'DETERMINISTIC', "
            + "\"NULL-ON-NULL\" 'true', JAVA_CLASS 'foo', JAVA_METHOD 'bar', RANDOM 'any', UUID 'x')";

    Schema s = helpParse(ddl, "model").getSchema();

    FunctionMethod fm = s.getFunction("x");
    assertNotNull(fm);
    assertEquals("string", fm.getOutputParameter().getType());
    assertEquals(FunctionMethod.PushDown.CAN_PUSHDOWN, fm.getPushdown());
    assertEquals(2, fm.getInputParameterCount());
    assertEquals("flag", fm.getInputParameters().get(0).getName());
    assertEquals("boolean", fm.getInputParameters().get(0).getType());
    assertEquals("msg", fm.getInputParameters().get(1).getName());
    assertEquals("string", fm.getInputParameters().get(1).getType());
    assertFalse(fm.getInputParameters().get(1).isVarArg());

    assertEquals(FunctionMethod.Determinism.DETERMINISTIC, fm.getDeterminism());
    assertEquals("misc", fm.getCategory());
    assertEquals(true, fm.isNullOnNull());
    assertEquals("foo", fm.getInvocationClass());
    assertEquals("bar", fm.getInvocationMethod());
    assertEquals("any", fm.getProperties().get("RANDOM"));
  }
    @Override
    public void execute(
        VDBMetaData vdb,
        MetadataStore store,
        ValidatorReport report,
        MetadataValidator metadataValidator) {
      for (Schema schema : store.getSchemaList()) {
        if (vdb.getImportedModels().contains(schema.getName())) {
          continue;
        }
        ModelMetaData model = vdb.getModel(schema.getName());
        for (Table t : schema.getTables().values()) {
          if (t.isPhysical() && !model.isSource()) {
            metadataValidator.log(
                report,
                model,
                Messages.gs(Messages.TEIID.TEIID31075, t.getFullName(), model.getName()));
          }
        }

        Set<String> names = new HashSet<String>();
        for (Procedure p : schema.getProcedures().values()) {
          boolean hasReturn = false;
          names.clear();
          for (int i = 0; i < p.getParameters().size(); i++) {
            ProcedureParameter param = p.getParameters().get(i);
            if (param.isVarArg() && param != p.getParameters().get(p.getParameters().size() - 1)) {
              // check that the rest of the parameters are optional
              // this accommodates variadic multi-source procedures
              // effective this and the resolving logic ensure that you can used named parameters
              // for everything,
              // or call the vararg procedure as normal
              if (isTeiidOrGreater(Version.TEIID_8_10)) {
                for (int j = i + 1; j < p.getParameters().size(); j++) {
                  ProcedureParameter param1 = p.getParameters().get(j);
                  if ((param1.getType() == Type.In || param1.getType() == Type.InOut)
                      && (param1.isVarArg()
                          || (param1.getNullType() != NullType.Nullable
                              && param1.getDefaultValue() == null))) {
                    metadataValidator.log(
                        report, model, Messages.gs(Messages.TEIID.TEIID31112, p.getFullName()));
                  }
                }
              } else {
                metadataValidator.log(
                    report, model, Messages.gs(Messages.TEIID.TEIID31112, p.getFullName()));
              }
            }
            if (param.getType() == ProcedureParameter.Type.ReturnValue) {
              if (hasReturn) {
                metadataValidator.log(
                    report, model, Messages.gs(Messages.TEIID.TEIID31107, p.getFullName()));
              }
              hasReturn = true;
            } else if (p.isFunction()
                && param.getType() != ProcedureParameter.Type.In
                && teiidVersion.isGreaterThanOrEqualTo(Version.TEIID_8_11)) {
              metadataValidator.log(
                  report,
                  model,
                  Messages.gs(Messages.TEIID.TEIID31165, p.getFullName(), param.getFullName()));
            }
            if (!names.add(param.getName())) {
              metadataValidator.log(
                  report,
                  model,
                  Messages.gs(Messages.TEIID.TEIID31106, p.getFullName(), param.getFullName()));
            }
          }
          if (!p.isVirtual() && !model.isSource()) {
            metadataValidator.log(
                report,
                model,
                Messages.gs(Messages.TEIID.TEIID31077, p.getFullName(), model.getName()));
          }

          if (p.isFunction() && teiidVersion.isGreaterThanOrEqualTo(Version.TEIID_8_11)) {
            if (!hasReturn) {
              metadataValidator.log(
                  report, model, Messages.gs(Messages.TEIID.TEIID31166, p.getFullName()));
            }
            if (p.isVirtual() && p.getQueryPlan() == null) {
              metadataValidator.log(
                  report, model, Messages.gs(Messages.TEIID.TEIID31167, p.getFullName()));
            }
          }
        }

        for (FunctionMethod func : schema.getFunctions().values()) {
          for (FunctionParameter param : func.getInputParameters()) {
            if (param.isVarArg()
                && param != func.getInputParameters().get(func.getInputParameterCount() - 1)) {
              metadataValidator.log(
                  report, model, Messages.gs(Messages.TEIID.TEIID31112, func.getFullName()));
            }
          }
          if (func.getPushdown().equals(FunctionMethod.PushDown.MUST_PUSHDOWN)
              && !model.isSource()) {
            metadataValidator.log(
                report,
                model,
                Messages.gs(Messages.TEIID.TEIID31078, func.getFullName(), model.getName()));
          }
        }
      }
    }