001package gudusoft.gsqlparser.sqlenv;
002
003import gudusoft.gsqlparser.nodes.TTypeName;
004import gudusoft.gsqlparser.util.SQLUtil;
005
006import java.util.*;
007
008public abstract class TSQLRoutine extends TSQLSchemaObject{
009    // volatile: written during registration, read lock-free by other threads
010    private volatile String definition;
011
012    public void setDefinition(String definition) {
013        this.definition = definition;
014    }
015
016    public String getDefinition() {
017        return definition;
018    }
019
020    public TSQLRoutine(TSQLSchema schema, String objectName, ESQLDataObjectType dataObjectType){
021        super(schema,objectName,dataObjectType);
022    }
023
024    /**
025     * column list
026     * @return a column list
027     */
028    public List<TSQLParameter> getParameterList() {
029        List<TSQLParameter> parameterList = new LinkedList<>();
030        Map<String, TSQLParameter> m = getParameterMap();
031        synchronized (m) {
032            for(String parameter: m.keySet()){
033                parameterList.add(m.get(parameter));
034            }
035        }
036        return parameterList;
037    }
038
039
040    // volatile + double-checked lazy init: concurrent analyzers registering the
041    // same routine share this instance, so the map must be published safely
042    private volatile Map<String, TSQLParameter> parameterMap;
043
044    private Map<String, TSQLParameter> getParameterMap() {
045        Map<String, TSQLParameter> m = parameterMap;
046        if (m == null) {
047            synchronized (this) {
048                if (parameterMap == null) {
049                    parameterMap = Collections.synchronizedMap(new LinkedHashMap<String, TSQLParameter>());
050                }
051                m = parameterMap;
052            }
053        }
054        return m;
055    }
056
057
058    public void addParameter(int index, TTypeName parameterDataType){
059        Map<String, TSQLParameter> m = getParameterMap();
060        // search-then-put must be atomic under concurrent registration
061        synchronized (m) {
062            if (!searchParameter(index,parameterDataType,null)){
063                m.put(SQLUtil.getIdentifierNormalColumnName(this.sqlEnv.getDBVendor(), makeParameterMapId(index,parameterDataType,null)), new TSQLParameter(this, index,parameterDataType,null));
064            }
065        }
066    }
067
068    public void addParameter(int index, TTypeName parameterDataType,String parameterName){
069        Map<String, TSQLParameter> m = getParameterMap();
070        // search-then-put must be atomic under concurrent registration
071        synchronized (m) {
072            if (!searchParameter(index,parameterDataType,parameterName)){
073                m.put(SQLUtil.getIdentifierNormalColumnName(this.sqlEnv.getDBVendor(), makeParameterMapId(index,parameterDataType,parameterName)), new TSQLParameter(this,index,parameterDataType,parameterName));
074            }
075        }
076    }
077
078
079    public boolean searchParameter(int index, TTypeName datatype, String parameterName){
080        return getParameterMap().containsKey(SQLUtil.getIdentifierNormalColumnName(this.sqlEnv.getDBVendor()
081                , makeParameterMapId(index,datatype,parameterName)));
082    }
083
084    public TSQLParameter getParameter(int index, TTypeName datatype, String parameterName){
085        return getParameterMap().get(SQLUtil.getIdentifierNormalColumnName(this.sqlEnv.getDBVendor()
086                , makeParameterMapId(index,datatype,parameterName)));
087    }
088
089    String makeParameterMapId(int index, TTypeName datatype, String parameterName){
090        return index+datatype.toString()+parameterName == null?"N/A":parameterName;
091    }
092
093
094}