001package gudusoft.gsqlparser.dlineage.util;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.util.Logger;
005import gudusoft.gsqlparser.util.LoggerFactory;
006import gudusoft.gsqlparser.util.SQLUtil;
007
008import java.io.InputStream;
009import java.util.HashMap;
010import java.util.HashSet;
011import java.util.Map;
012import java.util.Set;
013
014public final class FunctionUtility {
015    private static final Logger logger = LoggerFactory.getLogger(FunctionUtility.class);
016
017    static Map<EDbVendor, Map<String, Set<Integer>>> dbFunctionDirectRelationMap = new HashMap<>();
018    static Map<EDbVendor, Map<String, Set<Integer>>> dbFunctionIndirectRelationMap = new HashMap<>();
019
020    public static boolean isDirectRelation(EDbVendor vendor, String function, int argCount, int argIndex) {
021        if (!dbFunctionDirectRelationMap.containsKey(vendor)) {
022            initFunctionMap(vendor);
023        }
024        Map<String, Set<Integer>> functionMap = dbFunctionDirectRelationMap.get(vendor);
025        Set<Integer> relationsArgs = functionMap.get(function.toUpperCase() + "_" + argCount);
026        if (relationsArgs != null) {
027            return relationsArgs.contains(argIndex);
028        }
029        return true;
030    }
031    
032    public static boolean isIndirectRelation(EDbVendor vendor, String function, int argCount, int argIndex) {
033        if (!dbFunctionIndirectRelationMap.containsKey(vendor)) {
034            initFunctionMap(vendor);
035        }
036        Map<String, Set<Integer>> functionMap = dbFunctionIndirectRelationMap.get(vendor);
037        Set<Integer> relationsArgs = functionMap.get(function.toUpperCase() + "_" + argCount);
038        if (relationsArgs != null) {
039            return relationsArgs.contains(argIndex);
040        }
041        return false;
042    }
043
044    private static void initFunctionMap(EDbVendor vendor) {
045        Map<String, Set<Integer>> functionDirectRelationMap = new HashMap<>();
046        Map<String, Set<Integer>> functionIndirectRelationMap = new HashMap<>();
047        try {
048            InputStream is = FunctionUtility.class.getResourceAsStream("/gudusoft/gsqlparser/dataflow/"
049                    + vendor.name().replace("dbv", "") + "/function.properties");
050            if (is != null) {
051                String[] lines = SQLUtil.getInputStreamContent(is, false).split("\n");
052                for (String line : lines) {
053                    String[] function = line.trim().replace("(", ",").replace(")", "").split("\\s*,\\s*", -1);
054                    if (function.length <= 1) {
055                        continue;
056                    }
057                    String functionName = function[0].toUpperCase();
058                    Integer argCount = function.length - 1;
059                    Set<Integer> directRelationArgs = new HashSet<>();
060                    Set<Integer> indirectRelationArgs = new HashSet<>();
061                    for (int i = 1; i <= argCount; i++) {
062                        if ("fdd".equalsIgnoreCase(function[i])) {
063                            directRelationArgs.add(i - 1);
064                        }
065                        if ("fdr".equalsIgnoreCase(function[i])) {
066                            indirectRelationArgs.add(i - 1);
067                        }
068                    }
069                    functionDirectRelationMap.put(functionName + "_" + argCount, directRelationArgs);
070                    functionIndirectRelationMap.put(functionName + "_" + argCount, indirectRelationArgs);
071                }
072            }
073        } catch (Exception e) {
074            logger.error("init function map failed.", e);
075        }
076        dbFunctionDirectRelationMap.put(vendor, functionDirectRelationMap);
077        dbFunctionIndirectRelationMap.put(vendor, functionIndirectRelationMap);
078    }
079}