001package gudusoft.gsqlparser.sqlenv.parser.sqlflow;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.sqlenv.*;
005import gudusoft.gsqlparser.sqlenv.parser.sqldep.MultipleSQLDepSQLEnv;
006import gudusoft.gsqlparser.util.SQLUtil;
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.Map;
011import java.util.logging.Level;
012import java.util.logging.Logger;
013
014@SuppressWarnings("rawtypes")
015public class SqlflowSQLEnv extends TSQLEnv {
016
017        private Map server;
018
019        private Boolean init = false;
020
021        public SqlflowSQLEnv(String defaultServer, String defaultDatabase, String defaultSchema, EDbVendor dbVendor, Map server) {
022                super(dbVendor);
023                if(!SQLUtil.isEmpty(defaultServer) && !defaultServer.equals(TSQLEnv.DEFAULT_SERVER_NAME)) {
024                        setDefaultServerName(defaultServer);
025                }
026                if(!SQLUtil.isEmpty(defaultDatabase) && !defaultDatabase.equals(TSQLEnv.DEFAULT_DB_NAME)) {
027                        setDefaultCatalogName(defaultDatabase);
028                }
029                if(!SQLUtil.isEmpty(defaultSchema) && !defaultSchema.equals(TSQLEnv.DEFAULT_SCHEMA_NAME)) {
030                        setDefaultSchemaName(defaultSchema);
031                }
032                this.server = server;
033                initSQLEnv();
034        }
035
036        @Override
037        public void initSQLEnv() {
038                synchronized (init) {
039                        if (init)
040                                return;
041                        String dbVendor = (String) server.get("dbVendor");
042                        if (!SQLUtil.isEmpty((String) server.get("name"))) {
043                                this.setDefaultServerName((String) server.get("name"));
044                        }
045                        EDbVendor vendor = getDBVendor();
046                        if (dbVendor != null) {
047                                vendor = EDbVendor.valueOf(dbVendor);
048                        }
049
050                        boolean supportsCatalogs = TSQLEnv.supportCatalog(vendor);
051                        boolean supportsSchemas = TSQLEnv.supportSchema(vendor);
052
053                        // Synonyms are resolved in a final pass so that their source tables,
054                        // which may live in another schema/catalog, are already loaded.
055                        List<Object[]> pendingSynonyms = new ArrayList<Object[]>();
056
057                        try {
058                                if (supportsCatalogs && supportsSchemas) {
059                                        List databases = (List) server.get("databases");
060                                        if (databases != null) {
061                                                for (int i = 0; i < databases.size(); i++) {
062                                                        Map jsonDatabase = (Map) databases.get(i);
063                                                        String databaseName = (String) jsonDatabase.get("name");
064                                                        List schemas = (List) jsonDatabase.get("schemas");
065                                                        if (schemas == null) {
066                                                                continue;
067                                                        }
068                                                        TSQLCatalog sqlCatalog = getSQLCatalog(databaseName, true);
069                                                        for (int j = 0; j < schemas.size(); j++) {
070                                                                Map jsonSchema = (Map) schemas.get(j);
071                                                                String schemaName = (String) jsonSchema.get("name");
072                                                                TSQLSchema sqlSchema = sqlCatalog.getSchema(schemaName, true);
073                                                                appendTables(jsonSchema, sqlSchema);
074                                                                appendPackages(jsonSchema, sqlSchema);
075                                                                appendProcedures(jsonSchema, sqlSchema, null);
076                                                                collectSynonyms(jsonSchema, sqlSchema, pendingSynonyms);
077                                                        }
078                                                }
079                                        }
080                                } else if (supportsCatalogs) {
081                                        List databases = (List) server.get("databases");
082                                        if (databases != null) {
083                                                for (int i = 0; i < databases.size(); i++) {
084                                                        Map jsonDatabase = (Map) databases.get(i);
085                                                        String databaseName = (String) jsonDatabase.get("name");
086                                                        TSQLCatalog sqlCatalog = getSQLCatalog(databaseName, true);
087                                                        TSQLSchema sqlSchema = sqlCatalog.getSchema(TSQLEnv.DEFAULT_SCHEMA_NAME, true);
088                                                        appendTables(jsonDatabase, sqlSchema);
089                                                        appendPackages(jsonDatabase, sqlSchema);
090                                                        appendProcedures(jsonDatabase, sqlSchema, null);
091                                                        collectSynonyms(jsonDatabase, sqlSchema, pendingSynonyms);
092                                                }
093                                        }
094                                } else if (supportsSchemas) {
095                                        List schemas = (List) server.get("schemas");
096                                        if (schemas != null) {
097                                                for (int i = 0; i < schemas.size(); i++) {
098                                                        Map jsonSchema = (Map) schemas.get(i);
099                                                        String schemaName = (String) jsonSchema.get("name");
100                                                        TSQLCatalog sqlCatalog = getSQLCatalog(TSQLEnv.DEFAULT_DB_NAME, true);
101                                                        TSQLSchema sqlSchema = sqlCatalog.getSchema(schemaName, true);
102                                                        appendTables(jsonSchema, sqlSchema);
103                                                        appendPackages(jsonSchema, sqlSchema);
104                                                        appendProcedures(jsonSchema, sqlSchema, null);
105                                                        collectSynonyms(jsonSchema, sqlSchema, pendingSynonyms);
106                                                }
107                                        }
108                                }
109                                for (int i = 0; i < pendingSynonyms.size(); i++) {
110                                        Object[] pending = pendingSynonyms.get(i);
111                                        appendSynonym((TSQLSchema) pending[0], (Map) pending[1]);
112                                }
113                        } catch (Exception e) {
114                                Logger.getLogger(MultipleSQLDepSQLEnv.class.getName()).log(Level.WARNING, "Parse json failed.", e);
115                        }
116                        init = true;
117                }
118        }
119
120        private void appendTables(Map jsonSchema, TSQLSchema sqlSchema) {
121                List tables = (List) jsonSchema.get("tables");
122                List views = (List) jsonSchema.get("views");
123                List dbObjs = new ArrayList();
124                if (tables != null) {
125                        dbObjs.addAll(tables);
126                }
127                if (views != null) {
128                        dbObjs.addAll(views);
129                }
130                for (int k = 0; k < dbObjs.size(); k++) {
131                        Map jsonTable = (Map) dbObjs.get(k);
132                        String tableName = (String) jsonTable.get("name");
133                        TSQLTable sqlTable = sqlSchema.createTable(tableName, 3);
134                        String type = (String) jsonTable.get("type");
135                        if (type != null && type.toLowerCase().indexOf("view") != -1) {
136                                sqlTable.setView(true);
137                        }
138                        List columns = (List) jsonTable.get("columns");
139                        if(columns!=null) {
140                                for (int l = 0; l < columns.size(); l++) {
141                                        Map jsonColumn = (Map) columns.get(l);
142                                        sqlTable.addColumn((String) jsonColumn.get("name"));
143                                }
144                        }
145                }
146        }
147
148        private void collectSynonyms(Map jsonSchema, TSQLSchema sqlSchema, List<Object[]> pendingSynonyms) {
149                List synonyms = (List) jsonSchema.get("synonyms");
150                if (synonyms == null) {
151                        return;
152                }
153                for (int k = 0; k < synonyms.size(); k++) {
154                        Map jsonSynonym = (Map) synonyms.get(k);
155                        if (jsonSynonym == null) {
156                                continue;
157                        }
158                        pendingSynonyms.add(new Object[] { sqlSchema, jsonSynonym });
159                }
160        }
161
162        private void appendSynonym(TSQLSchema sqlSchema, Map jsonSynonym) {
163                String synonymName = (String) jsonSynonym.get("name");
164                if (SQLUtil.isEmpty(synonymName)) {
165                        return;
166                }
167                // Register the synonym as a table alias inside its own schema.
168                TSQLTable synonymTable = sqlSchema.createTable(synonymName, 3);
169                if (synonymTable == null) {
170                        return;
171                }
172                String sourceName = (String) jsonSynonym.get("sourceName");
173                if (SQLUtil.isEmpty(sourceName)) {
174                        return;
175                }
176                String sourceSchema = (String) jsonSynonym.get("sourceSchema");
177                // Inherit the source object's columns so the synonym resolves like the target.
178                TSQLTable sourceTable = findSourceTable(sourceSchema, sourceName);
179                if (sourceTable != null) {
180                        if (sourceTable.isView()) {
181                                synonymTable.setView(true);
182                        }
183                        List<String> columns = sourceTable.getColumns(true);
184                        if (columns != null) {
185                                for (int i = 0; i < columns.size(); i++) {
186                                        String column = columns.get(i);
187                                        if (!SQLUtil.isEmpty(column)) {
188                                                synonymTable.addColumn(column);
189                                        }
190                                }
191                        }
192                }
193        }
194
195        private TSQLTable findSourceTable(String sourceSchema, String sourceName) {
196                if (!SQLUtil.isEmpty(sourceSchema)) {
197                        for (TSQLCatalog catalog : getCatalogList()) {
198                                TSQLSchema schema = catalog.getSchema(sourceSchema, false);
199                                if (schema != null) {
200                                        TSQLTable table = schema.findTable(sourceName);
201                                        if (table != null) {
202                                                return table;
203                                        }
204                                }
205                        }
206                }
207                // Fallback: search across all schemas by the simple source name.
208                for (TSQLCatalog catalog : getCatalogList()) {
209                        for (TSQLSchema schema : catalog.getSchemaList()) {
210                                TSQLTable table = schema.findTable(sourceName);
211                                if (table != null) {
212                                        return table;
213                                }
214                        }
215                }
216                return null;
217        }
218
219        private void appendPackages(Map jsonSchema, TSQLSchema sqlSchema) {
220                List packages = (List) jsonSchema.get("packages");
221                List dbObjs = new ArrayList();
222                if (packages != null) {
223                        dbObjs.addAll(packages);
224                }
225                for (int k = 0; k < dbObjs.size(); k++) {
226                        Map jsonOraclePackage = (Map) dbObjs.get(k);
227                        String packageName = (String) jsonOraclePackage.get("name");
228                        TSQLOraclePackage sqlPackage = sqlSchema.createOraclePackage(packageName);
229                        appendProcedures(jsonOraclePackage, sqlSchema, sqlPackage);
230                }
231        }
232
233        private void appendProcedures(Map jsonProcedureParent, TSQLSchema sqlSchema, TSQLOraclePackage sqlPackage) {
234                if (jsonProcedureParent.containsKey("procedures")) {
235                        List<Map> procedures = (List<Map>) jsonProcedureParent.get("procedures");
236                        if(procedures!=null) {
237                                for (Map procedure : procedures) {
238                                        String procedureName = (String) procedure.get("name");
239                                        if (sqlPackage != null) {
240                                                sqlPackage.createProcedure(procedureName);
241                                        } else {
242                                                sqlSchema.createProcedure(procedureName);
243                                        }
244                                }
245                        }
246                }
247                if (jsonProcedureParent.containsKey("functions")) {
248                        List<Map> functions = (List<Map>) jsonProcedureParent.get("functions");
249                        if (functions != null) {
250                                for (Map function : functions) {
251                                        String functionName = (String) function.get("name");
252                                        if (sqlPackage != null) {
253                                                sqlPackage.createFunction(functionName);
254                                        } else {
255                                                sqlSchema.createFunction(functionName);
256                                        }
257                                }
258                        }
259                }
260                if (jsonProcedureParent.containsKey("triggers")) {
261                        List<Map> triggers = (List<Map>) jsonProcedureParent.get("triggers");
262                        if (triggers != null) {
263                                for (Map trigger : triggers) {
264                                        String triggerName = (String) trigger.get("name");
265                                        if (sqlPackage != null) {
266                                                sqlPackage.createTrigger(triggerName);
267                                        } else {
268                                                sqlSchema.createTrigger(triggerName);
269                                        }
270                                }
271                        }
272                }
273        }
274}