001package gudusoft.gsqlparser.dlineage.dataflow.model;
002
003import gudusoft.gsqlparser.dlineage.routine.RoutineAliasKey;
004import gudusoft.gsqlparser.EDbVendor;
005import gudusoft.gsqlparser.ESqlStatementType;
006import gudusoft.gsqlparser.TCustomSqlStatement;
007import gudusoft.gsqlparser.TSourceToken;
008import gudusoft.gsqlparser.dlineage.util.DlineageUtil;
009import gudusoft.gsqlparser.dlineage.util.Pair3;
010import gudusoft.gsqlparser.nodes.TFunctionCall;
011import gudusoft.gsqlparser.nodes.TObjectName;
012import gudusoft.gsqlparser.nodes.TParseTreeNode;
013import gudusoft.gsqlparser.sqlenv.ESQLDataObjectType;
014import gudusoft.gsqlparser.sqlenv.TSQLEnv;
015import gudusoft.gsqlparser.stmt.TStoredProcedureSqlStatement;
016import gudusoft.gsqlparser.stmt.teradata.TTeradataCreateProcedure;
017import gudusoft.gsqlparser.util.Logger;
018import gudusoft.gsqlparser.util.LoggerFactory;
019import gudusoft.gsqlparser.util.SQLUtil;
020
021import java.io.ByteArrayInputStream;
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.List;
025import java.util.Properties;
026
027public class OraclePackage {
028        private static final Logger logger = LoggerFactory.getLogger(OraclePackage.class);
029        private long id;
030        private String server;
031        private String database;
032        private String schema;
033        private String name;
034        private String fullName;
035        private Pair3<Long, Long, String> startPosition;
036        private Pair3<Long, Long, String> endPosition;
037        private List<Argument> arguments = new ArrayList<Argument>();
038        private List<Procedure> procedures = new ArrayList<Procedure>();
039        private ESqlStatementType type;
040        private TParseTreeNode procedureObject;
041
042        public OraclePackage(TStoredProcedureSqlStatement procedure) {
043                if (procedure == null) {
044                        throw new IllegalArgumentException("Procedure arguments can't be null.");
045                } else {
046                        this.id = ++ModelBindingManager.get().TABLE_COLUMN_ID;
047                        this.procedureObject = procedure;
048                        TObjectName procedureName = getPackageName();
049                        TSourceToken startToken = procedureName.getStartToken();
050                        TSourceToken endToken = procedureName.getEndToken();
051                        this.startPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo, ModelBindingManager.getGlobalHash());
052                        this.endPosition = new Pair3<Long, Long, String>(endToken.lineNo,
053                                        endToken.columnNo + (long) SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash());
054                        this.fullName = procedureName.toString();
055                        this.name = procedureName.toString();
056
057                        EDbVendor vendor = ModelBindingManager.getGlobalOption().getVendor();
058                        boolean supportCatalog = TSQLEnv.supportCatalog(vendor);
059                        boolean supportSchema = TSQLEnv.supportSchema(vendor);
060
061                        fillSchemaInfo();
062
063                        if(supportCatalog) {
064                                this.database = DlineageUtil.getTableDatabase(procedureName.toString());
065                                if (SQLUtil.isEmpty(this.database) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
066                                                && !SQLUtil.isEmpty(procedureName.getImplictDatabaseString())) {
067                                        this.database = procedureName.getImplictDatabaseString();
068                                }
069                        }
070
071                        if(supportSchema) {
072                                this.schema = DlineageUtil.getTableSchema(procedureName.toString());
073                                if (SQLUtil.isEmpty(this.schema) && ModelBindingManager.getGlobalOption().isShowImplicitSchema()
074                                                && !SQLUtil.isEmpty(procedureName.getImplictSchemaString())) {
075                                        this.schema = procedureName.getImplictSchemaString();
076                                }
077
078                                if (!SQLUtil.isEmpty(this.database) && SQLUtil.isEmpty(this.schema)) {
079                                        if (!SQLUtil.isEmpty(procedureName.getImplictSchemaString())) {
080                                                this.schema = procedureName.getImplictSchemaString();
081                                        } else {
082                                                this.schema = TSQLEnv.DEFAULT_SCHEMA_NAME;
083                                        }
084                                }
085                        }
086
087                        if (!supportCatalog) {
088                                this.database = null;
089                        } else if (this.database == null && !TSQLEnv.DEFAULT_DB_NAME.equals(getDefaultDatabase())) {
090                                this.database = getDefaultDatabase();
091                        }
092
093                        if (!supportSchema) {
094                                this.schema = null;
095                        } else if (this.schema == null && !TSQLEnv.DEFAULT_SCHEMA_NAME.equals(getDefaultSchema())) {
096                                this.schema = getDefaultSchema();
097                        }
098                        
099                        updatePackageName(supportCatalog, supportSchema);
100                        
101                        this.type = procedure.sqlstatementtype;
102
103                        if (this.server == null && !TSQLEnv.DEFAULT_SERVER_NAME.equals(getDefaultServer())) {
104                                this.server = getDefaultServer();
105                        }
106                }
107        }
108
109        protected void updatePackageName(boolean supportCatalog, boolean supportSchema) {
110                List<String> segments = SQLUtil.parseNames(this.name);
111                this.name = segments.get(segments.size() - 1);
112                // The typed key of the display name composed below, level for level (RoutineAliasKey.Display).
113                RoutineAliasKey.Display display;
114                try {
115                        display = new RoutineAliasKey.Display(getPackageName(), segments);
116                } catch (RuntimeException failure) {
117                        display = null;
118                }
119                if (supportCatalog && supportSchema) {
120                        StringBuilder builder = new StringBuilder();
121                        if (segments.size() > 2) {
122                                builder.append(segments.get(segments.size() - 3)).append(".");
123                                if (display != null) display.segment(segments.size() - 3);
124                        } else {
125                                if (!SQLUtil.isEmpty(this.database) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(this.database)) {
126                                        builder.append(this.database).append(".");
127                                        if (display != null) display.field(this.database);
128                                }
129                        }
130                        if (segments.size() > 1) {
131                                builder.append(segments.get(segments.size() - 2)).append(".");
132                                if (display != null) display.segment(segments.size() - 2);
133                        } else {
134                                if (builder.length() > 0) {
135                                        if (this.schema == null) {
136                                                if (ModelBindingManager.getGlobalVendor() == EDbVendor.dbvmssql) {
137                                                        this.schema = "dbo";
138                                                } else {
139                                                        this.schema = getDefaultSchema();
140                                                }
141                                        }
142                                        else if (TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)
143                                                        && ModelBindingManager.getGlobalVendor() == EDbVendor.dbvmssql) {
144                                                this.schema = "dbo";
145                                        }
146                                        builder.append(this.schema).append(".");
147                                        if (display != null) display.field(this.schema);
148                                } else {
149                                        if (!SQLUtil.isEmpty(this.schema) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)) {
150                                                builder.append(this.schema).append(".");
151                                                if (display != null) display.field(this.schema);
152                                        }
153                                }
154                        }
155                        builder.append(this.name);
156                        this.name = builder.toString();
157                } else if (supportCatalog) {
158                        if (segments.size() > 1) {
159                                this.name = segments.get(segments.size() - 2) + "." + this.name;
160                                if (display != null) display.segment(segments.size() - 2);
161                        }
162                        else {
163                                if (!SQLUtil.isEmpty(this.database) && !TSQLEnv.DEFAULT_DB_NAME.equalsIgnoreCase(this.database)) {
164                                        this.name = this.database + "." + this.name;
165                                        if (display != null) display.field(this.database);
166                                }
167                        }
168                } else if (supportSchema) {
169                        if (segments.size() > 1) {
170                                this.name = segments.get(segments.size() - 2) + "." + this.name;
171                                if (display != null) display.segment(segments.size() - 2);
172                        } else {
173                                if (!SQLUtil.isEmpty(this.schema) && !TSQLEnv.DEFAULT_SCHEMA_NAME.equalsIgnoreCase(this.schema)) {
174                                        this.name = this.schema + "." + this.name;
175                                        if (display != null) display.field(this.schema);
176                                }
177                        }
178                }
179                if (display != null) {
180                        try {
181                                aliasKey = display.finish();
182                        } catch (RuntimeException failure) {
183                                aliasKey = null;
184                        }
185                }
186        }
187        
188        private void fillSchemaInfo() {
189                TCustomSqlStatement stmt = DlineageUtil.getTopStmt(ModelBindingManager.getGlobalStmtStack().peek());
190                String sqlComment = null;
191                try {
192                        sqlComment = stmt.getCommentBeforeNode();
193                } catch (Exception e) {
194                }
195                if (!SQLUtil.isEmpty(sqlComment) && (sqlComment.indexOf("db") != -1 || sqlComment.indexOf("schema") != -1)) {
196                        Properties properties = new Properties();
197                        try {
198                                properties.load(
199                                                new ByteArrayInputStream(sqlComment.replace("--", "").trim().replace(",", "\n").getBytes()));
200                                if (SQLUtil.isEmpty(this.server) && properties.containsKey("db-instance")) {
201                                        this.server = properties.getProperty("db-instance");
202                                }
203                                if (SQLUtil.isEmpty(this.database) && properties.containsKey("db")) {
204                                        this.database = properties.getProperty("db");
205                                        if(this.database.indexOf(".")!=-1) {
206                                                this.database = SQLUtil.quoteDottedName(ModelBindingManager.getGlobalOption().getVendor(), ESQLDataObjectType.dotCatalog, this.database);
207                                        }
208                                }
209                                if (SQLUtil.isEmpty(this.schema) && properties.containsKey("schema")) {
210                                        this.schema = properties.getProperty("schema");
211                                        if(this.schema.indexOf(".")!=-1) {
212                                                this.schema = SQLUtil.quoteDottedName(ModelBindingManager.getGlobalOption().getVendor(), ESQLDataObjectType.dotSchema, this.schema);
213                                        }
214                                }
215                        } catch (IOException e) {
216                                logger.error("load sql comment properties failed.", e);
217                        }
218                }
219        }
220
221        protected String getDefaultServer() {
222                String defaultServer = null;
223                if (ModelBindingManager.getGlobalSQLEnv() != null) {
224                        defaultServer = ModelBindingManager.getGlobalSQLEnv().getDefaultServerName();
225                }
226                if (!SQLUtil.isEmpty(defaultServer))
227                        return defaultServer;
228                return TSQLEnv.DEFAULT_SERVER_NAME;
229        }
230
231        protected String getDefaultSchema() {
232                return ModelBindingManager.getEffectiveDefaultSchema();
233        }
234
235        protected String getDefaultDatabase() {
236                return ModelBindingManager.getEffectiveDefaultDatabase();
237        }
238
239        private TObjectName getPackageName() {
240                if(procedureObject instanceof TTeradataCreateProcedure)
241                {
242                        return ((TTeradataCreateProcedure)procedureObject).getProcedureName();
243                }
244                if(procedureObject instanceof TStoredProcedureSqlStatement)
245                {
246                        return ((TStoredProcedureSqlStatement)procedureObject).getStoredProcedureName();
247                }
248                if(procedureObject instanceof TFunctionCall)
249                {
250                        return ((TFunctionCall)procedureObject).getFunctionName();
251                }
252                return null;
253        }
254
255        public long getId() {
256                return this.id;
257        }
258
259        /**
260         * The typed key of {@link #getName()}, the display name the routine index is keyed by (see
261         * {@code RoutineAliasKey.Display}); null when it cannot be built.
262         */
263        private RoutineAliasKey aliasKey;
264
265        public RoutineAliasKey getAliasKey() {
266                return aliasKey;
267        }
268
269        public String getName() {
270                return this.name;
271        }
272
273        public void setName(String name) {
274                this.name = name;
275        }
276
277        public Pair3<Long, Long, String> getStartPosition() {
278                return this.startPosition;
279        }
280
281        public Pair3<Long, Long, String> getEndPosition() {
282                return this.endPosition;
283        }
284
285        public String getFullName() {
286                return this.fullName;
287        }
288
289        public void setFullName(String fullName) {
290                this.fullName = fullName;
291        }
292
293        public List<Argument> getArguments() {
294                return this.arguments;
295        }
296
297        public void setArguments(List<Argument> arguments) {
298                this.arguments = arguments;
299        }
300
301        public void addArgument(Argument argument) {
302                if (argument != null && !this.arguments.contains(argument)) {
303                        this.arguments.add(argument);
304                }
305
306        }
307        
308        public List<Procedure> getProcedures() {
309                return this.procedures;
310        }
311
312        public void setProcedures(List<Procedure> procedures) {
313                this.procedures = procedures;
314        }
315
316        public void addProcedure(Procedure procedure) {
317                if (procedure != null && !this.procedures.contains(procedure)) {
318                        this.procedures.add(procedure);
319                }
320        }
321
322        public ESqlStatementType getType() {
323                return this.type;
324        }
325
326        public void setType(ESqlStatementType type) {
327                this.type = type;
328        }
329
330        public TParseTreeNode getProcedureObject() {
331                return this.procedureObject;
332        }
333
334        public void setProcedureObject(TParseTreeNode procedureObject) {
335                this.procedureObject = procedureObject;
336        }
337
338        public void setId(int id) {
339                this.id = id;
340        }
341
342        public void setStartPosition(Pair3<Long, Long, String> startPosition) {
343                this.startPosition = startPosition;
344        }
345
346        public void setEndPosition(Pair3<Long, Long, String> endPosition) {
347                this.endPosition = endPosition;
348        }
349
350        public String getDatabase() {
351                return database;
352        }
353
354        public String getSchema() {
355                return schema;
356        }
357
358        public String getServer() {
359                return server;
360        }
361}