001package gudusoft.gsqlparser.ir.builder.postgresql; 002 003import java.util.Collections; 004import java.util.HashSet; 005import java.util.Set; 006 007/** 008 * Classifies PostgreSQL built-in functions and pg_catalog system functions 009 * that should be treated as external dependencies rather than user-defined calls. 010 */ 011public final class PostgresqlExternalDepClassifier { 012 013 private PostgresqlExternalDepClassifier() {} 014 015 private static final Set<String> BUILTIN_FUNCTIONS; 016 private static final Set<String> AGGREGATE_FUNCTIONS; 017 private static final Set<String> SYSTEM_FUNCTIONS; 018 private static final Set<String> PG_CATALOG_PREFIXES; 019 private static final Set<String> ALL_BUILTINS; 020 021 static { 022 BUILTIN_FUNCTIONS = unmodifiableSet( 023 // String 024 "LENGTH", "CHAR_LENGTH", "LOWER", "UPPER", "TRIM", "LTRIM", "RTRIM", 025 "SUBSTRING", "SUBSTR", "REPLACE", "TRANSLATE", "CONCAT", "CONCAT_WS", 026 "LEFT", "RIGHT", "LPAD", "RPAD", "REVERSE", "REPEAT", "POSITION", 027 "STRPOS", "INITCAP", "ASCII", "CHR", "ENCODE", "DECODE", 028 "MD5", "FORMAT", "QUOTE_IDENT", "QUOTE_LITERAL", "QUOTE_NULLABLE", 029 "REGEXP_MATCH", "REGEXP_MATCHES", "REGEXP_REPLACE", "REGEXP_SPLIT_TO_TABLE", 030 "REGEXP_SPLIT_TO_ARRAY", "SPLIT_PART", 031 // Numeric 032 "ABS", "CEIL", "CEILING", "FLOOR", "ROUND", "TRUNC", "MOD", 033 "POWER", "SQRT", "CBRT", "EXP", "LN", "LOG", "PI", 034 "SIGN", "RANDOM", "SETSEED", "WIDTH_BUCKET", 035 "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "ATAN2", 036 // Date/Time 037 "NOW", "CURRENT_TIMESTAMP", "CURRENT_DATE", "CURRENT_TIME", 038 "LOCALTIME", "LOCALTIMESTAMP", "CLOCK_TIMESTAMP", "STATEMENT_TIMESTAMP", 039 "TRANSACTION_TIMESTAMP", "TIMEOFDAY", 040 "AGE", "DATE_PART", "DATE_TRUNC", "EXTRACT", "MAKE_DATE", 041 "MAKE_TIME", "MAKE_TIMESTAMP", "MAKE_TIMESTAMPTZ", 042 "MAKE_INTERVAL", "TO_TIMESTAMP", "TO_DATE", "TO_CHAR", 043 // Type conversion 044 "CAST", "TO_NUMBER", "TO_CHAR", "TO_DATE", "TO_TIMESTAMP", 045 // Conditional 046 "COALESCE", "NULLIF", "GREATEST", "LEAST", 047 // Array 048 "ARRAY_AGG", "ARRAY_LENGTH", "ARRAY_DIMS", "ARRAY_LOWER", "ARRAY_UPPER", 049 "ARRAY_APPEND", "ARRAY_CAT", "ARRAY_PREPEND", "ARRAY_REMOVE", 050 "ARRAY_REPLACE", "ARRAY_TO_STRING", "STRING_TO_ARRAY", "UNNEST", 051 // JSON 052 "JSON_BUILD_OBJECT", "JSON_BUILD_ARRAY", "JSON_OBJECT", 053 "JSON_AGG", "JSON_ARRAY_AGG", "JSONB_BUILD_OBJECT", "JSONB_BUILD_ARRAY", 054 "ROW_TO_JSON", "TO_JSON", "TO_JSONB", "JSON_EXTRACT_PATH", 055 "JSONB_EXTRACT_PATH", "JSON_EXTRACT_PATH_TEXT", "JSONB_EXTRACT_PATH_TEXT", 056 "JSONB_SET", "JSONB_INSERT", "JSONB_PRETTY", 057 // System info 058 "CURRENT_USER", "SESSION_USER", "CURRENT_SCHEMA", "CURRENT_DATABASE", 059 "CURRENT_CATALOG", "VERSION", "PG_BACKEND_PID", "PG_POSTMASTER_START_TIME", 060 // Sequence 061 "NEXTVAL", "CURRVAL", "SETVAL", "LASTVAL", 062 // Misc 063 "GENERATE_SERIES", "GENERATE_SUBSCRIPTS", 064 "COALESCE", "ROW_NUMBER", "RANK", "DENSE_RANK", 065 "EXISTS", "NOT_EXISTS", 066 "PG_TYPEOF", "PG_COLUMN_SIZE", "PG_TABLE_SIZE", 067 "TXID_CURRENT", "TXID_SNAPSHOT_XIP" 068 ); 069 070 AGGREGATE_FUNCTIONS = unmodifiableSet( 071 "AVG", "COUNT", "MAX", "MIN", "SUM", 072 "BOOL_AND", "BOOL_OR", "BIT_AND", "BIT_OR", 073 "EVERY", "ARRAY_AGG", "STRING_AGG", "JSON_AGG", "JSONB_AGG", 074 "JSON_OBJECT_AGG", "JSONB_OBJECT_AGG", 075 "PERCENTILE_CONT", "PERCENTILE_DISC", 076 "CORR", "COVAR_POP", "COVAR_SAMP", 077 "REGR_AVGX", "REGR_AVGY", "REGR_COUNT", 078 "REGR_INTERCEPT", "REGR_R2", "REGR_SLOPE", 079 "REGR_SXX", "REGR_SXY", "REGR_SYY", 080 "STDDEV", "STDDEV_POP", "STDDEV_SAMP", 081 "VARIANCE", "VAR_POP", "VAR_SAMP", 082 "XMLAGG" 083 ); 084 085 SYSTEM_FUNCTIONS = unmodifiableSet( 086 "RAISE", "RAISE_EXCEPTION", 087 "PG_NOTIFY", "PG_SLEEP", "PG_ADVISORY_LOCK", 088 "PG_ADVISORY_UNLOCK", "PG_TRY_ADVISORY_LOCK", 089 "SET_CONFIG", "CURRENT_SETTING" 090 ); 091 092 PG_CATALOG_PREFIXES = unmodifiableSet( 093 "PG_CATALOG", "INFORMATION_SCHEMA", "PG_TOAST" 094 ); 095 096 Set<String> all = new HashSet<String>(); 097 all.addAll(BUILTIN_FUNCTIONS); 098 all.addAll(AGGREGATE_FUNCTIONS); 099 all.addAll(SYSTEM_FUNCTIONS); 100 ALL_BUILTINS = Collections.unmodifiableSet(all); 101 } 102 103 public static boolean isExternal(String name) { 104 if (name == null || name.isEmpty()) return false; 105 String upper = name.toUpperCase().trim(); 106 107 int dot = upper.indexOf('.'); 108 if (dot > 0) { 109 String prefix = upper.substring(0, dot); 110 if (PG_CATALOG_PREFIXES.contains(prefix)) return true; 111 } 112 113 String objectName = dot >= 0 ? upper.substring(dot + 1) : upper; 114 return ALL_BUILTINS.contains(objectName); 115 } 116 117 public static String classify(String name) { 118 if (name == null) return "BUILTIN_FUNCTION"; 119 String upper = name.toUpperCase().trim(); 120 121 int dot = upper.indexOf('.'); 122 if (dot > 0) { 123 String prefix = upper.substring(0, dot); 124 if (PG_CATALOG_PREFIXES.contains(prefix)) return "SYSTEM_CATALOG"; 125 } 126 127 String objectName = dot >= 0 ? upper.substring(dot + 1) : upper; 128 if (AGGREGATE_FUNCTIONS.contains(objectName)) return "AGGREGATE_FUNCTION"; 129 if (SYSTEM_FUNCTIONS.contains(objectName)) return "SYSTEM_FUNCTION"; 130 return "BUILTIN_FUNCTION"; 131 } 132 133 private static Set<String> unmodifiableSet(String... items) { 134 Set<String> set = new HashSet<String>(); 135 for (String item : items) set.add(item); 136 return Collections.unmodifiableSet(set); 137 } 138}