001package gudusoft.gsqlparser.dlineage.dataflow.metadata.sqlenv; 002 003import gudusoft.gsqlparser.EDbVendor; 004import gudusoft.gsqlparser.dlineage.dataflow.metadata.MetadataAnalyzer; 005import gudusoft.gsqlparser.dlineage.dataflow.model.ModelBindingManager; 006import gudusoft.gsqlparser.dlineage.dataflow.model.xml.*; 007import gudusoft.gsqlparser.dlineage.util.DlineageUtil; 008import gudusoft.gsqlparser.dlineage.util.Pair3; 009import gudusoft.gsqlparser.sqlenv.*; 010import gudusoft.gsqlparser.util.SQLUtil; 011 012import java.util.*; 013 014public class SQLEnvMetadataAnalyzer implements MetadataAnalyzer<TSQLEnv> { 015 016 private Map<String, procedure> procedureMap = new LinkedHashMap<String, procedure>(); 017 private Map<String, table> tableMap = new LinkedHashMap<String, table>(); 018 private Map<String, oraclePackage> oraclePackageMap = new LinkedHashMap<String, oraclePackage>(); 019 private Map<String, column> columnMap = new LinkedHashMap<String, column>(); 020 private EDbVendor vendor; 021 private boolean lower = false; 022 023 public SQLEnvMetadataAnalyzer(boolean lower) { 024 this.lower = lower; 025 } 026 027 @Override 028 public synchronized dataflow analyzeMetadata(EDbVendor metadataVendor, TSQLEnv sqlenv) { 029 init(vendor); 030 dataflow dataflow = new dataflow(); 031 032 String serverName = sqlenv.getDefaultServerName(); 033 EDbVendor vendor = metadataVendor; 034 if (sqlenv.getDBVendor() != null) { 035 vendor = sqlenv.getDBVendor(); 036 } 037 038 boolean supportsCatalogs = TSQLEnv.supportCatalog(vendor); 039 boolean supportsSchemas = TSQLEnv.supportSchema(vendor); 040 041 List<TSQLCatalog> databases = sqlenv.getCatalogList(); 042 if (databases != null) { 043 for (int i = 0; i < databases.size(); i++) { 044 TSQLCatalog catalog = databases.get(i); 045 String databaseName = catalog.getName(); 046 if (SQLUtil.parseNames(databaseName).size() > 1) { 047 databaseName = "\"" + databaseName + "\""; 048 } 049 List<TSQLSchema> schemas = catalog.getSchemaList(); 050 if (schemas == null) { 051 continue; 052 } 053 for (int j = 0; j < schemas.size(); j++) { 054 TSQLSchema jsonSchema = schemas.get(j); 055 String schemaName = (String) jsonSchema.getName(); 056 if (SQLUtil.parseNames(schemaName).size() > 1) { 057 schemaName = "\"" + schemaName + "\""; 058 } 059 List<TSQLSchemaObject> dbObjs = jsonSchema.getSchemaObjectList(); 060 if (dbObjs == null) { 061 continue; 062 } 063 for (int k = 0; k < dbObjs.size(); k++) { 064 TSQLSchemaObject jsonTable = dbObjs.get(k); 065 if (jsonTable instanceof TSQLTable) { 066 TSQLTable table = (TSQLTable) jsonTable; 067 String tableName = table.getName(); 068 boolean isView = table.isView(); 069 List<TSQLColumn> columns = table.getColumnList(); 070 if (columns == null) { 071 continue; 072 } 073 for (int l = 0; l < columns.size(); l++) { 074 TSQLColumn jsonColumn = columns.get(l); 075 String columnName = jsonColumn.getName(); 076 if (SQLUtil.isEmpty(columnName)) { 077 continue; 078 } 079 appendTable(vendor, supportsCatalogs, supportsSchemas, dataflow, serverName, databaseName, schemaName, tableName, isView, columnName); 080 } 081 } 082 if (jsonTable instanceof TSQLOraclePackage) { 083 TSQLOraclePackage sqlOraclePackage = (TSQLOraclePackage) jsonTable; 084 oraclePackage oraclePackage = appendOraclePackage(vendor, supportsCatalogs, supportsSchemas, dataflow, serverName, databaseName, schemaName, sqlOraclePackage); 085 if (sqlOraclePackage.getSchemaObjectList() != null) { 086 for (TSQLSchemaObject sqlProcedure : sqlOraclePackage.getSchemaObjectList()) { 087 appendProcedure(vendor, supportsCatalogs, supportsSchemas, dataflow, serverName, databaseName, schemaName, (TSQLSchemaObject) sqlProcedure, oraclePackage); 088 } 089 } 090 } 091 if(jsonTable instanceof TSQLProcedure){ 092 appendProcedure(vendor, supportsCatalogs, supportsSchemas, dataflow, serverName, databaseName, schemaName, (TSQLSchemaObject)jsonTable, null); 093 } 094 } 095 } 096 } 097 } 098 sortTableColumns(dataflow); 099 return dataflow; 100 } 101 102 private void appendProcedure(EDbVendor vendor, boolean supportsCatalogs, boolean supportsSchemas, dataflow dataflow, String serverName, String databaseName, String schemaName, TSQLSchemaObject sqlProcedure, oraclePackage oraclePackage) { 103 String qualifiedName = sqlProcedure.getQualifiedName(); 104 if (DlineageUtil.isProcedureExcluded(qualifiedName)) { 105 return; 106 } 107 String procedureName = sqlProcedure.getName(); 108 String procedureKey = getFullName(serverName, databaseName, schemaName, procedureName); 109 if (!procedureMap.containsKey(procedureKey)) { 110 procedure procedure = new procedure(); 111 if (serverName != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(serverName)) { 112 procedure.setServer(serverName); 113 } 114 if(supportsCatalogs && supportsSchemas){ 115 if(databaseName != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(databaseName)) { 116 if (lower) { 117 procedure.setDatabase(SQLUtil.trimColumnStringQuote(databaseName).toLowerCase()); 118 } else { 119 procedure.setDatabase(databaseName); 120 } 121 } 122 if(schemaName != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schemaName)) { 123 if (lower) { 124 procedure.setSchema(SQLUtil.trimColumnStringQuote(schemaName).toLowerCase()); 125 } else { 126 procedure.setSchema(schemaName); 127 } 128 } 129 } 130 else if(supportsCatalogs){ 131 if(databaseName != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(databaseName)) { 132 if (lower) { 133 procedure.setDatabase(SQLUtil.trimColumnStringQuote(databaseName).toLowerCase()); 134 } else { 135 procedure.setDatabase(databaseName); 136 } 137 } 138 } 139 else if(supportsSchemas){ 140 if(schemaName != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schemaName)) { 141 if (lower) { 142 procedure.setSchema(SQLUtil.trimColumnStringQuote(schemaName).toLowerCase()); 143 } else { 144 procedure.setSchema(schemaName); 145 } 146 } 147 } 148 149 if (lower) { 150 procedure.setName(SQLUtil.trimColumnStringQuote(procedureName).toLowerCase()); 151 } else { 152 procedure.setName(procedureName); 153 } 154 if (supportsSchemas && !SQLUtil.isEmpty(procedure.getSchema()) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(procedure.getSchema())) { 155 procedure.setName(procedure.getSchema() + "." + procedure.getName()); 156 } 157 if (supportsCatalogs && !SQLUtil.isEmpty(procedure.getDatabase()) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(procedure.getDatabase())) { 158 procedure.setName(procedure.getDatabase() + "." + procedure.getName()); 159 } 160 procedure.setId(String.valueOf(++ModelBindingManager.get().TABLE_COLUMN_ID)); 161 if (ModelBindingManager.getGlobalSqlInfo() != null) { 162 procedure.setCoordinate(new Pair3<Long, Long, Integer>(-1L, -1L, 163 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash())) + "," 164 + new Pair3<Long, Long, Integer>(-1L, -1L, 165 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash()))); 166 } 167 procedure.setType(sqlProcedure.getDataObjectType().name().replace("dot","").toLowerCase()); 168 if(oraclePackage!=null) { 169 oraclePackage.getProcedures().add(procedure); 170 } 171 else{ 172 dataflow.getProcedures().add(procedure); 173 } 174 procedureMap.put(procedureKey, procedure); 175 } 176 } 177 178 private oraclePackage appendOraclePackage(EDbVendor vendor, boolean supportsCatalogs, boolean supportsSchemas, dataflow dataflow, String serverName, String databaseName, String schemaName, TSQLOraclePackage sqlOraclePackage) { 179 String oraclePackageName = sqlOraclePackage.getName(); 180 String oraclePackageKey = getFullName(serverName, databaseName, schemaName, oraclePackageName); 181 if (!oraclePackageMap.containsKey(oraclePackageKey)) { 182 oraclePackage oraclePackage = new oraclePackage(); 183 if (serverName != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(serverName)) { 184 oraclePackage.setServer(serverName); 185 } 186 if(supportsCatalogs && supportsSchemas){ 187 if(databaseName != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(databaseName)) { 188 if (lower) { 189 oraclePackage.setDatabase(SQLUtil.trimColumnStringQuote(databaseName).toLowerCase()); 190 } else { 191 oraclePackage.setDatabase(databaseName); 192 } 193 } 194 if(schemaName != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schemaName)) { 195 if (lower) { 196 oraclePackage.setSchema(SQLUtil.trimColumnStringQuote(schemaName).toLowerCase()); 197 } else { 198 oraclePackage.setSchema(schemaName); 199 } 200 } 201 } 202 else if(supportsCatalogs){ 203 if(databaseName != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(databaseName)) { 204 if (lower) { 205 oraclePackage.setDatabase(SQLUtil.trimColumnStringQuote(databaseName).toLowerCase()); 206 } else { 207 oraclePackage.setDatabase(databaseName); 208 } 209 } 210 } 211 else if(supportsSchemas){ 212 if(schemaName != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schemaName)) { 213 if (lower) { 214 oraclePackage.setSchema(SQLUtil.trimColumnStringQuote(schemaName).toLowerCase()); 215 } else { 216 oraclePackage.setSchema(schemaName); 217 } 218 } 219 } 220 221 if (lower) { 222 oraclePackage.setName(SQLUtil.trimColumnStringQuote(oraclePackageName).toLowerCase()); 223 } else { 224 oraclePackage.setName(oraclePackageName); 225 } 226 if (supportsSchemas && !SQLUtil.isEmpty(oraclePackage.getSchema()) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(oraclePackage.getSchema())) { 227 oraclePackage.setName(oraclePackage.getSchema() + "." + oraclePackage.getName()); 228 } 229 if (supportsCatalogs && !SQLUtil.isEmpty(oraclePackage.getDatabase()) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(oraclePackage.getDatabase())) { 230 oraclePackage.setName(oraclePackage.getDatabase() + "." + oraclePackage.getName()); 231 } 232 oraclePackage.setId(String.valueOf(++ModelBindingManager.get().TABLE_COLUMN_ID)); 233 if (ModelBindingManager.getGlobalSqlInfo() != null) { 234 oraclePackage.setCoordinate(new Pair3<Long, Long, Integer>(-1L, -1L, 235 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash())) + "," 236 + new Pair3<Long, Long, Integer>(-1L, -1L, 237 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash()))); 238 } 239 dataflow.getPackages().add(oraclePackage); 240 oraclePackageMap.put(oraclePackageKey, oraclePackage); 241 } 242 return oraclePackageMap.get(oraclePackageKey); 243 } 244 245 private void init(EDbVendor vendor) { 246 this.vendor = vendor; 247 procedureMap.clear(); 248 tableMap.clear(); 249 columnMap.clear(); 250 if (ModelBindingManager.get() == null) { 251 ModelBindingManager.set(new ModelBindingManager()); 252 } 253 } 254 255 private void sortTableColumns(dataflow dataflow) { 256 if (dataflow.getTables() != null) { 257 for (table table : dataflow.getTables()) { 258 Collections.sort(table.getColumns(), new Comparator<column>() { 259 public int compare(column t1, column t2) { 260 if (t1.getName().equalsIgnoreCase("RelationRows")) 261 return 1; 262 if (t2.getName().equalsIgnoreCase("RelationRows")) 263 return -1; 264 return 0; 265 } 266 }); 267 } 268 } 269 270 if (dataflow.getResultsets() != null) { 271 for (table table : dataflow.getResultsets()) { 272 Collections.sort(table.getColumns(), new Comparator<column>() { 273 public int compare(column t1, column t2) { 274 if (t1.getName().equalsIgnoreCase("RelationRows")) 275 return 1; 276 if (t2.getName().equalsIgnoreCase("RelationRows")) 277 return -1; 278 return 0; 279 } 280 }); 281 } 282 } 283 } 284 285 private void appendTable(EDbVendor vendor, boolean supportsCatalogs, boolean supportsSchemas, dataflow dataflow, String serverName, String databaseName, String schemaName, String tableName, 286 boolean isView, String columnName) { 287 String tableKey = getFullName(serverName, databaseName, schemaName, tableName); 288 if (!tableMap.containsKey(tableKey)) { 289 table table = new table(); 290 if (serverName != null && !TSQLEnv.DEFAULT_SERVER_NAME.equalsIgnoreCase(serverName)) { 291 table.setServer(serverName); 292 } 293 if(supportsCatalogs && supportsSchemas){ 294 if(databaseName != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(databaseName)) { 295 if (lower) { 296 table.setDatabase(SQLUtil.trimColumnStringQuote(databaseName).toLowerCase()); 297 } else { 298 table.setDatabase(databaseName); 299 } 300 } 301 if(schemaName != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schemaName)) { 302 if (lower) { 303 table.setSchema(SQLUtil.trimColumnStringQuote(schemaName).toLowerCase()); 304 } else { 305 table.setSchema(schemaName); 306 } 307 } 308 } 309 else if(supportsCatalogs){ 310 if(databaseName != null && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(databaseName)) { 311 if (lower) { 312 table.setDatabase(SQLUtil.trimColumnStringQuote(databaseName).toLowerCase()); 313 } else { 314 table.setDatabase(databaseName); 315 } 316 } 317 } 318 else if(supportsSchemas){ 319 if(schemaName != null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(schemaName)) { 320 if (lower) { 321 table.setSchema(SQLUtil.trimColumnStringQuote(schemaName).toLowerCase()); 322 } else { 323 table.setSchema(schemaName); 324 } 325 } 326 } 327 328 if (lower) { 329 table.setName(SQLUtil.trimColumnStringQuote(tableName).toLowerCase()); 330 } else { 331 table.setName(tableName); 332 } 333 if (supportsSchemas && !SQLUtil.isEmpty(table.getSchema()) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(table.getSchema())) { 334 table.setName(table.getSchema() + "." + table.getName()); 335 } 336 if (supportsCatalogs && !SQLUtil.isEmpty(table.getDatabase()) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(table.getDatabase())) { 337 table.setName(table.getDatabase() + "." + table.getName()); 338 } 339 table.setId(String.valueOf(++ModelBindingManager.get().TABLE_COLUMN_ID)); 340 if (ModelBindingManager.getGlobalSqlInfo() != null) { 341 table.setCoordinate(new Pair3<Long, Long, Integer>(-1L, -1L, 342 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash())) + "," 343 + new Pair3<Long, Long, Integer>(-1L, -1L, 344 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash()))); 345 } 346 if (isView) { 347 table.setType("view"); 348 dataflow.getViews().add(table); 349 } else { 350 table.setType("table"); 351 dataflow.getTables().add(table); 352 } 353 tableMap.put(tableKey, table); 354 } 355 356 table table = tableMap.get(tableKey); 357 String sourceColumnKey = getFullName(serverName, databaseName, schemaName, tableName, columnName); 358 if (!columnMap.containsKey(sourceColumnKey)) { 359 column column = new column(); 360 column.setId(String.valueOf(++ModelBindingManager.get().TABLE_COLUMN_ID)); 361 column.setName(columnName); 362 if ("RelationRows".equalsIgnoreCase(columnName)) { 363 column.setSource("system"); 364 } 365 if (ModelBindingManager.getGlobalSqlInfo() != null) { 366 column.setCoordinate(new Pair3<Long, Long, Integer>(-1L, -1L, 367 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash())) + "," 368 + new Pair3<Long, Long, Integer>(-1L, -1L, 369 ModelBindingManager.getGlobalSqlInfo().getIndexOf(ModelBindingManager.getGlobalHash()))); 370 } 371 table.getColumns().add(column); 372 columnMap.put(sourceColumnKey, column); 373 } 374 } 375 376 private String getFullName(String... segments) { 377 StringBuilder builder = new StringBuilder(); 378 for (int i = 0; i < segments.length; i++) { 379 builder.append(segments[i]); 380 if (i < segments.length - 1) { 381 builder.append("."); 382 } 383 } 384 return builder.toString(); 385 } 386}