001
002package gudusoft.gsqlparser.util;
003
004import gudusoft.gsqlparser.EDbVendor;
005import gudusoft.gsqlparser.util.json.JSON;
006
007import java.util.*;
008
009public class functionChecker
010{
011    // Lazily initialized, immutable after publish; volatile for safe publication
012    private static volatile Set<String> oraclePredefinedPackageFunctionSet = null;
013    private static final Object ORACLE_INIT_LOCK = new Object();
014
015    private static final String COMMA = ",";
016        private static final String MINUS = "-";
017
018        private functionChecker( )
019        {
020        }
021
022    public static boolean isOraclePredefinedPackageFunction(String inputString) {
023        if (SQLUtil.isEmpty(inputString)) {
024            return false;
025        }
026
027        // Fast path if already initialized
028        Set<String> cache = oraclePredefinedPackageFunctionSet;
029        if (cache == null) {
030            synchronized (ORACLE_INIT_LOCK) {
031                cache = oraclePredefinedPackageFunctionSet;
032                if (cache == null) {
033                    // Build locally, then publish immutably to avoid further synchronization
034                    Set<String> local = new HashSet<>();
035                    Object parsed = JSON.parseObject(
036                            SQLUtil.getInputStreamContent(
037                                    functionChecker.class.getResourceAsStream("/gudusoft/gsqlparser/oracle/package/predefined.json"),
038                                    false));
039                    if (parsed instanceof Map) {
040                        Map<?, ?> jsonObject = (Map<?, ?>) parsed;
041                        for (Map.Entry<?, ?> entry : jsonObject.entrySet()) {
042                            String key = String.valueOf(entry.getKey());
043                            Object value = entry.getValue();
044                            if (value instanceof List) {
045                                for (Object item : (List<?>) value) {
046                                    local.add((key + "." + String.valueOf(item)).toUpperCase(java.util.Locale.ROOT));
047                                }
048                            }
049                        }
050                    }
051                    cache = java.util.Collections.unmodifiableSet(local);
052                    oraclePredefinedPackageFunctionSet = cache; // volatile publish
053                }
054            }
055        }
056
057        return cache.contains(inputString.toUpperCase(java.util.Locale.ROOT));
058    }
059
060        public static boolean isBuiltInFunction( String inputString,
061                        EDbVendor dbvendor, String dbVersion )
062        {
063                if ( inputString == null || inputString.trim( ).equals( "" ) )
064                        return false;
065
066                // Locale.ROOT: default-locale toUpperCase turns "td_friday" into
067                // "TD_FRİDAY" on Turkish JVMs, silently missing the list entry
068                String function = inputString.toUpperCase( java.util.Locale.ROOT );
069
070                functionList functionList = functionListFactory.getInstance( )
071                                .getBuiltInFunctionList( dbvendor, dbVersion );
072                if ( functionList == null )
073                {
074                        throw new IllegalArgumentException( "Can't get available built-in function list" );
075                }
076
077                return functionList.getBuiltInFunctionList( ).contains( function );
078        }
079
080        public static String getBuiltInFunctionList(EDbVendor dbvendor,
081                                                                                                String dbVersion) {
082                functionList functionList = functionListFactory.getInstance()
083                                .getBuiltInFunctionList(dbvendor, dbVersion);
084                if (functionList == null) {
085                        throw new IllegalArgumentException("Can't get available built-in function list");
086                }
087
088                Set<String> functions = functionList.getBuiltInFunctionList();
089
090                if (functions != null) {
091                        return String.join(COMMA, functions);
092                }
093                return null;
094        }
095
096        public static String compareBuiltInFunctionList( EDbVendor dbvendor1,
097                        String dbVersion1, EDbVendor dbvendor2, String dbVersion2 )
098        {
099                functionList functionList1 = functionListFactory.getInstance( )
100                                .getBuiltInFunctionList( dbvendor1, dbVersion1 );
101                functionList functionList2 = functionListFactory.getInstance( )
102                                .getBuiltInFunctionList( dbvendor2, dbVersion2 );
103
104                if ( functionList1 == null || functionList2 == null )
105                {
106                        throw new IllegalArgumentException( "Can't get available built-in function list" );
107                }
108
109                List<String> list1 = new ArrayList<String>( );
110                List<String> list2 = new ArrayList<String>( );
111                List<String> retainList = new ArrayList<String>( );
112
113                retainList.addAll( functionList1.getBuiltInFunctionList( ) );
114                retainList.retainAll( functionList2.getBuiltInFunctionList( ) );
115                list1.addAll( functionList1.getBuiltInFunctionList( ) );
116                list2.addAll( functionList2.getBuiltInFunctionList( ) );
117
118                list1.removeAll( retainList );
119                list2.removeAll( retainList );
120
121                for ( int i = 0; i < list2.size( ); i++ )
122                {
123                        list1.add( MINUS + list2.get( i ) );
124                }
125
126                Collections.sort( list1, new Comparator<String>( ) {
127
128                        public int compare( String str1, String str2 )
129                        {
130                                if ( !str1.startsWith( MINUS ) )
131                                        str1 = MINUS + str1;
132                                if ( !str2.startsWith( MINUS ) )
133                                        str2 = MINUS + str2;
134                                return str1.compareToIgnoreCase( str2 );
135                        }
136
137                } );
138
139                StringBuffer buffer = new StringBuffer( );
140                for ( int i = 0; i < list1.size( ); i++ )
141                {
142                        buffer.append( list1.get( i ) );
143                        if ( i < list1.size( ) - 1 )
144                                buffer.append( COMMA );
145                }
146                return buffer.toString( );
147        }
148
149        public static List<String> getAvailableDbVersions( EDbVendor dbvendor )
150        {
151                return functionListFactory.getInstance( )
152                                .getAvailableDbVersions( dbvendor );
153        }
154
155        public static boolean containsDbVersion( EDbVendor dbvendor,
156                        String dbVersion )
157        {
158                return functionListFactory.getInstance( ).containsDbVersion( dbvendor,
159                                dbVersion );
160        }
161
162        public static void main(String[] args) {
163                System.out.println(functionChecker.getBuiltInFunctionList(EDbVendor.dbvoracle, "11.2"));
164                System.out.println(functionChecker.isBuiltInFunction("power", EDbVendor.dbvoracle, "11.2"));
165                long time = System.currentTimeMillis();
166                for (int i = 0; i < 1000000; i++) {
167                        functionChecker.isBuiltInFunction("power", EDbVendor.dbvoracle, "11.2");
168                }
169                System.out.println(System.currentTimeMillis() - time);
170        }
171        
172//      public static void main( String[] args ){
173//        EDbVendor db = EDbVendor.dbvoracle;
174//        int i = functionChecker.getAvailableDbVersions(db).size();
175//        for(int k=0;k<i;k++) {
176//                      System.out.println(functionChecker.getAvailableDbVersions(db).get(k));
177//              }
178//              System.out.println(functionChecker.isOraclePredefinedPackageFunction("DBMS_RANDOM.RANDOM"));
179//      }
180
181}