001package gudusoft.gsqlparser.dlineage.dataflow.model;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.ESqlStatementType;
005import gudusoft.gsqlparser.TCustomSqlStatement;
006import gudusoft.gsqlparser.TSourceToken;
007import gudusoft.gsqlparser.dlineage.util.DlineageUtil;
008import gudusoft.gsqlparser.dlineage.util.Pair3;
009import gudusoft.gsqlparser.nodes.TFunctionCall;
010import gudusoft.gsqlparser.nodes.TObjectName;
011import gudusoft.gsqlparser.nodes.TParseTreeNode;
012import gudusoft.gsqlparser.sqlenv.TSQLEnv;
013import gudusoft.gsqlparser.stmt.TStoredProcedureSqlStatement;
014import gudusoft.gsqlparser.stmt.teradata.TTeradataCreateProcedure;
015import gudusoft.gsqlparser.util.Logger;
016import gudusoft.gsqlparser.util.LoggerFactory;
017import gudusoft.gsqlparser.util.SQLUtil;
018
019import java.io.ByteArrayInputStream;
020import java.io.IOException;
021import java.util.ArrayList;
022import java.util.List;
023import java.util.Properties;
024
025public class Procedure {
026    private static final Logger logger = LoggerFactory.getLogger(Procedure.class);
027    private long id;
028    private String server;
029    private String database;
030    private String schema;
031    private String name;
032    private String fullName;
033    private Pair3<Long, Long, String> startPosition;
034    private Pair3<Long, Long, String> endPosition;
035    private List<Argument> arguments = new ArrayList<Argument>();
036    private ESqlStatementType type;
037    private TParseTreeNode procedureObject;
038    private OraclePackage parentPackage;
039
040    public Procedure(TStoredProcedureSqlStatement procedure) {
041        if (procedure == null) {
042            throw new IllegalArgumentException("Procedure arguments can't be null.");
043        } else {
044            this.id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
045            this.procedureObject = procedure;
046            TObjectName procedureName = getProcedureName();
047            TSourceToken startToken = procedure.getStartToken();
048            TSourceToken endToken = procedure.getEndToken();
049            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo, ModelBindingManager.getGlobalHash());
050            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
051                    endToken.columnNo + (long) SQLUtil.endTrim(endToken.astext).length(), ModelBindingManager.getGlobalHash());
052            this.fullName = procedureName.toString();
053            this.name = procedureName.toString();
054
055            EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
056            boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
057            boolean supportSchema = TSQLEnv.supportSchema(vendor);
058
059            fillSchemaInfo();
060
061            if (supportCatalog) {
062                this.database = DlineageUtil.getTableDatabase(procedureName.toString());
063                if (SQLUtil.isEmpty(this.database) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
064                        && !SQLUtil.isEmpty(procedureName.getImplictDatabaseString())) {
065                    this.database = procedureName.getImplictDatabaseString();
066                }
067            }
068
069            if (supportSchema) {
070                this.schema = DlineageUtil.getTableSchema(procedureName.toString());
071                if (SQLUtil.isEmpty(this.schema) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
072                        && !SQLUtil.isEmpty(procedureName.getImplictSchemaString())) {
073                    this.schema = procedureName.getImplictSchemaString();
074                }
075
076                if (!SQLUtil.isEmpty(this.database) && SQLUtil.isEmpty(this.schema)) {
077                    if (!SQLUtil.isEmpty(procedureName.getImplictSchemaString())) {
078                        this.schema = procedureName.getImplictSchemaString();
079                    } else {
080                        this.schema = TSQLEnv.DEFAULT_SCHEMA_NAME;
081                    }
082                }
083            }
084
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            updateProcedureName(supportCatalog, supportSchema);
099
100            this.type = procedure.sqlstatementtype;
101
102            if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
103                this.server = getDefaultServer();
104            }
105        }
106    }
107
108    public Procedure(TObjectName procedureName) {
109        if (procedureName == null) {
110            throw new IllegalArgumentException("Procedure arguments can't be null.");
111        } else {
112            this.id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
113            this.procedureObject = procedureName;
114            TSourceToken startToken = procedureName.getStartToken();
115            TSourceToken endToken = procedureName.getEndToken();
116            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo, ModelBindingManager.getGlobalHash());
117            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
118                    endToken.columnNo + (long) SQLUtil.endTrim(endToken.astext).length(), ModelBindingManager.getGlobalHash());
119            this.fullName = procedureName.toString();
120            this.name = procedureName.toString();
121
122            EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
123            boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
124            boolean supportSchema = TSQLEnv.supportSchema(vendor);
125
126            fillSchemaInfo();
127
128            if (supportCatalog) {
129                this.database = DlineageUtil.getTableDatabase(procedureName.toString());
130                if (SQLUtil.isEmpty(this.database) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
131                        && !SQLUtil.isEmpty(procedureName.getImplictDatabaseString())) {
132                    this.database = procedureName.getImplictDatabaseString();
133                }
134            }
135
136            if (supportSchema) {
137                this.schema = DlineageUtil.getTableSchema(procedureName.toString());
138                if (SQLUtil.isEmpty(this.schema) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
139                        && !SQLUtil.isEmpty(procedureName.getImplictSchemaString())) {
140                    this.schema = procedureName.getImplictSchemaString();
141                }
142
143                if (!SQLUtil.isEmpty(this.database) && SQLUtil.isEmpty(this.schema)) {
144                    if (!SQLUtil.isEmpty(procedureName.getImplictSchemaString())) {
145                        this.schema = procedureName.getImplictSchemaString();
146                    } else {
147                        this.schema = TSQLEnv.DEFAULT_SCHEMA_NAME;
148                    }
149                }
150            }
151
152            if (!supportCatalog) {
153                this.database = null;
154            } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
155                this.database = getDefaultDatabase();
156            }
157
158            if (!supportSchema) {
159                this.schema = null;
160            } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
161                this.schema = getDefaultSchema();
162            }
163
164            updateProcedureName(supportCatalog, supportSchema);
165
166            if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
167                this.server = getDefaultServer();
168            }
169        }
170    }
171    
172    public Procedure(TFunctionCall function) {
173        if (function == null) {
174            throw new IllegalArgumentException("Procedure arguments can't be null.");
175        } else {
176            this.id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
177            this.procedureObject = function;
178            TObjectName procedureName = getProcedureName();
179            TSourceToken startToken = procedureName.getStartToken();
180            TSourceToken endToken = procedureName.getEndToken();
181            this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo, ModelBindingManager.getGlobalHash());
182            this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
183                    endToken.columnNo + (long) SQLUtil.endTrim(endToken.astext).length(), ModelBindingManager.getGlobalHash());
184            this.fullName = procedureName.toString();
185            this.name = procedureName.toString();
186
187            EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
188            boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
189            boolean supportSchema = TSQLEnv.supportSchema(vendor);
190
191            fillSchemaInfo();
192
193            if (supportCatalog) {
194                this.database = DlineageUtil.getTableDatabase(procedureName.toString());
195                if (SQLUtil.isEmpty(this.database) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
196                        && !SQLUtil.isEmpty(procedureName.getImplictDatabaseString())) {
197                    this.database = procedureName.getImplictDatabaseString();
198                }
199            }
200
201            if (supportSchema) {
202                this.schema = DlineageUtil.getTableSchema(procedureName.toString());
203                if (SQLUtil.isEmpty(this.schema) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
204                        && !SQLUtil.isEmpty(procedureName.getImplictSchemaString())) {
205                    this.schema = procedureName.getImplictSchemaString();
206                }
207
208                if (!SQLUtil.isEmpty(this.database) && SQLUtil.isEmpty(this.schema)) {
209                    if (!SQLUtil.isEmpty(procedureName.getImplictSchemaString())) {
210                        this.schema = procedureName.getImplictSchemaString();
211                    } else {
212                        this.schema = TSQLEnv.DEFAULT_SCHEMA_NAME;
213                    }
214                }
215            }
216
217            if (!supportCatalog) {
218                this.database = null;
219            } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
220                this.database = getDefaultDatabase();
221            }
222
223            if (!supportSchema) {
224                this.schema = null;
225            } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
226                this.schema = getDefaultSchema();
227            }
228
229            updateProcedureName(supportCatalog, supportSchema);
230
231            if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
232                this.server = getDefaultServer();
233            }
234        }
235    }
236    
237    private void fillSchemaInfo() {
238                TCustomSqlStatement stmt = DlineageUtil.getTopStmt(ModelBindingManager.getGlobalStmtStack().peek());
239                String sqlComment = null;
240                try {
241                        sqlComment = stmt.getCommentBeforeNode();
242                } catch (Exception e) {
243                }
244                if (!SQLUtil.isEmpty(sqlComment) && (sqlComment.indexOf("db") != -1 || sqlComment.indexOf("schema") != -1)) {
245                        Properties properties = new Properties();
246                        try {
247                                properties.load(
248                                                new ByteArrayInputStream(sqlComment.replace("--", "").trim().replace(",", "\n").getBytes()));
249                                if (SQLUtil.isEmpty(this.server) && properties.containsKey("db-instance")) {
250                                        this.server = properties.getProperty("db-instance");
251                                }
252                                if (SQLUtil.isEmpty(this.database) && properties.containsKey("db")) {
253                                        this.database = properties.getProperty("db");
254                                        if(this.database.indexOf(".")!=-1) {
255                                                String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
256                                                this.database = delimitedChar + SQLUtil.trimColumnStringQuote(this.database) + delimitedChar;
257                                        }
258                                }
259                                if (SQLUtil.isEmpty(this.schema) && properties.containsKey("schema")) {
260                                        this.schema = properties.getProperty("schema");
261                                        if(this.schema.indexOf(".")!=-1) {
262                                                String delimitedChar = TSQLEnv.delimitedChar(ModelBindingManager.getGlobalOption().getVendor());
263                                                this.schema = delimitedChar + SQLUtil.trimColumnStringQuote(this.schema) + delimitedChar;
264                                        }
265                                }
266                        } catch (IOException e) {
267                logger.error("load sql comment properties failed.", e);
268                        }
269                }
270        }
271
272        protected void updateProcedureName(boolean supportCatalog, boolean supportSchema) {
273                List<String> segments = SQLUtil.parseNames(this.name);
274                this.name = segments.get(segments.size() - 1);
275                if (supportCatalog && supportSchema) {
276                        StringBuilder builder = new StringBuilder();
277                        if (segments.size() > 2) {
278                                builder.append(segments.get(segments.size() - 3)).append(".");
279                        } else {
280                                if (!SQLUtil.isEmpty(this.database) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(this.database)) {
281                                        builder.append(this.database).append(".");
282                                }
283                        }
284                        if (segments.size() > 1) {
285                                builder.append(segments.get(segments.size() - 2)).append(".");
286                        } else {
287                                if (builder.length() > 0) {
288                                        if (this.schema == null) {
289                                                if (ModelBindingManager.getGlobalVendor() == EDbVendor.dbvmssql) {
290                                                        this.schema = "dbo";
291                                                } else {
292                                                        this.schema = getDefaultSchema();
293                                                }
294                                        }
295                                        else if (TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)
296                                                        && ModelBindingManager.getGlobalVendor() == EDbVendor.dbvmssql) {
297                                                this.schema = "dbo";
298                                        }
299                                        builder.append(this.schema).append(".");
300                                } else {
301                                        if (!SQLUtil.isEmpty(this.schema) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)) {
302                                                builder.append(this.schema).append(".");
303                                        }
304                                }
305                        }
306                        builder.append(this.name);
307                        this.name = builder.toString();
308                } else if (supportCatalog) {
309                        if (segments.size() > 1) {
310                                this.name = segments.get(segments.size() - 2) + "." + this.name;
311                        }
312                        else {
313                                if (!SQLUtil.isEmpty(this.database) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(this.database)) {
314                                        this.name = this.database + "." + this.name;
315                                }
316                        }
317                } else if (supportSchema) {
318                        if (segments.size() > 1) {
319                                this.name = segments.get(segments.size() - 2) + "." + this.name;
320                        } else {
321                                if (!SQLUtil.isEmpty(this.schema) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)) {
322                                        this.name = this.schema + "." + this.name;
323                                }
324                        }
325                }
326        }
327
328    protected String getDefaultServer() {
329        String defaultServer = null;
330        if (ModelBindingManager.getGlobalSQLEnv() != null) {
331            defaultServer = ModelBindingManager.getGlobalSQLEnv().getDefaultServerName();
332        }
333        if (!SQLUtil.isEmpty(defaultServer))
334            return defaultServer;
335        return TSQLEnv.DEFAULT_SERVER_NAME;
336    }
337
338    protected String getDefaultSchema() {
339        String defaultSchema = null;
340        if (ModelBindingManager.getGlobalSQLEnv() != null) {
341            defaultSchema = ModelBindingManager.getGlobalSQLEnv().getDefaultSchemaName();
342        }
343        if (!SQLUtil.isEmpty(defaultSchema))
344            return defaultSchema;
345        return TSQLEnv.DEFAULT_SCHEMA_NAME;
346    }
347
348    protected String getDefaultDatabase() {
349        String defaultDatabase = null;
350        if (ModelBindingManager.getGlobalSQLEnv() != null) {
351            defaultDatabase = ModelBindingManager.getGlobalSQLEnv().getDefaultCatalogName();
352        }
353        if (!SQLUtil.isEmpty(defaultDatabase))
354            return defaultDatabase;
355        return TSQLEnv.DEFAULT_DB_NAME;
356    }
357
358    private TObjectName getProcedureName() {
359        if (procedureObject instanceof TTeradataCreateProcedure) {
360            return ((TTeradataCreateProcedure) procedureObject).getProcedureName();
361        }
362        if (procedureObject instanceof TStoredProcedureSqlStatement) {
363            return ((TStoredProcedureSqlStatement) procedureObject).getStoredProcedureName();
364        }
365        if (procedureObject instanceof TFunctionCall) {
366            return ((TFunctionCall) procedureObject).getFunctionName();
367        }
368        return null;
369    }
370
371    public long getId() {
372        return this.id;
373    }
374
375    public String getName() {
376        return this.name;
377    }
378
379    public void setName(String name) {
380        this.name = name;
381    }
382
383    public Pair3<Long, Long, String> getStartPosition() {
384        return this.startPosition;
385    }
386
387    public Pair3<Long, Long, String> getEndPosition() {
388        return this.endPosition;
389    }
390
391    public String getFullName() {
392        return this.fullName;
393    }
394
395    public void setFullName(String fullName) {
396        this.fullName = fullName;
397    }
398
399    public List<Argument> getArguments() {
400        return this.arguments;
401    }
402
403    public void setArguments(List<Argument> arguments) {
404        this.arguments = arguments;
405    }
406
407    public void addArgument(Argument argument) {
408        if (argument != null && !this.arguments.contains(argument)) {
409            this.arguments.add(argument);
410        }
411
412    }
413
414    public ESqlStatementType getType() {
415        return this.type;
416    }
417
418    public void setType(ESqlStatementType type) {
419        this.type = type;
420    }
421
422    public TParseTreeNode getProcedureObject() {
423        return this.procedureObject;
424    }
425
426    public void setProcedureObject(TParseTreeNode procedureObject) {
427        this.procedureObject = procedureObject;
428    }
429
430    public void setId(int id) {
431        this.id = id;
432    }
433
434    public void setStartPosition(Pair3<Long, Long, String> startPosition) {
435        this.startPosition = startPosition;
436    }
437
438    public void setEndPosition(Pair3<Long, Long, String> endPosition) {
439        this.endPosition = endPosition;
440    }
441
442    public String getDatabase() {
443        return database;
444    }
445
446    public String getSchema() {
447        return schema;
448    }
449
450    public OraclePackage getParentPackage() {
451        return parentPackage;
452    }
453
454    public void setParentPackage(OraclePackage parentPackage) {
455        this.parentPackage = parentPackage;
456    }
457
458    public String getServer() {
459        return server;
460    }
461}