001package gudusoft.gsqlparser.dlineage.dataflow.model;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.ESetOperatorType;
005import gudusoft.gsqlparser.TCustomSqlStatement;
006import gudusoft.gsqlparser.TSourceToken;
007import gudusoft.gsqlparser.dlineage.util.DlineageUtil;
008import gudusoft.gsqlparser.dlineage.util.Pair3;
009import gudusoft.gsqlparser.nodes.TCTE;
010import gudusoft.gsqlparser.nodes.TFunctionCall;
011import gudusoft.gsqlparser.nodes.TJoinList;
012import gudusoft.gsqlparser.pp.utils.SourceTokenSearcher;
013import gudusoft.gsqlparser.sqlenv.TSQLEnv;
014import gudusoft.gsqlparser.stmt.*;
015import gudusoft.gsqlparser.stmt.hive.THiveLoad;
016import gudusoft.gsqlparser.stmt.mssql.TCreateExternalDataSourceStmt;
017import gudusoft.gsqlparser.stmt.mssql.TMssqlCreateFunction;
018import gudusoft.gsqlparser.stmt.mssql.TMssqlDeclare;
019import gudusoft.gsqlparser.stmt.mssql.TMssqlExecute;
020import gudusoft.gsqlparser.stmt.snowflake.TCreateStageStmt;
021import gudusoft.gsqlparser.stmt.snowflake.TCreateStreamStmt;
022import gudusoft.gsqlparser.stmt.snowflake.TSnowflakeCopyIntoStmt;
023import gudusoft.gsqlparser.stmt.teradata.TTeradataCreateProcedure;
024import gudusoft.gsqlparser.util.Logger;
025import gudusoft.gsqlparser.util.LoggerFactory;
026import gudusoft.gsqlparser.util.SQLUtil;
027
028import java.io.ByteArrayInputStream;
029import java.io.IOException;
030import java.util.ArrayDeque;
031import java.util.ArrayList;
032import java.util.Deque;
033import java.util.List;
034import java.util.Properties;
035
036public class Process {
037    private static final Logger logger = LoggerFactory.getLogger(Process.class);
038    private long id;
039    protected String server;
040    protected String schema;
041    protected String database;
042    private String name;
043    private String procedureName;
044    private Long procedureId;
045    private String queryHashId;
046    private String type;
047    private String customType;
048    private TCustomSqlStatement gspObject;
049    private Pair3<Long, Long, String> startPosition;
050    private Pair3<Long, Long, String> endPosition;
051    private List<Object> targetColumns = new ArrayList<Object>();
052    private List<Transform> transforms = new ArrayList<Transform>();
053
054    public Process(TCustomSqlStatement gspObject) {
055
056        if (gspObject == null) {
057            throw new IllegalArgumentException("Process arguments can't be null.");
058        }
059
060        id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
061
062        this.gspObject = gspObject;
063
064        TSourceToken startToken = gspObject.getStartToken();
065        TSourceToken endToken = gspObject.getEndToken();
066        if (startToken != null) {
067            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
068                    ModelBindingManager.getGlobalHash());
069        }
070
071        if (endToken != null) {
072            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
073                    endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
074        }
075
076        this.schema = ModelBindingManager.getGlobalSchema();
077        this.database = ModelBindingManager.getGlobalDatabase();
078        this.queryHashId = SQLUtil.stringToMD5(gspObject.asCanonical().replaceAll("\r?\n", "\r\n"));
079
080        EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
081        boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
082        boolean supportSchema = TSQLEnv.supportSchema(vendor);
083
084        fillSchemaInfo();
085
086        if (!supportCatalog) {
087            this.database = null;
088        } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
089            this.database = getDefaultDatabase();
090        }
091
092        if (!supportSchema) {
093            this.schema = null;
094        } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
095            this.schema = getDefaultSchema();
096        }
097
098        String procedureParent = getProcedureParentName(gspObject);
099        if (procedureParent != null) {
100            procedureName = procedureParent;
101            Procedure procedure = ModelBindingManager.get()
102                    .getProcedureByName(DlineageUtil.getIdentifierNormalTableName(
103                            DlineageUtil.getProcedureNameWithArgs(getParentProcedure(gspObject))));
104            if (procedure == null) {
105                procedure = ModelBindingManager.get().getProcedureByName(DlineageUtil.getIdentifierNormalTableName(
106                        DlineageUtil.getProcedureNameWithArgNum(getParentProcedure(gspObject))));
107            }
108            if (procedure != null) {
109                this.procedureId = procedure.getId();
110            }
111        } else {
112            procedureName = "batchQueries";
113        }
114
115        TCustomSqlStatement stmt = DlineageUtil.getTopStmt(ModelBindingManager.getGlobalStmtStack().peek());
116        String sqlComment = null;
117        try {
118            sqlComment = stmt.getCommentBeforeNode();
119        } catch (Exception e) {
120        }
121        if (!SQLUtil.isEmpty(sqlComment) && sqlComment.indexOf("process") != -1) {
122            Properties properties = new Properties();
123            try {
124                properties.load(
125                        new ByteArrayInputStream(sqlComment.replace("--", "").trim().replace(",", "\n").getBytes()));
126                if (properties.containsKey("process_label")) {
127                    this.customType = properties.getProperty("process_label");
128                } else if (properties.containsKey("process")) {
129                    this.customType = properties.getProperty("process");
130                }
131            } catch (IOException e) {
132                logger.error("load sql comment properties failed.", e);
133            }
134        }
135
136        if (gspObject instanceof TCreateTableSqlStatement) {
137            this.type = "Create Table";
138        } else if (gspObject instanceof TCreateViewSqlStatement) {
139            this.type = "Create View";
140        } else if (gspObject instanceof TUpdateSqlStatement) {
141            this.type = "Update";
142        } else if (gspObject instanceof TMergeSqlStatement) {
143            this.type = "Merge";
144        } else if (gspObject instanceof TInsertSqlStatement) {
145            this.type = "Insert";
146        } else if (gspObject instanceof TSelectSqlStatement
147                && ((TSelectSqlStatement) gspObject).getIntoClause() != null) {
148            this.type = "Select Into";
149        } else if (gspObject instanceof TCreateTriggerStmt) {
150            this.type = "Create Trigger";
151        } else if (gspObject instanceof TCreateFunctionStmt) {
152            this.type = "Create Function";
153        } else if (gspObject instanceof TMssqlCreateFunction) {
154            this.type = "Create Function";
155        } else if (gspObject instanceof TCreateProcedureStmt) {
156            this.type = "Create Procedure";
157        } else if (gspObject instanceof THiveLoad) {
158            this.type = "Hive Load";
159        } else if (gspObject instanceof TSnowflakeCopyIntoStmt) {
160            this.type = "Copy Into";
161        } else if (gspObject instanceof TAlterTableStatement) {
162            this.type = "Alter Table";
163        } else if (gspObject instanceof TRenameStmt) {
164            this.type = "Rename Table";
165        } else if (gspObject instanceof TMssqlDeclare) {
166            this.type = "Mssql Declare";
167        } else if (gspObject instanceof TCreateStageStmt) {
168            this.type = "Create Stage";
169        } else if (gspObject instanceof TCreateSynonymStmt) {
170            this.type = "Create Synonym";
171        } else if (gspObject instanceof TCreateExternalDataSourceStmt) {
172            this.type = "Create Datasource";
173        } else if (gspObject instanceof TCreateStreamStmt) {
174            this.type = "Create Stream";
175        } else if (gspObject instanceof TCreateDatabaseSqlStatement) {
176            this.type = "Create Database";
177        } else if (gspObject instanceof TCreateSchemaSqlStatement) {
178            this.type = "Create Schema";
179        } else if (gspObject instanceof TMssqlExecute && ((TMssqlExecute)gspObject).getModuleName().toString().equalsIgnoreCase("sp_rename")) {
180            this.type = "Rename Table";
181        } else if (gspObject instanceof TCallStatement){
182            this.type = "Function Call";
183        } else {
184            this.type = gspObject.getClass().getSimpleName();
185        }
186
187        if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
188            this.server = getDefaultServer();
189        }
190
191        if (stmt.getStatements() != null) {
192            for (int i = 0; i < stmt.getStatements().size(); i++) {
193                TCustomSqlStatement subquery = stmt.getStatements().get(i);
194                if (subquery instanceof TSelectSqlStatement) {
195                    TSelectSqlStatement select = (TSelectSqlStatement) subquery;
196                    appendTransform(select, ESetOperatorType.none);
197                }
198            }
199        }
200    }
201
202    public Process(TFunctionCall gspObject) {
203
204        if (gspObject == null) {
205            throw new IllegalArgumentException("Process arguments can't be null.");
206        }
207
208        id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
209
210
211        TSourceToken startToken = gspObject.getStartToken();
212        TSourceToken endToken = gspObject.getEndToken();
213        if (startToken != null) {
214            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
215                    ModelBindingManager.getGlobalHash());
216        }
217
218        if (endToken != null) {
219            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
220                    endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
221        }
222
223        TCustomSqlStatement stmt = DlineageUtil.getTopStmt(ModelBindingManager.getGlobalStmtStack().peek());
224        this.gspObject = stmt;
225
226        this.schema = ModelBindingManager.getGlobalSchema();
227        this.database = ModelBindingManager.getGlobalDatabase();
228
229        if (stmt != null) {
230            this.queryHashId = SQLUtil.stringToMD5(stmt.asCanonical().replaceAll("\r?\n", "\r\n"));
231        }
232
233        EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
234        boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
235        boolean supportSchema = TSQLEnv.supportSchema(vendor);
236
237        fillSchemaInfo();
238
239        if (!supportCatalog) {
240            this.database = null;
241        } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
242            this.database = getDefaultDatabase();
243        }
244
245        if (!supportSchema) {
246            this.schema = null;
247        } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
248            this.schema = getDefaultSchema();
249        }
250
251        String procedureParent = getProcedureParentName(stmt);
252        if (procedureParent != null) {
253            procedureName = procedureParent;
254            Procedure procedure = ModelBindingManager.get()
255                    .getProcedureByName(DlineageUtil.getIdentifierNormalTableName(
256                            DlineageUtil.getProcedureNameWithArgs(getParentProcedure(stmt))));
257            if (procedure == null) {
258                procedure = ModelBindingManager.get().getProcedureByName(DlineageUtil.getIdentifierNormalTableName(
259                        DlineageUtil.getProcedureNameWithArgNum(getParentProcedure(stmt))));
260            }
261            if (procedure != null) {
262                this.procedureId = procedure.getId();
263            }
264        } else {
265            procedureName = "batchQueries";
266        }
267
268        String sqlComment = null;
269        try {
270            sqlComment = stmt.getCommentBeforeNode();
271        } catch (Exception e) {
272        }
273        if (!SQLUtil.isEmpty(sqlComment) && sqlComment.indexOf("process") != -1) {
274            Properties properties = new Properties();
275            try {
276                properties.load(
277                        new ByteArrayInputStream(sqlComment.replace("--", "").trim().replace(",", "\n").getBytes()));
278                if (properties.containsKey("process_label")) {
279                    this.customType = properties.getProperty("process_label");
280                } else if (properties.containsKey("process")) {
281                    this.customType = properties.getProperty("process");
282                }
283            } catch (IOException e) {
284                logger.error("load sql comment properties failed.", e);
285            }
286        }
287
288        this.type = "Function Call";
289
290        if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
291            this.server = getDefaultServer();
292        }
293    }
294
295    private void appendTransform(TSelectSqlStatement select, ESetOperatorType operatorType) {
296        // Iterative traversal of the UNION tree to avoid StackOverflow with deeply nested unions.
297        Deque<Object[]> stack = new ArrayDeque<>();
298        stack.push(new Object[]{select, operatorType});
299
300        while (!stack.isEmpty()) {
301            Object[] entry = stack.pop();
302            TSelectSqlStatement current = (TSelectSqlStatement) entry[0];
303            ESetOperatorType currentOp = (ESetOperatorType) entry[1];
304
305            if (currentOp != ESetOperatorType.none) {
306                Transform transform = new Transform();
307                transform.setType(currentOp.name());
308                transform.setCodeString(current.toString());
309                transform.setStartToken(current.getStartToken());
310                transform.setEndToken(current.getEndToken());
311                transforms.add(transform);
312            } else {
313                if (current.getCteList() != null && current.getCteList().size() > 0) {
314                    for (int i = 0; i < current.getCteList().size(); i++) {
315                        TCTE cte = current.getCteList().getCTE(i);
316                        Transform transform = new Transform();
317                        transform.setType(Transform.CTE);
318                        transform.setCodeString(cte.toString());
319                        transform.setStartToken(cte.getStartToken());
320                        transform.setEndToken(cte.getEndToken());
321                        transforms.add(transform);
322                    }
323                }
324                if (current.getSetOperatorType() != ESetOperatorType.none) {
325                    // Push right first so left is processed first (stack is LIFO)
326                    if (current.getRightStmt() != null) {
327                        ESetOperatorType rightOp = current.getRightStmt().getSetOperatorType() != ESetOperatorType.none
328                                ? ESetOperatorType.none : current.getSetOperatorType();
329                        stack.push(new Object[]{current.getRightStmt(), rightOp});
330                    }
331                    if (current.getLeftStmt() != null) {
332                        ESetOperatorType leftOp = current.getLeftStmt().getSetOperatorType() != ESetOperatorType.none
333                                ? ESetOperatorType.none : current.getSetOperatorType();
334                        stack.push(new Object[]{current.getLeftStmt(), leftOp});
335                    }
336                } else {
337                    if (current.getJoins() != null && current.getJoins().size() > 0) {
338                        TJoinList joins = current.getJoins();
339                        TSourceToken startToken = joins.getStartToken();
340                        TSourceToken fromToken = SourceTokenSearcher.backforwardSearch(startToken, 10, "from");
341                        if (fromToken == null) {
342                            if (startToken.getAstext().equalsIgnoreCase("from")) {
343                                fromToken = startToken;
344                            } else {
345                                continue;
346                            }
347                        }
348                        StringBuilder builder = new StringBuilder();
349                        if (joins.getEndToken().posinlist < fromToken.container.size()
350                                && joins.getEndToken().posinlist >= fromToken.posinlist) {
351                            for (int j = fromToken.posinlist; j <= joins.getEndToken().posinlist; j++) {
352                                builder.append(fromToken.container.get(j));
353                            }
354                        } else {
355                            System.err.println("Handle statement transform error, statemet is:");
356                            System.err.println(current.toString());
357                        }
358                        Transform transform = new Transform();
359                        transform.setType(Transform.FROM);
360                        transform.setCodeString(builder.toString());
361                        transform.setStartToken(fromToken);
362                        transform.setEndToken(joins.getEndToken());
363                        transforms.add(transform);
364                    }
365                }
366            }
367        }
368    }
369
370    private TSelectSqlStatement getFirstSubquery(TSelectSqlStatement select) {
371        // Iterative left-chain walk to avoid StackOverflow with deeply nested unions.
372        TSelectSqlStatement current = select;
373        while (current.getSetOperatorType() != ESetOperatorType.none) {
374            current = current.getLeftStmt();
375        }
376        return current;
377    }
378
379    private TSelectSqlStatement getLastSubquery(TSelectSqlStatement select) {
380        // Iterative right-chain walk to avoid StackOverflow with deeply nested unions.
381        TSelectSqlStatement current = select;
382        while (current.getSetOperatorType() != ESetOperatorType.none) {
383            current = current.getRightStmt();
384        }
385        return current;
386    }
387
388    private void fillSchemaInfo() {
389        TCustomSqlStatement stmt = DlineageUtil.getTopStmt(ModelBindingManager.getGlobalStmtStack().peek());
390        String sqlComment = null;
391        try {
392            sqlComment = stmt.getCommentBeforeNode();
393        } catch (Exception e) {
394        }
395        if (!SQLUtil.isEmpty(sqlComment) && (sqlComment.indexOf("db") != -1 || sqlComment.indexOf("schema") != -1)) {
396            Properties properties = new Properties();
397            try {
398                properties.load(
399                        new ByteArrayInputStream(sqlComment.replace("--", "").trim().replace(",", "\n").getBytes()));
400                if (SQLUtil.isEmpty(this.server) && properties.containsKey("db-instance")) {
401                    this.server = properties.getProperty("db-instance");
402                }
403                if (SQLUtil.isEmpty(this.database) && properties.containsKey("db")) {
404                    this.database = properties.getProperty("db");
405                    if (this.database.indexOf(".") != -1) {
406                        String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
407                        this.database = delimitedChar + SQLUtil.trimColumnStringQuote(this.database) + delimitedChar;
408                    }
409                }
410                if (SQLUtil.isEmpty(this.schema) && properties.containsKey("schema")) {
411                    this.schema = properties.getProperty("schema");
412                    if (this.schema.indexOf(".") != -1) {
413                        String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
414                        this.schema = delimitedChar + SQLUtil.trimColumnStringQuote(this.schema) + delimitedChar;
415                    }
416                }
417            } catch (IOException e) {
418                logger.error("load sql comment properties failed.", e);
419            }
420        }
421    }
422
423    protected String getDefaultServer() {
424        String defaultServer = null;
425        if (ModelBindingManager.getGlobalSQLEnv() != null) {
426            defaultServer = ModelBindingManager.getGlobalSQLEnv().getDefaultServerName();
427        }
428        if (!SQLUtil.isEmpty(defaultServer))
429            return defaultServer;
430        return TSQLEnv.DEFAULT_SERVER_NAME;
431    }
432
433    protected String getDefaultSchema() {
434        String defaultSchema = null;
435        if (ModelBindingManager.getGlobalSQLEnv() != null) {
436            defaultSchema = ModelBindingManager.getGlobalSQLEnv().getDefaultSchemaName();
437        }
438        if (!SQLUtil.isEmpty(defaultSchema))
439            return defaultSchema;
440        return TSQLEnv.DEFAULT_SCHEMA_NAME;
441    }
442
443    protected String getDefaultDatabase() {
444        String defaultDatabase = null;
445        if (ModelBindingManager.getGlobalSQLEnv() != null) {
446            defaultDatabase = ModelBindingManager.getGlobalSQLEnv().getDefaultCatalogName();
447        }
448        if (!SQLUtil.isEmpty(defaultDatabase))
449            return defaultDatabase;
450        return TSQLEnv.DEFAULT_DB_NAME;
451    }
452
453    private String getProcedureParentName(TCustomSqlStatement stmt) {
454        if (stmt instanceof TStoredProcedureSqlStatement) {
455                        if (((TStoredProcedureSqlStatement) stmt).getStoredProcedureName() != null) {
456                                return ((TStoredProcedureSqlStatement) stmt).getStoredProcedureName().toString();
457                        }
458                }
459
460        if (stmt == null) {
461                return null;
462        }
463        
464        if (stmt instanceof TTeradataCreateProcedure) {
465            if (((TTeradataCreateProcedure) stmt).getProcedureName() != null) {
466                return ((TTeradataCreateProcedure) stmt).getProcedureName().toString();
467            }
468        }
469        
470        if (stmt instanceof TStoredProcedureSqlStatement) {
471            if (((TStoredProcedureSqlStatement) stmt).getStoredProcedureName() != null) {
472                return ((TStoredProcedureSqlStatement) stmt).getStoredProcedureName().toString();
473            }
474
475            if (stmt instanceof TCommonBlock) {
476                if (((TCommonBlock) stmt).getBlockBody().getParentObjectName() instanceof TStoredProcedureSqlStatement) {
477                    stmt = (TStoredProcedureSqlStatement) ((TCommonBlock) stmt).getBlockBody().getParentObjectName();
478                }
479                else {
480                        return getProcedureParentName(stmt.getParentStmt());
481                }
482            }
483            
484            return null;
485        }
486        
487                stmt = stmt.getParentStmt();
488        if (stmt == null) {
489            if(ModelBindingManager.getGlobalProcedure()!=null) {
490                return getProcedureParentName(ModelBindingManager.getGlobalProcedure());
491            }
492            else {
493                return null;
494            }
495        }
496        
497
498        if (stmt instanceof TCommonBlock) {
499            if (((TCommonBlock) stmt).getBlockBody().getParentObjectName() instanceof TStoredProcedureSqlStatement) {
500                stmt = (TStoredProcedureSqlStatement) ((TCommonBlock) stmt).getBlockBody().getParentObjectName();
501            }
502        }
503
504        return getProcedureParentName(stmt);
505    }
506
507    private TStoredProcedureSqlStatement getParentProcedure(TCustomSqlStatement stmt) {
508        if (stmt == null) {
509                return null;
510        }
511        
512        if (stmt instanceof TStoredProcedureSqlStatement) {
513            if (((TStoredProcedureSqlStatement) stmt).getStoredProcedureName() != null) {
514                return ((TStoredProcedureSqlStatement) stmt);
515            }
516            
517            if (stmt instanceof TCommonBlock) {
518                if (((TCommonBlock) stmt).getBlockBody().getParentObjectName() instanceof TStoredProcedureSqlStatement) {
519                    return (TStoredProcedureSqlStatement) ((TCommonBlock) stmt).getBlockBody().getParentObjectName();
520                }
521                else {
522                        return getParentProcedure(stmt.getParentStmt());
523                }
524            }
525            
526            return null;
527        }
528        
529            stmt = stmt.getParentStmt();
530        if (stmt == null) {
531            if(ModelBindingManager.getGlobalProcedure()!=null) {
532                return ModelBindingManager.getGlobalProcedure();
533            }
534            else {
535                return null;
536            }
537        }
538        
539        if (stmt instanceof TCommonBlock) {
540            if (((TCommonBlock) stmt).getBlockBody().getParentObjectName() instanceof TStoredProcedureSqlStatement) {
541                stmt = (TStoredProcedureSqlStatement) ((TCommonBlock) stmt).getBlockBody().getParentObjectName();
542            }
543        }
544
545        return getParentProcedure(stmt);
546    }
547
548    public Pair3<Long, Long, String> getStartPosition() {
549        return startPosition;
550    }
551
552    public Pair3<Long, Long, String> getEndPosition() {
553        return endPosition;
554    }
555
556    public TCustomSqlStatement getGspObject() {
557        return gspObject;
558    }
559
560    public long getId() {
561        return id;
562    }
563
564    public String getSchema() {
565        return schema;
566    }
567
568    public String getDatabase() {
569        return database;
570    }
571
572    public String getName() {
573        return name;
574    }
575
576    public String getType() {
577        return type;
578    }
579
580    public void setName(String name) {
581        this.name = name;
582    }
583
584    public void setType(String type) {
585        this.type = type;
586    }
587
588    public String getProcedureName() {
589        return procedureName;
590    }
591
592    public void setProcedureName(String procedureName) {
593        this.procedureName = procedureName;
594    }
595
596    public String getQueryHashId() {
597        return queryHashId;
598    }
599
600    public void setQueryHashId(String queryHashId) {
601        this.queryHashId = queryHashId;
602    }
603
604    public void appendColumn(Object tableColumn) {
605        if (tableColumn != null && !targetColumns.contains(tableColumn)) {
606            targetColumns.add(tableColumn);
607        }
608    }
609
610    public List<Object> getTargetColumns() {
611        return targetColumns;
612    }
613
614    public String getCustomType() {
615        return customType;
616    }
617
618    public Long getProcedureId() {
619        return procedureId;
620    }
621
622    public String getServer() {
623        return server;
624    }
625
626    public List<Transform> getTransforms() {
627        return transforms;
628    }
629}