001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.dao.orm.hibernate;
016    
017    import com.liferay.portal.kernel.cache.PortalCache;
018    import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
019    import com.liferay.portal.kernel.util.CharPool;
020    import com.liferay.portal.kernel.util.StringUtil;
021    
022    import java.util.HashSet;
023    import java.util.Set;
024    
025    /**
026     * @author Shuyang Zhou
027     */
028    public class SQLQueryTableNamesUtil {
029    
030            public static String[] getTableNames(String sql) {
031                    String[] tableNames = _portalCache.get(sql);
032    
033                    if (tableNames != null) {
034                            return tableNames;
035                    }
036    
037                    String lowerCaseSQL = StringUtil.toLowerCase(sql);
038    
039                    Set<String> tableNameSet = new HashSet<>();
040    
041                    // Find table name from the "from" clause
042    
043                    int index = 0;
044    
045                    while ((index = lowerCaseSQL.indexOf(" from ", index)) != -1) {
046                            index += 6;
047    
048                            int[] indexes = _getTableNameIndexes(lowerCaseSQL, index);
049    
050                            if (indexes != null) {
051                                    tableNameSet.add(sql.substring(indexes[0], indexes[1]));
052                            }
053                    }
054    
055                    // Find table name from the "join" clause
056    
057                    index = 0;
058    
059                    while ((index = lowerCaseSQL.indexOf(" join ", index)) != -1) {
060                            index += 6;
061    
062                            int[] indexes = _getTableNameIndexes(lowerCaseSQL, index);
063    
064                            if (indexes != null) {
065                                    tableNameSet.add(sql.substring(indexes[0], indexes[1]));
066                            }
067                    }
068    
069                    tableNames = tableNameSet.toArray(new String[tableNameSet.size()]);
070    
071                    _portalCache.put(sql, tableNames);
072    
073                    return tableNames;
074            }
075    
076            private static int[] _getTableNameIndexes(String sql, int index) {
077                    int start = -1;
078                    int end = sql.length();
079    
080                    for (int i = index; i < sql.length(); i++) {
081                            char c = sql.charAt(i);
082    
083                            if (c == CharPool.OPEN_PARENTHESIS) {
084    
085                                    // There is a subquery in the current clause, so no need to
086                                    // parse for a table name
087    
088                                    break;
089                            }
090                            else if ((c == CharPool.SPACE) ||
091                                             (c == CharPool.CLOSE_PARENTHESIS)) {
092    
093                                    if (start != -1) {
094                                            end = i;
095    
096                                            break;
097                                    }
098                            }
099                            else if (start == -1) {
100                                    start = i;
101                            }
102                    }
103    
104                    if (start == -1) {
105                            return null;
106                    }
107    
108                    return new int[] {start, end};
109            }
110    
111            private static final PortalCache<String, String[]> _portalCache =
112                    SingleVMPoolUtil.getPortalCache(SQLQueryTableNamesUtil.class.getName());
113    
114    }