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}