001package gudusoft.gsqlparser.sqlenv; 002 003import gudusoft.gsqlparser.nodes.TTypeName; 004import gudusoft.gsqlparser.util.SQLUtil; 005 006import java.util.*; 007 008/** 009 * SQL function 010 */ 011public class TSQLFunction extends TSQLProcedure { 012 013 public TSQLFunction(TSQLSchema sqlSchema, String functionName){ 014 super(sqlSchema,functionName,ESQLDataObjectType.dotFunction); 015 } 016 017 public TSQLFunction(TSQLOraclePackage oraclePackage, String functionName) { 018 super(oraclePackage, functionName, ESQLDataObjectType.dotFunction); 019 } 020 021 022 // volatile: routine metadata written during registration (TMetadataCollector) 023 // and read lock-free by resolver helpers on other threads 024 private volatile TTypeName returnType; 025 026 public void setReturnType(TTypeName returnType) { 027 this.returnType = returnType; 028 } 029 030 public TTypeName getReturnType() { 031 return returnType; 032 } 033 034 /** 035 * column list 036 * @return a column list 037 */ 038 public List<TFunctoinColumn> getColumnsInReturnTable() { 039 return columnsInReturnTable(); 040 } 041 042 // No field initializer + volatile: the TSQLSchemaObject constructor publishes 043 // `this` into shared env indexes before subclass initializers run, and concurrent 044 // analyzers registering the same function share this instance. COW list keeps 045 // external iteration (getColumnsInReturnTable callers) safe against appends. 046 private volatile java.util.concurrent.CopyOnWriteArrayList<TFunctoinColumn> columnsInReturnTable; 047 048 private java.util.concurrent.CopyOnWriteArrayList<TFunctoinColumn> columnsInReturnTable() { 049 java.util.concurrent.CopyOnWriteArrayList<TFunctoinColumn> l = columnsInReturnTable; 050 if (l == null) { 051 synchronized (this) { 052 if (columnsInReturnTable == null) { 053 columnsInReturnTable = new java.util.concurrent.CopyOnWriteArrayList<TFunctoinColumn>(); 054 } 055 l = columnsInReturnTable; 056 } 057 } 058 return l; 059 } 060 061 /** 062 * add a new column to the table 063 * 064 * @param columnName column name 065 */ 066 public void addReturnColumn(String columnName){ 067 java.util.concurrent.CopyOnWriteArrayList<TFunctoinColumn> l = columnsInReturnTable(); 068 // search-then-add must be atomic under concurrent registration 069 synchronized (l) { 070 if (!searchColumnInReturnTable(columnName)){ 071 l.add(new TFunctoinColumn(this,columnName)); 072 } 073 } 074 } 075 076 public boolean searchColumnInReturnTable(String columnName){ 077 boolean isFound = false; 078 079 for(TFunctoinColumn s : columnsInReturnTable()){ 080 if (s.compareTo(columnName) == 0){ 081 isFound = true; 082 break; 083 } 084 } 085 086 return isFound; 087 } 088 089 @Override 090 public String toString(){ 091 StringBuilder sb = new StringBuilder(); 092 sb.append(getName().toString()); 093 sb.append("\n\t\t\tparameters:"); 094 for(TSQLParameter p: getParameterList()){ 095 sb.append("\n\t\t\t\t"+p.getName()+",\t"+p.getParameterType().toString()); 096 } 097 if (getReturnType() != null){ 098 sb.append("\n\t\t\t return type:"+getReturnType().toString()); 099 } 100 101 102 return sb.toString(); 103 } 104 105}