public FunctionLibrary getSystemFunctionLibrary() { return new FunctionLibrary(getSystemFunctions()); }
ConversionResult cr = library.determineNecessaryConversions(function.getName(), function.getType(), args, types, hasArgWithoutType); if (cr.method == null) { return Collections.emptyList(); FunctionDescriptor[] conversions = library.getConverts(cr.method, types); newSignature = new Class[conversions.length]; return library.findAllFunctions(name, newSignature);
private void helpFindFunctionFail(String fname, Class<?>[] types) { FunctionDescriptor actual = library.findFunction(fname, types); assertNull("Function was found but should not have been: " + actual, actual); //$NON-NLS-1$ }
/** * Find conversion function and set return type to proper type. * @param sourceType The source type class * @param targetType The target type class * @return A CONVERT function descriptor or null if not possible */ public FunctionDescriptor findTypedConversionFunction(Class<?> sourceType, Class<?> targetType) { //TODO: should array to string be prohibited? FunctionDescriptor fd = findFunction(CONVERT, new Class[] {sourceType, DataTypeManager.DefaultDataClasses.STRING}); if (fd != null) { return copyFunctionChangeReturnType(fd, targetType); } return null; }
public FunctionDescriptor[] getConverts(FunctionMethod method, Class<?>[] types) { final List<FunctionParameter> methodTypes = method.getInputParameters(); FunctionDescriptor[] result = new FunctionDescriptor[types.length]; for(int i = 0; i < types.length; i++) { //treat all varags as the same type final String tmpTypeName = methodTypes.get(Math.min(i, methodTypes.size() - 1)).getRuntimeType(); Class<?> targetType = DataTypeManager.getDataTypeClass(tmpTypeName); Class<?> sourceType = types[i]; if (sourceType == null) { result[i] = findTypedConversionFunction(DataTypeManager.DefaultDataClasses.NULL, targetType); } else if (sourceType != targetType){ if (isVarArgArrayParam(method, types, i, targetType)) { //vararg array parameter continue; } result[i] = findTypedConversionFunction(sourceType, targetType); } } return result; }
@Override protected NavigableMap<String, FunctionMethod> getChildren(Schema s, TransformationMetadata metadata) { //since there is no proper schema for a UDF model, no results will show up for legacy functions if (s.getName().equals(CoreConstants.SYSTEM_MODEL)) { //currently all system functions are contributed via alternative mechanisms //system source, push down functions. FunctionLibrary library = metadata.getFunctionLibrary(); FunctionTree tree = library.getSystemFunctions(); FunctionTree[] userFuncs = library.getUserFunctions(); TreeMap<String, FunctionMethod> functions = new TreeMap<String, FunctionMethod>(String.CASE_INSENSITIVE_ORDER); for (FunctionTree userFunc : userFuncs) { if (userFunc.getSchemaName().equals(CoreConstants.SYSTEM_MODEL)) { functions.putAll(userFunc.getFunctionsByUuid()); } } functions.putAll(tree.getFunctionsByUuid()); return functions; } return s.getFunctions(); } }
if (FunctionLibrary.isConvert(function) && hasArgWithoutType) { Constant constant = (Constant)function.getArg(1); Class<?> type = metadata.getDataTypeClass((String)constant.getValue()); fds = findWithImplicitConversions(library, function, args, types, hasArgWithoutType); if(fds.isEmpty()) { if(!library.hasFunctionMethod(function.getName(), args.length)) { if (fd.getMethod().isVarArgs() && fd.getTypes().length == types.length && library.isVarArgArrayParam(fd.getMethod(), types, types.length - 1, fd.getTypes()[types.length - 1])) { fd = fd.clone(); fd.setCalledWithVarArgArrayParam(true); String dataType = (String) ((Constant)args[1]).getValue(); Class<?> dataTypeClass = metadata.getDataTypeClass(dataType); fd = library.findTypedConversionFunction(args[0].getType(), dataTypeClass); fd = library.copyFunctionChangeReturnType(fd, lookup.getReturnElement().getType()); } else if (fd.isSystemFunction(FunctionLibrary.ARRAY_GET)) { if (args[0].getType() != null && args[0].getType().isArray()) { fd = library.copyFunctionChangeReturnType(fd, args[0].getType().getComponentType()); } else { if (function.getType() != null) { fd = library.copyFunctionChangeReturnType(fd, args[0].getType()); } else if (library.getSystemFunctions().hasFunctionWithName(function.getName()) && !StringUtil.startsWithIgnoreCase(function.getName(), function.getFunctionDescriptor().getSchema() + ElementSymbol.SEPARATOR)) {
if (isVarArgArrayParam(nextMethod, types, i, targetType)) { Transform t = getConvertFunctionDescriptor(sourceType, targetType); if (t != null) { if (t.isExplicit()) { if (returnType != null) { try { Transform t = getConvertFunctionDescriptor(DataTypeManager.getDataTypeClass(nextMethod.getOutputParameter().getRuntimeType()), returnType); if (t != null) { if (t.isExplicit()) { int partCount = partCount(result.getName()); int nextPartCount = partCount(nextMethod.getName()); if (partCount < nextPartCount) {
@Test public void testMultiPartName() throws Exception { FunctionMethod method = new FunctionMethod( "x.y.dummy", null, null, PushDown.CANNOT_PUSHDOWN, TestFunctionTree.class.getName(), "toString", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ Arrays.asList(new FunctionParameter("in", DataTypeManager.DefaultDataTypes.VARBINARY)), //$NON-NLS-1$ new FunctionParameter("output", DataTypeManager.DefaultDataTypes.STRING), //$NON-NLS-1$ true, Determinism.DETERMINISTIC); FunctionTree sys = RealMetadataFactory.SFM.getSystemFunctions(); FunctionLibrary fl = new FunctionLibrary(sys, new FunctionTree("foo", new UDFSource(Arrays.asList(method)), true)); assertNotNull(fl.findFunction("dummy", new Class<?>[] {DataTypeManager.DefaultDataClasses.VARBINARY})); assertNotNull(fl.findFunction("y.dummy", new Class<?>[] {DataTypeManager.DefaultDataClasses.VARBINARY})); }
FunctionDescriptor descriptor = funcLibrary.findFunction(actualName, types); function.setFunctionDescriptor(descriptor); Function result = new Function(SourceSystemFunctions.PARSEBIGDECIMAL, function.getArgs()); FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.PARSEBIGDECIMAL, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING }); result.setFunctionDescriptor(descriptor); result.setType(DataTypeManager.DefaultDataClasses.BIG_DECIMAL); Expression arg = function.getArg(0); if ((arg instanceof Function) && FunctionLibrary.isConvert((Function)arg) && java.util.Date.class.isAssignableFrom(((Function)arg).getArg(0).getType())) { return rewriteExpressionDirect(ResolverUtil.getConversion(arg, DataTypeManager.DefaultDataTypes.STRING, type, false, metadata.getFunctionLibrary())); Function result = new Function(SourceSystemFunctions.FORMATBIGDECIMAL, new Expression[] {bigDecimalParam, function.getArg(1)}); FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.FORMATBIGDECIMAL, new Class[] { DataTypeManager.DefaultDataClasses.BIG_DECIMAL, DataTypeManager.DefaultDataClasses.STRING }); result.setFunctionDescriptor(descriptor); result.setType(DataTypeManager.DefaultDataClasses.STRING); funcLibrary.findFunction(SourceSystemFunctions.REPEAT, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.INTEGER}); result.setFunctionDescriptor(descriptor); result.setType(DataTypeManager.DefaultDataClasses.STRING); funcLibrary.findFunction(SourceSystemFunctions.IFNULL, new Class[] { function.getType(), function.getType() }); result.setFunctionDescriptor(descriptor); result.setType(function.getType());
@Test public void testMultiPartNameSystemConflict() throws Exception { FunctionMethod method = new FunctionMethod( "x.concat", null, null, PushDown.MUST_PUSHDOWN, null, null, Arrays.asList(new FunctionParameter("in", DataTypeManager.DefaultDataTypes.STRING), new FunctionParameter("in", DataTypeManager.DefaultDataTypes.STRING)), //$NON-NLS-1$ new FunctionParameter("output", DataTypeManager.DefaultDataTypes.STRING), //$NON-NLS-1$ true, Determinism.DETERMINISTIC); FunctionTree sys = RealMetadataFactory.SFM.getSystemFunctions(); FunctionLibrary fl = new FunctionLibrary(sys, new FunctionTree("foo", new UDFSource(Arrays.asList(method)), true)); fl.determineNecessaryConversions("concat", DataTypeManager.DefaultDataClasses.STRING, new Expression[] {new Constant(1), new Constant(2)}, new Class[] {DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.INTEGER},false); }
ConversionResult result = library.determineNecessaryConversions(fname, null, new Expression[types.length], types, false); if (result.needsConverion) { actual = library.getConverts(result.method, types); } else if (result.method != null) { actual = new FunctionDescriptor[types.length];
private void initWrapper(QueryMetadataInterface acutalMetadata) { functionLibrary = acutalMetadata.getFunctionLibrary(); this.functions.addAll(Arrays.asList(this.functionLibrary.getUserFunctions())); metadata = new BasicQueryMetadataWrapper(acutalMetadata) { @Override public FunctionLibrary getFunctionLibrary() { return functionLibrary; } }; }
private void helpFindForm(String fname, int numArgs) { assertTrue(library.hasFunctionMethod(fname, numArgs)); }
/** * IMPORTANT: source and target must be basic runtime types * @param sourceExpression * @param sourceTypeName * @param targetTypeName * @param implicit * @param library * @return */ public static Function getConversion(Expression sourceExpression, String sourceTypeName, String targetTypeName, boolean implicit, FunctionLibrary library) { Class<?> srcType = DataTypeManager.getDataTypeClass(sourceTypeName); Class<?> targetType = DataTypeManager.getDataTypeClass(targetTypeName); try { setDesiredType(sourceExpression, targetType, sourceExpression); } catch (QueryResolverException e) { } FunctionDescriptor fd = library.findTypedConversionFunction(srcType, DataTypeManager.getDataTypeClass(targetTypeName)); Function conversion = new Function(fd.getName(), new Expression[] { sourceExpression, new Constant(targetTypeName) }); conversion.setType(DataTypeManager.getDataTypeClass(targetTypeName)); conversion.setFunctionDescriptor(fd); if (implicit) { conversion.makeImplicit(); } return conversion; }
if (FunctionLibrary.isConvert(function) && hasArgWithoutType) { Constant constant = (Constant)function.getArg(1); Class<?> type = metadata.getDataTypeClass((String)constant.getValue()); fds = findWithImplicitConversions(library, function, args, types, hasArgWithoutType); if(fds.isEmpty()) { if(!library.hasFunctionMethod(function.getName(), args.length)) { if (fd.getMethod().isVarArgs() && fd.getTypes().length == types.length && library.isVarArgArrayParam(fd.getMethod(), types, types.length - 1, fd.getTypes()[types.length - 1])) { fd = fd.clone(); fd.setCalledWithVarArgArrayParam(true); String dataType = (String) ((Constant)args[1]).getValue(); Class<?> dataTypeClass = metadata.getDataTypeClass(dataType); fd = library.findTypedConversionFunction(args[0].getType(), dataTypeClass); fd = library.copyFunctionChangeReturnType(fd, lookup.getReturnElement().getType()); } else if (fd.isSystemFunction(FunctionLibrary.ARRAY_GET)) { if (args[0].getType() != null && args[0].getType().isArray()) { fd = library.copyFunctionChangeReturnType(fd, args[0].getType().getComponentType()); } else { if (function.getType() != null) { fd = library.copyFunctionChangeReturnType(fd, args[0].getType()); } else if (library.getSystemFunctions().hasFunctionWithName(function.getName()) && !StringUtil.startsWithIgnoreCase(function.getName(), function.getFunctionDescriptor().getSchema() + ElementSymbol.SEPARATOR)) {
if (isVarArgArrayParam(nextMethod, types, i, targetType)) { Transform t = getConvertFunctionDescriptor(sourceType, targetType); if (t != null) { if (t.isExplicit()) { if (returnType != null) { try { Transform t = getConvertFunctionDescriptor(DataTypeManager.getDataTypeClass(nextMethod.getOutputParameter().getRuntimeType()), returnType); if (t != null) { if (t.isExplicit()) { int partCount = partCount(result.getName()); int nextPartCount = partCount(nextMethod.getName()); if (partCount < nextPartCount) {
@Test public void testVarbinary() throws Exception { FunctionMethod method = new FunctionMethod( "dummy", null, null, PushDown.CANNOT_PUSHDOWN, TestFunctionTree.class.getName(), "toString", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ Arrays.asList(new FunctionParameter("in", DataTypeManager.DefaultDataTypes.VARBINARY)), //$NON-NLS-1$ new FunctionParameter("output", DataTypeManager.DefaultDataTypes.STRING), //$NON-NLS-1$ true, Determinism.DETERMINISTIC); FunctionTree sys = RealMetadataFactory.SFM.getSystemFunctions(); FunctionLibrary fl = new FunctionLibrary(sys, new FunctionTree("foo", new UDFSource(Arrays.asList(method)), true)); FunctionDescriptor fd = fl.findFunction("dummy", new Class<?>[] {DataTypeManager.DefaultDataClasses.VARBINARY}); String hello = "hello"; assertEquals(hello, fd.invokeFunction(new Object[] {new BinaryType(hello.getBytes())}, null, null)); }
/** * Find conversion function and set return type to proper type. * @param sourceType The source type class * @param targetType The target type class * @return A CONVERT function descriptor or null if not possible */ public FunctionDescriptor findTypedConversionFunction(Class<?> sourceType, Class<?> targetType) { //TODO: should array to string be prohibited? FunctionDescriptor fd = findFunction(CONVERT, new Class[] {sourceType, DataTypeManager.DefaultDataClasses.STRING}); if (fd != null) { return copyFunctionChangeReturnType(fd, targetType); } return null; }
@Override protected NavigableMap<String, FunctionMethod> getChildren(Schema s, TransformationMetadata metadata) { //since there is no proper schema for a UDF model, no results will show up for legacy functions if (s.getName().equals(CoreConstants.SYSTEM_MODEL)) { //currently all system functions are contributed via alternative mechanisms //system source, push down functions. FunctionLibrary library = metadata.getFunctionLibrary(); FunctionTree tree = library.getSystemFunctions(); FunctionTree[] userFuncs = library.getUserFunctions(); TreeMap<String, FunctionMethod> functions = new TreeMap<String, FunctionMethod>(String.CASE_INSENSITIVE_ORDER); for (FunctionTree userFunc : userFuncs) { if (userFunc.getSchemaName().equals(CoreConstants.SYSTEM_MODEL)) { functions.putAll(userFunc.getFunctionsByUuid()); } } functions.putAll(tree.getFunctionsByUuid()); return functions; } return s.getFunctions(); } }