2 * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.md.sal.dom.xsql.jdbc;
11 import java.net.ServerSocket;
12 import java.net.Socket;
13 import java.sql.SQLException;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
18 import java.util.StringTokenizer;
19 import java.util.concurrent.ConcurrentHashMap;
20 import org.opendaylight.controller.md.sal.dom.xsql.XSQLAdapter;
21 import org.opendaylight.controller.md.sal.dom.xsql.XSQLBluePrint;
22 import org.opendaylight.controller.md.sal.dom.xsql.XSQLBluePrintNode;
23 import org.opendaylight.controller.md.sal.dom.xsql.XSQLColumn;
24 import org.opendaylight.controller.md.sal.dom.xsql.XSQLCriteria;
26 public class JDBCServer extends Thread {
27 private ServerSocket socket = null;
28 private XSQLAdapter adapter = null;
30 public JDBCServer(XSQLAdapter a) {
38 socket = new ServerSocket(40004);
39 while (!adapter.stopped) {
40 Socket s = socket.accept();
41 new JDBCConnection(s, adapter);
43 } catch (Exception err) {
44 err.printStackTrace();
48 public void connectToClient(String addr) {
50 Socket s = new Socket(addr, 50003);
51 new JDBCConnection(s, adapter);
52 } catch (Exception err) {
53 err.printStackTrace();
57 public static void execute(JDBCResultSet rs, XSQLAdapter adapter)throws SQLException {
58 if(rs.getSQL().toLowerCase().trim().equals("select 1")){
62 checkAndBreakSubQueries(rs, adapter);
63 if (rs.getSubQueries().size() == 0) {
64 parseTables(rs, adapter.getBluePrint());
65 parseFields(rs, adapter.getBluePrint());
66 parseCriteria(rs, adapter.getBluePrint());
69 } catch (Exception err) {
70 throw new SQLException("Error", err);
73 parseExternalQuery(rs);
77 public static void parseExternalQuery(JDBCResultSet rs) throws SQLException {
78 String sql = rs.getSQL();
79 for (Map.Entry<String, JDBCResultSet> entry : rs.getSubQueries()
81 int index = sql.toLowerCase().indexOf(entry.getValue().getSQL());
82 String extSql = sql.substring(0, index);
83 index = extSql.lastIndexOf("(");
84 extSql = extSql.substring(0, index);
85 System.out.println("External SQL=" + extSql);
86 parseLogicalFields(extSql, rs);
90 public static void parseLogicalFields(String sql, JDBCResultSet rs)
92 if(sql.trim().toLowerCase().equals("select * from")){
93 for (Map.Entry<String, JDBCResultSet> entry : rs.getSubQueries().entrySet()) {
94 for(XSQLBluePrintNode node:entry.getValue().getTables()){
95 rs.addTableToQuery(node);
97 rs.getFields().addAll(entry.getValue().getFields());
98 while (entry.getValue().next()) {
99 Map<String, Object> rec = entry.getValue().getCurrent();
100 Map<String, Object> newRec = new HashMap<>();
102 rs.addRecord(newRec);
105 rs.setFinished(true);
109 Map<String, XSQLBluePrintNode> logicalNameToNode = new HashMap<String, XSQLBluePrintNode>();
110 Map<String, String> origNameToName = new HashMap<String, String>();
111 List<XSQLColumn> columnOrder = new ArrayList<>();
112 int nextLogField = addNextLogicalField(sql, 0,
113 logicalNameToNode, origNameToName,columnOrder);
114 int next = sql.toLowerCase().indexOf(" as ", nextLogField);
116 nextLogField = addNextLogicalField(sql, nextLogField + 1,
117 logicalNameToNode, origNameToName,columnOrder);
118 next = sql.toLowerCase().indexOf(" as ", nextLogField + 1);
121 for (XSQLBluePrintNode node : logicalNameToNode.values()) {
122 rs.addTableToQuery(node);
124 rs.getFields().addAll(columnOrder);
125 for (Map.Entry<String, JDBCResultSet> entry : rs.getSubQueries().entrySet()) {
126 while (entry.getValue().next()) {
127 Map<String, Object> rec = entry.getValue().getCurrent();
128 Map<String, Object> newRec = new HashMap<>();
129 for (Map.Entry<String, Object> e : rec.entrySet()) {
130 Object value = e.getValue();
131 String logicalKey = origNameToName.get(e.getKey());
132 if (value != null && logicalKey != null) {
133 newRec.put(logicalKey, value);
136 rs.addRecord(newRec);
139 rs.setFinished(true);
142 public static void main(String args[]) {
143 String sql = "SELECT DISTINCT"
144 + "\"LOGICAL_TABLE_1\".\"nodes/node.id\" AS \"COL0\"\n"
145 + ",\"LOGICAL_TABLE_1\".\"nodes/node.id\" AS \"COL1\"\n"
146 + ",\"LOGICAL_TABLE_1\".\"nodes/node.id\" AS \"COL2\"\n"
148 + "(select * from nodes/node;) \"LOGICAL_TABLE_1\"\n";
149 JDBCResultSet rs = new JDBCResultSet(sql);
151 parseLogicalFields(sql, rs);
152 } catch (Exception err) {
153 err.printStackTrace();
157 public static int addNextLogicalField(String sql, int startIndex,
158 Map<String, XSQLBluePrintNode> logicalNameToNode,
159 Map<String, String> origNameToName, List<XSQLColumn> columnOrder) {
160 int index1 = sql.indexOf("\"", startIndex);
161 int index2 = sql.indexOf("\".\"", index1);
162 int index3 = sql.indexOf("\"", index2 + 3);
163 int index4 = sql.toLowerCase().indexOf(" as ", startIndex);
164 int index5 = sql.indexOf("\"", index4);
165 int index6 = sql.indexOf("\"", index5 + 1);
167 String tblName = sql.substring(index1 + 1, index2);
168 String origFieldNameFull = sql.substring(index2 + 3, index3);
169 String origTableName = "";
170 String origFieldName = "";
171 if (origFieldNameFull.indexOf(".") != -1) {
172 origTableName = origFieldNameFull.substring(0,origFieldNameFull.indexOf("."));
173 origFieldName = origFieldNameFull.substring(origFieldNameFull.indexOf(".") + 1);
175 String logicalFieldName = sql.substring(index5 + 1, index6);
176 XSQLBluePrintNode node = logicalNameToNode.get(tblName);
178 node = new XSQLBluePrintNode(tblName, origTableName, 0);
179 logicalNameToNode.put(tblName, node);
181 columnOrder.add(node.addColumn(logicalFieldName, tblName, origFieldName, origTableName));
182 origNameToName.put(origFieldNameFull, tblName + "." + logicalFieldName);
186 public static void checkAndBreakSubQueries(JDBCResultSet rs,XSQLAdapter adapter) throws SQLException {
187 String sql = rs.getSQL().toLowerCase();
188 int index = sql.indexOf("select");
190 throw new SQLException("Select statement is missing...");
191 int index2 = sql.indexOf("select", index + 6);
193 int startSubQuery = index2;
194 for (int i = startSubQuery; i >= 0; i--) {
195 if (sql.charAt(i) == '(') {
201 int endSubQuery = startSubQuery;
203 if (sql.charAt(endSubQuery) == '(') {
206 else if (sql.charAt(endSubQuery) == ')') {
210 } while (braketCount > 0 || endSubQuery == sql.length());
211 String subQuerySQL = sql.substring(startSubQuery + 1,endSubQuery - 1);
212 if(rs.getSQL().toLowerCase().substring(0,startSubQuery).trim().equals("select * from")){
213 rs.setSQL(subQuerySQL);
216 index = sql.indexOf("\"", endSubQuery);
217 index2 = sql.indexOf("\"", index + 1);
220 index2 = sql.length();
222 String logicalName = rs.getSQL().substring(index + 1, index2).trim();
223 JDBCResultSet subRS = rs.addSubQuery(subQuerySQL, logicalName);
224 JDBCServer.execute(subRS, adapter);
228 public static void parseTables(JDBCResultSet rs, XSQLBluePrint bp)
229 throws SQLException {
230 String lowSQL = rs.getSQL().toLowerCase();
231 int from = lowSQL.indexOf("from");
232 int where = lowSQL.indexOf("where");
233 int subQuery = lowSQL.indexOf("select", 2);
234 int fromTo = lowSQL.indexOf(";");
236 if (where != -1 && subQuery != -1 && where < subQuery) {
238 } else if (where != -1 && subQuery != -1 && where > subQuery) {
240 } else if (where != -1) {
242 } else if (subQuery != -1) {
247 throw new SQLException("Missing \"from\" statement.");
251 throw new SQLException("Missing terminating \";\".");
254 String tableNames = rs.getSQL().substring(from + 4, fromTo).trim();
255 StringTokenizer tokens = new StringTokenizer(tableNames, ",");
256 while (tokens.hasMoreTokens()) {
257 String tableName = tokens.nextToken().trim();
258 XSQLBluePrintNode table = bp.getBluePrintNodeByTableName(tableName);
260 throw new SQLException("Unknown table name \"" + tableName
263 rs.addTableToQuery(table);
267 public static void addCriteria(XSQLColumn col, XSQLCriteria c,
269 Map<XSQLColumn, List<XSQLCriteria>> tblCriteria = rs.getCriteria().get(
271 if (tblCriteria == null) {
272 tblCriteria = new ConcurrentHashMap<XSQLColumn, List<XSQLCriteria>>();
273 rs.getCriteria().put(col.getTableName(), tblCriteria);
275 List<XSQLCriteria> lstCriteria = tblCriteria.get(col);
276 if (lstCriteria == null) {
277 lstCriteria = new ArrayList<XSQLCriteria>();
278 tblCriteria.put(col, lstCriteria);
283 public static void parseFields(JDBCResultSet rs, XSQLBluePrint bp)
284 throws SQLException {
285 String lowSQL = rs.getSQL().toLowerCase();
286 if (!lowSQL.startsWith("select")) {
287 throw new SQLException("Missing 'select' statement.");
289 int from = lowSQL.indexOf("from");
291 throw new SQLException("Missing 'from' statement.");
293 String fields = rs.getSQL().substring(6, from).trim();
294 StringTokenizer tokens = new StringTokenizer(fields, ",");
295 while (tokens.hasMoreTokens()) {
296 String token = tokens.nextToken().trim();
297 if (token.equals("*")) {
298 for (XSQLBluePrintNode table : rs.getTables()) {
299 rs.getFields().addAll(table.getColumns());
303 if (token.indexOf(".") != -1) {
304 XSQLBluePrintNode tbl = bp.getBluePrintNodeByTableName(token
305 .substring(0, token.indexOf(".")).trim());
306 String p = token.substring(token.indexOf(".") + 1);
308 for (XSQLColumn c : tbl.getColumns()) {
309 rs.getFields().add(c);
312 XSQLColumn col = tbl.findColumnByName(p);
313 rs.getFields().add(col);
316 XSQLColumn col = null;
317 for (XSQLBluePrintNode table : rs.getTables()) {
319 col = table.findColumnByName(token);
320 } catch (Exception err) {
327 throw new SQLException("Unknown field name '" + token
331 rs.getFields().add(col);
336 public static void parseCriteria(JDBCResultSet rs, XSQLBluePrint bp) {
337 String lowSQL = rs.getSQL().toLowerCase();
338 int where = lowSQL.indexOf("where");
339 int order = lowSQL.indexOf("order");
340 int whereTo = lowSQL.indexOf(";");
351 whereTo=lowSQL.length();
354 String whereStatement = rs.getSQL().substring(where + 5, whereTo)
356 XSQLCriteria cr = new XSQLCriteria(whereStatement, -1);
357 for (XSQLBluePrintNode tbl : rs.getTables()) {
358 for (XSQLColumn col : tbl.getColumns()) {
359 String colCriteria = cr.getCriteriaForProperty(col);
360 if (colCriteria != null && !colCriteria.trim().equals("")) {
361 addCriteria(col, new XSQLCriteria(colCriteria, -1), rs);